App window
app menu
This is a list item in an unordered list
ul .click-me
ul .and-me
This is a list item in an ordered list
ol .click-me
ol .and-me
This is the output area
{"ScriptPreparationCode":"(function(exposeAs){\r\n var Dex = function(selector, nodes){\r\n\r\n // Return Dex object\r\n return new Dex.fn.init(selector, nodes);\r\n\r\n };\r\n\r\n Dex.fn = Dex.prototype = {\r\n init: function(selector, nodes){\r\n this.selector = selector;\r\n\r\n if(nodes){\r\n this.nodes = nodes;\r\n } else {\r\n this.nodes = document.querySelectorAll(selector);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n\r\n };\r\n\r\n var delegatedEventListeners = {},\r\n\t\t\tattachEventListeners = function(eventType, dexObject){\r\n\r\n\t\t\t\tvar n,\r\n\t\t\t\t\tselector = {\r\n\t\t\t\t\t\tstring: dexObject.selector\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\tfor(n = 0; n \u003C dexObject.nodes.length; n\u002B\u002B){\r\n\t\t\t\t\tselector.node = dexObject.nodes[n];\r\n\r\n\t\t\t\t\tselector.node.addEventListener(eventType, function(e){\r\n\r\n\t\t\t\t\t\tvar eventHandlers = delegatedEventListeners[eventType][selector.string];\r\n\r\n\t\t\t\t\t\tfor(handlerSelector in eventHandlers){\r\n\r\n\t\t\t\t\t\t\tclickedNode = e.target;\r\n\r\n\t\t\t\t\t\t\twhile(\tclickedNode !== document \u0026\u0026\r\n\t\t\t\t\t\t\t\t\tclickedNode !== selector.node) { // Stop looking when we hit the node that contains the event listener\r\n\r\n\t\t\t\t\t\t\t\tif (clickedNode.matches(handlerSelector)) {\r\n\r\n\t\t\t\t\t\t\t\t\tvar handlerIndex = 0;\r\n\r\n\t\t\t\t\t\t\t\t\twhile (eventHandlers[handlerSelector][handlerIndex]){\r\n\t\t\t\t\t\t\t\t\t\teventHandlers[handlerSelector][handlerIndex].callback.call(clickedNode, e);\r\n\r\n\t\t\t\t\t\t\t\t\t\tif(!eventHandlers[handlerSelector][handlerIndex].persistant){\r\n\t\t\t\t\t\t\t\t\t\t\tdelete eventHandlers[handlerSelector][handlerIndex];\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t\t\thandlerIndex\u002B\u002B;\r\n\t\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\tclickedNode = clickedNode.parentNode;\r\n\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t};\r\n\r\n // EXPOSED SELECTOR FUNCTIONS\r\n Dex.fn.init.prototype = {\r\n\r\n\t\t\t\tfirst: function(){\r\n\t\t\t\t\t/* Remove all nodes except first from node list */\r\n\r\n\t\t\t\t\tthis.nodes = [this.nodes[0]];\r\n\r\n\t\t\t\t\treturn this;\r\n\t\t\t\t},\r\n\r\n\t\t\t\tindex: function(index){\r\n\t\t\t\t\t/* Remove all nodes except requested index */\r\n\r\n\t\t\t\t\tthis.nodes = [this.nodes[index]];\r\n\r\n\t\t\t\t\treturn this;\r\n\t\t\t\t},\r\n\r\n\t\t\t\tgetNode: function(index){\r\n\t\t\t\t\t/* Return DOM node */\r\n\r\n\t\t\t\t\treturn this.nodes[index];\r\n\t\t\t\t},\r\n\r\n\t\t exists: function(){\r\n\t\t\t\t\t/* See if the node list contains at least one node */\r\n\r\n\t\t return this.nodes[0] != null;\r\n\t\t },\r\n\r\n\t\t append: function(node){\r\n\r\n\t\t var n;\r\n\r\n\t\t for(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\t\t this.nodes[n].appendChild(node);\r\n\t\t }\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\t\t },\r\n\r\n\t\t remove: function(){\r\n\r\n\t\t var n;\r\n\r\n\t\t for(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\t\t this.nodes[n];\r\n\r\n\t\t if (this.nodes[n].parentNode) {\r\n\t\t this.nodes[n].parentNode.removeChild(this.nodes[n]);\r\n\t\t }\r\n\t\t }\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\t\t },\r\n\r\n\t\t parent: function(){\r\n\r\n\t\t this.nodes = [this.nodes[0].parentNode];\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\t\t },\r\n\r\n\t\t closest: function(matchSelector){\r\n\r\n\t\t var closest = [];\r\n\r\n\t\t node = this.nodes[0];\r\n\r\n\t\t // Go through parents\r\n\t\t while(node \u0026\u0026 node !== document) {\r\n\t\t if (node.matches(matchSelector)) {\r\n\r\n\t\t closest = [node];\r\n\t\t break;\r\n\r\n\t\t }\r\n\r\n\t\t node = node.parentNode;\r\n\r\n\t\t }\r\n\r\n\t\t this.nodes = closest;\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\t\t },\r\n\r\n\t\t\t\tfilter: function(selector){\r\n\t\t\t\t\t/* Filter then current node list - note: only filters on the first node in list */\r\n\r\n\t\t\t\t\tthis.nodes = this.nodes[0].querySelectorAll(selector);\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t // DOM modification\r\n\t\t setHTML: function(value){\r\n\t\t\t\t\t/* Set innerHTML of all nodes in nodelist */\r\n\r\n\t\t var n;\r\n\r\n\t\t for(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\t\t this.nodes[n].innerHTML = value;\r\n\t\t }\r\n\r\n\t\t\t\t\treturn this;\r\n\t\t },\r\n\r\n\t\t getHTML: function(value){\r\n\t\t\t\t\t/* Get innerHTML of all first node in nodelist */\r\n\r\n\t\t return this.nodes[0].innerHTML;\r\n\t\t },\r\n\r\n\t\t\t\tcss: function(styles){\r\n\t\t\t\t\t/* Set CSS of all nodes in nodelist */\r\n\r\n\t\t\t\t\tvar style,\r\n\t\t\t\t\t\tn;\r\n\r\n\t\t\t\t\tfor(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\r\n\t\t\t\t\t\tfor(style in styles){\r\n\r\n\t\t\t\t\t\t\tthis.nodes[n].style[style] = styles[style];\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetAttribute: function(key, value){\r\n\t\t\t\t\t/* Set attribute of all nodes in nodelist */\r\n\r\n\t\t var n;\r\n\r\n\t\t for(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\t\t this.nodes[n].setAttribute(key, value);\r\n\t\t }\r\n\r\n\t\t\t\t\treturn this;\r\n\t\t },\r\n\r\n\t\t getAttribute: function(key){\r\n\t\t\t\t\t/* Get attribute of first node in nodelist */\r\n\r\n\t\t return this.nodes[0].getAttribute(key);\r\n\t\t },\r\n\r\n\t\t toggleAttribute: function(key, value){\r\n\t\t\t\t\t/* Get attribute of first node in nodelist */\r\n\r\n\t\t var n,\r\n\t\t attrValue;\r\n\r\n\t\t for(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\t\t attrValue = this.nodes[n].getAttribute(key);\r\n\r\n\t\t if(attrValue == value[0]){\r\n\t\t this.nodes[n].setAttribute(key, value[1]);\r\n\t\t } else {\r\n\t\t this.nodes[n].setAttribute(key, value[0]);\r\n\t\t }\r\n\t\t }\r\n\r\n\t\t\t\t\treturn this;\r\n\t\t },\r\n\r\n\t\t\t\tcache: function(cacheID){\r\n\t\t\t\t\t/* Cache node list with cacheID as ID */\r\n\r\n\t\t\t\t\tcachedSelections[cacheID] = this;\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// Classes\r\n\t\t addClass: function(classname){\r\n\t\t\t\t\t/* Add class to all nodes in nodelist */\r\n\r\n\t\t var n;\r\n\r\n\t\t for(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\t\t this.nodes[n].classList.add(classname);\r\n\t\t }\r\n\r\n\t\t\t\t\treturn this;\r\n\t\t },\r\n\r\n\t\t removeClass: function(classname){\r\n\t\t\t\t\t/* Remove class from all nodes in nodelist */\r\n\r\n\t\t var n;\r\n\r\n\t\t for(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\t\t this.nodes[n].classList.remove(classname);\r\n\t\t }\r\n\t\t\t\t\treturn this;\r\n\t\t },\r\n\r\n\t\t\t\thasClass: function(classname){\r\n\t\t\t\t\t/* Check whether first node in list contains a classname */\r\n\r\n\t\t\t\t\tvar result = false;\r\n\r\n\t\t\t\t\tif(this.nodes[0]){\r\n\t\t\t\t\t\tresult = this.nodes[0].classList.contains(classname);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn result;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\ttoggleClass: function(classname){\r\n\t\t\t\t\t/* Toggle classnames on all nodes in nodelist */\r\n\r\n\t\t\t\t\tvar n;\r\n\r\n\t\t for(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\t\t this.nodes[n].classList.toggle(classname);\r\n\t\t }\r\n\r\n\t\t\t\t\treturn this;\r\n\t\t\t\t},\r\n\r\n\t\t\t\treplaceClass: function(old_classname, new_classname){\r\n\t\t\t\t\t/* Replace old_classname with new_classname on all nodes in nodelist */\r\n\r\n\t\t\t\t\tvar n;\r\n\r\n\t\t for(n = 0; n \u003C this.nodes.length; n\u002B\u002B){\r\n\t\t this.nodes[n].classList.replace(old_classname, new_classname);\r\n\t\t }\r\n\r\n\t\t\t\t\treturn this;\r\n\t\t\t\t},\r\n\r\n\t\t trigger: function(eventType){\r\n\t\t\t\t\t/* Trigger eventType (click, mouseover, etc, ...) on all nodes in nodelist */\r\n\r\n\t\t if(this.nodes[0]){\r\n\t\t var clickEvent = document.createEvent(\u0022MouseEvents\u0022);\r\n\r\n\t\t clickEvent.initEvent(eventType, true, true);\r\n\t\t this.nodes[0].dispatchEvent(clickEvent);\r\n\t\t }\r\n\r\n\t\t\t\t\treturn this;\r\n\t\t },\r\n\r\n onClick: function(target, callback){\r\n\r\n // Check that the event type exists in queue\r\n if(!delegatedEventListeners[\u0022click\u0022]){\r\n delegatedEventListeners[\u0022click\u0022] = {};\r\n }\r\n\r\n // Check that this selector is registered\r\n if(!delegatedEventListeners[\u0022click\u0022][this.selector]){\r\n delegatedEventListeners[\u0022click\u0022][this.selector] = {};\r\n\r\n // Setup listener\r\n\r\n attachEventListeners(\u0022click\u0022, this);\r\n }\r\n\r\n // Check that this target is registered\r\n if(!delegatedEventListeners[\u0022click\u0022][this.selector][target]){\r\n delegatedEventListeners[\u0022click\u0022][this.selector][target] = [];\r\n }\r\n\r\n // register delegated event listener\r\n delegatedEventListeners[\u0022click\u0022][this.selector][target].push({\r\n callback: callback,\r\n persistant: true\r\n });\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n },\r\n\r\n\r\n }\r\n\r\n\t\t\tDex.appendCSS = function(url){\r\n\t\t var head = document.head,\r\n\t\t link = document.createElement(\u0027link\u0027);\r\n\r\n\t\t link.type = \u0022text/css\u0022;\r\n\t\t link.rel = \u0022stylesheet\u0022;\r\n\t\t link.href = url;\r\n\r\n\t\t head.appendChild(link);\r\n\r\n\t\t return link;\r\n\t\t }\r\n\r\n\t\t\tDex.getCached = function(cacheID){\r\n\t\t\t\treturn cachedSelections[cacheID];\r\n\t\t\t}\r\n\r\n\t\t\tDex.clearCache = function(cacheID){\r\n\t\t\t\tdelete cachedSelections[cacheID];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tDex.tag = function(tag){\r\n\t\t\t\t/* Use Tag() to select nodes using the getElementsByTagName */\r\n\r\n\t\t\t\tvar nodes = document.getElementsByTagName(tag);\r\n\r\n\t\t\t\treturn Dex(tag, nodes);\r\n\r\n\t\t\t}\r\n\r\n\t\t\tDex.class = function(classname){\r\n\t\t\t\t/* Use Tag() to select nodes using the getElementsByClassName */\r\n\r\n\t\t\t\tvar nodes = document.getElementsByClassName(classname);\r\n\r\n\t\t\t\treturn Dex(\u0022.\u0022 \u002B classname, nodes);\r\n\r\n\t\t\t}\r\n\r\n\t\t Dex.iframe = function(selector){\r\n\r\n\t\t var iframe = document.querySelectorAll(selector)[0];\r\n\r\n\t\t return Dex.node(iframe.contentDocument || iframe.contentWindow.document);\r\n\r\n\t\t }\r\n\r\n\t\t\tDex.id = function(id){\r\n\t\t\t\t/* Use Tag() to select nodes using the getElementById */\r\n\r\n\t\t\t\tvar nodes = [document.getElementById(id)];\r\n\r\n\t\t\t\treturn Dex(\u0022#\u0022 \u002B id, nodes);\r\n\r\n\t\t\t}\r\n\r\n\t\t\tDex.node = function(node){\r\n\t\t\t\t/* Use Node to create a Dex object with a DOM node directly */\r\n\r\n\t\t\t\treturn Dex(\u0022node\u0022, [node]);\r\n\r\n\t\t\t}\r\n\r\n\t\t\tDex.collection = function(nodeCollection){\r\n\t\t\t\t/* Use Node to create a Dex object with an HTML Node Collection directly */\r\n\r\n\t\t\t\tvar nodes = [];\r\n\r\n\t\t\t\tfor(n = 0; n \u003C nodeCollection.length; n\u002B\u002B){\r\n\t\t\t\t\tnodes.push(nodeCollection[n]);\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn Dex(\u0022node\u0022, nodes)\r\n\t\t\t}\r\n\r\n if(exposeAs){\r\n window[exposeAs] = Dex;\r\n }\r\n\r\n })(\u0022Dex\u0022);","TestCases":[{"Name":"Dex","Code":"Dex.class(\u0022app-container\u0022)\r\n .onClick(\u0022.app-menu\u0022, function(){\r\n // Handler\r\n })\r\n .onClick(\u0022.click-me-ul\u0022, function(){\r\n // Handler\r\n })\r\n .onClick(\u0022.and-me\u0022, function(){\r\n // Handler\r\n });\r\n\r\ndocument.getElementsByClassName(\u0022app-menu\u0022)[0].click();\r\ndocument.getElementsByClassName(\u0022click-me-ul\u0022)[0].click();\r\ndocument.getElementsByClassName(\u0022and-me\u0022)[0].click();\r\ndocument.getElementsByClassName(\u0022and-me\u0022)[1].click();","IsDeferred":false},{"Name":"jQuery","Code":"$(\u0022.app-container\u0022)\r\n .on(\u0022click\u0022, \u0022.app-menu\u0022, function(){\r\n // Handler\r\n })\r\n .on(\u0022click\u0022, \u0022.click-me-ul\u0022, function(){\r\n // Handler\r\n })\r\n .on(\u0022click\u0022, \u0022.and-me\u0022, function(){\r\n // Handler\r\n })\r\n\r\ndocument.getElementsByClassName(\u0022app-menu\u0022)[0].click();\r\ndocument.getElementsByClassName(\u0022click-me-ul\u0022)[0].click();\r\ndocument.getElementsByClassName(\u0022and-me\u0022)[0].click();\r\ndocument.getElementsByClassName(\u0022and-me\u0022)[1].click();","IsDeferred":false}]}