diff --git a/maquette-v3.0.1-keyed/build.js b/maquette-v3.0.1-keyed/build.js new file mode 100644 index 000000000..dc0ff244e --- /dev/null +++ b/maquette-v3.0.1-keyed/build.js @@ -0,0 +1,16 @@ +const rollup = require('rollup').rollup; +const buble = require('rollup-plugin-buble'); +const uglify = require('rollup-plugin-uglify'); +const commonjs = require('rollup-plugin-commonjs'); + +rollup({ + input: 'src/main.es6.js', + plugins: [ + commonjs(), + buble(), + uglify(), + ] +}).then(bundle => bundle.write({ + file: 'dist/bundle.js', + format: 'iife' +})).catch(err => console.log(err.stack)); \ No newline at end of file diff --git a/maquette-v3.0.1-keyed/index.html b/maquette-v3.0.1-keyed/index.html new file mode 100644 index 000000000..2e0c7bc67 --- /dev/null +++ b/maquette-v3.0.1-keyed/index.html @@ -0,0 +1,11 @@ + + + + + maquette v3.0.1-keyed + + + + + + diff --git a/maquette-v3.0.1-keyed/package.json b/maquette-v3.0.1-keyed/package.json new file mode 100644 index 000000000..517fec7ff --- /dev/null +++ b/maquette-v3.0.1-keyed/package.json @@ -0,0 +1,18 @@ +{ + "name": "js-framework-benchmark-maquette-keyed", + "version": "3.0.1-non-keyed", + "description": "Benchmark for maquette framework (keyed)", + "scripts": { + "build-dev": "node build.js", + "build-prod": "node build.js" + }, + "devDependencies": { + "rollup": "*", + "rollup-plugin-buble": "*", + "rollup-plugin-commonjs": "*", + "rollup-plugin-uglify": "*" + }, + "dependencies": { + "maquette": "^3.0.1" + } +} diff --git a/maquette-v3.0.1-keyed/src/main.es6.js b/maquette-v3.0.1-keyed/src/main.es6.js new file mode 100644 index 000000000..3fc465034 --- /dev/null +++ b/maquette-v3.0.1-keyed/src/main.es6.js @@ -0,0 +1,112 @@ +import maquette from './maquette.umd.js'; +import {Store} from './store.es6'; + +const h = maquette.h; +const projector = maquette.createProjector(); + +const store = new Store(); +const app = App(); + +projector.append(document.body, app.render); + +function App() { + const jumbo = Jumbotron(); + const table = Table(); + + return { + render: () => + h("div#main", [ + h("div.container", [ + jumbo.render(), + table.render(), + h("span.preloadicon.glyphicon.glyphicon-remove", {"aria-hidden": ""}) + ]) + ]) + }; +} + +function Jumbotron() { + let exec = name => e => { + store[name](); + }; + + let run = exec("run"); + let runLots = exec("runLots"); + let add = exec("add"); + let update = exec("update"); + let clear = exec("clear"); + let swapRows = exec("swapRows"); + + return { + render: () => + h("div.jumbotron", [ + h("div.row", [ + h("div.col-md-6", [ + h("h1", ["maquette v3.0.1 (keyed)"]) + ]), + h("div.col-md-6", [ + h("div.row", [ + h("div.col-sm-6.smallpad", [ + h("button.btn.btn-primary.btn-block#run", {type: "button", onclick: run}, ["Create 1,000 rows"]) + ]), + h("div.col-sm-6.smallpad", [ + h("button.btn.btn-primary.btn-block#runlots", {type: "button", onclick: runLots}, ["Create 10,000 rows"]) + ]), + h("div.col-sm-6.smallpad", [ + h("button.btn.btn-primary.btn-block#add", {type: "button", onclick: add}, ["Append 1,000 rows"]) + ]), + h("div.col-sm-6.smallpad", [ + h("button.btn.btn-primary.btn-block#update", {type: "button", onclick: update}, ["Update every 10th row"]) + ]), + h("div.col-sm-6.smallpad", [ + h("button.btn.btn-primary.btn-block#clear", {type: "button", onclick: clear}, ["Clear"]) + ]), + h("div.col-sm-6.smallpad", [ + h("button.btn.btn-primary.btn-block#swaprows", {type: "button", onclick: swapRows}, ["Swap Rows"]) + ]) + ]) + ]) + ]) + ]) + }; +} + +function Table() { + // delegated handler + function tableClick(e) { + var node = e.target; + + if (node.matches(".remove, .remove *")) { + while (node.nodeName != "TR") + node = node.parentNode; + store.delete(+node.firstChild.textContent); + e.stopPropagation(); + } + else if (node.matches(".lbl")) { + while (node.nodeName != "TR") + node = node.parentNode; + store.select(+node.firstChild.textContent); + e.stopPropagation(); + } + } + + return { + render: () => + h("table.table.table-hover.table-striped.test-data", {onclick: tableClick}, [ + h("tbody", store.data.map(item => + h("tr" + (item.id === store.selected ? '.danger' : ''), {key: item.id}, [ + h("td.col-md-1", [""+item.id]), + h("td.col-md-4", [ + h("a.lbl", [item.label]) + ]), + h("td.col-md-1", [ + h("a.remove", [ + h("span.glyphicon.glyphicon-remove", {"aria-hidden": ""}) + ]) + ]), + h("td.col-md-6") + ]) + )) + ]) + }; +} \ No newline at end of file diff --git a/maquette-v3.0.1-keyed/src/maquette.umd.js b/maquette-v3.0.1-keyed/src/maquette.umd.js new file mode 100644 index 000000000..1b1b86795 --- /dev/null +++ b/maquette-v3.0.1-keyed/src/maquette.umd.js @@ -0,0 +1,856 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.maquette = {}))); +}(this, (function (exports) { 'use strict'; + +/* tslint:disable no-http-string */ +var NAMESPACE_W3 = 'http://www.w3.org/'; +/* tslint:enable no-http-string */ +var NAMESPACE_SVG = NAMESPACE_W3 + "2000/svg"; +var NAMESPACE_XLINK = NAMESPACE_W3 + "1999/xlink"; +var emptyArray = []; +var extend = function (base, overrides) { + var result = {}; + Object.keys(base).forEach(function (key) { + result[key] = base[key]; + }); + if (overrides) { + Object.keys(overrides).forEach(function (key) { + result[key] = overrides[key]; + }); + } + return result; +}; +var same = function (vnode1, vnode2) { + if (vnode1.vnodeSelector !== vnode2.vnodeSelector) { + return false; + } + if (vnode1.properties && vnode2.properties) { + if (vnode1.properties.key !== vnode2.properties.key) { + return false; + } + return vnode1.properties.bind === vnode2.properties.bind; + } + return !vnode1.properties && !vnode2.properties; +}; +var checkStyleValue = function (styleValue) { + if (typeof styleValue !== 'string') { + throw new Error('Style values must be strings'); + } +}; +var findIndexOfChild = function (children, sameAs, start) { + if (sameAs.vnodeSelector !== '') { + // Never scan for text-nodes + for (var i = start; i < children.length; i++) { + if (same(children[i], sameAs)) { + return i; + } + } + } + return -1; +}; +var checkDistinguishable = function (childNodes, indexToCheck, parentVNode, operation) { + var childNode = childNodes[indexToCheck]; + if (childNode.vnodeSelector === '') { + return; // Text nodes need not be distinguishable + } + var properties = childNode.properties; + var key = properties ? (properties.key === undefined ? properties.bind : properties.key) : undefined; + if (!key) { + for (var i = 0; i < childNodes.length; i++) { + if (i !== indexToCheck) { + var node = childNodes[i]; + if (same(node, childNode)) { + throw new Error(parentVNode.vnodeSelector + " had a " + childNode.vnodeSelector + " child " + (operation === 'added' ? operation : 'removed') + ", but there is now more than one. You must add unique key properties to make them distinguishable."); + } + } + } + } +}; +var nodeAdded = function (vNode) { + if (vNode.properties) { + var enterAnimation = vNode.properties.enterAnimation; + if (enterAnimation) { + enterAnimation(vNode.domNode, vNode.properties); + } + } +}; +var removedNodes = []; +var requestedIdleCallback = false; +var visitRemovedNode = function (node) { + (node.children || []).forEach(visitRemovedNode); + if (node.properties && node.properties.afterRemoved) { + node.properties.afterRemoved.apply(node.properties.bind || node.properties, [node.domNode]); + } +}; +var processPendingNodeRemovals = function () { + requestedIdleCallback = false; + removedNodes.forEach(visitRemovedNode); + removedNodes.length = 0; +}; +var scheduleNodeRemoval = function (vNode) { + removedNodes.push(vNode); + if (!requestedIdleCallback) { + requestedIdleCallback = true; + if (typeof window !== 'undefined' && 'requestIdleCallback' in window) { + window.requestIdleCallback(processPendingNodeRemovals, { timeout: 16 }); + } + else { + setTimeout(processPendingNodeRemovals, 16); + } + } +}; +var nodeToRemove = function (vNode) { + var domNode = vNode.domNode; + if (vNode.properties) { + var exitAnimation = vNode.properties.exitAnimation; + if (exitAnimation) { + domNode.style.pointerEvents = 'none'; + var removeDomNode = function () { + if (domNode.parentNode) { + domNode.parentNode.removeChild(domNode); + scheduleNodeRemoval(vNode); + } + }; + exitAnimation(domNode, removeDomNode, vNode.properties); + return; + } + } + if (domNode.parentNode) { + domNode.parentNode.removeChild(domNode); + scheduleNodeRemoval(vNode); + } +}; +var setProperties = function (domNode, properties, projectionOptions) { + if (!properties) { + return; + } + var eventHandlerInterceptor = projectionOptions.eventHandlerInterceptor; + var propNames = Object.keys(properties); + var propCount = propNames.length; + var _loop_1 = function (i) { + var propName = propNames[i]; + var propValue = properties[propName]; + if (propName === 'className') { + throw new Error('Property "className" is not supported, use "class".'); + } + else if (propName === 'class') { + propValue.split(/\s+/).forEach(function (token) { return domNode.classList.add(token); }); + } + else if (propName === 'classes') { + // object with string keys and boolean values + var classNames = Object.keys(propValue); + var classNameCount = classNames.length; + for (var j = 0; j < classNameCount; j++) { + var className = classNames[j]; + if (propValue[className]) { + domNode.classList.add(className); + } + } + } + else if (propName === 'styles') { + // object with string keys and string (!) values + var styleNames = Object.keys(propValue); + var styleCount = styleNames.length; + for (var j = 0; j < styleCount; j++) { + var styleName = styleNames[j]; + var styleValue = propValue[styleName]; + if (styleValue) { + checkStyleValue(styleValue); + projectionOptions.styleApplyer(domNode, styleName, styleValue); + } + } + } + else if (propName !== 'key' && propValue !== null && propValue !== undefined) { + var type = typeof propValue; + if (type === 'function') { + if (propName.lastIndexOf('on', 0) === 0) { + if (eventHandlerInterceptor) { + propValue = eventHandlerInterceptor(propName, propValue, domNode, properties); // intercept eventhandlers + } + if (propName === 'oninput') { + /* tslint:disable no-this-keyword no-invalid-this only-arrow-functions no-void-expression */ + (function () { + // record the evt.target.value, because IE and Edge sometimes do a requestAnimationFrame between changing value and running oninput + var oldPropValue = propValue; + propValue = function (evt) { + oldPropValue.apply(this, [evt]); + evt.target['oninput-value'] = evt.target.value; // may be HTMLTextAreaElement as well + }; + }()); + /* tslint:enable */ + } + domNode[propName] = propValue; + } + } + else if (type === 'string' && propName !== 'value' && propName !== 'innerHTML') { + if (projectionOptions.namespace === NAMESPACE_SVG && propName === 'href') { + domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue); + } + else { + domNode.setAttribute(propName, propValue); + } + } + else { + domNode[propName] = propValue; + } + } + }; + for (var i = 0; i < propCount; i++) { + _loop_1(i); + } +}; +var addChildren = function (domNode, children, projectionOptions) { + if (!children) { + return; + } + for (var _i = 0, children_1 = children; _i < children_1.length; _i++) { + var child = children_1[_i]; + createDom(child, domNode, undefined, projectionOptions); + } +}; +var initPropertiesAndChildren = function (domNode, vnode, projectionOptions) { + addChildren(domNode, vnode.children, projectionOptions); // children before properties, needed for value property of