Toggle navigation
MeasureThat.net
Create a benchmark
Tools
Feedback
FAQ
Register
Log In
DEX vs JQUERY ::: Matched element manipulation
(version: 1)
Comparing performance of:
Dex ::: first() vs jQuery ::: first()
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; } }; // CONSTANTS var UNDEFINED = "undefined"; // HIDDEN VARIABLES var cachedSelections = {}, delegatedEventListeners = {}, mutationObservers = {}, DOMMutationCallback = function(mutations, selector, parentNodes){ var n, x, y, mutationRecord, addedNode, removedNode, modifiedNodeAttribute, callbacks, modifiedSelector, _target, executeCallbacks = function(queue, node, arg1, arg2){ var n = 0; while(queue[n]){ // Call callback function queue[n].callback.call(node, arg1, arg2); if(!queue[n].persistant){ queue.splice(n, 1); } n++; } }, executeAttributecallbacks = function(queue, node, attrKey, attrValue){ y = 0; while(queue[y]){ // Call callback function if(queue[y].attrKey == attrKey){ queue[y].callback.call(node, attrKey, attrValue); if(!queue[y].persistant){ queue.splice(y, 1); } } y++; } }; // 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].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){ modifiedSelector = callbacks[_target].matchType.modifiedSelector; // See if addedNode matches the _target of the callback switch(callbacks[_target].matchType.type){ case "tag": if(addedNode.tagName.toUpperCase() == modifiedSelector){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, addedNode); } break; case "id": if(addedNode.id == modifiedSelector){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, addedNode); } break; case "classname": if(addedNode.classList.contains(modifiedSelector)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, addedNode, mutationRecord.addedNodes); } break; case "complex": if(addedNode.matches(modifiedSelector)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, addedNode); } break; } } } } } } if(mutationRecord.removedNodes.length > 0){ callbacks = mutationObservers[selector].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){ modifiedSelector = callbacks[_target].matchType.modifiedSelector; // See if removedNode matches the _target of the callback switch(callbacks[_target].matchType.type){ case "tag": if(removedNode.tagName.toUpperCase() == modifiedSelector){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, removedNode); } break; case "id": if(removedNode.id == modifiedSelector){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, removedNode); } break; case "classname": if(removedNode.classList.contains(modifiedSelector)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, removedNode); } break; case "complex": if(removedNode.matches(modifiedSelector)){ // Loop through all callbacks executeCallbacks(callbacks[_target].queue, removedNode); } break; } } } } } } if(mutationRecord.attributeName){ callbacks = mutationObservers[selector].callbacks.onAttribute; if(callbacks){ // Loop through modified attributes modifiedNodeAttribute = mutationRecord.target; // Loop through callbacks for(_target in callbacks){ modifiedSelector = callbacks[_target].matchType.modifiedSelector; // See if modifiedNodeAttribute matches the _target of the callback switch(callbacks[_target].matchType.type){ case "tag": if(modifiedNodeAttribute.tagName.toUpperCase() == modifiedSelector){ // Loop through all callbacks if(mutationRecord.target.attributes[mutationRecord.attributeName]){ // Its a live list, so check it hasnt been removed executeAttributecallbacks(callbacks[_target].queue, modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } } break; case "id": if(modifiedNodeAttribute.id == modifiedSelector){ // Loop through all callbacks if(mutationRecord.target.attributes[mutationRecord.attributeName]){ // Its a live list, so check it hasnt been removed executeAttributecallbacks(callbacks[_target].queue, modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } } break; case "classname": if(modifiedNodeAttribute.classList.contains(modifiedSelector)){ // Loop through all callbacks if(mutationRecord.target.attributes[mutationRecord.attributeName]){ // Its a live list, so check it hasnt been removed executeAttributecallbacks(callbacks[_target].queue, modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } } break; case "complex": if(modifiedNodeAttribute.matches(modifiedSelector)){ // Loop through all callbacks if(mutationRecord.target.attributes[mutationRecord.attributeName]){ // Its a live list, so check it hasnt been removed executeAttributecallbacks(callbacks[_target].queue, modifiedNodeAttribute, mutationRecord.attributeName, mutationRecord.target.attributes[mutationRecord.attributeName].value); } } break; } } } } } }, createEventListener = function(dexObject, eventType, selector, target, callback, persistant){ // Check that the event type exists in queue if(!delegatedEventListeners[eventType]){ delegatedEventListeners[eventType] = {}; } // Check that this selector is registered if(!delegatedEventListeners[eventType][selector]){ delegatedEventListeners[eventType][selector] = {}; // Setup listener attachEventListeners(eventType, dexObject); } // Check that this target is registered if(!delegatedEventListeners[eventType][selector][target]){ delegatedEventListeners[eventType][selector][target] = []; } // register delegated event listener delegatedEventListeners[eventType][selector][target].push({ callback: callback, persistant: persistant }); }, 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 && 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){ eventHandlers[handlerSelector].splice(handlerIndex, 1); } 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, persistant: true }); return this; }, onceOpen: function(target, callback){ this.onMutation("onOpen", target, callback, { children: false, persistant: false }); return this; }, onClose: function(target, callback){ this.onMutation("onClose", target, callback, { children: false, persistant: true }); return this; }, onceClose: function(target, callback){ this.onMutation("onClose", target, callback, { children: false, persistant: false }); return this; }, onAttribute: function(target, attrKey, callback){ this.onMutation("onAttribute", target, callback, { attrKey: attrKey, persistant: true }); return this; }, onceAttribute: function(target, attrKey, callback){ this.onMutation("onAttribute", target, callback, { attrKey: attrKey, persistant: false }); 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 = { type: "classname", modifiedSelector: target.slice(1) } } else if(target[0] == "#"){ result = { type: "id", modifiedSelector: target.slice(1) } } else if(target[0] == "["){ result = { type: "complex", modifiedSelector: target } } else { result = { type: "tag", modifiedSelector: target.toUpperCase() } } return result; }(target), n, parameters = parameters || {}; // See if we need to attach a mutation observer if(!mutationObservers[this.selector]){ mutationObservers[this.selector] = { observer: new MutationObserver(function(mutations){ DOMMutationCallback(mutations, selector, parentNodes); }), callbacks: {} } // Attach observer to all matches nodes for(n = 0; n < this.nodes.length; n++){ mutationObservers[this.selector].observer.observe(this.nodes[n], { attributes: true, childList: true, characterData: false, subtree: true }); } } // See if there are already callbacks for mutationType if(!mutationObservers[this.selector].callbacks[mutationType]){ mutationObservers[this.selector].callbacks[mutationType] = {} } // See if there are already calbacks for this target if(!mutationObservers[this.selector].callbacks[mutationType][target]){ // mutationObservers[this.selector][childtree].callbacks[mutationType][target] = [] mutationObservers[this.selector].callbacks[mutationType][target] = { matchType: matchType, queue: [] } } // Save callback mutationObservers[this.selector].callbacks[mutationType][target].queue.push({ callback: callback, attrKey: parameters.attrKey, persistant: parameters.persistant }); }, onClick: function(target, callback){ createEventListener(this, "click", this.selector, target, callback, true); return this; }, oneClick: function(target, callback){ createEventListener(this, "click", this.selector, target, callback, false); return this; }, onMouseUp: function(target, callback){ createEventListener(this, "mouseup", this.selector, target, callback, true); return this; }, oneMouseUp: function(target, callback){ createEventListener(this, "mouseup", this.selector, target, callback, false); return this; }, onMouseDown: function(target, callback){ createEventListener(this, "mousedown", this.selector, target, callback, true); return this; }, oneMouseDown: function(target, callback){ createEventListener(this, "mousedown", this.selector, target, callback, false); return this; }, onMouseEnter: function(target, callback){ createEventListener(this, "mouseenter", this.selector, target, callback, true); return this; }, oneMouseEnter: function(target, callback){ createEventListener(this, "mouseenter", this.selector, target, callback, false); return this; }, onMouseLeave: function(target, callback){ createEventListener(this, "mouseleave", this.selector, target, callback, true); return this; }, oneMouseLeave: function(target, callback){ createEventListener(this, "mouseleave", this.selector, target, callback, false); return this; }, onMouseOver: function(target, callback){ createEventListener(this, "mouseover", this.selector, target, callback, true); return this; }, oneMouseOver: function(target, callback){ createEventListener(this, "mouseover", this.selector, target, callback, false); return this; }, onMouseOut: function(target, callback){ createEventListener(this, "mouseout", this.selector, target, callback, true); return this; }, oneMouseOut: function(target, callback){ createEventListener(this, "mouseout", this.selector, target, callback, false); 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) } Dex.dump = function(object){ console.log(mutationObservers); }; if(exposeAs){ window[exposeAs] = Dex; } })("DexV2"); </script> <style> .add-colour { background: red; } .add-more-colour { background: red; } </style> <section> <table> <tbody> <tr> <td> <div class="app-container"> <table> <tbody> <tr> <td> <div class="app-window"> App window <table> <tbody> <tr> <td> <div class="app-menu" id="the-menu"> <h1 class="h1" id="h1" data-attr="hello there">Button</h1> app menu <div> <div> <ul> <li class="add-more-colour"> <span class="title">This is a list item in an unordered list</span> </li> <li class="add-more-colour"> <button class="click-me-ul">ul .click-me</button> <button class="and-me">ul .and-me</button> </li> </ul> <ol> <li class="add-more-colour"> <span class="title">This is a list item in an ordered list</span> </li> <li class="add-more-colour"> <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>
Script Preparation code:
var v1 = DexV2.tag("li"); var v2 = $("li");
Tests:
Dex ::: first()
v1.first();
jQuery ::: first()
v2.first();
Rendered benchmark preparation results:
Suite status:
<idle, ready to run>
Run tests (2)
Previous results
Fork
Test case name
Result
Dex ::: first()
jQuery ::: first()
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 code appears to be an HTML template with embedded JavaScript and data structures, likely for testing or benchmarking purposes. It defines several elements: * `ul`, `li`, and `ol` (unordered lists) * `div` elements with various classes and IDs * A table structure * Two test cases: "Dex ::: first()" and "jQuery ::: first()" * A latest benchmark result section To provide a meaningful answer, I'll need to make some assumptions about the context. Are you looking for help with: 1. Optimizing the HTML structure or JavaScript code? 2. Understanding the data structures or data format used in the template? 3. Writing a script or test that interacts with this HTML template? Please clarify your question, and I'll do my best to assist you!
Related benchmarks:
Dex vs jQuery event delegation
DEX vs JQUERY ::: Matched element manipulation
DEX vs JQUERY ::: Attribute manipulation 2
DEX vs JQUERY ::: Event Delegation
Comments
Confirm delete:
Do you really want to delete benchmark?