// Developed by Robert Nyman, code/licensing: http://code.google.com/p/domassistant/, documentation: http://www.robertnyman.com/domassistant var DOMAssistant = function () { var methodsToAdd = []; var baseMethodsToAdd = [ "elmsByClass", "elmsByAttribute", "elmsByTag", "each", "end", "setPrevious" ]; var HTMLArray = function (prevSet) { // Constructor }; var HTMLArrayBaseMethods = { elmsByClass : function (className, tag) { var elmsWithClass = new HTMLArray(); elmsWithClass.setPrevious(this); var elms; for (var i=0, il=this.length; i\+#\.\[\s\:]/.test(arg)) { elm = DOMAssistant.cssSelection(arg); } else { elm = (arguments.length > 1)? new HTMLArray() : null; var current; for (var u=0, ul=arguments.length; u 1) { elm.push(current); } else { elm = current; } } } DOMAssistant.addMethods(elm); } return elm; }, cssSelection : function (cssRule) { if (document.evaluate && !isOpera) { DOMAssistant.cssSelection = function (cssRule) { var cssRules = cssRule.replace(/\s*(,)\s*/, "$1").split(","); var elm = new HTMLArray(); var cssSelectors, xPathExpression, cssSelector, splitRule, nextTag, followingElm; for (var i=0, il=cssRules.length; i|\+|~)?/.exec(cssSelectors[j]); splitRule = { tag : (!cssSelector[1] || cssSelector[2] === "*")? "*" : cssSelector[1], id : (cssSelector[2] !== "*")? cssSelector[2] : null, allClasses : cssSelector[3], allAttr : cssSelector[5], pseudoClass : cssSelector[10], pseudoValue : cssSelector[12], tagRelation : cssSelector[19] }; if (splitRule.tagRelation) { switch (splitRule.tagRelation) { case ">": xPathExpression += "/child::"; break; case "+": xPathExpression += "/following-sibling::*[1]/self::"; break; case "~": xPathExpression += "/following-sibling::"; break; } } else { xPathExpression += (j > 0 && /(>|\+|~)/.test(cssSelectors[j-1]))? splitRule.tag : ("//" + splitRule.tag); } if (splitRule.id) { xPathExpression += "[@id = '" + splitRule.id.replace(/^#/, "") + "']"; } if (splitRule.allClasses) { xPathExpression += splitRule.allClasses.replace(/\.([\w\-_]+)/g, "[contains(concat(' ', @class, ' '), ' $1 ')]"); } if (splitRule.allAttr) { xPathExpression += splitRule.allAttr.replace(/(\w+)(\^|\$|\*)?=?([\w\-_]+)?/g, function (match, p1, p2, p3, p4) { var regExpReturn = match; switch (p2) { case "^": regExpReturn = "starts-with(@" + p1 + ", '" + p3 + "')"; break; case "$": regExpReturn = "substring(@" + p1 + ", (string-length(@" + p1 + ") - " + (p3.length - 1) + "), 6) = '" + p3 + "'"; break; case "*": regExpReturn = "contains(concat(' ', @" + p1 + ", ' '), '" + p3 + "')"; break; default : regExpReturn = "@" + p1 + ((p3)? "='" + p3 + "'" : ""); } return regExpReturn; }); } if (splitRule.pseudoClass) { var pseudoValue = splitRule.pseudoValue; switch (splitRule.pseudoClass.replace(/^:/, "")) { case "first-child": xPathExpression += "[1 and not(preceding-sibling::*)]"; break; case "first-of-type": xPathExpression += "[1]"; break; case "last-child": xPathExpression += "[last() and not(following-sibling::*)]"; break; case "last-of-type": xPathExpression += "[last()]"; break; case "only-child": xPathExpression += "[1 and not(preceding-sibling::*) and not(following-sibling::*)]"; break; case "only-of-type": xPathExpression += "[count(preceding-sibling::" + splitRule.tag + ") = 0 and position() = last()]"; break; case "nth-of-type": xPathExpression += "[" + pseudoValue + "]"; break; case "nth-last-of-type": xPathExpression += "[last() - " + pseudoValue + "]"; break; case "empty": xPathExpression += "[count(child::*) = 0 and string-length(text()) = 0]"; break; case "enabled": xPathExpression += "[not(@disabled)]"; break; case "disabled": xPathExpression += "[@disabled]"; break; case "checked": xPathExpression += "[@checked='checked']"; // Doesn't work in Opera 9.24 break; case "nth-child": var pseudoSelection = "/child::*[position()"; if (/^\d+$/.test(pseudoValue)) { pseudoSelection += " = " + pseudoValue; } else if (/^odd|even$/.test(pseudoValue)) { pseudoSelection += " mod 2 = " + ((pseudoValue === "odd")? 1 : 0); } else{ var pseudoSelector = /^(\d+)n((\+|\-)(\d+))?$/.exec(pseudoValue); var nthSelector = parseInt(pseudoSelector[1], 10); var nOperatorVal = 0; if (pseudoSelector[3] && pseudoSelector[4]) { nOperatorVal = parseInt((pseudoSelector[3] + pseudoSelector[4]), 10); if (nOperatorVal < 0) { nOperatorVal = nthSelector + nOperatorVal; } pseudoSelection += " = " + nOperatorVal + " or "; } if (nthSelector < nOperatorVal) { var nOperatorDiff = ((nOperatorVal - nthSelector) % 2 === 0)? 0 : 1; pseudoSelection += ((pseudoSelector[3])? " position()" : "") + " mod " + nthSelector + " = " + nOperatorDiff + " and position() > " + nOperatorVal; } else if (nOperatorVal === nthSelector) { pseudoSelection += ((pseudoSelector[3])? " position()" : "") + " mod " + nthSelector + " = 0"; } else { pseudoSelection += ((pseudoSelector[3])? " position()" : "") + " mod " + nthSelector + " = " + nOperatorVal; } } pseudoSelection += "]"; xPathExpression += pseudoSelection; break; case "not": pseudoValue = pseudoValue.replace(/^\[#([\w\-\_]+)\]$/, "[id=$1]"); var notSelector = pseudoValue.replace(/^(\w+)/, "self::$1"); notSelector = notSelector.replace(/\.([\w\-_]+)/g, "contains(concat(' ', @class, ' '), ' $1 ')"); notSelector = notSelector.replace(/\[(\w+)(\^|\$|\*)?=?([\w\-_]+)?\]/g, function (match, p1, p2, p3, p4) { var regExpReturn = match; switch (p2) { case "^": regExpReturn = "starts-with(@" + p1 + ", '" + p3 + "')"; break; case "$": regExpReturn = "substring(@" + p1 + ", (string-length(@" + p1 + ") - " + (p3.length - 1) + "), 6) = '" + p3 + "'"; break; case "*": regExpReturn = "contains(concat(' ', @" + p1 + ", ' '), '" + p3 + "')"; break; default : regExpReturn = "@" + p1 + ((p3)? "='" + p3 + "'" : ""); } return regExpReturn; }); xPathExpression += "[not(" + notSelector + ")]"; break; } } } var xPathNodes = document.evaluate(xPathExpression, document, null, 0, null); var node = xPathNodes.iterateNext(); while(node) { elm.push(node); node = xPathNodes.iterateNext(); } } return elm; }; } else { DOMAssistant.cssSelection = function (cssRule) { var cssRules = cssRule.replace(/\s*(,)\s*/, "$1").split(","); var elm = new HTMLArray(); var prevElm = new HTMLArray(); var matchingElms = new HTMLArray(); var cssSelectors, childOrSiblingRef, nextTag, nextRegExp, refSeparator, refPrevElm, nextSib, refPrevElmFound; function addToMatchingElms (item) { var exists = false; for (var b=0, bl=matchingElms.length; b=0; c--) { matchingElms[c] = null; } matchingElms = new HTMLArray(); } function emptyPrevElm () { for (var c=(prevElm.length-1); c>=0; c--) { prevElm[c] = null; } prevElm = new HTMLArray(); } function emptyPrevElmAndAddMatching () { if (prevElm !== matchingElms) { emptyPrevElm(); for (var d=0, dl=matchingElms.length; d|\+|~)$/.exec(rule); if (childOrSiblingRef) { nextTag = /^\w+/.exec(cssSelectors[i+1]); if (nextTag) { nextRegExp = new RegExp("(^|\\s)" + nextTag + "(\\s|$)", "i"); refSeparator = childOrSiblingRef[0]; for (var j=0, jl=prevElm.length, children; j/.test(refSeparator)) { children = refPrevElm.childNodes; refPrevElmFound = true; } else { children = refPrevElm.parentNode.childNodes; refPrevElmFound = false; } for (var k=0, kl=children.length, refChild; k 0 && /(>|\+|~)/.test(cssSelectors[i - 1])) { emptyMatchingElms(); matchingElms = prevElm; } else if (splitRule.tag && !splitRule.id) { emptyMatchingElms(); matchingElms = prevElm.elmsByTag(splitRule.tag); } if (splitRule.id) { var idElm = DOMAssistant.$(splitRule.id.replace(/^#/, "")); emptyMatchingElms(); if (idElm) { addToMatchingElms(idElm); } } if (splitRule.allClasses) { splitRule.allClasses = splitRule.allClasses.replace(/^\./, "").split("."); var classTag = (matchingElms.length > 0)? matchingElms : null; for (var n=0, nl=splitRule.allClasses.length, matchingClassElms; n 0)? matchingElms : null; for (var p=0, pl=splitRule.allAttr.length, matchingAttributeElms, attributeMatch, attribute, attrVal, tag, substrMatchSelector; p 0) { if (firstLastOnly) { if ((/first-(child|of-type)/.test(pseudoClass) && previous === childNodes[0]) || (/last-(child|of-type)/.test(pseudoClass) && previous === childNodes[childNodes.length - 1]) || (/only-(child|of-type)/.test(pseudoClass) && childNodes.length === 1)) { var isRightElm = true; if (/(first|last|only)-child/.test(pseudoClass)) { var childNode = (/first/.test(pseudoClass))? childNodes[0] : childNodes[childNodes.length - 1]; var sibling; if (/first/.test(pseudoClass)) { sibling = childNode.previousSibling; while (sibling) { if (sibling.nodeType === 1) { isRightElm = false; break; } sibling = sibling.previousSibling; } } else if (/last/.test(pseudoClass)) { sibling = childNode.nextSibling; while (sibling) { if (sibling.nodeType === 1) { isRightElm = false; break; } sibling = sibling.nextSibling; } } else { sibling = childNode.previousSibling; while (sibling) { if (sibling.nodeType === 1) { isRightElm = false; break; } sibling = sibling.previousSibling; } if (isRightElm) { sibling = childNode.nextSibling; while (sibling) { if (sibling.nodeType === 1) { isRightElm = false; break; } sibling = sibling.nextSibling; } } } } if (isRightElm) { addToMatchingElms(previous); } } continue; } if (nthOfType) { nthPos = (/last/i.test(pseudoClass))? ((childNodes.length-1) - pseudoValue) : (pseudoValue - 1); if (childNodes[nthPos]) { addToMatchingElms(childNodes[nthPos]); } } if (/nth-child/.test(pseudoClass)) { var pseudoSelector = /^(odd|even)|(\d+)n((\+|\-)(\d+))?$/.exec(pseudoValue); if (/^\d+$/.test(pseudoValue)) { addToMatchingElms(childNodes[pseudoValue-1]); } else if (pseudoSelector) { var iteratorStart = (pseudoSelector[1] === "even")? 1 : 0; var iteratorAdd = 2; var nRepeat = parseInt(pseudoSelector[2], 10); if (nRepeat > 0) { iteratorAdd = nRepeat; var nOperatorVal = parseInt((pseudoSelector[4] + pseudoSelector[5]), 10); if (nOperatorVal !== 0) { iteratorStart = nOperatorVal - 1; } } for (var u=iteratorStart, ul=childNodes.length; u 0) { if (!attributeRegExp || typeof attributeRegExp === "undefined" || (attributeRegExp && attributeRegExp.test(currentAttr))) { returnElms.push(current); } } } return returnElms; }; } return DOMAssistant.elmsByAttribute.call(this, attr, attrVal, tag, substrMatchSelector); }, elmsByTag : function (tag) { if (document.evaluate && !isOpera) { DOMAssistant.elmsByTag = function (tag) { var returnElms = new HTMLArray(); var xPathNodes = document.evaluate(".//" + ((typeof tag === "string")? tag : "*"), this, null, 0, null); var node = xPathNodes.iterateNext(); while(node) { returnElms.push(node); node = xPathNodes.iterateNext(); } return returnElms; }; } else { DOMAssistant.elmsByTag = function (tag) { var returnElms = new HTMLArray(); var elmsWithTag = this.getElementsByTagName(tag); for (var i=0, il=elmsWithTag.length; i 0)? " " : "") + className; } return this; }, removeClass : function (className) { var classToRemove = new RegExp(("(^|\\s)" + className + "(\\s|$)"), "i"); this.className = this.className.replace(classToRemove, function (match) { var retVal = ""; if (new RegExp("^\\s+.*\\s+$").test(match)) { retVal = match.replace(/(\s+).+/, "$1"); } return retVal; }).replace(/^\s+|\s+$/g, ""); return this; }, replaceClass : function (className, newClass) { var classToRemove = new RegExp(("(^|\\s)" + className + "(\\s|$)"), "i"); this.className = this.className.replace(classToRemove, function (match, p1, p2) { var retVal = p1 + newClass + p2; if (new RegExp("^\\s+.*\\s+$").test(match)) { retVal = match.replace(/(\s+).+/, "$1"); } return retVal; }).replace(/^\s+|\s+$/g, ""); return this; }, hasClass : function (className) { return new RegExp(("(^|\\s)" + className + "(\\s|$)"), "i").test(this.className); }, getStyle : function (cssRule) { var cssVal = ""; if (document.defaultView && document.defaultView.getComputedStyle) { cssVal = document.defaultView.getComputedStyle(this, "").getPropertyValue(cssRule); } else if (this.currentStyle) { cssVal = cssRule.replace(/\-(\w)/g, function (match, p1) { return p1.toUpperCase(); }); cssVal = this.currentStyle[cssVal]; } return cssVal; } }; }(); DOMAssistant.CSS.init(); DOMAssistant.Content = function () { var baseMethodsToAdd = [ "prev", "next", "create", "setAttributes", "addContent", "replaceContent", "remove" ]; var createHTMLArray = DOMAssistant.createHTMLArray; var HTMLArrayContentMethods = { prev : function () { var previousElms = createHTMLArray(); previousElms.setPrevious(this); var elm; for (var i=0, il=this.length; i=0; i--) { child = this.childNodes[i]; attr = child.attributes; if (attr) { for (var j=0, jl=attr.length; j<\/script>"); document.getElementById("ieScriptLoad").onreadystatechange = function() { if (this.readyState === "complete") { DOMHasLoaded(); } }; } /*@end @*/ /* Mozilla/Opera 9 */ if (document.addEventListener) { document.addEventListener("DOMContentLoaded", DOMHasLoaded, false); } /* Safari */ if (navigator.userAgent.search(/WebKit/i) !== -1) { DOMLoadTimer = setInterval(function () { if (document.readyState.search(/loaded|complete/i) !== -1) { var loaded = new DOMHasLoaded(); } }, 10); } /* Other web browsers */ window.onload = DOMHasLoaded; return { DOMReady : function () { for (var i=0, il=arguments.length, func, callFunc; i