Toggle navigation
MeasureThat.net
Create a benchmark
Tools
Feedback
FAQ
Register
Log In
DexV9 vs DexV10
(version: 8)
Comparing performance of:
DexV9 vs DexV10 by TAG vs DexV10 by CLASS vs DexV10 by ID
Created:
8 years ago
by:
Registered User
Jump to the latest result
HTML Preparation code:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> (function(exposeAs){ var Dex = function(selector, nodes){ // Return Dex object return new Dex.fn.init(selector, nodes); }; Dex.fn = Dex.prototype = { init: function(selector, nodes){ this.selector = selector; if(nodes){ this.nodes = nodes; } else { this.nodes = document.querySelectorAll(selector); } return this; } }; var delegatedEventListeners = {}, mutationObservers = {}, DOMMutationCallback = function(mutations, selector, parentNodes, childtree){ var n, x, y, mutationRecord, addedNode, removedNode, modifiedNodeAttribute, callbacks, _target; // Loop through mutation records for(n = 0; n < mutations.length; n++){ mutationRecord = mutations[n]; // Loop through added nodes for(x = 0; x < mutationRecord.addedNodes.length; x++){ addedNode = mutationRecord.addedNodes[x]; // Check if node type is valid if(addedNode.nodeType == 1){ // Check if an observer has been created for this selector and this event type if( mutationObservers[selector] && mutationObservers[selector][childtree] && mutationObservers[selector][childtree].callbacks.onOpen){ callbacks = mutationObservers[selector][childtree].callbacks.onOpen; // Loop through callbacks for(_target in callbacks){ // See if addedNode matches the _target of the callback if(addedNode.matches(_target)){ // Loop through all callbacks for(y = 0; y < callbacks[_target].length; y++){ // Call callback function callbacks[_target][y].call(addedNode); } } } } } } // Loop through removed nodes for(x = 0; x < mutationRecord.removedNodes.length; x++){ removedNode = mutationRecord.removedNodes[x]; // Check if node type is valid if(removedNode.nodeType == 1){ // Check if an observer has been created for this selector and this event type if( mutationObservers[selector] && mutationObservers[selector][childtree] && mutationObservers[selector][childtree].callbacks.onClose){ callbacks = mutationObservers[selector][childtree].callbacks.onClose; // Loop through callbacks for(_target in callbacks){ // See if removedNode matches the _target of the callback if(removedNode.matches(_target)){ // Loop through all callbacks for(y = 0; y < callbacks[_target].length; y++){ // Call callback function callbacks[_target][y].call(removedNode); } } } } } } // Loop through modified attributes if(mutationRecord.attributeName){ modifiedNodeAttribute = mutationRecord.target; // Check if an observer has been created for this selector and this event type if( mutationObservers[selector] && mutationObservers[selector][childtree] && mutationObservers[selector][childtree].callbacks.onAttribute){ callbacks = mutationObservers[selector][childtree].callbacks.onAttribute; // Loop through callbacks for(_target in callbacks){ // See if modifiedNodeAttribute matches the _target of the callback if(modifiedNodeAttribute.matches(_target)){ // Loop through all callbacks for(y = 0; y < callbacks[_target].length; y++){ // Call callback function callbacks[_target][y].call(modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } } } } } } }, DOMMutationCallbackFast = function(mutations, selector, parentNodes, childtree){ var n, x, y, mutationRecord, addedNode, removedNode, modifiedNodeAttribute, callbacks, _target; // Loop through mutation records for(n = 0; n < mutations.length; n++){ mutationRecord = mutations[n]; // Loop through added nodes for(x = 0; x < mutationRecord.addedNodes.length; x++){ addedNode = mutationRecord.addedNodes[x]; // Check if node type is valid if(addedNode.nodeType == 1){ // Check if an observer has been created for this selector and this event type if( mutationObservers[selector] && mutationObservers[selector][childtree] && mutationObservers[selector][childtree].callbacks.onOpen){ callbacks = mutationObservers[selector][childtree].callbacks.onOpen; // Loop through callbacks for(_target in callbacks){ // See if addedNode matches the _target of the callback if(addedNode.matches(_target)){ // Loop through all callbacks for(y = 0; y < callbacks[_target].length; y++){ // Call callback function callbacks[_target][y].call(addedNode); } } } } } } // Loop through removed nodes for(x = 0; x < mutationRecord.removedNodes.length; x++){ removedNode = mutationRecord.removedNodes[x]; // Check if node type is valid if(removedNode.nodeType == 1){ // Check if an observer has been created for this selector and this event type if( mutationObservers[selector] && mutationObservers[selector][childtree] && mutationObservers[selector][childtree].callbacks.onClose){ callbacks = mutationObservers[selector][childtree].callbacks.onClose; // Loop through callbacks for(_target in callbacks){ // See if removedNode matches the _target of the callback if(removedNode.matches(_target)){ // Loop through all callbacks for(y = 0; y < callbacks[_target].length; y++){ // Call callback function callbacks[_target][y].call(removedNode); } } } } } } // Loop through modified attributes if(mutationRecord.attributeName){ modifiedNodeAttribute = mutationRecord.target; // Check if an observer has been created for this selector and this event type if( mutationObservers[selector] && mutationObservers[selector][childtree] && mutationObservers[selector][childtree].callbacks.onAttribute){ callbacks = mutationObservers[selector][childtree].callbacks.onAttribute; // Loop through callbacks for(_target in callbacks){ // See if modifiedNodeAttribute matches the _target of the callback if(modifiedNodeAttribute.matches(_target)){ // Loop through all callbacks for(y = 0; y < callbacks[_target].length; y++){ // Call callback function callbacks[_target][y].call(modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } } } } } } }, attachEventListeners = function(eventType, dexObject){ var n, selector = { string: dexObject.selector }; for(n = 0; n < dexObject.nodes.length; n++){ selector.node = dexObject.nodes[n]; selector.node.addEventListener(eventType, function(e){ var eventHandlers = delegatedEventListeners[eventType][selector.string]; for(handlerSelector in eventHandlers){ clickedNode = e.target; while( clickedNode !== document && clickedNode !== selector.node) { // Stop looking when we hit the node that contains the event listener if (clickedNode.matches(handlerSelector)) { var handlerIndex = 0; while (eventHandlers[handlerSelector][handlerIndex]){ eventHandlers[handlerSelector][handlerIndex].callback.call(clickedNode, e); if(!eventHandlers[handlerSelector][handlerIndex].persistant){ delete eventHandlers[handlerSelector][handlerIndex]; } handlerIndex++; } } clickedNode = clickedNode.parentNode; } } }); } }; // EXPOSED SELECTOR FUNCTIONS Dex.fn.init.prototype = { first: function(){ /* Remove all nodes except first from node list */ this.nodes = [this.nodes[0]]; return this; }, index: function(index){ /* Remove all nodes except requested index */ this.nodes = [this.nodes[index]]; return this; }, getNode: function(index){ /* Return DOM node */ return this.nodes[index]; }, exists: function(){ /* See if the node list contains at least one node */ return this.nodes[0] != null; }, appendClone: function(node){ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].appendChild(node.cloneNode(true)); } return this; }, append: function(node){ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].appendChild(node); } return this; }, remove: function(){ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n]; if (this.nodes[n].parentNode) { this.nodes[n].parentNode.removeChild(this.nodes[n]); } } return this; }, clone: function(){ var n, clonedNodes = []; for(n = 0; n < this.nodes.length; n++){ clonedNodes.push(this.nodes[n].cloneNode(true)); } this.nodes = clonedNodes; return this; }, parent: function(){ this.nodes = [this.nodes[0].parentNode]; return this; }, closest: function(matchSelector){ var closest = []; node = this.nodes[0]; // Go through parents while(node && node !== document) { if (node.matches(matchSelector)) { closest = [node]; break; } node = node.parentNode; } this.nodes = closest; return this; }, filter: function(selector){ /* Filter then current node list - note: only filters on the first node in list */ this.nodes = this.nodes[0].querySelectorAll(selector); return this; }, // DOM modification setHTML: function(value){ /* Set innerHTML of all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].innerHTML = value; } return this; }, getHTML: function(value){ /* Get innerHTML of all first node in nodelist */ return this.nodes[0].innerHTML; }, css: function(styles){ /* Set CSS of all nodes in nodelist */ var style, n; for(n = 0; n < this.nodes.length; n++){ for(style in styles){ this.nodes[n].style[style] = styles[style]; } } return this; }, setAttribute: function(key, value){ /* Set attribute of all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].setAttribute(key, value); } return this; }, getAttribute: function(key){ /* Get attribute of first node in nodelist */ return this.nodes[0].getAttribute(key); }, toggleAttribute: function(key, value){ /* Get attribute of first node in nodelist */ var n, attrValue; for(n = 0; n < this.nodes.length; n++){ attrValue = this.nodes[n].getAttribute(key); if(attrValue == value[0]){ this.nodes[n].setAttribute(key, value[1]); } else { this.nodes[n].setAttribute(key, value[0]); } } return this; }, cache: function(cacheID){ /* Cache node list with cacheID as ID */ cachedSelections[cacheID] = this; }, // Classes addClass: function(classname){ /* Add class to all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].classList.add(classname); } return this; }, removeClass: function(classname){ /* Remove class from all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].classList.remove(classname); } return this; }, hasClass: function(classname){ /* Check whether first node in list contains a classname */ var result = false; if(this.nodes[0]){ result = this.nodes[0].classList.contains(classname); } return result; }, toggleClass: function(classname){ /* Toggle classnames on all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].classList.toggle(classname); } return this; }, replaceClass: function(old_classname, new_classname){ /* Replace old_classname with new_classname on all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].classList.replace(old_classname, new_classname); } return this; }, trigger: function(eventType){ /* Trigger eventType (click, mouseover, etc, ...) on all nodes in nodelist */ if(this.nodes[0]){ var clickEvent = document.createEvent("MouseEvents"); clickEvent.initEvent(eventType, true, true); this.nodes[0].dispatchEvent(clickEvent); } return this; }, onOpen: function(target, callback){ this.onMutation("onOpen", target, callback, { children: false }); return this; }, onChildOpen: function(target, callback){ this.onMutation("onOpen", target, callback, { children: true }); return this; }, onClose: function(target, callback){ this.onMutation("onClose", target, callback, { children: false }); return this; }, onChildClose: function(target, callback){ this.onMutation("onClose", target, callback, { children: true }); return this; }, onAttribute: function(target, callback){ this.onMutation("onAttribute", target, callback, { attributes: true, children: false }); return this; }, onChildAttribute: function(target, callback){ console.log("create child attribute istener"); this.onMutation("onAttribute", target, callback, { attributes: true, children: true }); return this; }, onMutation: function(mutationType, target, callback, parameters){ var selector = this.selector, parentNodes = this.nodes, n, parameters = parameters || {}, monitorAttributes = (parameters.attributes != undefined) ? parameters.attributes : false; monitorChildren = (parameters.children != undefined) ? parameters.children : true, childtree = (monitorChildren) ? "children" : "nochildren"; // See if we need to attach a mutation observer if(!mutationObservers[this.selector]){ mutationObservers[this.selector] = {} } if(!mutationObservers[this.selector][childtree]){ mutationObservers[this.selector][childtree] = { observer: new MutationObserver(function(mutations){ DOMMutationCallback(mutations, selector, parentNodes, childtree); }), callbacks: {}, parameters: { attributes: monitorAttributes, subtree: monitorChildren } } // Attach observer to all matches nodes for(n = 0; n < this.nodes.length; n++){ mutationObservers[this.selector][childtree].observer.observe(this.nodes[n], { attributes: true, childList: true, characterData: false, subtree: monitorChildren }); } } // See if there are already callbacks for mutationType if(!mutationObservers[this.selector][childtree].callbacks[mutationType]){ mutationObservers[this.selector][childtree].callbacks[mutationType] = {} } // See if there are already calbacks for this target if(!mutationObservers[this.selector][childtree].callbacks[mutationType][target]){ mutationObservers[this.selector][childtree].callbacks[mutationType][target] = [] } // Save callback mutationObservers[this.selector][childtree].callbacks[mutationType][target].push(callback); }, onClick: function(target, callback){ // Check that the event type exists in queue if(!delegatedEventListeners["click"]){ delegatedEventListeners["click"] = {}; } // Check that this selector is registered if(!delegatedEventListeners["click"][this.selector]){ delegatedEventListeners["click"][this.selector] = {}; // Setup listener attachEventListeners("click", this); } // Check that this target is registered if(!delegatedEventListeners["click"][this.selector][target]){ delegatedEventListeners["click"][this.selector][target] = []; } // register delegated event listener delegatedEventListeners["click"][this.selector][target].push({ callback: callback, persistant: true }); return this; }, } Dex.appendCSS = function(url){ var head = document.head, link = document.createElement('link'); link.type = "text/css"; link.rel = "stylesheet"; link.href = url; head.appendChild(link); return link; } Dex.getCached = function(cacheID){ return cachedSelections[cacheID]; } Dex.clearCache = function(cacheID){ delete cachedSelections[cacheID]; } Dex.tag = function(tag){ /* Use Tag() to select nodes using the getElementsByTagName */ var nodes = document.getElementsByTagName(tag); return Dex(tag, nodes); } Dex.class = function(classname){ /* Use Tag() to select nodes using the getElementsByClassName */ var nodeCollection = document.getElementsByClassName(classname), nodes = Array.prototype.slice.call(nodeCollection); return Dex("." + classname, nodes); } Dex.iframe = function(selector){ var iframe = document.querySelectorAll(selector)[0]; return Dex.node(iframe.contentDocument || iframe.contentWindow.document); } Dex.id = function(id){ /* Use Tag() to select nodes using the getElementById */ var nodes = [document.getElementById(id)]; return Dex("#" + id, nodes); } Dex.node = function(node){ /* Use Node to create a Dex object with a DOM node directly */ return Dex("node", [node]); } Dex.collection = function(nodeCollection){ /* Use Node to create a Dex object with an HTML Node Collection directly */ var nodes = []; for(n = 0; n < nodeCollection.length; n++){ nodes.push(nodeCollection[n]); } return Dex("node", nodes) } if(exposeAs){ window[exposeAs] = Dex; } })("DexV9"); (function(exposeAs){ var Dex = function(selector, nodes){ // Return Dex object return new Dex.fn.init(selector, nodes); }; Dex.fn = Dex.prototype = { init: function(selector, nodes){ this.selector = selector; if(nodes){ this.nodes = nodes; } else { this.nodes = document.querySelectorAll(selector); } return this; } }; var delegatedEventListeners = {}, mutationObservers = {}, DOMMutationCallback = function(mutations, selector, parentNodes, childtree){ var n, x, y, mutationRecord, addedNode, removedNode, modifiedNodeAttribute, callbacks, _target, executeCallbacks = function(queue, node, arg1, arg2){ for(y = 0; y < queue.length; y++){ // Call callback function queue[y].call(node, arg1, arg2); } }; // Loop through mutation records for(n = 0; n < mutations.length; n++){ mutationRecord = mutations[n]; // Loop through added nodes if(mutationRecord.addedNodes.length > 0){ callbacks = mutationObservers[selector][childtree].callbacks.onOpen; if(callbacks){ for(x = 0; x < mutationRecord.addedNodes.length; x++){ addedNode = mutationRecord.addedNodes[x]; // Check if node type is valid if(addedNode.nodeType == 1){ // Loop through callbacks for(_target in callbacks){ // See if addedNode matches the _target of the callback switch(callbacks[_target].matchType){ case "tag": if(addedNode.tagName.toUpperCase() == _target.toUpperCase()){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, addedNode); } break; case "id": if(addedNode.id == _target.slice(1)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, addedNode); } break; case "classname": if(addedNode.classList.contains(_target.slice(1))){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, addedNode); } break; case "complex": if(addedNode.matches(_target)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, addedNode); } break; } } } } } } if(mutationRecord.removedNodes.length > 0){ callbacks = mutationObservers[selector][childtree].callbacks.onClose; if(callbacks){ // Loop through removed nodes for(x = 0; x < mutationRecord.removedNodes.length; x++){ removedNode = mutationRecord.removedNodes[x]; // Check if node type is valid if(removedNode.nodeType == 1){ // Loop through callbacks for(_target in callbacks){ // See if removedNode matches the _target of the callback switch(callbacks[_target].matchType){ case "tag": if(removedNode.tagName.toUpperCase() == _target.toUpperCase()){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, removedNode); } break; case "id": if(removedNode.id == _target.slice(1)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, removedNode); } break; case "classname": if(removedNode.classList.contains(_target.slice(1))){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, removedNode); } break; case "complex": if(removedNode.matches(_target)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, removedNode); } break; } } } } } } if(mutationRecord.attributeName){ callbacks = mutationObservers[selector][childtree].callbacks.onAttribute; if(callbacks){ // Loop through modified attributes modifiedNodeAttribute = mutationRecord.target; // Loop through callbacks for(_target in callbacks){ // See if modifiedNodeAttribute matches the _target of the callback switch(callbacks[_target].matchType){ case "tag": if(modifiedNodeAttribute.tagName.toUpperCase() == _target.toUpperCase()){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } break; case "id": if(modifiedNodeAttribute.id == _target.slice(1)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } break; case "classname": if(modifiedNodeAttribute.classList.contains(_target.slice(1))){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } break; case "complex": if(modifiedNodeAttribute.matches(_target)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } break; } } } } } }, attachEventListeners = function(eventType, dexObject){ var n, selector = { string: dexObject.selector }; for(n = 0; n < dexObject.nodes.length; n++){ selector.node = dexObject.nodes[n]; selector.node.addEventListener(eventType, function(e){ var eventHandlers = delegatedEventListeners[eventType][selector.string]; for(handlerSelector in eventHandlers){ clickedNode = e.target; while( clickedNode !== document && clickedNode !== selector.node) { // Stop looking when we hit the node that contains the event listener if (clickedNode.matches(handlerSelector)) { var handlerIndex = 0; while (eventHandlers[handlerSelector][handlerIndex]){ eventHandlers[handlerSelector][handlerIndex].callback.call(clickedNode, e); if(!eventHandlers[handlerSelector][handlerIndex].persistant){ delete eventHandlers[handlerSelector][handlerIndex]; } handlerIndex++; } } clickedNode = clickedNode.parentNode; } } }); } }; // EXPOSED SELECTOR FUNCTIONS Dex.fn.init.prototype = { first: function(){ /* Remove all nodes except first from node list */ this.nodes = [this.nodes[0]]; return this; }, index: function(index){ /* Remove all nodes except requested index */ this.nodes = [this.nodes[index]]; return this; }, getNode: function(index){ /* Return DOM node */ return this.nodes[index]; }, exists: function(){ /* See if the node list contains at least one node */ return this.nodes[0] != null; }, appendClone: function(node){ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].appendChild(node.cloneNode(true)); } return this; }, append: function(node){ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].appendChild(node); } return this; }, remove: function(){ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n]; if (this.nodes[n].parentNode) { this.nodes[n].parentNode.removeChild(this.nodes[n]); } } return this; }, clone: function(){ var n, clonedNodes = []; for(n = 0; n < this.nodes.length; n++){ clonedNodes.push(this.nodes[n].cloneNode(true)); } this.nodes = clonedNodes; return this; }, parent: function(){ this.nodes = [this.nodes[0].parentNode]; return this; }, closest: function(matchSelector){ var closest = []; node = this.nodes[0]; // Go through parents while(node && node !== document) { if (node.matches(matchSelector)) { closest = [node]; break; } node = node.parentNode; } this.nodes = closest; return this; }, filter: function(selector){ /* Filter then current node list - note: only filters on the first node in list */ this.nodes = this.nodes[0].querySelectorAll(selector); return this; }, // DOM modification setHTML: function(value){ /* Set innerHTML of all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].innerHTML = value; } return this; }, getHTML: function(value){ /* Get innerHTML of all first node in nodelist */ return this.nodes[0].innerHTML; }, css: function(styles){ /* Set CSS of all nodes in nodelist */ var style, n; for(n = 0; n < this.nodes.length; n++){ for(style in styles){ this.nodes[n].style[style] = styles[style]; } } return this; }, setAttribute: function(key, value){ /* Set attribute of all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].setAttribute(key, value); } return this; }, getAttribute: function(key){ /* Get attribute of first node in nodelist */ return this.nodes[0].getAttribute(key); }, toggleAttribute: function(key, value){ /* Get attribute of first node in nodelist */ var n, attrValue; for(n = 0; n < this.nodes.length; n++){ attrValue = this.nodes[n].getAttribute(key); if(attrValue == value[0]){ this.nodes[n].setAttribute(key, value[1]); } else { this.nodes[n].setAttribute(key, value[0]); } } return this; }, cache: function(cacheID){ /* Cache node list with cacheID as ID */ cachedSelections[cacheID] = this; }, // Classes addClass: function(classname){ /* Add class to all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].classList.add(classname); } return this; }, removeClass: function(classname){ /* Remove class from all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].classList.remove(classname); } return this; }, hasClass: function(classname){ /* Check whether first node in list contains a classname */ var result = false; if(this.nodes[0]){ result = this.nodes[0].classList.contains(classname); } return result; }, toggleClass: function(classname){ /* Toggle classnames on all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].classList.toggle(classname); } return this; }, replaceClass: function(old_classname, new_classname){ /* Replace old_classname with new_classname on all nodes in nodelist */ var n; for(n = 0; n < this.nodes.length; n++){ this.nodes[n].classList.replace(old_classname, new_classname); } return this; }, trigger: function(eventType){ /* Trigger eventType (click, mouseover, etc, ...) on all nodes in nodelist */ if(this.nodes[0]){ var clickEvent = document.createEvent("MouseEvents"); clickEvent.initEvent(eventType, true, true); this.nodes[0].dispatchEvent(clickEvent); } return this; }, onOpen: function(target, callback){ this.onMutation("onOpen", target, callback, { children: false }); return this; }, onChildOpen: function(target, callback){ this.onMutation("onOpen", target, callback, { children: true }); return this; }, onClose: function(target, callback){ this.onMutation("onClose", target, callback, { children: false }); return this; }, onChildClose: function(target, callback){ this.onMutation("onClose", target, callback, { children: true }); return this; }, onAttribute: function(target, callback){ this.onMutation("onAttribute", target, callback, { attributes: true, children: false }); return this; }, onChildAttribute: function(target, callback){ this.onMutation("onAttribute", target, callback, { attributes: true, children: true }); return this; }, onMutation: function(mutationType, target, callback, parameters){ var selector = this.selector, parentNodes = this.nodes, matchType = function(target){ // This needs updating to cater for complex selectors. var result; if(target[0] == "."){ result = "classname"; } else if(target[0] == "#"){ result = "id"; } else if(target[0] == "["){ result = "complex"; } else { result = "tag"; } return result; }(target), n, parameters = parameters || {}, monitorAttributes = (parameters.attributes != undefined) ? parameters.attributes : false; monitorChildren = (parameters.children != undefined) ? parameters.children : true, childtree = (monitorChildren) ? "children" : "nochildren"; // See if we need to attach a mutation observer if(!mutationObservers[this.selector]){ mutationObservers[this.selector] = {} } if(!mutationObservers[this.selector][childtree]){ mutationObservers[this.selector][childtree] = { observer: new MutationObserver(function(mutations){ DOMMutationCallback(mutations, selector, parentNodes, childtree); }), callbacks: {}, parameters: { attributes: monitorAttributes, subtree: monitorChildren } } // Attach observer to all matches nodes for(n = 0; n < this.nodes.length; n++){ mutationObservers[this.selector][childtree].observer.observe(this.nodes[n], { attributes: true, childList: true, characterData: false, subtree: monitorChildren }); } } // See if there are already callbacks for mutationType if(!mutationObservers[this.selector][childtree].callbacks[mutationType]){ mutationObservers[this.selector][childtree].callbacks[mutationType] = {} } // See if there are already calbacks for this target if(!mutationObservers[this.selector][childtree].callbacks[mutationType][target]){ // mutationObservers[this.selector][childtree].callbacks[mutationType][target] = [] mutationObservers[this.selector][childtree].callbacks[mutationType][target] = { matchType: matchType, queue: [] } } // Save callback mutationObservers[this.selector][childtree].callbacks[mutationType][target].queue.push(callback); }, onClick: function(target, callback){ // Check that the event type exists in queue if(!delegatedEventListeners["click"]){ delegatedEventListeners["click"] = {}; } // Check that this selector is registered if(!delegatedEventListeners["click"][this.selector]){ delegatedEventListeners["click"][this.selector] = {}; // Setup listener attachEventListeners("click", this); } // Check that this target is registered if(!delegatedEventListeners["click"][this.selector][target]){ delegatedEventListeners["click"][this.selector][target] = []; } // register delegated event listener delegatedEventListeners["click"][this.selector][target].push({ callback: callback, persistant: true }); return this; }, } Dex.appendCSS = function(url){ var head = document.head, link = document.createElement('link'); link.type = "text/css"; link.rel = "stylesheet"; link.href = url; head.appendChild(link); return link; } Dex.getCached = function(cacheID){ return cachedSelections[cacheID]; } Dex.clearCache = function(cacheID){ delete cachedSelections[cacheID]; } Dex.tag = function(tag){ /* Use Tag() to select nodes using the getElementsByTagName */ var nodes = document.getElementsByTagName(tag); return Dex(tag, nodes); } Dex.class = function(classname){ /* Use Tag() to select nodes using the getElementsByClassName */ var nodeCollection = document.getElementsByClassName(classname), nodes = Array.prototype.slice.call(nodeCollection); return Dex("." + classname, nodes); } Dex.iframe = function(selector){ var iframe = document.querySelectorAll(selector)[0]; return Dex.node(iframe.contentDocument || iframe.contentWindow.document); } Dex.id = function(id){ /* Use Tag() to select nodes using the getElementById */ var nodes = [document.getElementById(id)]; return Dex("#" + id, nodes); } Dex.node = function(node){ /* Use Node to create a Dex object with a DOM node directly */ return Dex("node", [node]); } Dex.collection = function(nodeCollection){ /* Use Node to create a Dex object with an HTML Node Collection directly */ var nodes = []; for(n = 0; n < nodeCollection.length; n++){ nodes.push(nodeCollection[n]); } return Dex("node", nodes) } if(exposeAs){ window[exposeAs] = Dex; } })("DexV10"); </script> <style> .add-colour { background: red; } </style> <section> <table class="single-class"> <tbody> <tr> <td> <div class="app-container"> <table class="change-attr"> <tbody> <tr> <td> <div class="app-window"> App window <table> <tbody> <tr> <td class="change-attr"> <div class="app-menu"> app menu <div> <div> <ul class="first-ul"> <li> <span class="title">This is a list item in an unordered list</span> </li> <li> <button class="click-me-ul">ul .click-me</button> <button class="and-me">ul .and-me</button> </li> </ul> <ul class="second-ul"> <li> <span class="title">This is a list item in an unordered list</span> </li> <li> <button class="click-me-ul">ul .click-me</button> <button class="and-me">ul .and-me</button> </li> </ul> <ol class="first-ol"> <li class="list-item" id="list-id"> <span class="title">This is a list item in an ordered list</span> </li> <li class="list-item"> <button class="click-me-ol">ol .click-me</button> <button class="and-me">ol .and-me</button> </li> </ol> </div> <span id="output">This is the output area</span> </div> </div> </td> </tr> </tbody> </table> </div> </td> </tr> </tbody> </table> </div> </td> </tr> </tbody> </table> </section>
Tests:
DexV9
// Setup listeners DexV9("ol").onChildAttribute("li", function(key, value){ // handler }); // Trigger listeners by affecting DOM DexV9("ol li").toggleAttribute("data-attr", ["on", "off"]);
DexV10 by TAG
// Setup listeners DexV10("ol").onChildAttribute("li", function(key, value){ // handler }); // Trigger listeners by affecting DOM DexV10("ol li").toggleAttribute("data-attr", ["on", "off"]);
DexV10 by CLASS
// Setup listeners DexV10("ol").onChildAttribute("li.list-item", function(key, value){ // handler }); // Trigger listeners by affecting DOM DexV10("ol li.list-item").toggleAttribute("data-attr", ["on", "off"]);
DexV10 by ID
// Setup listeners DexV10("ol").onChildAttribute("#list-id", function(key, value){ // handler }); // Trigger listeners by affecting DOM DexV10("#list-id").toggleAttribute("data-attr", ["on", "off"]);
Rendered benchmark preparation results:
Suite status:
<idle, ready to run>
Run tests (4)
Previous results
Fork
Test case name
Result
DexV9
DexV10 by TAG
DexV10 by CLASS
DexV10 by ID
Fastest:
N/A
Slowest:
N/A
Latest run results:
No previous run results
This benchmark does not have any results yet. Be the first one
to run it!
Autogenerated LLM Summary
(model
llama3.2:3b
, generated one year ago):
The test cases appear to be benchmarking the performance of different versions of the `DexV9` and `DexV10` libraries, specifically in relation to attribute listeners and DOM manipulation. The "Test Name" column suggests that the tests are comparing the performance of three different scenarios: * `DexV9`: With a `li` element as the child node. * `DexV10 by TAG`: With a `list-item` class on the `li` element. * `DexV10 by CLASS`: With an `#list-id` ID on the parent element. * `DexV10 by ID`: With an `#list-id` ID on the child element. The "Benchmark Definition" column provides more details about each test, including the setup and trigger events for the attribute listeners. Based on the latest benchmark result, it appears that: * `DexV9` is performing well with a high execution rate of 1568.3697509765625 executions per second. * `DexV10 by TAG` has a slightly lower execution rate of 1815.1243896484375 executions per second. * `DexV10 by CLASS` and `DexV10 by ID` have the lowest execution rates, at 1941.572265625 and 5155.9296875 executions per second, respectively. Overall, it seems that `DexV9` is performing relatively well across all test cases, but there may be some nuances depending on the specific use case and requirements.
Related benchmarks:
Dex vs jQuery event delegation
Test Tag
DEX vs JQUERY ::: Attribute manipulation
DEX vs JQUERY ::: Event Delegation
Comments
Confirm delete:
Do you really want to delete benchmark?