25

html.js - Write HTML in JS easily.

 4 years ago
source link: https://www.tuicool.com/articles/NnyYzuJ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

html.js - Write HTML in JS easily.

html.js is a simple library (< 5kb minified + gzipped) that:

  • Allows you to write HTML in JS in a clean, powerful and extensible manner
    (contrary to what many people believe is impossible).
  • Lazily load JS and CSS files (it also auto-prefixes your CSS).
  • Does routing with page anchor tags (hash routing, e.g. href="#path/to/page" )

Just these 3 functions alonewill allow you to easily build frontend web-apps

(e.g. Single page applications, Progressive web apps) that are performant and scalable.

Download

Just copy and paste the html.min.js from this github.

If you want to read the entire file (it's less than 1k lines), you can look at html.js .

The Problem

Writing HTML in JS is a traditionally messy experience.

You'll have to carefully fiddle with quotes, double quotes, string concatenation, escaping characters, etc.

This breaks syntax highlighting, causes mistakes, and a LOT of stress.

It is little wonder why most people resort to backend templating solutions, or use frontend templating frameworks/libraries/transpilers.

Unfortunately, these solutions are not good enough (even JSX is not good enough by our standards, seriously).

Their are usually either too complex, clunky, slow, obscure, incomplete, bloated, or inflexible.

The Solution

Imagine you want to write the following shit:

$('.page').html(['<div class="dropdown">',
	'<button class="btn dropdown-toggle"',
	'type="button"',
	'id="dropdownMenuButton"',
	'data-toggle="dropdown"',
	'aria-haspopup="true"',
	'aria-expanded="false">',
		dropdown.text,
	'</button>',
	'<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">',
		$.map(dropdown.values, function (x) {
			return ['<a class="dropdown-item">', x ,'</a>'].join('')
		}).join(''),
	'</div>',
'</div>'].join(''));

Wouldn't it be better to write it like:

$('.page').html(HTML(['div', {class: 'dropdown'},
	['button', dropdown.text, {
		class: 'btn dropdown-toggle', 
		type: 'button', 
		id: 'dropdownMenuButton', 
		dataToggle: 'dropdown', 
		ariaHaspopup: true, 
		ariaExpanded: false
	}],
	['div', {class: 'dropdown-menu', ariaLabelledby: 'dropdownMenuButton'},
		$.map(dropdown.values, function (x) { 
			return ['a', {class: 'dropdown-item'}, x]
		})
	]
]));

Wow! Such syntax. Much highlighting.

Notice how the HTML is being expressed in an intermediate form with native JS objects and arrays.

(We call this intermediate form a HTML context ).

Functions

Some examples are provided at the bottom.

HTML writing functions:

  • HTML(context)
    Creates a HTML string with the context.

SVG writing functions (for the artsy coders):

  • HTML.SVG(width, height, ...context)
    Creates a HTML SVG string, with common boilerplate attributes automatically-filled.

  • HTML.SVG.Path(...context).<command>(...).<command>(...)

    Creates an HTML SVG Path string.

    See ( https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths )

    for an overview on the path commands.

Lazy loading functions:

  • HTML.load(file0, file1, ...).done(fn)

    Loads (.js, .css) files, then execute the done function fn .

    The files are downloaded asyncronously in parallel, but attached to the webpage in the specified order.

    Each file is only loaded once .

    The done function is always executed once per load call ,

    irregardless of whether the files have been loaded previously.

  • HTML.load.css(file0, file1, ...).done(fn)

    Loads .css files, then execute the done function fn .

    All files are treated as .css files, irregardless of the file extension.

    This is useful if your file is dynamically routed with PHP scripts.

  • HTML.load.js(file0, file1, ...).done(fn)

    Loads .js files, then execute the done function fn .

    All files are treated as .js files, irregardless of the file extension.

    This is useful if your file is dynamically routed with PHP scripts.

Hash routing functions:

  • HTML.route("#path/to/page/anchor", fn)
    Attaches the function fn to "#path/to/page/anchor".

  • HTML.route.go(#path/to/page/anchor")
    Executes the function attached to "#path/to/page/anchor".

  • HTML.route.go(#path/to/page/:anchor")

    Attemps to execute the function attached to the path.

    The prefix : on the path component denotes that it is is default option.

    If the visitor has visited #path/to/page/one , or if the address bar points to #path/to/page/one , it will execute the function attached to #path/to/page/one .

    Otherwise, it will execute the function attached to #path/to/page/anchor .

  • HTML.route.go("#:path/:to/:page")
    You can prefix any path component with ":" to mark it as the default option.

  • HTML.route.go()

    Attempts to execute the function attached to the path in the address bar.

    (i.e. window.location.hash )

Examples

HTML Context:

HTML(["div", {id: "y", class: "a b", style: {color: "red"}, ariaLabel: "x"}, 
    "Text",
    ["a", {href: "example.com", target: "_blank"}, "link"],
    {style: {width: 1, opacity: 0.5}, class: "c", pos: 1},
    [["div", 0], ["div", 1]]
])

Turns into:

<div id="y" class="a b c" style="color: red; width: 1px; opacity: 0.5"
  ariaLabel="x" aria-label="x" aria_label="x" pos="1">
    Text
    <a href="example.com" target="_blank">link</a>
    <div>0</div><div>1</div>
</div>
  • If the starting element is a string, it is treated as a tag name.

    ['div', 'Text'] => <div>Text</div>

  • Attributes are added via objects.

    The object can be anywhere in the array except for the starting element.

    You can use any preferred style:

    ['div', {id: 'x'}, 'a', 'b', 'c'] OR ['div', 'a', 'b', 'c', {id: 'x'}]

  • Attributes can be defined via camelCase.

    They will automatically converted to kebab-case and snake_case.

    This is so that you can avoid using quotes on the keys.

    {ariaLabel: "x"} => aria-label="x"

  • If the starting element is an array, the contents of the entire

    array will be converted to HTML and joined. [['div', 0], ['div', 1]] => <div>0</div><div>1</div>

  • Inline CSS can be defined via objects.

    They will be combined in sequential order.

    The CSS will be auto-magically prefixed.

    For numerical properties, px will be automatically added if where applicable. (similar to jQuery).

Advantages

  • You can make functions to return HTML contexts, enabling you to reuse common HTML.
    "Write less, do more!" - jQuery
  • You can use loops to create contexts (a context is essentially an array).
  • You can add attributes or children to contexts to specialize contexts for different use cases.
  • Syntax errors are detected when the code is compiled.
    You can check the browser console for the exact line of the error if your page has display errors.
  • No more incorrect HTML closing tags!
  • Inline CSS styles are auto-magically prefixed.
  • You can easily create complex DOM updates in a single call, resulting in buttery smooth performance.
  • Code is automatically syntax highlighted in most text editors without special plugins.
  • Code is autocompleted in most text editors (e.g. SublimeText will auto-close braces for you).
  • No need for transpilers and complicated build tools. A browser and text editor is all you need.
    Get up to speed quick!
  • Makes debugging much easier (it's just VanillaJS).
  • Greatly reduce developer onboarding times (again, it's just VanillaJS).
  • Zero dependencies.
  • Compatible with IE 9+, and practically every other major browser.
  • Compatible with other JS frameworks/libraries out of the box.
  • You can do ALL your HTML generation on the frontend now, resulting in MUCH lower server load.
  • Naturally, you'll also have better seperation between data and UX logic.
  • For teams, frontend and backend coders can work in parallel better.
  • A happier life.

Performance

Don't worry about it!

We have heavily micro-optimized and profiled html.js.

It performs with so little overhead, it's as if you have written that HTML and CSS in plaintext.

Even tens of megabytes is processed in a tiny fraction of a second. You'll hardly notice a thing.

You should probably be worried about performance, if you are not using html.js. ;)

Coming Soon

  • A simple 3 page web example

License

MIT


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK