Respectful contenteditable
: avoids <div>
, respects white-space: pre*
styles line breaks.
npm i @itrocks/contenteditable
import ContentEditable from './node_modules/@itrocks/contenteditable.js'
new ContentEditable(document.querySelector('#edit-me'))
More examples are available in the demo
folder of the
GitHub repository.
The feature manages the content of a contenteditable
DOM element during typing
to maintain clean and consistent text.
The last line break is preserved as well.
The line break characters inserted in your contenteditable
element
depend on its white-space
style attribute:
-
pre
,pre-line
orpre-wrap
: inserts a\n
character, - other
white-space
values result result in a<br>
element.
Any content ending with a line break will have a trailing <br>
added to ensure proper display in your browser.
The following properties and methods are publicly available in the ContentEditable
class.
The element associated with the ContentEditable
instance,
extended as an HTMLEditableElement
. It includes a editable
property that contains the ContentEditable
instance.
new ContentEditable(element)
Applies the @itrocks/contenteditable
feature to an element.
Invokes activate() for initialisation.
Starts a mutation observer to:
- automatically invoke deactivate() when the
contenteditable
attribute is removed, - automatically invoke activate() when the
contenteditable
attribute is re-added.
-
element
An HTMLElement to apply the feature to.
activate()
Sets the contenteditable
attribute on your element if it's not already set,
Enables a keydown event listener to keep line breaks in sync with a clean content structure following the line break matching white-space rule.
br()
Determines and returns the current line break string used for your contenteditable
element,
in accordance with the line break matching white-space rule.
brNode()
Creates a node that matches the current line break string. Result is either a TextNode containing '\n' or an HTMLBRElement.
deactivate()
Removes the contenteditable
attribute from your element.
Deactivates the now unnecessary keydown event listener.
If the value contains no line break, removes the trailing <br>
.
onKeyDown(event)
Handles the keydown event
for the contenteditable
element, ensuring the correct behavior when the 'Enter'
key is pressed.
By default, this method determines the appropriate action for the 'Enter'
key
based on the library's implementation of line break management.
This method is designed to be extensible
using Aspect-Oriented Programming (AOP) principles.
Developers can intercept and augment the behavior of onKeyDown
to customize keyboard event handling
while carefully managing execution priority relative to the library's default behavior.
This extension can be performed before, after, or even instead of the default behavior.
-
Control execution order:
Adding akeydown
event listener viaaddEventListener
does not provide fine-grained control over execution priority relative to the library's built-in handling. ExtendingonKeyDown
allows you to execute your logic either before, after, or instead of the library's processing of the event. -
Avoid unintended interference:
Preventing the library's default'Enter'
key behavior by stopping event propagation (event.stopPropagation()
orevent.preventDefault()
) may inadvertently interfere with other components or listeners unrelated to this library. By extendingonKeyDown
, you ensure your changes are isolated and do not disrupt other listeners.
The following example demonstrates how to extend onKeyDown
for a specific ContentEditable
instance
to prevent the default behavior of the 'Enter'
key when the element does not have a data-multiline
attribute:
const contentEditable = new ContentEditable(document.queryElement('#my-editable'))
const superOnKeyDown = contentEditable.onKeyDown
contentEditable.onKeyDown = function (event: KeyboardEvent): void {
if ((event.key === 'Enter') && !this.element?.hasAttribute('data-multiline')) {
event.preventDefault()
return
}
superOnKeyDown.call(this, event)
}
- By overriding
onKeyDown
, you can implement custom behaviors tailored to your requirements. - Ensure you call the original method (
superOnKeyDown
) when appropriate to preserve the default functionality, unless you intend to completely replace it. - This approach provides precise control over execution order without impacting unrelated components or listeners.
- Using this pattern, multiple plugins can safely and independently modify the behavior of the same instance.
This makes it easier to apply different behaviors to individual contentEditable
instances
without relying on inheritance or risking conflicts with other plugins.
value()
Returns the effective value of the edited content.
This corresponds to the innerHTML
of the content,
excluding the trailing <br>
added to display the final empty line in the browser
(see Line break matching white-space rule).