diff --git a/.zs/scripts b/.zs/scripts index 2363e98..362d4e7 100755 --- a/.zs/scripts +++ b/.zs/scripts @@ -2,7 +2,7 @@ set -e -JS="highlight" +JS="highlight umbrella" # Load live.js for non-production builds for faster development if [ -z "$ZS_PRODUCTION" ]; then diff --git a/TestCGI.md b/TestCGI.md new file mode 100644 index 0000000..6b7f64c --- /dev/null +++ b/TestCGI.md @@ -0,0 +1,50 @@ +--- +title: Test CGI +--- + +# Test CGI + +## Form + +
+ +## Results + + + +--- + + \ No newline at end of file diff --git a/assets/js/umbrella.js b/assets/js/umbrella.js new file mode 100644 index 0000000..316d9a6 --- /dev/null +++ b/assets/js/umbrella.js @@ -0,0 +1,806 @@ +// Umbrella JS http://umbrellajs.com/ +// ----------- +// Small, lightweight jQuery alternative +// @author Francisco Presencia Fandos https://francisco.io/ +// @inspiration http://youmightnotneedjquery.com/ + +// Initialize the library +var u = function (parameter, context) { + // Make it an instance of u() to avoid needing 'new' as in 'new u()' and just + // use 'u().bla();'. + // @reference http://stackoverflow.com/q/24019863 + // @reference http://stackoverflow.com/q/8875878 + if (!(this instanceof u)) { + return new u(parameter, context); + } + + // No need to further processing it if it's already an instance + if (parameter instanceof u) { + return parameter; + } + + // Parse it as a CSS selector if it's a string + if (typeof parameter === 'string') { + parameter = this.select(parameter, context); + } + + // If we're referring a specific node as in on('click', function(){ u(this) }) + // or the select() function returned a single node such as in '#id' + if (parameter && parameter.nodeName) { + parameter = [parameter]; + } + + // Convert to an array, since there are many 'array-like' stuff in js-land + this.nodes = this.slice(parameter); +}; + +// Map u(...).length to u(...).nodes.length +u.prototype = { + get length () { + return this.nodes.length; + } +}; + +// This made the code faster, read "Initializing instance variables" in +// https://developers.google.com/speed/articles/optimizing-javascript +u.prototype.nodes = []; + +// Add class(es) to the matched nodes +u.prototype.addClass = function () { + return this.eacharg(arguments, function (el, name) { + el.classList.add(name); + }); +}; + + +// [INTERNAL USE ONLY] +// Add text in the specified position. It is used by other functions +u.prototype.adjacent = function (html, data, callback) { + if (typeof data === 'number') { + if (data === 0) { + data = []; + } else { + data = new Array(data).join().split(',').map(Number.call, Number); + } + } + + // Loop through all the nodes. It cannot reuse the eacharg() since the data + // we want to do it once even if there's no "data" and we accept a selector + return this.each(function (node, j) { + var fragment = document.createDocumentFragment(); + + // Allow for data to be falsy and still loop once + u(data || {}).map(function (el, i) { + // Allow for callbacks that accept some data + var part = (typeof html === 'function') ? html.call(this, el, i, node, j) : html; + + if (typeof part === 'string') { + return this.generate(part); + } + + return u(part); + }).each(function (n) { + this.isInPage(n) + ? fragment.appendChild(u(n).clone().first()) + : fragment.appendChild(n); + }); + + callback.call(this, node, fragment); + }); +}; + +// Add some html as a sibling after each of the matched elements. +u.prototype.after = function (html, data) { + return this.adjacent(html, data, function (node, fragment) { + node.parentNode.insertBefore(fragment, node.nextSibling); + }); +}; + + +// Add some html as a child at the end of each of the matched elements. +u.prototype.append = function (html, data) { + return this.adjacent(html, data, function (node, fragment) { + node.appendChild(fragment); + }); +}; + + +// [INTERNAL USE ONLY] + +// Normalize the arguments to an array of strings +// Allow for several class names like "a b, c" and several parameters +u.prototype.args = function (args, node, i) { + if (typeof args === 'function') { + args = args(node, i); + } + + // First flatten it all to a string http://stackoverflow.com/q/22920305 + // If we try to slice a string bad things happen: ['n', 'a', 'm', 'e'] + if (typeof args !== 'string') { + args = this.slice(args).map(this.str(node, i)); + } + + // Then convert that string to an array of not-null strings + return args.toString().split(/[\s,]+/).filter(function (e) { + return e.length; + }); +}; + + +// Merge all of the nodes that the callback return into a simple array +u.prototype.array = function (callback) { + callback = callback; + var self = this; + return this.nodes.reduce(function (list, node, i) { + var val; + if (callback) { + val = callback.call(self, node, i); + if (!val) val = false; + if (typeof val === 'string') val = u(val); + if (val instanceof u) val = val.nodes; + } else { + val = node.innerHTML; + } + return list.concat(val !== false ? val : []); + }, []); +}; + + +// [INTERNAL USE ONLY] + +// Handle attributes for the matched elements +u.prototype.attr = function (name, value, data) { + data = data ? 'data-' : ''; + + // This will handle those elements that can accept a pair with these footprints: + // .attr('a'), .attr('a', 'b'), .attr({ a: 'b' }) + return this.pairs(name, value, function (node, name) { + return node.getAttribute(data + name); + }, function (node, name, value) { + if (value) { + node.setAttribute(data + name, value); + } else { + node.removeAttribute(data + name); + } + }); +}; + + +// Add some html before each of the matched elements. +u.prototype.before = function (html, data) { + return this.adjacent(html, data, function (node, fragment) { + node.parentNode.insertBefore(fragment, node); + }); +}; + + +// Get the direct children of all of the nodes with an optional filter +u.prototype.children = function (selector) { + return this.map(function (node) { + return this.slice(node.children); + }).filter(selector); +}; + + +/** + * Deep clone a DOM node and its descendants. + * @return {[Object]} Returns an Umbrella.js instance. + */ +u.prototype.clone = function () { + return this.map(function (node, i) { + var clone = node.cloneNode(true); + var dest = this.getAll(clone); + + this.getAll(node).each(function (src, i) { + for (var key in this.mirror) { + if (this.mirror[key]) { + this.mirror[key](src, dest.nodes[i]); + } + } + }); + + return clone; + }); +}; + +/** + * Return an array of DOM nodes of a source node and its children. + * @param {[Object]} context DOM node. + * @param {[String]} tag DOM node tagName. + * @return {[Array]} Array containing queried DOM nodes. + */ +u.prototype.getAll = function getAll (context) { + return u([context].concat(u('*', context).nodes)); +}; + +// Store all of the operations to perform when cloning elements +u.prototype.mirror = {}; + +/** + * Copy all JavaScript events of source node to destination node. + * @param {[Object]} source DOM node + * @param {[Object]} destination DOM node + * @return {[undefined]]} + */ +u.prototype.mirror.events = function (src, dest) { + if (!src._e) return; + + for (var type in src._e) { + src._e[type].forEach(function (ref) { + u(dest).on(type, ref.callback); + }); + } +}; + +/** + * Copy select input value to its clone. + * @param {[Object]} src DOM node + * @param {[Object]} dest DOM node + * @return {[undefined]} + */ +u.prototype.mirror.select = function (src, dest) { + if (u(src).is('select')) { + dest.value = src.value; + } +}; + +/** + * Copy textarea input value to its clone + * @param {[Object]} src DOM node + * @param {[Object]} dest DOM node + * @return {[undefined]} + */ +u.prototype.mirror.textarea = function (src, dest) { + if (u(src).is('textarea')) { + dest.value = src.value; + } +}; + + +// Find the first ancestor that matches the selector for each node +u.prototype.closest = function (selector) { + return this.map(function (node) { + // Keep going up and up on the tree. First element is also checked + do { + if (u(node).is(selector)) { + return node; + } + } while ((node = node.parentNode) && node !== document); + }); +}; + + +// Handle data-* attributes for the matched elements +u.prototype.data = function (name, value) { + return this.attr(name, value, true); +}; + + +// Loops through every node from the current call +u.prototype.each = function (callback) { + // By doing callback.call we allow "this" to be the context for + // the callback (see http://stackoverflow.com/q/4065353 precisely) + this.nodes.forEach(callback.bind(this)); + + return this; +}; + + +// [INTERNAL USE ONLY] +// Loop through the combination of every node and every argument passed +u.prototype.eacharg = function (args, callback) { + return this.each(function (node, i) { + this.args(args, node, i).forEach(function (arg) { + // Perform the callback for this node + // By doing callback.call we allow "this" to be the context for + // the callback (see http://stackoverflow.com/q/4065353 precisely) + callback.call(this, node, arg); + }, this); + }); +}; + + +// Remove all children of the matched nodes from the DOM. +u.prototype.empty = function () { + return this.each(function (node) { + while (node.firstChild) { + node.removeChild(node.firstChild); + } + }); +}; + + +// .filter(selector) +// Delete all of the nodes that don't pass the selector +u.prototype.filter = function (selector) { + // The default function if it's a CSS selector + // Cannot change name to 'selector' since it'd mess with it inside this fn + var callback = function (node) { + // Make it compatible with some other browsers + node.matches = node.matches || node.msMatchesSelector || node.webkitMatchesSelector; + + // Check if it's the same element (or any element if no selector was passed) + return node.matches(selector || '*'); + }; + + // filter() receives a function as in .filter(e => u(e).children().length) + if (typeof selector === 'function') callback = selector; + + // filter() receives an instance of Umbrella as in .filter(u('a')) + if (selector instanceof u) { + callback = function (node) { + return (selector.nodes).indexOf(node) !== -1; + }; + } + + // Just a native filtering function for ultra-speed + return u(this.nodes.filter(callback)); +}; + + +// Find all the nodes children of the current ones matched by a selector +u.prototype.find = function (selector) { + return this.map(function (node) { + return u(selector || '*', node); + }); +}; + + +// Get the first of the nodes +u.prototype.first = function () { + return this.nodes[0] || false; +}; + + +// [INTERNAL USE ONLY] +// Generate a fragment of HTML. This irons out the inconsistences +u.prototype.generate = function (html) { + // Table elements need to be child of