UNPKG

lighty

Version:

The tiny engine for your handy microframework

199 lines (149 loc) 4.34 kB
/*! * lighty v0.9.0 * https://github.com/demiazz/lighty * * Copyright 2016-present Alexey Plutalov <demiazz.py@gmail.com> * Released under the MIT license */ (function(global, factory) { typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define("lighty", factory) : (global.lighty = factory()); })(this, function() { "use strict"; var doc = window.document; var body = doc.body; /* ----- Matches Helper ----- */ function getMatchesFn() { var e = doc.createElement("div"); return ( e.matches || e.matchesSelector || e.msMatchesSelector || e.mozMatchesSelector || e.webkitMatchesSelector || e.oMatchesSelector ); } var matchesFn = getMatchesFn(); function matches(element, selector) { return matchesFn.call(element, selector); } /* ----- Walk Helper ----- */ function filterElements(elements) { return elements.filter(function(e) { return e instanceof Element; }); } function toArray(nodeList) { return [].slice.call(nodeList); } function walk(trees, selector, callback) { var roots = void 0; if (trees instanceof Element) { roots = [trees]; } else if (trees instanceof NodeList) { roots = filterElements(toArray(trees)); } else if (Array.isArray(trees)) { roots = filterElements(trees); } else if (typeof trees === "string") { roots = toArray(doc.querySelectorAll(trees)); } else { throw new TypeError("Unsupported type of tree root"); } roots.forEach(function(root) { if (matches(root, selector)) { callback(root); } toArray(root.querySelectorAll(selector)).forEach(callback); }); } /* ----- Engine ID Helper ----- */ var getEngineId = (function() { var engineId = -1; return function() { engineId += 1; return "__lighty__" + engineId; }; })(); /* ----- Binding Helpers ----- */ function hasBinding(element, key, id) { var bindings = element[key]; return bindings ? bindings.indexOf(id) !== -1 : false; } function bind(element, key, id) { var bindings = element[key]; element[key] = bindings ? bindings.concat(id) : [id]; } /* ----- DOM Ready Helper ----- */ function onDOMContentLoaded(action) { if (doc.readyState === "loading") { doc.addEventListener("DOMContentLoaded", action); } else { // See https://connect.microsoft.com/IE/feedback/details/792880/document-readystat setTimeout(action, 1); } } /* ----- Engine Factory ----- */ function createEngine(builder, onStart) { var engineId = getEngineId(); var components = []; var isRunning = false; /* ----- Components Instatiation ----- */ function build(trees, component) { var id = component[0]; var selector = component[1]; var args = component[2]; walk(trees, selector, function(element) { if (hasBinding(element, engineId, id)) { return; } builder.apply(null, [element].concat(args)); bind(element, engineId, id); }); } function vitalize(trees) { if (!isRunning) { throw Error("Document is not ready yet."); } var roots = trees || body; components.forEach(function(component) { return build(roots, component); }); } /* ----- Components Registration ----- */ function register(selector) { var id = components.length; for ( var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++ ) { args[_key - 1] = arguments[_key]; } var component = [id, selector, args]; components.push(component); if (isRunning) { build(body, component); } } /* ----- Initialization ----- */ function start() { isRunning = true; vitalize(); if (onStart) { onStart(); } } if (!(builder instanceof Function)) { throw new TypeError("Builder must be a function"); } onDOMContentLoaded(start); return { component: register, vitalize: vitalize }; } return createEngine; });