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

dom-factory

v1.1.0

Published

Enhance HTML elements using plain JavaScript objects.

Downloads

1,234

Readme

dom-factory

npm version

The DOM factory provides a convenient API (inspired by Polymer) to enhance HTML elements with custom behavior, using plain JavaScript objects with advanced features like property change observers, property reflection to attributes on HTML elements and simplify mundane tasks like adding and removing event listeners.

Compatibility

Supports the last two versions of every major browser.

  • Chrome
  • Safari
  • Firefox
  • IE 11/Edge
  • Opera
  • Mobile Safari
  • Chrome on Android

Installation

npm install dom-factory

Usage

The DOM factory library exports to AMD, CommonJS and global.

Global

<script src="node_modules/dom-factory/dist/dom-factory.js"></script>
<script>
  var handler = domFactory.handler
</script>

CommonJS

var handler = require('dom-factory').handler

ES6

import { handler } from 'dom-factory'

Components

The following ES6 example, illustrates a component definition for an enhanced button using properties as a public API, property reflection to attributes, property change observers and event listeners.

Component definition

A component definition is nothing more than a simple object factory (a function that creates an object) which accepts a HTMLElement node as it's argument.

/**
 * A component definition
 * @return {Object}
 */
const buttonComponent = () => ({

  /**
   * Properties part of the component's public API.
   * @type {Object}
   */
  properties: {

    /**
     * Maps to [data-a-property="value"] attribute
     * Also sets a default property value 
     * and updates the attribute on the HTMLElement
     * @type {Object}
     */
    aProperty: {
      reflectToAttribute: true,
      value: 'value for aProperty'
    },

    /**
     * Maps to [data-b-property] attribute
     * It removes the attribute when the property value is `false`
     * @type {Object}
     */
    bProperty: {
      reflectToAttribute: true,
      type: Boolean
    },

    /**
     * Maps to [data-c-property] attribute
     * It casts the value to a Number
     * Sets the initial value to 0
     * @type {Object}
     */
    cProperty: {
      reflectToAttribute: true,
      type: Number,
      value: 0
    }
  },

  /**
   * Property change observers.
   * @type {Array}
   */
  observers: [
    '_onPropertyChanged(aProperty, bProperty)'
  ],

  /**
   * Event listeners.
   * @type {Array}
   */
  listeners: [
    '_onClick(click)'
  ],

  /**
   * Property change observer handler
   * @param  {?}      newValue The new property value
   * @param  {?}      oldValue The old property value
   * @param  {String} propName The property name
   */
  _onPropertyChanged (newValue, oldValue, propName) {
    switch (propName) {
      case 'aProperty':
        console.log('aProperty has changed', newValue, oldValue)
        break
      case 'bProperty':
        console.log('bProperty has changed', newValue, oldValue)
        break
    }

    // access from context, with the new values
    console.log(this.aProperty, this.bProperty)
  },

  /**
   * Click event listener
   * @param  {MouseEvent} event The Mouse Event
   */
  _onClick (event) {
    event.preventDefault()
    console.log('The button was clicked!')
  }
})

Register the component

handler.register('my-button', buttonComponent)

Initializing

When calling the autoInit() method, the component handler attempts to self-initialize all registered components which match the component CSS class. The CSS class is computed automatically from the component ID which was provided at registration, prefixed with js-.

In this example, since we registered the buttonComponent with a component ID of my-button, the handler will try to initialize all the HTML elements which have the js-my-button CSS class.

<button class="js-my-button">Press me</button>
// Initialize all components on window.DOMContentLoaded and window.load events.
handler.autoInit()

You can also initialize components manually.

// Initialize all components immediately.
handler.upgradeAll()

// Initialize all components on a single element.
var myButtonNode = document.querySelector('.js-my-button')
handler.upgradeElement(myButtonNode)

// Initialize a single component on a single element.
handler.upgradeElement(myButtonNode, 'my-button')

// Upgrade all elements matching a registered component ID.
handler.upgrade('my-button')

Downgrade

Sometimes we need component lifecycle control when integrating with other libraries (Vue.js, Angular, etc).

var myButtonNode = document.querySelector('.js-my-button')
handler.downgradeElement(myButtonNode)

Interact with the component API

When the handler initializes a component on a HTML element, a reference to the created component is stored as a property on the HTML element, matching the camelCase version of the component ID.

var buttonNode = document.querySelector('button')
var button = buttonNode.myButton

We can use this reference to interact with the component's API.

console.log(button.aProperty)
// => 'value for aProperty'

Property reflection to attribute

button.aProperty = 'something else'
button.bProperty = true
button.cProperty = 5

When using the reflectToAttribute: true property option, the property reflects a string representation of it's value to the corresponding data-* attribute on the HTML element using the dataset API, which means you can use the HTML element attribute to configure the property value.

Casting values

Because component properties using reflectToAttribute: true are using the dataset API, all values are strings by default, but you can cast them to Boolean or Number.

Boolean

When using a Boolean property type and assigning a property value of true, the attribute will be created on the HTML element with an empty value and when assigning a property value of false, the attribute will be removed from the DOM.

For example, an attribute with an empty value called [data-my-boolean-attribute] will map to button.myBooleanAttribute.

<button data-my-boolean-attribute class="js-my-button">
  Press me
</button>
`console.log(button.myBooleanAttribute) // => true`

Number

Cast the component property value to a Number by adding type: Number to the property definition. It returns NaN when the value is not a valid number.

button.cProperty = '50'
console.log(button.cProperty) // => 50

button.cProperty = 'abc'
console.log(button.cProperty) // => NaN
<button class="js-my-button" 
  data-a-property="something else" 
  data-b-property
  data-c-property="13">
  Press me
</button>
console.log(button.aProperty) // => 'something else'
console.log(button.bProperty) // => true
console.log(button.cProperty) // => 13

Destroy

Calling the destroy method on the component reference, removes observers and event listeners. Useful before removing the HTML element from the DOM, for example when using libraries like Vue.js or Angular2 where you need to hook into the application lifecycle.

button.destroy()