2.2.1 • Published 6 years ago

nominal-create-element v2.2.1

Weekly downloads
22
License
MIT
Repository
github
Last release
6 years ago

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.

2.2.1

6 years ago

2.2.0

6 years ago

2.1.0

6 years ago

2.0.0

6 years ago

1.1.0

7 years ago

1.0.0

7 years ago