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

nominal-create-element

v2.2.1

Published

#### What?

Downloads

87

Readme

createElement

What?

Forgive the unoriginal module name, but this 'script is here to encourage you to use the browser native document interface, rather than any attempt to brand itself.

A few principles here:

  • (0) Save space, save bandwidth, save parse time.

For writing out HTML with attached events, the DOM API is so full-featured there is no need for a template DSL or front end framework.

Take responsibility for every kilobyte you ship to your users.

The lib contains a handful of functions and is measured in bytes (~492 bytes with gzip/minify) rather than kilobytes.

  • (1) There's no need for document query selectors.

Avoid the class of errors caused by over or under-binding events, the need to match class/id/tag, or waiting for your elements to appear on the document. Leave classNames for styling.

Bind events to elements created in memory, before they are attached to the document. Attach/append to the document when you are ready to give an interactive element to the user, not to query or store intermediate application states.

  • (2) Components are still the way to go.

This is a rejection of front end frameworks, diff algorithms, even jQuery, but it is not a rejection of component-based view architecture.

Even using the document API, you can still compose your views by a hierarchy of components.

Related Information

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement

https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement

http://youmightnotneedjquery.com/

Similar to: https://github.com/hyperhype/hyperscript + https://github.com/ohanhi/hyperscript-helpers

Import

// CJS module style
const createElement = require('nominal-create-element');
const render = createElement.render;
const nominate = createElement.nominate;
// ESM style, also available in TypeScript
import { createElement, nominate, render } from 'nominal-create-element/createElement.esm';

API

Although there is only one source file of 100 lines, here is the API:

function createElement(tag: string, ...body: body_t[]): HTMLElement;
function createElement(tag: string, className: string, ...body: body_t[]): HTMLElement;
function createElement(tag: string, attributes: { [key: string]: any|(() => void) }, ...body: body_t[]): HTMLElement;

You'll mostly use a partial binding of the createElement function with the tag already provided, via the nominate(string) function.

type nominal_creator_t = {
    (...body: body_t[]): HTMLElement;
    (className: string, ...body: body_t[]): HTMLElement;
    (attributes: { [key: string]: any|(() => void) }, ...body: body_t[]): HTMLElement;
};
function nominate(tag: string): nominal_creator_t;

You can also use the provided render function if you adhere to a certain component interface.

type component_t = {
    element: HTMLElement;
    template(): HTMLElement;
}
function render(component: component_t): void {
    var element = component.element;
    element.parentNode.replaceChild(component.template(), element);
}

examples

"Hold the phone, my friend. What about bundlers and typescript and tsx and component organization? Take me straight to the enterprisey example."

or, start simple:

const div = nominate('div');
const span = nominate('span');

Create a simple element.

div(); // HTMLDivElement

Create an element with a css class.

div('my-css-class');

Create an element with a css class, some body text and additional attributes.

div({ id: 'my-css-id', class: 'my-css-class' }, 'my body text');
div({}, 'Hello, world'); // no attributes.

Nest elements

div(
    span('a', 'Hello'),
    span('b', 'World')
);
form(
    { submit: () => { ... /* my handler here */ } }
    div(
        input({ placeholder: 'username' })
        input({ placeholder: 'password' })
        div(
            input({ type: 'checkbox', checked: '' }),
            span({}, 'Remember my username')
        )
    )
    button({ type: 'submit' }, 'Login')
)

A todo list example.


import { nominate, render } from 'nominal-create-element/createElement.esm';

const div = nominate('div');
const li = nominate('li');
const ul = nominate('ul');
const form = nominate('form');
const input = nominate('input');
const h = n => nominate('h' + n);
const button = nominate('button');

/**
 *
 * @implements component_t
 *
 */
class Todo {

    constructor() {
        /**
         * @type {string[]}
         */
        this.list = [
            'add something to my todo list'
        ];

        /** @type {HTMLElement} */
        this.form = null;

        /** @type {HTMLElement} */
        this.input = null;

        /** @type {HTMLElement} */
        this.element = null;

    }

    /**
     * @returns {HTMLElement}
     */
    template() {

        // This is equivalent to the following HTML:
        const html = `
        <div style="margin: 25px; padding: 15px;">
            <h5>To Do List</h5>
            <ul>
                <li>add something to my todo list</li>
            </ul>
            <form>
                <input placeholder="Enter to submit">
                <button type="submit">Add</button>
            </form>
        </div>
        `;

        return this.element =
            div(
                { style: 'margin: 25px; padding: 15px;' },
                h(5)('', 'To Do List'),
                ul(this.list.map(item => li('', item))),
                this.form = form(
                    {
                        submit: (e) => {
                            e.preventDefault();
                            this.list.push(this.input.value);
                            this.input.value = '';
                            render(this);
                        }
                    },
                    this.input = input({
                        placeholder: 'Enter to submit'
                    }),
                    button({ type: 'submit' }, 'Add')
                )
            );

    }

}

var todo = new Todo();
document.body.appendChild(todo.template());

Test

open test.html in your browser.

Curios

An HTML-to-createElement converter can be found here.

An enterprisey example written in ts/tsx can be found here.