From d52a98ff8dd7d06da4d217db42b2307692067680 Mon Sep 17 00:00:00 2001 From: Pat Cavit Date: Thu, 21 Apr 2016 10:46:41 -0700 Subject: [PATCH] Add mithril@0.2.x version for comparison --- examples/dbmonster/mithril-0.2.x/app.js | 44 + examples/dbmonster/mithril-0.2.x/index.html | 17 + .../dbmonster/mithril-0.2.x/mithril-0.2.4.js | 2190 +++++++++++++++++ 3 files changed, 2251 insertions(+) create mode 100644 examples/dbmonster/mithril-0.2.x/app.js create mode 100644 examples/dbmonster/mithril-0.2.x/index.html create mode 100644 examples/dbmonster/mithril-0.2.x/mithril-0.2.4.js diff --git a/examples/dbmonster/mithril-0.2.x/app.js b/examples/dbmonster/mithril-0.2.x/app.js new file mode 100644 index 00000000..ebfa2253 --- /dev/null +++ b/examples/dbmonster/mithril-0.2.x/app.js @@ -0,0 +1,44 @@ +"use strict" + +var data = [] + +var root = document.getElementById("app") +update() + +function update() { + data = ENV.generateData().toArray() + + Monitoring.renderRate.ping() + + m.redraw(); + + setTimeout(update, ENV.timeout) +} + +m.mount(root, { + view : function() { + return m("div", [ + m("table", { className: "table table-striped latest-data" }, [ + m("tbody", + data.map(function(db) { + return m("tr", {key: db.dbname}, [ + m("td", { className: "dbname" }, db.dbname), + m("td", { className: "query-count" }, [ + m("span", { className: db.lastSample.countClassName }, db.lastSample.nbQueries) + ]), + db.lastSample.topFiveQueries.map(function(query) { + return m("td", { className: query.elapsedClassName }, [ + m("span", query.formatElapsed), + m("div", { className: "popover left" }, [ + m("div", { className: "popover-content" }, query.query), + m("div", { className: "arrow" }) + ]) + ]) + }) + ]) + }) + ) + ]) + ]) + } +}); diff --git a/examples/dbmonster/mithril-0.2.x/index.html b/examples/dbmonster/mithril-0.2.x/index.html new file mode 100644 index 00000000..d6000ee0 --- /dev/null +++ b/examples/dbmonster/mithril-0.2.x/index.html @@ -0,0 +1,17 @@ + + + + + + + dbmon (Mithril 0.2.x) + + +
+ + + + + + + diff --git a/examples/dbmonster/mithril-0.2.x/mithril-0.2.4.js b/examples/dbmonster/mithril-0.2.x/mithril-0.2.4.js new file mode 100644 index 00000000..b98d933a --- /dev/null +++ b/examples/dbmonster/mithril-0.2.x/mithril-0.2.4.js @@ -0,0 +1,2190 @@ +;(function (global, factory) { // eslint-disable-line + "use strict" + /* eslint-disable no-undef */ + var m = factory(global) + if (typeof module === "object" && module != null && module.exports) { + module.exports = m + } else if (typeof define === "function" && define.amd) { + define(function () { return m }) + } else { + global.m = m + } + /* eslint-enable no-undef */ +})(typeof window !== "undefined" ? window : this, function (global, undefined) { // eslint-disable-line + "use strict" + + m.version = function () { + return "v0.2.3" + } + + var hasOwn = {}.hasOwnProperty + var type = {}.toString + + function isFunction(object) { + return typeof object === "function" + } + + function isObject(object) { + return type.call(object) === "[object Object]" + } + + function isString(object) { + return type.call(object) === "[object String]" + } + + var isArray = Array.isArray || function (object) { + return type.call(object) === "[object Array]" + } + + function noop() {} + + var voidElements = { + AREA: 1, + BASE: 1, + BR: 1, + COL: 1, + COMMAND: 1, + EMBED: 1, + HR: 1, + IMG: 1, + INPUT: 1, + KEYGEN: 1, + LINK: 1, + META: 1, + PARAM: 1, + SOURCE: 1, + TRACK: 1, + WBR: 1 + } + + // caching commonly used variables + var $document, $location, $requestAnimationFrame, $cancelAnimationFrame + + // self invoking function needed because of the way mocks work + function initialize(mock) { + $document = mock.document + $location = mock.location + $cancelAnimationFrame = mock.cancelAnimationFrame || mock.clearTimeout + $requestAnimationFrame = mock.requestAnimationFrame || mock.setTimeout + } + + // testing API + m.deps = function (mock) { + initialize(global = mock || window) + return global + } + + m.deps(global) + + /** + * @typedef {String} Tag + * A string that looks like -> div.classname#id[param=one][param2=two] + * Which describes a DOM node + */ + + function parseTagAttrs(cell, tag) { + var classes = [] + var parser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[.+?\])/g + var match + + while ((match = parser.exec(tag))) { + if (match[1] === "" && match[2]) { + cell.tag = match[2] + } else if (match[1] === "#") { + cell.attrs.id = match[2] + } else if (match[1] === ".") { + classes.push(match[2]) + } else if (match[3][0] === "[") { + var pair = /\[(.+?)(?:=("|'|)(.*?)\2)?\]/.exec(match[3]) + cell.attrs[pair[1]] = pair[3] || "" + } + } + + return classes + } + + function getVirtualChildren(args, hasAttrs) { + var children = hasAttrs ? args.slice(1) : args + + if (children.length === 1 && isArray(children[0])) { + return children[0] + } else { + return children + } + } + + function assignAttrs(target, attrs, classes) { + var classAttr = "class" in attrs ? "class" : "className" + + for (var attrName in attrs) { + if (hasOwn.call(attrs, attrName)) { + if (attrName === classAttr && + attrs[attrName] != null && + attrs[attrName] !== "") { + classes.push(attrs[attrName]) + // create key in correct iteration order + target[attrName] = "" + } else { + target[attrName] = attrs[attrName] + } + } + } + + if (classes.length) target[classAttr] = classes.join(" ") + } + + /** + * + * @param {Tag} The DOM node tag + * @param {Object=[]} optional key-value pairs to be mapped to DOM attrs + * @param {...mNode=[]} Zero or more Mithril child nodes. Can be an array, + * or splat (optional) + */ + function m(tag, pairs) { + var args = [] + + for (var i = 1, length = arguments.length; i < length; i++) { + args[i - 1] = arguments[i] + } + + if (isObject(tag)) return parameterize(tag, args) + + if (!isString(tag)) { + throw new Error("selector in m(selector, attrs, children) should " + + "be a string") + } + + var hasAttrs = pairs != null && isObject(pairs) && + !("tag" in pairs || "view" in pairs || "subtree" in pairs) + + var attrs = hasAttrs ? pairs : {} + var cell = { + tag: "div", + attrs: {}, + children: getVirtualChildren(args, hasAttrs) + } + + assignAttrs(cell.attrs, attrs, parseTagAttrs(cell, tag)) + return cell + } + + function forEach(list, f) { + for (var i = 0; i < list.length && !f(list[i], i++);) { + // function called in condition + } + } + + function forKeys(list, f) { + forEach(list, function (attrs, i) { + return (attrs = attrs && attrs.attrs) && + attrs.key != null && + f(attrs, i) + }) + } + // This function was causing deopts in Chrome. + function dataToString(data) { + // data.toString() might throw or return null if data is the return + // value of Console.log in some versions of Firefox (behavior depends on + // version) + try { + if (data != null && data.toString() != null) return data + } catch (e) { + // silently ignore errors + } + return "" + } + + // This function was causing deopts in Chrome. + function injectTextNode(parentElement, first, index, data) { + try { + insertNode(parentElement, first, index) + first.nodeValue = data + } catch (e) { + // IE erroneously throws error when appending an empty text node + // after a null + } + } + + function flatten(list) { + // recursively flatten array + for (var i = 0; i < list.length; i++) { + if (isArray(list[i])) { + list = list.concat.apply([], list) + // check current index again and flatten until there are no more + // nested arrays at that index + i-- + } + } + return list + } + + function insertNode(parentElement, node, index) { + parentElement.insertBefore(node, + parentElement.childNodes[index] || null) + } + + var DELETION = 1 + var INSERTION = 2 + var MOVE = 3 + + function handleKeysDiffer(data, existing, cached, parentElement) { + forKeys(data, function (key, i) { + existing[key = key.key] = existing[key] ? { + action: MOVE, + index: i, + from: existing[key].index, + element: cached.nodes[existing[key].index] || + $document.createElement("div") + } : {action: INSERTION, index: i} + }) + + var actions = [] + for (var prop in existing) { + if (hasOwn.call(existing, prop)) { + actions.push(existing[prop]) + } + } + + var changes = actions.sort(sortChanges) + var newCached = new Array(cached.length) + + newCached.nodes = cached.nodes.slice() + + forEach(changes, function (change) { + var index = change.index + if (change.action === DELETION) { + clear(cached[index].nodes, cached[index]) + newCached.splice(index, 1) + } + if (change.action === INSERTION) { + var dummy = $document.createElement("div") + dummy.key = data[index].attrs.key + insertNode(parentElement, dummy, index) + newCached.splice(index, 0, { + attrs: {key: data[index].attrs.key}, + nodes: [dummy] + }) + newCached.nodes[index] = dummy + } + + if (change.action === MOVE) { + var changeElement = change.element + var maybeChanged = parentElement.childNodes[index] + if (maybeChanged !== changeElement && changeElement !== null) { + parentElement.insertBefore(changeElement, + maybeChanged || null) + } + newCached[index] = cached[change.from] + newCached.nodes[index] = changeElement + } + }) + + return newCached + } + + function diffKeys(data, cached, existing, parentElement) { + var keysDiffer = data.length !== cached.length + + if (!keysDiffer) { + forKeys(data, function (attrs, i) { + var cachedCell = cached[i] + return keysDiffer = cachedCell && + cachedCell.attrs && + cachedCell.attrs.key !== attrs.key + }) + } + + if (keysDiffer) { + return handleKeysDiffer(data, existing, cached, parentElement) + } else { + return cached + } + } + + function diffArray(data, cached, nodes) { + // diff the array itself + + // update the list of DOM nodes by collecting the nodes from each item + forEach(data, function (_, i) { + if (cached[i] != null) nodes.push.apply(nodes, cached[i].nodes) + }) + // remove items from the end of the array if the new array is shorter + // than the old one. if errors ever happen here, the issue is most + // likely a bug in the construction of the `cached` data structure + // somewhere earlier in the program + forEach(cached.nodes, function (node, i) { + if (node.parentNode != null && nodes.indexOf(node) < 0) { + clear([node], [cached[i]]) + } + }) + + if (data.length < cached.length) cached.length = data.length + cached.nodes = nodes + } + + function buildArrayKeys(data) { + var guid = 0 + forKeys(data, function () { + forEach(data, function (attrs) { + if ((attrs = attrs && attrs.attrs) && attrs.key == null) { + attrs.key = "__mithril__" + guid++ + } + }) + return 1 + }) + } + + function isDifferentEnough(data, cached, dataAttrKeys) { + if (data.tag !== cached.tag) return true + + if (dataAttrKeys.sort().join() !== + Object.keys(cached.attrs).sort().join()) { + return true + } + + if (data.attrs.id !== cached.attrs.id) { + return true + } + + if (data.attrs.key !== cached.attrs.key) { + return true + } + + if (m.redraw.strategy() === "all") { + return !cached.configContext || cached.configContext.retain !== true + } + + if (m.redraw.strategy() === "diff") { + return cached.configContext && cached.configContext.retain === false + } + + return false + } + + function maybeRecreateObject(data, cached, dataAttrKeys) { + // if an element is different enough from the one in cache, recreate it + if (isDifferentEnough(data, cached, dataAttrKeys)) { + if (cached.nodes.length) clear(cached.nodes) + + if (cached.configContext && + isFunction(cached.configContext.onunload)) { + cached.configContext.onunload() + } + + if (cached.controllers) { + forEach(cached.controllers, function (controller) { + if (controller.onunload) { + controller.onunload({preventDefault: noop}) + } + }) + } + } + } + + function getObjectNamespace(data, namespace) { + if (data.attrs.xmlns) return data.attrs.xmlns + if (data.tag === "svg") return "http://www.w3.org/2000/svg" + if (data.tag === "math") return "http://www.w3.org/1998/Math/MathML" + return namespace + } + + var pendingRequests = 0 + m.startComputation = function () { pendingRequests++ } + m.endComputation = function () { + if (pendingRequests > 1) { + pendingRequests-- + } else { + pendingRequests = 0 + m.redraw() + } + } + + function unloadCachedControllers(cached, views, controllers) { + if (controllers.length) { + cached.views = views + cached.controllers = controllers + forEach(controllers, function (controller) { + if (controller.onunload && controller.onunload.$old) { + controller.onunload = controller.onunload.$old + } + + if (pendingRequests && controller.onunload) { + var onunload = controller.onunload + controller.onunload = noop + controller.onunload.$old = onunload + } + }) + } + } + + function scheduleConfigsToBeCalled(configs, data, node, isNew, cached) { + // schedule configs to be called. They are called after `build` finishes + // running + if (isFunction(data.attrs.config)) { + var context = cached.configContext = cached.configContext || {} + + // bind + configs.push(function () { + return data.attrs.config.call(data, node, !isNew, context, + cached) + }) + } + } + + function buildUpdatedNode( + cached, + data, + editable, + hasKeys, + namespace, + views, + configs, + controllers + ) { + var node = cached.nodes[0] + + if (hasKeys) { + setAttributes(node, data.tag, data.attrs, cached.attrs, namespace) + } + + cached.children = build( + node, + data.tag, + undefined, + undefined, + data.children, + cached.children, + false, + 0, + data.attrs.contenteditable ? node : editable, + namespace, + configs + ) + + cached.nodes.intact = true + + if (controllers.length) { + cached.views = views + cached.controllers = controllers + } + + return node + } + + function handleNonexistentNodes(data, parentElement, index) { + var nodes + if (data.$trusted) { + nodes = injectHTML(parentElement, index, data) + } else { + nodes = [$document.createTextNode(data)] + if (!(parentElement.nodeName in voidElements)) { + insertNode(parentElement, nodes[0], index) + } + } + + var cached + + if (typeof data === "string" || + typeof data === "number" || + typeof data === "boolean") { + cached = new data.constructor(data) + } else { + cached = data + } + + cached.nodes = nodes + return cached + } + + function reattachNodes( + data, + cached, + parentElement, + editable, + index, + parentTag + ) { + var nodes = cached.nodes + if (!editable || editable !== $document.activeElement) { + if (data.$trusted) { + clear(nodes, cached) + nodes = injectHTML(parentElement, index, data) + } else if (parentTag === "textarea") { + //