<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 = {},
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;
},
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;
},
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;
},
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 nodes = document.getElementsByClassName(classname);
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;
}
})("Dex");
</script>
<style>
.add-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">
app menu
<div>
<div>
<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>
<li>
<span class="title">This is a list item in an ordered list</span>
</li>
<li>
<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>
var copiedHTML = Dex(".app-menu ul .title").getHTML();
Dex.id("output").setHTML(copiedHTML);
var copiedHTML = $(".app-menu ul .title").html();
$("#output").html(copiedHTML);
var copiedHTML = Dex(".app-menu ul .title").getHTML();
Dex("#output").setHTML(copiedHTML);
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
Dex ID | |
jQuery | |
Dex All |
Test name | Executions per second |
---|---|
Dex ID | 7980.2 Ops/sec |
jQuery | 7361.3 Ops/sec |
Dex All | 7891.7 Ops/sec |
A complex HTML parsing benchmark!
After analyzing the provided HTML code and benchmark data, I'll attempt to provide an answer.
Benchmarking Results
The benchmark results show that the execution speed of the three test cases (Dex ID, jQuery, and Dex All) varies across different browsers. The latest result for Firefox 55 on a Mac OS X 10.12 system is as follows:
Comparison and Insights
Comparing the results, we can see that Dex ID is slightly faster than jQuery, while Dex All is slower. The performance difference between these two test cases might be due to the way they handle HTML parsing:
Dex.js
) for parsing and rendering HTML elements. The fact that it has the highest execution speed suggests that this implementation is efficient.Conclusion
Based on the provided benchmark results, the order of execution speed for these three test cases is:
The custom implementation of Dex ID appears to be the fastest, followed closely by jQuery. However, it's essential to note that these results are specific to this particular benchmark and might not generalize across all use cases or browsers.
If you'd like me to elaborate on any aspect of this analysis, feel free to ask!