From c774a58f4a21b9bfb6c55c55bd40d91d1fb18d9e Mon Sep 17 00:00:00 2001 From: Tim Branyen Date: Fri, 12 Feb 2016 10:17:26 -0800 Subject: [PATCH] Adds in diffHTML example diffHTML is a React-inspired tiny library that efficiently diffs HTML to the DOM and patches in changes. It also provides a Custom Element polyfill and a transitions API. While it's still under development, it has already been successfully used on an internal Netflix application. Adding to your list in hopes that I'll encourage others who are interested to contribute. Relevant links: [http://github.com/tbranyen/diffhtml](http://github.com/tbranyen/diffhtml) [http://diffhtml.org](http://diffhtml.org) --- diffhtml/app.js | 39 +++++++++++++++++++++++++++++++++++++++ diffhtml/index.html | 27 +++++++++++++++++++++++++++ lib/diffhtml.min.js | 3 +++ library-list.js | 1 + 4 files changed, 70 insertions(+) create mode 100644 diffhtml/app.js create mode 100644 diffhtml/index.html create mode 100644 lib/diffhtml.min.js diff --git a/diffhtml/app.js b/diffhtml/app.js new file mode 100644 index 00000000..44f4cce9 --- /dev/null +++ b/diffhtml/app.js @@ -0,0 +1,39 @@ +const element = document.querySelector('#dbmon tbody'); +const cached = _.template(` + <% databases.map(function(database) { %> + + + <%= database.dbname %> + + + + <%= database.lastSample.nbQueries %> + + + <% database.lastSample.topFiveQueries.map(function(sample) { %> + + <%= sample.formatElapsed %> +
+
<%- sample.query %>
+
+
+ + <% }); %> + + <% }); %> +`); + +function template(databases) { + return cached({ databases }); +} + +function render() { + var databases = ENV.generateData().toArray(); + Monitoring.renderRate.ping(); + + setTimeout(render, ENV.timeout); + + diff.innerHTML(element, template(databases)); +} + +render(); diff --git a/diffhtml/index.html b/diffhtml/index.html new file mode 100644 index 00000000..11661bfb --- /dev/null +++ b/diffhtml/index.html @@ -0,0 +1,27 @@ + + + + + + + + dbmon (diffHTML) + + +
+
+ + +
+
+
+ + + + + + + + + + diff --git a/lib/diffhtml.min.js b/lib/diffhtml.min.js new file mode 100644 index 00000000..4b05db55 --- /dev/null +++ b/lib/diffhtml.min.js @@ -0,0 +1,3 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.diff=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o-1){isSvg=true;element=document.createElementNS(svg.namespace,descriptor.nodeName)}else{element=document.createElement(descriptor.nodeName)}if(descriptor.attributes&&descriptor.attributes.length){for(var i=0;ioldChildNodesLength){var fragment=[];for(var i=oldChildNodesLength;ichildNodesLength){var diff=oldChildNodesLength-childNodesLength;var toRemove=oldChildNodes.splice(oldChildNodesLength-diff,diff);oldChildNodesLength=oldChildNodes.length;if(oldChildNodesLength===0&&childNodesLength===0){patches.push({__do__:REMOVE_ELEMENT_CHILDREN,element:oldTree,toRemove:toRemove})}else{for(var i=0;i=childNodesLength){for(var i=0;ioldLength){var toAdd=slice.call(attributes,oldLength);for(var i=0;inewLength){var toRemove=slice.call(oldTree.attributes,newLength);for(var i=0;i-1){parentNode.nodeValue=(0,_entities.decodeEntities)(descriptor.nodeValue)}}triggerTransition("textChanged",textPromises,function(promises){})}if(descriptor.attributes&&descriptor.attributes.length){descriptor.attributes.forEach(function(attr){var attrChangePromises=transition.makePromises("attributeChanged",[el],attr.name,null,attr.value);triggerTransition("attributeChanged",attrChangePromises,function(promises){})})}if(descriptor.childNodes&&descriptor.childNodes.length){descriptor.childNodes.forEach(function(x){return attached(x,null,el)})}if(fragment){fragment.appendChild(el)}return el};var _loop=function _loop(i){var patch=patches[i];var newDescriptor=undefined,oldDescriptor=undefined,elementDescriptor=undefined;var element=patch.new;if(patch.element){elementDescriptor=patch.element;var result=(0,_get2.default)(patch.element);patch.element=result.element}if(patch.old){oldDescriptor=patch.old;var result=(0,_get2.default)(patch.old);patch.old=result.element}if(patch.new){newDescriptor=patch.new;var result=(0,_get2.default)(patch.new);patch.new=result.element}if(patch.__do__===sync.REMOVE_ELEMENT_CHILDREN){var childNodes=patch.element.childNodes;var detachPromises=transition.makePromises("detached",childNodes);triggerTransition("detached",detachPromises,function(promises){patch.toRemove.forEach(function(x){return(0,_memory.unprotectElement)(x,_make2.default)});patch.element.innerHTML=""})}else if(patch.__do__===sync.REMOVE_ENTIRE_ELEMENT){var detachPromises=transition.makePromises("detached",[patch.elemnt]);if(patch.element.parentNode){triggerTransition("detached",detachPromises,function(promises){patch.element.parentNode.removeChild(patch.element);patch.toRemove.forEach(function(x){return(0,_memory.unprotectElement)(x,_make2.default)})})}else{patch.toRemove.forEach(function(x){return(0,_memory.unprotectElement)(x,_make2.default)})}}else if(patch.__do__===sync.REPLACE_ENTIRE_ELEMENT){(function(){var allPromises=[];var attachedPromises=transition.makePromises("attached",[patch.new]);var detachedPromises=transition.makePromises("detached",[patch.old]);var replacedPromises=transition.makePromises("replaced",[patch.old],patch.new);triggerTransition("detached",detachedPromises,function(promises){allPromises.push.apply(allPromises,promises)});triggerTransition("attached",attachedPromises,function(promises){allPromises.push.apply(allPromises,promises);attached(newDescriptor,null,patch.new)});triggerTransition("replaced",replacedPromises,function(promises){allPromises.push.apply(allPromises,promises)});(0,_memory.unprotectElement)(oldDescriptor,_make2.default);_tree.TreeCache.set(patch.new,{oldTree:newDescriptor,element:patch.new});if(allPromises.length){Promise.all(allPromises).then(function replaceEntireElement(){if(!patch.old.parentNode){(0,_memory.unprotectElement)(newDescriptor,_make2.default);throw new Error("Can't replace without parent, is this the "+"document root?")}patch.old.parentNode.replaceChild(patch.new,patch.old)},function(ex){return console.log(ex)})}else{if(!patch.old.parentNode){(0,_memory.unprotectElement)(newDescriptor,_make2.default);throw new Error("Can't replace without parent, is this the "+"document root?")}patch.old.parentNode.replaceChild(patch.new,patch.old)}})()}else if(patch.__do__===sync.MODIFY_ELEMENT){if(patch.element&&patch.fragment&&!patch.old){(function(){var fragment=document.createDocumentFragment();toAttach=patch.fragment.map(function(el){return attached(el,fragment,patch.element)});patch.element.appendChild(fragment);var makeAttached=transition.makePromises("attached",toAttach);triggerTransition("attached",makeAttached)})()}else if(patch.old&&!patch.new){if(!patch.old.parentNode){(0,_memory.unprotectElement)(oldDescriptor,_make2.default);throw new Error("Can't remove without parent, is this the "+"document root?")}var makeDetached=transition.makePromises("detached",[patch.old]);triggerTransition("detached",makeDetached,function(){patch.old.innerHTML="";if(patch.old.parentNode){patch.old.parentNode.removeChild(patch.old)}(0,_memory.unprotectElement)(oldDescriptor,_make2.default)})}else if(patch.old&&patch.new){(function(){if(!patch.old.parentNode){(0,_memory.unprotectElement)(oldDescriptor,_make2.default);(0,_memory.unprotectElement)(newDescriptor,_make2.default);throw new Error("Can't replace without parent, is this the "+"document root?")}if(patch.old.nextSibling){patch.old.parentNode.insertBefore(patch.new,patch.old.nextSibling)}else{patch.old.parentNode.appendChild(patch.new)}var allPromises=[];var attachPromises=transition.makePromises("attached",[patch.new]);var detachPromises=transition.makePromises("detached",[patch.old]);var replacePromises=transition.makePromises("replaced",[patch.old],patch.new);triggerTransition("detached",detachPromises,function(promises){allPromises.push.apply(allPromises,promises)});triggerTransition("attached",attachPromises,function(promises){allPromises.push.apply(allPromises,promises);attached(newDescriptor)});triggerTransition("replaced",replacePromises,function(promises){allPromises.push.apply(allPromises,promises)});if(allPromises.length){Promise.all(allPromises).then(function replaceElement(){patch.old.parentNode.replaceChild(patch.new,patch.old);(0,_memory.unprotectElement)(oldDescriptor,_make2.default);(0,_memory.protectElement)(newDescriptor);if(elementMeta.workerCache){elementMeta.workerCache.push(newDescriptor)}},function(ex){return console.log(ex)})}else{if(!patch.old.parentNode){(0,_memory.unprotectElement)(oldDescriptor,_make2.default);(0,_memory.unprotectElement)(newDescriptor,_make2.default);throw new Error("Can't replace without parent, is this the "+"document root?")}patch.old.parentNode.replaceChild(patch.new,patch.old);(0,_memory.unprotectElement)(oldDescriptor,_make2.default);(0,_memory.protectElement)(newDescriptor);if(elementMeta.workerCache){elementMeta.workerCache.push(newDescriptor)}}})()}}else if(patch.__do__===sync.MODIFY_ATTRIBUTE){var attrChangePromises=transition.makePromises("attributeChanged",[patch.element],patch.name,patch.element.getAttribute(patch.name),patch.value);triggerTransition("attributeChanged",attrChangePromises,function(promises){if(patch.value===undefined){patch.element.removeAttribute(patch.name)}else{patch.element.setAttribute(patch.name,patch.value);if(patch.name==="value"){patch.element[patch.name]=patch.value}}})}else if(patch.__do__===sync.CHANGE_TEXT){var textChangePromises=transition.makePromises("textChanged",[patch.element],patch.element.nodeValue,patch.value);triggerTransition("textChanged",textChangePromises,function(promises){elementDescriptor.nodeValue=(0,_entities.decodeEntities)(patch.value);patch.element.nodeValue=elementDescriptor.nodeValue;if(patch.element.parentNode){var nodeName=patch.element.parentNode.nodeName.toLowerCase();if(blockTextElements.indexOf(nodeName)>-1){patch.element.parentNode.nodeValue=elementDescriptor.nodeValue}}})}};for(var i=0;i1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key]}var elements=slice.call(args[0]);triggerLifecycleEvent(stateName,args.slice(1),elements);return function(promises){return make[stateName](elements,args.slice(1),promises)}}},{"./element/custom":1}],14:[function(_dereq_,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.decodeEntities=decodeEntities;var element=document.createElement("div");function decodeEntities(string){element.innerHTML=string;return element.textContent}},{}],15:[function(_dereq_,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.protectElement=protectElement;exports.unprotectElement=unprotectElement;exports.cleanMemory=cleanMemory;var _pools2=_dereq_("../util/pools");var _make=_dereq_("../node/make");var _make2=_interopRequireDefault(_make);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{"default":obj}}var pools=_pools2.pools;var makeNode=_make2.default;var elementObject=pools.elementObject;var attributeObject=pools.attributeObject;function protectElement(element){pools.elementObject.protect(element);element.attributes.forEach(pools.attributeObject.protect,pools.attributeObject);if(element.childNodes){element.childNodes.forEach(protectElement)}return element}function unprotectElement(element,makeNode){elementObject.unprotect(element);elementObject.cache.uuid.delete(element.uuid);element.attributes.forEach(attributeObject.unprotect,attributeObject);if(element.childNodes){element.childNodes.forEach(function(node){return unprotectElement(node,makeNode)})}if(makeNode&&makeNode.nodes){delete makeNode.nodes[element.uuid]}return element}function cleanMemory(makeNode){if(makeNode&&makeNode.nodes){for(var uuid in makeNode.nodes){if(!elementObject.cache.uuid.has(uuid)){delete makeNode.nodes[uuid]}}}elementObject.cache.allocated.forEach(function(v){return elementObject.cache.free.push(v)});elementObject.cache.allocated.clear()}},{"../node/make":6,"../util/pools":17}],16:[function(_dereq_,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.parseHTML=parseHTML;exports.makeParser=makeParser;var _pools2=_dereq_("./pools");var pools=_pools2.pools;var parser=makeParser();var slice=Array.prototype.slice;function parseHTML(newHTML,isInner){var documentElement=parser.parse(newHTML);var nodes=documentElement.childNodes;return isInner?nodes:nodes[0]}function makeParser(){var kMarkupPattern=/)-->|<(\/?)([a-z\-][a-z0-9\-]*)\s*([^>]*?)(\/?)>/gi;var kAttributePattern=/\b(id|class)\s*(=\s*("([^"]+)"|'([^']+)'|(\S+)))?/gi;var reAttrPattern=/\b([a-z][a-z0-9\-]*)\s*(=\s*("([^"]+)"|'([^']+)'|(\S+)))?/gi;var kSelfClosingElements={meta:true,img:true,link:true,input:true,area:true,br:true,hr:true};var kElementsClosedByOpening={li:{li:true},p:{p:true,div:true},td:{td:true,th:true},th:{td:true,th:true}};var kElementsClosedByClosing={li:{ul:true,ol:true},a:{div:true},b:{div:true},i:{div:true},p:{div:true},td:{tr:true,table:true},th:{tr:true,table:true}};var kBlockTextElements={script:true,noscript:true,style:true,template:true};var escapeMap={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};function TextNode(value){var instance=pools.elementObject.get();instance.nodeName="#text";instance.nodeValue=value;instance.nodeType=3;instance.childNodes.length=0;instance.attributes.length=0;return instance}function HTMLElement(name,keyAttrs,rawAttrs){var instance=pools.elementObject.get();instance.nodeName=name;instance.nodeValue="";instance.nodeType=1;instance.childNodes.length=0;instance.attributes.length=0;if(rawAttrs){for(var match;match=reAttrPattern.exec(rawAttrs);){var attr=pools.attributeObject.get();attr.name=match[1];attr.value=match[6]||match[5]||match[4]||match[1];if(match[6]==='""'){attr.value=""}instance.attributes[instance.attributes.length]=attr}}return instance}var htmlParser={parse:function parse(data){var rootObject={};var root=HTMLElement(null,rootObject);var currentParent=root;var stack=[root];var lastTextPos=-1;if(data.indexOf("<")===-1&&data){currentParent.childNodes[currentParent.childNodes.length]=TextNode(data);return root}for(var match,text;match=kMarkupPattern.exec(data);){if(lastTextPos>-1){if(lastTextPos+match[0].length";var index=data.indexOf(closeMarkup,kMarkupPattern.lastIndex);var length=match[2].length;if(index===-1){lastTextPos=kMarkupPattern.lastIndex=data.length+1}else{lastTextPos=kMarkupPattern.lastIndex=index+closeMarkup.length;match[1]=true}var newText=data.slice(match.index+match[0].length,index);if(newText.trim()){newText=slice.call(newText).map(function(ch){return escapeMap[ch]||ch}).join("");currentParent.childNodes.push(TextNode(newText))}}}if(match[1]||match[4]||kSelfClosingElements[match[2]]){while(currentParent){if(currentParent.nodeName==match[2]){stack.pop();currentParent=stack[stack.length-1];break}else{if(kElementsClosedByClosing[currentParent.nodeName]){if(kElementsClosedByClosing[currentParent.nodeName][match[2]]){stack.pop();currentParent=stack[stack.length-1];continue}}break}}}}if(root.childNodes.length&&root.childNodes[0].nodeName==="html"){(function(){var head={before:[],after:[]};var body={after:[]};var beforeHead=true;var beforeBody=true;var HTML=root.childNodes[0];HTML.childNodes=HTML.childNodes.filter(function(el){if(el.nodeName==="body"||el.nodeName==="head"){if(el.nodeName==="head"){beforeHead=false}if(el.nodeName==="body"){beforeBody=false}return true}else if(el.nodeType===1){if(beforeHead&&beforeBody){head.before.push(el)}else if(!beforeHead&&beforeBody){head.after.push(el)}else if(!beforeBody){body.after.push(el)}}});if(!HTML.childNodes[0]||HTML.childNodes[0].nodeName!=="head"){var headInstance=pools.elementObject.get();headInstance.nodeName="head";headInstance.childNodes.length=0;headInstance.attributes.length=0;var existing=headInstance.childNodes;existing.unshift.apply(existing,head.before);existing.push.apply(existing,head.after);HTML.childNodes.unshift(headInstance)}else{var existing=HTML.childNodes[0].childNodes;existing.unshift.apply(existing,head.before);existing.push.apply(existing,head.after)}if(!HTML.childNodes[1]||HTML.childNodes[1].nodeName!=="body"){var bodyInstance=pools.elementObject.get();bodyInstance.nodeName="body";bodyInstance.childNodes.length=0;bodyInstance.attributes.length=0;var existing=bodyInstance.childNodes;existing.push.apply(existing,body.after);HTML.childNodes.push(bodyInstance)}else{var existing=HTML.childNodes[1].childNodes;existing.push.apply(existing,body.after)}})()}return root}};return htmlParser}},{"./pools":17}],17:[function(_dereq_,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.count=exports.pools=undefined;exports.createPool=createPool;exports.initializePools=initializePools;var _uuid2=_dereq_("./uuid");var _uuid3=_interopRequireDefault(_uuid2);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{"default":obj}}var uuid=_uuid3.default;var pools=exports.pools={};var count=exports.count=1e4;function createPool(name,opts){var size=opts.size;var fill=opts.fill;var cache={free:[],allocated:new Set,"protected":new Set,uuid:new Set};for(var i=0;i