npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@itrocks/contenteditable

v0.0.14

Published

Respectful contenteditable: avoids <div>, respects white-space: pre* styles line breaks

Downloads

398

Readme

npm version npm downloads GitHub issues discord

contenteditable

Respectful contenteditable: avoids <div>, respects white-space: pre* styles line breaks.

Installation

npm i @itrocks/contenteditable

Usage

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.

Behavior

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.

Line break matching white-space rule

The line break characters inserted in your contenteditable element depend on its white-space style attribute:

  • pre, pre-line or pre-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.

API

The following properties and methods are publicly available in the ContentEditable class.

element

The element associated with the ContentEditable instance, extended as an HTMLEditableElement. It includes a editable property that contains the ContentEditable instance.

ContentEditable() constructor

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.

Parameters

activate()

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()

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()

brNode()

Creates a node that matches the current line break string. Result is either a TextNode containing '\n' or an HTMLBRElement.

deactivate()

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()

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.

Extending onKeyDown

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.

Why extend onKeyDown instead of adding a keydown listener?

  1. Control execution order:
    Adding a keydown event listener via addEventListener does not provide fine-grained control over execution priority relative to the library's built-in handling. Extending onKeyDown allows you to execute your logic either before, after, or instead of the library's processing of the event.

  2. Avoid unintended interference:
    Preventing the library's default 'Enter' key behavior by stopping event propagation (event.stopPropagation() or event.preventDefault()) may inadvertently interfere with other components or listeners unrelated to this library. By extending onKeyDown, you ensure your changes are isolated and do not disrupt other listeners.

Example: Preventing multiline input using AOP

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)
}

Key Points

  • 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()

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).