Socket
Socket
Sign inDemoInstall

jsdom

Package Overview
Dependencies
Maintainers
2
Versions
264
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsdom - npm Package Compare versions

Comparing version 0.2.15 to 0.2.16

5

lib/jsdom.js

@@ -51,2 +51,7 @@ var dom = exports.dom = require("./jsdom/level3/index").dom,

module.parent.filename;
options.url = options.url.replace(/\\/g, '/');
if (options.url[0] !== '/') {
options.url = '/' + options.url;
}
options.url = 'file://' + options.url;
}

@@ -53,0 +58,0 @@

0

lib/jsdom/browser/documentfeatures.js

@@ -0,0 +0,0 @@ exports.availableDocumentFeatures = [

@@ -0,0 +0,0 @@ var charByEntityName = {

4

lib/jsdom/browser/index.js

@@ -418,7 +418,7 @@ var http = require('http'),

dom.Document.prototype.__defineGetter__('outerHTML', function() {
return domToHtml(this);
return domToHtml(this, true);
});
dom.Element.prototype.__defineGetter__('outerHTML', function() {
return domToHtml(this);
return domToHtml(this, true);
});

@@ -425,0 +425,0 @@

@@ -737,3 +737,3 @@ /*

// Level2/core clean off empty nodes
if (child.value === "") {
if (child.nodeValue === "") {
this.removeChild(child);

@@ -752,3 +752,3 @@ i--;

// remove the child and decrement i
prevChild.appendData(child.value);
prevChild.appendData(child.nodeValue);

@@ -847,3 +847,3 @@ this.removeChild(child);

var name = arg.name;
var name = arg.name || arg.tagName;
var ret = this._nodes[name];

@@ -999,3 +999,2 @@ if (!ret) {

get name() { return this.nodeName;},
/* returns string */

@@ -1027,4 +1026,6 @@ getAttribute: function(/* string */ name) {

} else {
// We're an element.
self._ownerDocument.parentWindow.run(value);
// We're an element. Use awesome hacks to get the correct `this` context for the inline event handler.
self._ownerDocument.parentWindow.__tempContextForInlineEventHandler = self;
self._ownerDocument.parentWindow.run("(function () {" + value + "}).call(window.__tempContextForInlineEventHandler);");
delete self.ownerDocument.parentWindow.__tempContextForInlineEventHandler;
}

@@ -1410,3 +1411,3 @@ };

this._nodeValue = (value) ? value + "" : "";
this._nodeValue = value + "";
};

@@ -1607,4 +1608,2 @@ core.CharacterData.prototype = {

get attributes() { return null;},
get value() { return this._nodeValue;},
set value(value) { this.nodeValue = value;},

@@ -1611,0 +1610,0 @@ /* returns Text */

@@ -75,8 +75,3 @@ /* DOM Level2 Events implemented as described here:

events.HTMLEvent = function(eventType) {
events.Event.call(this, eventType);
};
events.HTMLEvent.prototype.__proto__ = events.Event.prototype;
events.UIEvent = function(eventType) {

@@ -405,3 +400,3 @@ events.Event.call(this, eventType);

case "MouseEvents": return new events.MouseEvent(eventType);
case "HTMLEvents": return new events.HTMLEvent(eventType);
case "HTMLEvents": return new events.Event(eventType);
}

@@ -408,0 +403,0 @@ return new events.Event(eventType);

@@ -143,3 +143,3 @@ var core = require("./core").dom.level2.core,

readFile: function(url, callback) {
fs.readFile(url.replace(/^file:\/\//, ""), 'utf8', callback);
fs.readFile(url.replace(/^file:\/\//, "").replace(/^\/([a-z]):\//i, '$1:/'), 'utf8', callback);
}

@@ -179,3 +179,3 @@ };

}
if (n.normalize) {
if (typeof n === 'object' && n.normalize) { // see GH-491
return n.normalize(s);

@@ -780,6 +780,6 @@ }

get text() {
return (this.hasAttribute('value')) ? this.getAttribute('value') : this.innerHTML;
return this.innerHTML;
},
get value() {
return (this.hasAttribute('value')) ? this.getAttribute('value') : this.innerHTML;
return (this.hasAttribute('value')) ? this.getAttribute('value') : this.innerHTML;
},

@@ -854,7 +854,11 @@ set value(val) {

get checked() {
return !!this.getAttribute('checked');
return !!this._attributes.getNamedItem('checked');
},
set checked(checked) {
this._initDefaultChecked();
this.setAttribute('checked', checked);
if (checked) {
this.setAttribute('checked', 'checked');
} else {
this.removeAttribute('checked');
}
},

@@ -1303,3 +1307,3 @@ get value() {

for (i; i<l; i++) {
ret.push(children.item(i).value);
ret.push(children.item(i).nodeValue);
}

@@ -1306,0 +1310,0 @@

@@ -0,0 +0,0 @@ exports.dom = {

@@ -0,0 +0,0 @@ exports.javascript = function(element, code, filename) {

@@ -5,2 +5,3 @@ var core = require("./core").dom.level2.core,

cssom = require("cssom"),
cssstyle = require("cssstyle"),
assert = require('assert');

@@ -32,3 +33,3 @@

core.CSSImportRule = cssom.CSSImportRule;
core.CSSStyleDeclaration = cssom.CSSStyleDeclaration;
core.CSSStyleDeclaration = cssstyle.CSSStyleDeclaration;

@@ -125,3 +126,3 @@ // Relavant specs

* @param {string} data
* @param {cssom.CSSStyleDeclaration} style
* @param {cssstyle.CSSStyleDeclaration} style
*/

@@ -185,3 +186,3 @@ function evaluateStyleAttribute(data) {

if (!style) {
style = this._cssStyleDeclaration = new cssom.CSSStyleDeclaration();
style = this._cssStyleDeclaration = new cssstyle.CSSStyleDeclaration();
if (!this.getAttributeNode('style')) {

@@ -188,0 +189,0 @@ this.setAttribute('style', '');

@@ -0,0 +0,0 @@ var events = require("../level2/events").dom.level2.events;

@@ -0,0 +0,0 @@ var core = require("./core").dom.level3.core,

module.exports.dom = {
level3 : {
core : require("./core").dom.level3.core,
xpath : require("./xpath").xpath,
xpath : require("./xpath"),
events : require("./events").dom.level3.events,

@@ -6,0 +6,0 @@ html : require("./html").dom.level3.html,

@@ -0,0 +0,0 @@ // w3c Load/Save functionality: http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/

/*!
* Sizzle CSS Selector Engine
* Copyright 2011, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
* More information: http://sizzlejs.com/
* Copyright 2012 jQuery Foundation and other contributors
* Released under the MIT license
* http://sizzlejs.com/
*/
// Patch for jsdom
module.exports = function(document){
module.exports = function( document ) {
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
expando = "sizcache" + (Math.random() + '').replace('.', ''),
done = 0,
toString = Object.prototype.toString,
hasDuplicate = false,
var dirruns,
cachedruns,
assertGetIdNotName,
Expr,
getText,
isXML,
contains,
compile,
sortOrder,
hasDuplicate,
baseHasDuplicate = true,
rBackslash = /\\/g,
rReturn = /\r\n/g,
rNonWord = /\W/;
strundefined = "undefined",
expando = ( "sizcache" + Math.random() ).replace( ".", "" ),
// Here we check if the JavaScript engine is using some sort of
// optimization where it does not always call our comparision
// function. If that is the case, discard the hasDuplicate value.
// Thus far that includes Google Chrome.
[0, 0].sort(function() {
baseHasDuplicate = false;
return 0;
});
// jsdom document = window.document,
docElem = document.documentElement,
done = 0,
slice = [].slice,
push = [].push,
var Sizzle = function( selector, context, results, seed ) {
results = results || [];
// PATCH for jsdom
// context = context || document;
// See: https://github.com/tmpvar/jsdom/issues/375
context = context || seed[0].ownerDocument;
var origContext = context;
// Augment a function for special use by Sizzle
markFunction = function( fn, value ) {
fn[ expando ] = value || true;
return fn;
},
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
return [];
}
createCache = function() {
var cache = {},
keys = [];
if ( !selector || typeof selector !== "string" ) {
return results;
}
return markFunction(function( key, value ) {
// Only keep the most recent entries
if ( keys.push( key ) > Expr.cacheLength ) {
delete cache[ keys.shift() ];
}
var m, set, checkSet, extra, ret, cur, pop, i,
prune = true,
contextXML = Sizzle.isXML( context ),
parts = [],
soFar = selector;
return (cache[ key ] = value);
}, cache );
},
// Reset the position of the chunker regexp (start from head)
do {
chunker.exec( "" );
m = chunker.exec( soFar );
classCache = createCache(),
tokenCache = createCache(),
compilerCache = createCache(),
if ( m ) {
soFar = m[3];
// Regex
parts.push( m[1] );
// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
whitespace = "[\\x20\\t\\r\\n\\f]",
// http://www.w3.org/TR/css3-syntax/#characters
characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",
if ( m[2] ) {
extra = m[3];
break;
}
}
} while ( m );
// Loosely modeled on CSS identifier characters
// An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)
// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
identifier = characterEncoding.replace( "w", "w#" ),
if ( parts.length > 1 && origPOS.exec( selector ) ) {
// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
operators = "([*^$|!~]?=)",
attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
"*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
set = posProcess( parts[0] + parts[1], context, seed );
// Prefer arguments not in parens/brackets,
// then attribute selectors and non-pseudos (denoted by :),
// then anything else
// These preferences are here to reduce the number of selectors
// needing tokenize in the PSEUDO preFilter
pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",
} else {
set = Expr.relative[ parts[0] ] ?
[ context ] :
Sizzle( parts.shift(), context );
// For matchExpr.POS and matchExpr.needsContext
pos = ":(nth|eq|gt|lt|first|last|even|odd)(?:\\(((?:-\\d)?\\d*)\\)|)(?=[^-]|$)",
while ( parts.length ) {
selector = parts.shift();
// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
if ( Expr.relative[ selector ] ) {
selector += parts.shift();
}
rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
rpseudo = new RegExp( pseudos ),
set = posProcess( selector, set, seed );
}
}
// Easily-parseable/retrievable ID or TAG or CLASS selectors
rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,
} else {
// Take a shortcut and set the context if the root selector is an ID
// (but not if it'll be faster if the inner selector is an ID)
if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
rnot = /^:not/,
rsibling = /[\x20\t\r\n\f]*[+~]/,
rendsWithNot = /:not\($/,
ret = Sizzle.find( parts.shift(), context, contextXML );
context = ret.expr ?
Sizzle.filter( ret.expr, ret.set )[0] :
ret.set[0];
}
rheader = /h\d/i,
rinputs = /input|select|textarea|button/i,
if ( context ) {
ret = seed ?
{ expr: parts.pop(), set: makeArray(seed) } :
Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
rbackslash = /\\(?!\\)/g,
set = ret.expr ?
Sizzle.filter( ret.expr, ret.set ) :
ret.set;
matchExpr = {
"ID": new RegExp( "^#(" + characterEncoding + ")" ),
"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
"NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
"ATTR": new RegExp( "^" + attributes ),
"PSEUDO": new RegExp( "^" + pseudos ),
"CHILD": new RegExp( "^:(only|nth|last|first)-child(?:\\(" + whitespace +
"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
"POS": new RegExp( pos, "ig" ),
// For use in libraries implementing .is()
"needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" )
},
if ( parts.length > 0 ) {
checkSet = makeArray( set );
// Support
} else {
prune = false;
}
// Used for testing something on an element
assert = function( fn ) {
var div = document.createElement("div");
while ( parts.length ) {
cur = parts.pop();
pop = cur;
try {
return fn( div );
} catch (e) {
return false;
} finally {
// release memory in IE
div = null;
}
},
if ( !Expr.relative[ cur ] ) {
cur = "";
} else {
pop = parts.pop();
}
// Check if getElementsByTagName("*") returns only elements
assertTagNameNoComments = assert(function( div ) {
div.appendChild( document.createComment("") );
return !div.getElementsByTagName("*").length;
}),
if ( pop == null ) {
pop = context;
}
// Check if getAttribute returns normalized href attributes
assertHrefNotNormalized = assert(function( div ) {
div.innerHTML = "<a href='#'></a>";
return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
div.firstChild.getAttribute("href") === "#";
}),
Expr.relative[ cur ]( checkSet, pop, contextXML );
}
// Check if attributes should be retrieved by attribute nodes
assertAttributes = assert(function( div ) {
div.innerHTML = "<select></select>";
var type = typeof div.lastChild.getAttribute("multiple");
// IE8 returns a string for some attributes even when not present
return type !== "boolean" && type !== "string";
}),
} else {
checkSet = parts = [];
// Check if getElementsByClassName can be trusted
assertUsableClassName = assert(function( div ) {
// Opera can't find a second classname (in 9.6)
div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
return false;
}
}
if ( !checkSet ) {
checkSet = set;
}
// Safari 3.2 caches class attributes and doesn't catch changes
div.lastChild.className = "e";
return div.getElementsByClassName("e").length === 2;
}),
if ( !checkSet ) {
Sizzle.error( cur || selector );
}
// Check if getElementById returns elements by name
// Check if getElementsByName privileges form controls or returns elements by ID
assertUsableName = assert(function( div ) {
// Inject content
div.id = expando + 0;
div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
docElem.insertBefore( div, docElem.firstChild );
if ( toString.call(checkSet) === "[object Array]" ) {
if ( !prune ) {
results.push.apply( results, checkSet );
// Test
var pass = document.getElementsByName &&
// buggy browsers will return fewer than the correct 2
document.getElementsByName( expando ).length === 2 +
// buggy browsers will return more than the correct 0
document.getElementsByName( expando + 0 ).length;
assertGetIdNotName = !document.getElementById( expando );
} else if ( context && context.nodeType === 1 ) {
for ( i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
results.push( set[i] );
}
}
// Cleanup
docElem.removeChild( div );
} else {
for ( i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
results.push( set[i] );
}
}
}
return pass;
});
} else {
makeArray( checkSet, results );
}
if ( extra ) {
Sizzle( extra, origContext, results, seed );
Sizzle.uniqueSort( results );
}
return results;
};
Sizzle.uniqueSort = function( results ) {
if ( sortOrder ) {
hasDuplicate = baseHasDuplicate;
results.sort( sortOrder );
if ( hasDuplicate ) {
for ( var i = 1; i < results.length; i++ ) {
if ( results[i] === results[ i - 1 ] ) {
results.splice( i--, 1 );
}
}
// If slice is not available, provide a backup
try {
slice.call( docElem.childNodes, 0 )[0].nodeType;
} catch ( e ) {
slice = function( i ) {
var elem, results = [];
for ( ; (elem = this[i]); i++ ) {
results.push( elem );
}
}
return results;
};
}
return results;
};
function Sizzle( selector, context, results, seed ) {
results = results || [];
// PATCH for jsdom
// context = context || document;
// See: https://github.com/tmpvar/jsdom/issues/375
context = context || seed[0].ownerDocument;
var match, elem, xml, m,
nodeType = context.nodeType;
Sizzle.matches = function( expr, set ) {
return Sizzle( expr, null, null, set );
};
Sizzle.matchesSelector = function( node, expr ) {
return Sizzle( expr, null, null, [node] ).length > 0;
};
Sizzle.find = function( expr, context, isXML ) {
var set, i, len, match, type, left;
if ( !expr ) {
if ( nodeType !== 1 && nodeType !== 9 ) {
return [];
}
for ( i = 0, len = Expr.order.length; i < len; i++ ) {
type = Expr.order[i];
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
left = match[1];
match.splice( 1, 1 );
if ( left.substr( left.length - 1 ) !== "\\" ) {
match[1] = (match[1] || "").replace( rBackslash, "" );
set = Expr.find[ type ]( match, context, isXML );
if ( set != null ) {
expr = expr.replace( Expr.match[ type ], "" );
break;
}
}
}
if ( !selector || typeof selector !== "string" ) {
return results;
}
if ( !set ) {
set = typeof context.getElementsByTagName !== "undefined" ?
context.getElementsByTagName( "*" ) :
[];
}
xml = isXML( context );
return { set: set, expr: expr };
};
Sizzle.filter = function( expr, set, inplace, not ) {
var match, anyFound,
type, found, item, filter, left,
i, pass,
old = expr,
result = [],
curLoop = set,
isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
while ( expr && set.length ) {
for ( type in Expr.filter ) {
if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
filter = Expr.filter[ type ];
left = match[1];
anyFound = false;
match.splice(1,1);
if ( left.substr( left.length - 1 ) === "\\" ) {
continue;
}
if ( curLoop === result ) {
result = [];
}
if ( Expr.preFilter[ type ] ) {
match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
if ( !match ) {
anyFound = found = true;
} else if ( match === true ) {
continue;
}
}
if ( match ) {
for ( i = 0; (item = curLoop[i]) != null; i++ ) {
if ( item ) {
found = filter( item, match, i, curLoop );
pass = not ^ found;
if ( inplace && found != null ) {
if ( pass ) {
anyFound = true;
} else {
curLoop[i] = false;
}
} else if ( pass ) {
result.push( item );
anyFound = true;
}
if ( !xml && !seed ) {
if ( (match = rquickExpr.exec( selector )) ) {
// Speed-up: Sizzle("#ID")
if ( (m = match[1]) ) {
if ( nodeType === 9 ) {
elem = context.getElementById( m );
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
if ( elem && elem.parentNode ) {
// Handle the case where IE, Opera, and Webkit return items
// by name instead of ID
if ( elem.id === m ) {
results.push( elem );
return results;
}
} else {
return results;
}
}
if ( found !== undefined ) {
if ( !inplace ) {
curLoop = result;
} else {
// Context is not a document
if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
contains( context, elem ) && elem.id === m ) {
results.push( elem );
return results;
}
expr = expr.replace( Expr.match[ type ], "" );
if ( !anyFound ) {
return [];
}
break;
}
}
}
// Improper expression
if ( expr === old ) {
if ( anyFound == null ) {
Sizzle.error( expr );
// Speed-up: Sizzle("TAG")
} else if ( match[2] ) {
push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
return results;
} else {
break;
// Speed-up: Sizzle(".CLASS")
} else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {
push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
return results;
}
}
old = expr;
}
return curLoop;
// All others
return select( selector, context, results, seed, xml );
}
Sizzle.matches = function( expr, elements ) {
return Sizzle( expr, null, null, elements );
};
Sizzle.error = function( msg ) {
throw new Error( "Syntax error, unrecognized expression: " + msg );
Sizzle.matchesSelector = function( elem, expr ) {
return Sizzle( expr, null, null, [ elem ] ).length > 0;
};
// Returns a function to use in pseudos for input types
function createInputPseudo( type ) {
return function( elem ) {
var name = elem.nodeName.toLowerCase();
return name === "input" && elem.type === type;
};
}
// Returns a function to use in pseudos for buttons
function createButtonPseudo( type ) {
return function( elem ) {
var name = elem.nodeName.toLowerCase();
return (name === "input" || name === "button") && elem.type === type;
};
}
/**
* Utility function for retreiving the text value of an array of DOM nodes
* Utility function for retrieving the text value of an array of DOM nodes
* @param {Array|Element} elem
*/
var getText = Sizzle.getText = function( elem ) {
var i, node,
nodeType = elem.nodeType,
ret = "";
getText = Sizzle.getText = function( elem ) {
var node,
ret = "",
i = 0,
nodeType = elem.nodeType;
if ( nodeType ) {
if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
// Use textContent || innerText for elements
if ( typeof elem.textContent === 'string' ) {
// Use textContent for elements
// innerText usage removed for consistency of new lines (see #11153)
if ( typeof elem.textContent === "string" ) {
return elem.textContent;
} else if ( typeof elem.innerText === 'string' ) {
// Replace IE's carriage returns
return elem.innerText.replace( rReturn, '' );
} else {
// Traverse it's children
for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
// Traverse its children
for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
ret += getText( elem );

@@ -361,10 +314,9 @@ }

}
// Do not include comment or processing instruction nodes
} else {
// If no nodeType, this is expected to be an array
for ( i = 0; (node = elem[i]); i++ ) {
for ( ; (node = elem[i]); i++ ) {
// Do not traverse comment nodes
if ( node.nodeType !== 8 ) {
ret += getText( node );
}
ret += getText( node );
}

@@ -375,272 +327,414 @@ }

var Expr = Sizzle.selectors = {
order: [ "ID", "NAME", "TAG" ],
isXML = Sizzle.isXML = function isXML( elem ) {
// documentElement is verified for cases where it doesn't yet exist
// (such as loading iframes in IE - #4833)
var documentElement = elem && (elem.ownerDocument || elem).documentElement;
return documentElement ? documentElement.nodeName !== "HTML" : false;
};
match: {
ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
},
// Element contains another
contains = Sizzle.contains = docElem.contains ?
function( a, b ) {
var adown = a.nodeType === 9 ? a.documentElement : a,
bup = b && b.parentNode;
return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );
} :
docElem.compareDocumentPosition ?
function( a, b ) {
return b && !!( a.compareDocumentPosition( b ) & 16 );
} :
function( a, b ) {
while ( (b = b.parentNode) ) {
if ( b === a ) {
return true;
}
}
return false;
};
leftMatch: {},
Sizzle.attr = function( elem, name ) {
var attr,
xml = isXML( elem );
attrMap: {
"class": "className",
"for": "htmlFor"
},
if ( !xml ) {
name = name.toLowerCase();
}
if ( Expr.attrHandle[ name ] ) {
return Expr.attrHandle[ name ]( elem );
}
if ( assertAttributes || xml ) {
return elem.getAttribute( name );
}
attr = elem.getAttributeNode( name );
return attr ?
typeof elem[ name ] === "boolean" ?
elem[ name ] ? name : null :
attr.specified ? attr.value : null :
null;
};
attrHandle: {
href: function( elem ) {
return elem.getAttribute( "href" );
},
type: function( elem ) {
return elem.getAttribute( "type" );
}
},
Expr = Sizzle.selectors = {
relative: {
"+": function(checkSet, part){
var isPartStr = typeof part === "string",
isTag = isPartStr && !rNonWord.test( part ),
isPartStrNotTag = isPartStr && !isTag;
// Can be adjusted by the user
cacheLength: 50,
if ( isTag ) {
part = part.toLowerCase();
}
createPseudo: markFunction,
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
if ( (elem = checkSet[i]) ) {
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
match: matchExpr,
checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
elem || false :
elem === part;
}
}
order: new RegExp( "ID|TAG" +
(assertUsableName ? "|NAME" : "") +
(assertUsableClassName ? "|CLASS" : "")
),
if ( isPartStrNotTag ) {
Sizzle.filter( part, checkSet, true );
// IE6/7 return a modified href
attrHandle: assertHrefNotNormalized ?
{} :
{
"href": function( elem ) {
return elem.getAttribute( "href", 2 );
},
"type": function( elem ) {
return elem.getAttribute("type");
}
},
">": function( checkSet, part ) {
var elem,
isPartStr = typeof part === "string",
i = 0,
l = checkSet.length;
find: {
"ID": assertGetIdNotName ?
function( id, context, xml ) {
if ( typeof context.getElementById !== strundefined && !xml ) {
var m = context.getElementById( id );
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
return m && m.parentNode ? [m] : [];
}
} :
function( id, context, xml ) {
if ( typeof context.getElementById !== strundefined && !xml ) {
var m = context.getElementById( id );
if ( isPartStr && !rNonWord.test( part ) ) {
part = part.toLowerCase();
return m ?
m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
[m] :
undefined :
[];
}
},
for ( ; i < l; i++ ) {
elem = checkSet[i];
if ( elem ) {
var parent = elem.parentNode;
checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
}
"TAG": assertTagNameNoComments ?
function( tag, context ) {
if ( typeof context.getElementsByTagName !== strundefined ) {
return context.getElementsByTagName( tag );
}
} :
function( tag, context ) {
var results = context.getElementsByTagName( tag );
} else {
for ( ; i < l; i++ ) {
elem = checkSet[i];
// Filter out possible comments
if ( tag === "*" ) {
var elem,
tmp = [],
i = 0;
if ( elem ) {
checkSet[i] = isPartStr ?
elem.parentNode :
elem.parentNode === part;
for ( ; (elem = results[i]); i++ ) {
if ( elem.nodeType === 1 ) {
tmp.push( elem );
}
}
return tmp;
}
return results;
},
if ( isPartStr ) {
Sizzle.filter( part, checkSet, true );
}
"NAME": function( tag, context ) {
if ( typeof context.getElementsByName !== strundefined ) {
return context.getElementsByName( name );
}
},
"": function(checkSet, part, isXML){
var nodeCheck,
doneName = done++,
checkFn = dirCheck;
"CLASS": function( className, context, xml ) {
if ( typeof context.getElementsByClassName !== strundefined && !xml ) {
return context.getElementsByClassName( className );
}
}
},
if ( typeof part === "string" && !rNonWord.test( part ) ) {
part = part.toLowerCase();
nodeCheck = part;
checkFn = dirNodeCheck;
relative: {
">": { dir: "parentNode", first: true },
" ": { dir: "parentNode" },
"+": { dir: "previousSibling", first: true },
"~": { dir: "previousSibling" }
},
preFilter: {
"ATTR": function( match ) {
match[1] = match[1].replace( rbackslash, "" );
// Move the given value to match[3] whether quoted or unquoted
match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" );
if ( match[2] === "~=" ) {
match[3] = " " + match[3] + " ";
}
checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
return match.slice( 0, 4 );
},
"~": function( checkSet, part, isXML ) {
var nodeCheck,
doneName = done++,
checkFn = dirCheck;
"CHILD": function( match ) {
/* matches from matchExpr.CHILD
1 type (only|nth|...)
2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
3 xn-component of xn+y argument ([+-]?\d*n|)
4 sign of xn-component
5 x of xn-component
6 sign of y-component
7 y of y-component
*/
match[1] = match[1].toLowerCase();
if ( typeof part === "string" && !rNonWord.test( part ) ) {
part = part.toLowerCase();
nodeCheck = part;
checkFn = dirNodeCheck;
}
if ( match[1] === "nth" ) {
// nth-child requires argument
if ( !match[2] ) {
Sizzle.error( match[0] );
}
checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
}
},
// numeric x and y parameters for Expr.filter.CHILD
// remember that false/true cast respectively to 0/1
match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) );
match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" );
find: {
ID: function( match, context, isXML ) {
if ( typeof context.getElementById !== "undefined" && !isXML ) {
var m = context.getElementById(match[1]);
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
return m && m.parentNode ? [m] : [];
// other types prohibit arguments
} else if ( match[2] ) {
Sizzle.error( match[0] );
}
return match;
},
NAME: function( match, context ) {
if ( typeof context.getElementsByName !== "undefined" ) {
var ret = [],
results = context.getElementsByName( match[1] );
"PSEUDO": function( match, context, xml ) {
var unquoted, excess;
if ( matchExpr["CHILD"].test( match[0] ) ) {
return null;
}
for ( var i = 0, l = results.length; i < l; i++ ) {
if ( results[i].getAttribute("name") === match[1] ) {
ret.push( results[i] );
}
if ( match[3] ) {
match[2] = match[3];
} else if ( (unquoted = match[4]) ) {
// Only check arguments that contain a pseudo
if ( rpseudo.test(unquoted) &&
// Get excess from tokenize (recursively)
(excess = tokenize( unquoted, context, xml, true )) &&
// advance to the next closing parenthesis
(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
// excess is a negative index
unquoted = unquoted.slice( 0, excess );
match[0] = match[0].slice( 0, excess );
}
match[2] = unquoted;
}
return ret.length === 0 ? null : ret;
// Return only captures needed by the pseudo filter method (type and argument)
return match.slice( 0, 3 );
}
},
filter: {
"ID": assertGetIdNotName ?
function( id ) {
id = id.replace( rbackslash, "" );
return function( elem ) {
return elem.getAttribute("id") === id;
};
} :
function( id ) {
id = id.replace( rbackslash, "" );
return function( elem ) {
var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
return node && node.value === id;
};
},
"TAG": function( nodeName ) {
if ( nodeName === "*" ) {
return function() { return true; };
}
nodeName = nodeName.replace( rbackslash, "" ).toLowerCase();
return function( elem ) {
return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
};
},
TAG: function( match, context ) {
if ( typeof context.getElementsByTagName !== "undefined" ) {
return context.getElementsByTagName( match[1] );
"CLASS": function( className ) {
var pattern = classCache[ expando ][ className ];
if ( !pattern ) {
pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") );
}
}
},
preFilter: {
CLASS: function( match, curLoop, inplace, result, not, isXML ) {
match = " " + match[1].replace( rBackslash, "" ) + " ";
return function( elem ) {
return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
};
},
if ( isXML ) {
return match;
"ATTR": function( name, operator, check ) {
if ( !operator ) {
return function( elem ) {
return Sizzle.attr( elem, name ) != null;
};
}
for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
if ( elem ) {
if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
if ( !inplace ) {
result.push( elem );
}
return function( elem ) {
var result = Sizzle.attr( elem, name ),
value = result + "";
} else if ( inplace ) {
curLoop[i] = false;
}
if ( result == null ) {
return operator === "!=";
}
}
return false;
switch ( operator ) {
case "=":
return value === check;
case "!=":
return value !== check;
case "^=":
return check && value.indexOf( check ) === 0;
case "*=":
return check && value.indexOf( check ) > -1;
case "$=":
return check && value.substr( value.length - check.length ) === check;
case "~=":
return ( " " + value + " " ).indexOf( check ) > -1;
case "|=":
return value === check || value.substr( 0, check.length + 1 ) === check + "-";
}
};
},
ID: function( match ) {
return match[1].replace( rBackslash, "" );
},
"CHILD": function( type, argument, first, last ) {
TAG: function( match, curLoop ) {
return match[1].replace( rBackslash, "" ).toLowerCase();
},
if ( type === "nth" ) {
var doneName = done++;
CHILD: function( match ) {
if ( match[1] === "nth" ) {
if ( !match[2] ) {
Sizzle.error( match[0] );
}
return function( elem ) {
var parent, diff,
count = 0,
node = elem;
match[2] = match[2].replace(/^\+|\s*/g, '');
if ( first === 1 && last === 0 ) {
return true;
}
// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
parent = elem.parentNode;
// calculate the numbers (first)n+(last) including if they are negative
match[2] = (test[1] + (test[2] || 1)) - 0;
match[3] = test[3] - 0;
}
else if ( match[2] ) {
Sizzle.error( match[0] );
}
if ( parent && (parent[ expando ] !== doneName || !elem.sizset) ) {
for ( node = parent.firstChild; node; node = node.nextSibling ) {
if ( node.nodeType === 1 ) {
node.sizset = ++count;
if ( node === elem ) {
break;
}
}
}
// TODO: Move to normal caching system
match[0] = done++;
parent[ expando ] = doneName;
}
return match;
},
diff = elem.sizset - last;
ATTR: function( match, curLoop, inplace, result, not, isXML ) {
var name = match[1] = match[1].replace( rBackslash, "" );
if ( first === 0 ) {
return diff === 0;
if ( !isXML && Expr.attrMap[name] ) {
match[1] = Expr.attrMap[name];
} else {
return ( diff % first === 0 && diff / first >= 0 );
}
};
}
// Handle if an un-quoted value was used
match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
return function( elem ) {
var node = elem;
if ( match[2] === "~=" ) {
match[4] = " " + match[4] + " ";
}
switch ( type ) {
case "only":
case "first":
while ( (node = node.previousSibling) ) {
if ( node.nodeType === 1 ) {
return false;
}
}
return match;
},
if ( type === "first" ) {
return true;
}
PSEUDO: function( match, curLoop, inplace, result, not ) {
if ( match[1] === "not" ) {
// If we're dealing with a complex expression, or a simple one
if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
match[3] = Sizzle(match[3], null, null, curLoop);
node = elem;
} else {
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
/* falls through */
case "last":
while ( (node = node.nextSibling) ) {
if ( node.nodeType === 1 ) {
return false;
}
}
if ( !inplace ) {
result.push.apply( result, ret );
}
return false;
return true;
}
};
},
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
return true;
"PSEUDO": function( pseudo, argument, context, xml ) {
// pseudo-class names are case-insensitive
// http://www.w3.org/TR/selectors/#pseudo-classes
// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
var args,
fn = Expr.pseudos[ pseudo ] || Expr.pseudos[ pseudo.toLowerCase() ];
if ( !fn ) {
Sizzle.error( "unsupported pseudo: " + pseudo );
}
return match;
},
// The user may use createPseudo to indicate that
// arguments are needed to create the filter function
// just as Sizzle does
if ( !fn[ expando ] ) {
if ( fn.length > 1 ) {
args = [ pseudo, pseudo, "", argument ];
return function( elem ) {
return fn( elem, 0, args );
};
}
return fn;
}
POS: function( match ) {
match.unshift( true );
return match;
return fn( argument, context, xml );
}
},
filters: {
enabled: function( elem ) {
return elem.disabled === false && elem.type !== "hidden";
pseudos: {
"not": markFunction(function( selector, context, xml ) {
// Trim the selector passed to compile
// to avoid treating leading and trailing
// spaces as combinators
var matcher = compile( selector.replace( rtrim, "$1" ), context, xml );
return function( elem ) {
return !matcher( elem );
};
}),
"enabled": function( elem ) {
return elem.disabled === false;
},
disabled: function( elem ) {
"disabled": function( elem ) {
return elem.disabled === true;
},
checked: function( elem ) {
return elem.checked === true;
"checked": function( elem ) {
// In CSS3, :checked should return both checked and selected elements
// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
var nodeName = elem.nodeName.toLowerCase();
return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
},
selected: function( elem ) {
"selected": function( elem ) {
// Accessing this property makes selected-by-default

@@ -655,250 +749,118 @@ // options in Safari work properly

parent: function( elem ) {
return !!elem.firstChild;
"parent": function( elem ) {
return !Expr.pseudos["empty"]( elem );
},
empty: function( elem ) {
return !elem.firstChild;
"empty": function( elem ) {
// http://www.w3.org/TR/selectors/#empty-pseudo
// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
// not comment, processing instructions, or others
// Thanks to Diego Perini for the nodeName shortcut
// Greater than "@" means alpha characters (specifically not starting with "#" or "?")
var nodeType;
elem = elem.firstChild;
while ( elem ) {
if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {
return false;
}
elem = elem.nextSibling;
}
return true;
},
has: function( elem, i, match ) {
return !!Sizzle( match[3], elem ).length;
},
"contains": markFunction(function( text ) {
return function( elem ) {
return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
};
}),
header: function( elem ) {
return (/h\d/i).test( elem.nodeName );
"has": markFunction(function( selector ) {
return function( elem ) {
return Sizzle( selector, elem ).length > 0;
};
}),
"header": function( elem ) {
return rheader.test( elem.nodeName );
},
text: function( elem ) {
var attr = elem.getAttribute( "type" ), type = elem.type;
"text": function( elem ) {
var type, attr;
// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
// use getAttribute instead to test this case
return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
return elem.nodeName.toLowerCase() === "input" &&
(type = elem.type) === "text" &&
( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type );
},
radio: function( elem ) {
return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
},
// Input types
"radio": createInputPseudo("radio"),
"checkbox": createInputPseudo("checkbox"),
"file": createInputPseudo("file"),
"password": createInputPseudo("password"),
"image": createInputPseudo("image"),
checkbox: function( elem ) {
return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
},
"submit": createButtonPseudo("submit"),
"reset": createButtonPseudo("reset"),
file: function( elem ) {
return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
},
password: function( elem ) {
return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
},
submit: function( elem ) {
"button": function( elem ) {
var name = elem.nodeName.toLowerCase();
return (name === "input" || name === "button") && "submit" === elem.type;
return name === "input" && elem.type === "button" || name === "button";
},
image: function( elem ) {
return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
"input": function( elem ) {
return rinputs.test( elem.nodeName );
},
reset: function( elem ) {
var name = elem.nodeName.toLowerCase();
return (name === "input" || name === "button") && "reset" === elem.type;
"focus": function( elem ) {
var doc = elem.ownerDocument;
return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);
},
button: function( elem ) {
var name = elem.nodeName.toLowerCase();
return name === "input" && "button" === elem.type || name === "button";
},
input: function( elem ) {
return (/input|select|textarea|button/i).test( elem.nodeName );
},
focus: function( elem ) {
"active": function( elem ) {
return elem === elem.ownerDocument.activeElement;
}
},
setFilters: {
first: function( elem, i ) {
return i === 0;
"first": function( elements, argument, not ) {
return not ? elements.slice( 1 ) : [ elements[0] ];
},
last: function( elem, i, match, array ) {
return i === array.length - 1;
"last": function( elements, argument, not ) {
var elem = elements.pop();
return not ? elements : [ elem ];
},
even: function( elem, i ) {
return i % 2 === 0;
},
odd: function( elem, i ) {
return i % 2 === 1;
},
lt: function( elem, i, match ) {
return i < match[3] - 0;
},
gt: function( elem, i, match ) {
return i > match[3] - 0;
},
nth: function( elem, i, match ) {
return match[3] - 0 === i;
},
eq: function( elem, i, match ) {
return match[3] - 0 === i;
}
},
filter: {
PSEUDO: function( elem, match, i, array ) {
var name = match[1],
filter = Expr.filters[ name ];
if ( filter ) {
return filter( elem, i, match, array );
} else if ( name === "contains" ) {
return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
} else if ( name === "not" ) {
var not = match[3];
for ( var j = 0, l = not.length; j < l; j++ ) {
if ( not[j] === elem ) {
return false;
}
}
return true;
} else {
Sizzle.error( name );
"even": function( elements, argument, not ) {
var results = [],
i = not ? 1 : 0,
len = elements.length;
for ( ; i < len; i = i + 2 ) {
results.push( elements[i] );
}
return results;
},
CHILD: function( elem, match ) {
var first, last,
doneName, parent, cache,
count, diff,
type = match[1],
node = elem;
switch ( type ) {
case "only":
case "first":
while ( (node = node.previousSibling) ) {
if ( node.nodeType === 1 ) {
return false;
}
}
if ( type === "first" ) {
return true;
}
node = elem;
/* falls through */
case "last":
while ( (node = node.nextSibling) ) {
if ( node.nodeType === 1 ) {
return false;
}
}
return true;
case "nth":
first = match[2];
last = match[3];
if ( first === 1 && last === 0 ) {
return true;
}
doneName = match[0];
parent = elem.parentNode;
if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
count = 0;
for ( node = parent.firstChild; node; node = node.nextSibling ) {
if ( node.nodeType === 1 ) {
node.nodeIndex = ++count;
}
}
parent[ expando ] = doneName;
}
diff = elem.nodeIndex - last;
if ( first === 0 ) {
return diff === 0;
} else {
return ( diff % first === 0 && diff / first >= 0 );
}
"odd": function( elements, argument, not ) {
var results = [],
i = not ? 0 : 1,
len = elements.length;
for ( ; i < len; i = i + 2 ) {
results.push( elements[i] );
}
return results;
},
ID: function( elem, match ) {
return elem.nodeType === 1 && elem.getAttribute("id") === match;
"lt": function( elements, argument, not ) {
return not ? elements.slice( +argument ) : elements.slice( 0, +argument );
},
TAG: function( elem, match ) {
return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
"gt": function( elements, argument, not ) {
return not ? elements.slice( 0, +argument + 1 ) : elements.slice( +argument + 1 );
},
CLASS: function( elem, match ) {
return (" " + (elem.className || elem.getAttribute("class")) + " ")
.indexOf( match ) > -1;
},
ATTR: function( elem, match ) {
var name = match[1],
result = Sizzle.attr ?
Sizzle.attr( elem, name ) :
Expr.attrHandle[ name ] ?
Expr.attrHandle[ name ]( elem ) :
elem[ name ] != null ?
elem[ name ] :
elem.getAttribute( name ),
value = result + "",
type = match[2],
check = match[4];
return result == null ?
type === "!=" :
!type && Sizzle.attr ?
result != null :
type === "=" ?
value === check :
type === "*=" ?
value.indexOf(check) >= 0 :
type === "~=" ?
(" " + value + " ").indexOf(check) >= 0 :
!check ?
value && result !== false :
type === "!=" ?
value !== check :
type === "^=" ?
value.indexOf(check) === 0 :
type === "$=" ?
value.substr(value.length - check.length) === check :
type === "|=" ?
value === check || value.substr(0, check.length + 1) === check + "-" :
false;
},
POS: function( elem, match, i, array ) {
var name = match[2],
filter = Expr.setFilters[ name ];
if ( filter ) {
return filter( elem, i, match, array );
}
"eq": function( elements, argument, not ) {
var elem = elements.splice( +argument, 1 );
return not ? elements : elem;
}

@@ -908,63 +870,22 @@ }

var origPOS = Expr.match.POS,
fescape = function(all, num){
return "\\" + (num - 0 + 1);
};
function siblingCheck( a, b, ret ) {
if ( a === b ) {
return ret;
}
for ( var type in Expr.match ) {
Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
}
// Expose origPOS
// "global" as in regardless of relation to brackets/parens
Expr.match.globalPOS = origPOS;
var cur = a.nextSibling;
var makeArray = function( array, results ) {
array = Array.prototype.slice.call( array, 0 );
while ( cur ) {
if ( cur === b ) {
return -1;
}
if ( results ) {
results.push.apply( results, array );
return results;
cur = cur.nextSibling;
}
return array;
};
// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
// Also verifies that the returned array holds DOM nodes
// (which is not the case in the Blackberry browser)
try {
Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
// Provide a fallback method if it does not work
} catch( e ) {
makeArray = function( array, results ) {
var i = 0,
ret = results || [];
if ( toString.call(array) === "[object Array]" ) {
Array.prototype.push.apply( ret, array );
} else {
if ( typeof array.length === "number" ) {
for ( var l = array.length; i < l; i++ ) {
ret.push( array[i] );
}
} else {
for ( ; array[i]; i++ ) {
ret.push( array[i] );
}
}
}
return ret;
};
return 1;
}
var sortOrder, siblingCheck;
if ( document.documentElement.compareDocumentPosition ) {
sortOrder = function( a, b ) {
sortOrder = docElem.compareDocumentPosition ?
function( a, b ) {
if ( a === b ) {

@@ -975,11 +896,8 @@ hasDuplicate = true;

if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
return a.compareDocumentPosition ? -1 : 1;
}
return a.compareDocumentPosition(b) & 4 ? -1 : 1;
};
} else {
sortOrder = function( a, b ) {
return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?
a.compareDocumentPosition :
a.compareDocumentPosition(b) & 4
) ? -1 : 1;
} :
function( a, b ) {
// The nodes are identical, we can exit early

@@ -1044,412 +962,590 @@ if ( a === b ) {

siblingCheck = function( a, b, ret ) {
if ( a === b ) {
return ret;
}
// Always assume the presence of duplicates if sort doesn't
// pass them to our comparison function (as in Google Chrome).
[0, 0].sort( sortOrder );
baseHasDuplicate = !hasDuplicate;
var cur = a.nextSibling;
// Document sorting and removing duplicates
Sizzle.uniqueSort = function( results ) {
var elem,
i = 1;
while ( cur ) {
if ( cur === b ) {
return -1;
hasDuplicate = baseHasDuplicate;
results.sort( sortOrder );
if ( hasDuplicate ) {
for ( ; (elem = results[i]); i++ ) {
if ( elem === results[ i - 1 ] ) {
results.splice( i--, 1 );
}
cur = cur.nextSibling;
}
}
return 1;
};
}
return results;
};
// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
(function(){
// We're going to inject a fake input element with a specified name
var form = document.createElement("div"),
id = "script" + (new Date()).getTime(),
root = document.documentElement;
Sizzle.error = function( msg ) {
throw new Error( "Syntax error, unrecognized expression: " + msg );
};
form.innerHTML = "<a name='" + id + "'/>";
function tokenize( selector, context, xml, parseOnly ) {
var matched, match, tokens, type,
soFar, groups, group, i,
preFilters, filters,
checkContext = !xml && context !== document,
// Token cache should maintain spaces
key = ( checkContext ? "<s>" : "" ) + selector.replace( rtrim, "$1<s>" ),
cached = tokenCache[ expando ][ key ];
// Inject it into the root element, check its status, and remove it quickly
root.insertBefore( form, root.firstChild );
if ( cached ) {
return parseOnly ? 0 : slice.call( cached, 0 );
}
// The workaround has to do additional checks after a getElementById
// Which slows things down for other browsers (hence the branching)
if ( document.getElementById( id ) ) {
Expr.find.ID = function( match, context, isXML ) {
if ( typeof context.getElementById !== "undefined" && !isXML ) {
var m = context.getElementById(match[1]);
soFar = selector;
groups = [];
i = 0;
preFilters = Expr.preFilter;
filters = Expr.filter;
return m ?
m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
[m] :
undefined :
[];
while ( soFar ) {
// Comma and first run
if ( !matched || (match = rcomma.exec( soFar )) ) {
if ( match ) {
soFar = soFar.slice( match[0].length );
tokens.selector = group;
}
};
groups.push( tokens = [] );
group = "";
Expr.filter.ID = function( elem, match ) {
var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
// Need to make sure we're within a narrower context if necessary
// Adding a descendant combinator will generate what is needed
if ( checkContext ) {
soFar = " " + soFar;
}
}
return elem.nodeType === 1 && node && node.nodeValue === match;
};
}
matched = false;
root.removeChild( form );
// Combinators
if ( (match = rcombinators.exec( soFar )) ) {
group += match[0];
soFar = soFar.slice( match[0].length );
// release memory in IE
root = form = null;
})();
// Cast descendant combinators to space
matched = tokens.push({
part: match.pop().replace( rtrim, " " ),
string: match[0],
captures: match
});
}
(function(){
// Check to see if the browser returns only elements
// when doing getElementsByTagName("*")
// Filters
for ( type in filters ) {
if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
( match = preFilters[ type ](match, context, xml) )) ) {
// Create a fake element
var div = document.createElement("div");
div.appendChild( document.createComment("") );
group += match[0];
soFar = soFar.slice( match[0].length );
matched = tokens.push({
part: type,
string: match.shift(),
captures: match
});
}
}
// Make sure no comments are found
if ( div.getElementsByTagName("*").length > 0 ) {
Expr.find.TAG = function( match, context ) {
var results = context.getElementsByTagName( match[1] );
if ( !matched ) {
break;
}
}
// Filter out possible comments
if ( match[1] === "*" ) {
var tmp = [];
// Attach the full group as a selector
if ( group ) {
tokens.selector = group;
}
for ( var i = 0; results[i]; i++ ) {
if ( results[i].nodeType === 1 ) {
tmp.push( results[i] );
}
}
// Return the length of the invalid excess
// if we're just parsing
// Otherwise, throw an error or return tokens
return parseOnly ?
soFar.length :
soFar ?
Sizzle.error( selector ) :
// Cache the tokens
slice.call( tokenCache(key, groups), 0 );
}
results = tmp;
}
function addCombinator( matcher, combinator, context, xml ) {
var dir = combinator.dir,
doneName = done++;
return results;
if ( !matcher ) {
// If there is no matcher to check, check against the context
matcher = function( elem ) {
return elem === context;
};
}
return combinator.first ?
function( elem ) {
while ( (elem = elem[ dir ]) ) {
if ( elem.nodeType === 1 ) {
return matcher( elem ) && elem;
}
}
} :
xml ?
function( elem ) {
while ( (elem = elem[ dir ]) ) {
if ( elem.nodeType === 1 ) {
if ( matcher( elem ) ) {
return elem;
}
}
}
} :
function( elem ) {
var cache,
dirkey = doneName + "." + dirruns,
cachedkey = dirkey + "." + cachedruns;
while ( (elem = elem[ dir ]) ) {
if ( elem.nodeType === 1 ) {
if ( (cache = elem[ expando ]) === cachedkey ) {
return elem.sizset;
} else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) {
if ( elem.sizset ) {
return elem;
}
} else {
elem[ expando ] = cachedkey;
if ( matcher( elem ) ) {
elem.sizset = true;
return elem;
}
elem.sizset = false;
}
}
}
};
}
// Check to see if an attribute returns normalized href attributes
div.innerHTML = "<a href='#'></a>";
function addMatcher( higher, deeper ) {
return higher ?
function( elem ) {
var result = deeper( elem );
return result && higher( result === true ? elem : result );
} :
deeper;
}
if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
div.firstChild.getAttribute("href") !== "#" ) {
// ["TAG", ">", "ID", " ", "CLASS"]
function matcherFromTokens( tokens, context, xml ) {
var token, matcher,
i = 0;
Expr.attrHandle.href = function( elem ) {
return elem.getAttribute( "href", 2 );
};
for ( ; (token = tokens[i]); i++ ) {
if ( Expr.relative[ token.part ] ) {
matcher = addCombinator( matcher, Expr.relative[ token.part ], context, xml );
} else {
matcher = addMatcher( matcher, Expr.filter[ token.part ].apply(null, token.captures.concat( context, xml )) );
}
}
// release memory in IE
div = null;
})();
return matcher;
}
// Patch for jsdom
if ( document.querySelectorAll && false ) {
(function(){
var oldSizzle = Sizzle,
div = document.createElement("div"),
id = "__sizzle__";
div.innerHTML = "<p class='TEST'></p>";
// Safari can't handle uppercase or unicode characters when
// in quirks mode.
if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
return;
function matcherFromGroupMatchers( matchers ) {
return function( elem ) {
var matcher,
j = 0;
for ( ; (matcher = matchers[j]); j++ ) {
if ( matcher(elem) ) {
return true;
}
}
return false;
};
}
Sizzle = function( query, context, extra, seed ) {
context = context || document;
compile = Sizzle.compile = function( selector, context, xml ) {
var group, i, len,
cached = compilerCache[ expando ][ selector ];
// Only use querySelectorAll on non-XML documents
// (ID selectors don't work in non-HTML documents)
if ( !seed && !Sizzle.isXML(context) ) {
// See if we find a selector to speed up
var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
// Return a cached group function if already generated (context dependent)
if ( cached && cached.context === context ) {
return cached;
}
if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
// Speed-up: Sizzle("TAG")
if ( match[1] ) {
return makeArray( context.getElementsByTagName( query ), extra );
// Generate a function of recursive functions that can be used to check each element
group = tokenize( selector, context, xml );
for ( i = 0, len = group.length; i < len; i++ ) {
group[i] = matcherFromTokens(group[i], context, xml);
}
// Speed-up: Sizzle(".CLASS")
} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
return makeArray( context.getElementsByClassName( match[2] ), extra );
}
}
// Cache the compiled function
cached = compilerCache( selector, matcherFromGroupMatchers(group) );
cached.context = context;
cached.runs = cached.dirruns = 0;
return cached;
};
if ( context.nodeType === 9 ) {
// Speed-up: Sizzle("body")
// The body element only exists once, optimize finding it
if ( query === "body" && context.body ) {
return makeArray( [ context.body ], extra );
function multipleContexts( selector, contexts, results, seed ) {
var i = 0,
len = contexts.length;
for ( ; i < len; i++ ) {
Sizzle( selector, contexts[i], results, seed );
}
}
// Speed-up: Sizzle("#ID")
} else if ( match && match[3] ) {
var elem = context.getElementById( match[3] );
function handlePOSGroup( selector, posfilter, argument, contexts, seed, not ) {
var results,
fn = Expr.setFilters[ posfilter.toLowerCase() ];
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
if ( elem && elem.parentNode ) {
// Handle the case where IE and Opera return items
// by name instead of ID
if ( elem.id === match[3] ) {
return makeArray( [ elem ], extra );
}
if ( !fn ) {
Sizzle.error( posfilter );
}
} else {
return makeArray( [], extra );
}
}
if ( selector || !(results = seed) ) {
multipleContexts( selector || "*", contexts, (results = []), seed );
}
try {
return makeArray( context.querySelectorAll(query), extra );
} catch(qsaError) {}
return results.length > 0 ? fn( results, argument, not ) : [];
}
// qSA works strangely on Element-rooted queries
// We can work around this by specifying an extra ID on the root
// and working up from there (Thanks to Andrew Dupont for the technique)
// IE 8 doesn't work on object elements
} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
var oldContext = context,
old = context.getAttribute( "id" ),
nid = old || id,
hasParent = context.parentNode,
relativeHierarchySelector = /^\s*[+~]/.test( query );
function handlePOS( groups, context, results, seed ) {
var group, part, j, groupLen, token, selector,
anchor, elements, match, matched,
lastIndex, currentContexts, not,
i = 0,
len = groups.length,
rpos = matchExpr["POS"],
// This is generated here in case matchExpr["POS"] is extended
rposgroups = new RegExp( "^" + rpos.source + "(?!" + whitespace + ")", "i" ),
// This is for making sure non-participating
// matching groups are represented cross-browser (IE6-8)
setUndefined = function() {
var i = 1,
len = arguments.length - 2;
for ( ; i < len; i++ ) {
if ( arguments[i] === undefined ) {
match[i] = undefined;
}
}
};
if ( !old ) {
context.setAttribute( "id", nid );
} else {
nid = nid.replace( /'/g, "\\$&" );
}
if ( relativeHierarchySelector && hasParent ) {
context = context.parentNode;
}
for ( ; i < len; i++ ) {
group = groups[i];
part = "";
elements = seed;
for ( j = 0, groupLen = group.length; j < groupLen; j++ ) {
token = group[j];
selector = token.string;
if ( token.part === "PSEUDO" ) {
// Reset regex index to 0
rpos.exec("");
anchor = 0;
while ( (match = rpos.exec( selector )) ) {
matched = true;
lastIndex = rpos.lastIndex = match.index + match[0].length;
if ( lastIndex > anchor ) {
part += selector.slice( anchor, match.index );
anchor = lastIndex;
currentContexts = [ context ];
try {
if ( !relativeHierarchySelector || hasParent ) {
return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
if ( rcombinators.test(part) ) {
if ( elements ) {
currentContexts = elements;
}
elements = seed;
}
} catch(pseudoError) {
} finally {
if ( !old ) {
oldContext.removeAttribute( "id" );
if ( (not = rendsWithNot.test( part )) ) {
part = part.slice( 0, -5 ).replace( rcombinators, "$&*" );
anchor++;
}
if ( match.length > 1 ) {
match[0].replace( rposgroups, setUndefined );
}
elements = handlePOSGroup( part, match[1], match[2], currentContexts, elements, not );
}
part = "";
}
}
return oldSizzle(query, context, extra, seed);
};
if ( !matched ) {
part += selector;
}
matched = false;
}
for ( var prop in oldSizzle ) {
Sizzle[ prop ] = oldSizzle[ prop ];
if ( part ) {
if ( rcombinators.test(part) ) {
multipleContexts( part, elements || [ context ], results, seed );
} else {
Sizzle( part, context, results, seed ? seed.concat(elements) : elements );
}
} else {
push.apply( results, elements );
}
}
// release memory in IE
div = null;
})();
// Do not sort if this is a single filter
return len === 1 ? results : Sizzle.uniqueSort( results );
}
(function(){
var html = document.documentElement,
matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
function select( selector, context, results, seed, xml ) {
// Remove excessive whitespace
selector = selector.replace( rtrim, "$1" );
var elements, matcher, cached, elem,
i, tokens, token, lastToken, findContext, type,
match = tokenize( selector, context, xml ),
contextNodeType = context.nodeType;
if ( matches ) {
// Check to see if it's possible to do matchesSelector
// on a disconnected node (IE 9 fails this)
var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
pseudoWorks = false;
// POS handling
if ( matchExpr["POS"].test(selector) ) {
return handlePOS( match, context, results, seed );
}
try {
// This should fail with an exception
// Gecko does not error, returns false instead
matches.call( document.documentElement, "[test!='']:sizzle" );
if ( seed ) {
elements = slice.call( seed, 0 );
} catch( pseudoError ) {
pseudoWorks = true;
}
// To maintain document order, only narrow the
// set if there is one group
} else if ( match.length === 1 ) {
Sizzle.matchesSelector = function( node, expr ) {
// Make sure that attribute selectors are quoted
expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
// Take a shortcut and set the context if the root selector is an ID
if ( (tokens = slice.call( match[0], 0 )).length > 2 &&
(token = tokens[0]).part === "ID" &&
contextNodeType === 9 && !xml &&
Expr.relative[ tokens[1].part ] ) {
if ( !Sizzle.isXML( node ) ) {
try {
if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
var ret = matches.call( node, expr );
// IE 9's matchesSelector returns false on disconnected nodes
if ( ret || !disconnectedMatch ||
// As well, disconnected nodes are said to be in a document
// fragment in IE 9, so check for that
node.document && node.document.nodeType !== 11 ) {
return ret;
}
}
} catch(e) {}
context = Expr.find["ID"]( token.captures[0].replace( rbackslash, "" ), context, xml )[0];
if ( !context ) {
return results;
}
return Sizzle(expr, null, null, [node]).length > 0;
};
}
})();
selector = selector.slice( tokens.shift().string.length );
}
(function(){
var div = document.createElement("div");
findContext = ( (match = rsibling.exec( tokens[0].string )) && !match.index && context.parentNode ) || context;
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
// Reduce the set if possible
lastToken = "";
for ( i = tokens.length - 1; i >= 0; i-- ) {
token = tokens[i];
type = token.part;
lastToken = token.string + lastToken;
if ( Expr.relative[ type ] ) {
break;
}
if ( Expr.order.test(type) ) {
elements = Expr.find[ type ]( token.captures[0].replace( rbackslash, "" ), findContext, xml );
if ( elements == null ) {
continue;
} else {
selector = selector.slice( 0, selector.length - lastToken.length ) +
lastToken.replace( matchExpr[ type ], "" );
// Opera can't find a second classname (in 9.6)
// Also, make sure that getElementsByClassName actually exists
if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
return;
}
if ( !selector ) {
push.apply( results, slice.call(elements, 0) );
}
// Safari caches class attributes, doesn't catch changes (in 3.2)
div.lastChild.className = "e";
if ( div.getElementsByClassName("e").length === 1 ) {
return;
break;
}
}
}
}
Expr.order.splice(1, 0, "CLASS");
Expr.find.CLASS = function( match, context, isXML ) {
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
return context.getElementsByClassName(match[1]);
// Only loop over the given elements once
if ( selector ) {
matcher = compile( selector, context, xml );
dirruns = matcher.dirruns++;
if ( elements == null ) {
elements = Expr.find["TAG"]( "*", (rsibling.test( selector ) && context.parentNode) || context );
}
};
// release memory in IE
div = null;
})();
for ( i = 0; (elem = elements[i]); i++ ) {
cachedruns = matcher.runs++;
if ( matcher(elem) ) {
results.push( elem );
}
}
}
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
return results;
}
if ( elem ) {
var match = false;
// Patch for jsdom
// we use sizzle to implement querySelectorAll, so sizzle cannot use it
if ( document.querySelectorAll && false ) {
(function() {
var disconnectedMatch,
oldSelect = select,
rescape = /'|\\/g,
rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
rbuggyQSA = [],
// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
// A support test would require too much code (would include document ready)
// just skip matchesSelector for :active
rbuggyMatches = [":active"],
matches = docElem.matchesSelector ||
docElem.mozMatchesSelector ||
docElem.webkitMatchesSelector ||
docElem.oMatchesSelector ||
docElem.msMatchesSelector;
elem = elem[dir];
// Build QSA regex
// Regex strategy adopted from Diego Perini
assert(function( div ) {
// Select is set to empty string on purpose
// This is to test IE's treatment of not explictly
// setting a boolean content attribute,
// since its presence should be enough
// http://bugs.jquery.com/ticket/12359
div.innerHTML = "<select><option selected=''></option></select>";
while ( elem ) {
if ( elem[ expando ] === doneName ) {
match = checkSet[elem.sizset];
break;
}
// IE8 - Some boolean attributes are not treated correctly
if ( !div.querySelectorAll("[selected]").length ) {
rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
}
if ( elem.nodeType === 1 && !isXML ){
elem[ expando ] = doneName;
elem.sizset = i;
}
// Webkit/Opera - :checked should return selected option elements
// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
// IE8 throws error here (do not put tests after this one)
if ( !div.querySelectorAll(":checked").length ) {
rbuggyQSA.push(":checked");
}
});
if ( elem.nodeName.toLowerCase() === cur ) {
match = elem;
break;
}
assert(function( div ) {
elem = elem[dir];
// Opera 10-12/IE9 - ^= $= *= and empty values
// Should not select anything
div.innerHTML = "<p test=''></p>";
if ( div.querySelectorAll("[test^='']").length ) {
rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
}
checkSet[i] = match;
}
}
}
// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
// IE8 throws error here (do not put tests after this one)
div.innerHTML = "<input type='hidden'/>";
if ( !div.querySelectorAll(":enabled").length ) {
rbuggyQSA.push(":enabled", ":disabled");
}
});
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
if ( elem ) {
var match = false;
select = function( selector, context, results, seed, xml ) {
// Only use querySelectorAll when not filtering,
// when this is not xml,
// and when no QSA bugs apply
if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
if ( context.nodeType === 9 ) {
try {
push.apply( results, slice.call(context.querySelectorAll( selector ), 0) );
return results;
} catch(qsaError) {}
// qSA works strangely on Element-rooted queries
// We can work around this by specifying an extra ID on the root
// and working up from there (Thanks to Andrew Dupont for the technique)
// IE 8 doesn't work on object elements
} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
var groups, i, len,
old = context.getAttribute("id"),
nid = old || expando,
newContext = rsibling.test( selector ) && context.parentNode || context;
elem = elem[dir];
if ( old ) {
nid = nid.replace( rescape, "\\$&" );
} else {
context.setAttribute( "id", nid );
}
while ( elem ) {
if ( elem[ expando ] === doneName ) {
match = checkSet[elem.sizset];
break;
}
if ( elem.nodeType === 1 ) {
if ( !isXML ) {
elem[ expando ] = doneName;
elem.sizset = i;
groups = tokenize(selector, context, xml);
// Trailing space is unnecessary
// There is always a context check
nid = "[id='" + nid + "']";
for ( i = 0, len = groups.length; i < len; i++ ) {
groups[i] = nid + groups[i].selector;
}
if ( typeof cur !== "string" ) {
if ( elem === cur ) {
match = true;
break;
try {
push.apply( results, slice.call( newContext.querySelectorAll(
groups.join(",")
), 0 ) );
return results;
} catch(qsaError) {
} finally {
if ( !old ) {
context.removeAttribute("id");
}
} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
match = elem;
break;
}
}
elem = elem[dir];
}
checkSet[i] = match;
}
}
}
return oldSelect( selector, context, results, seed, xml );
};
if ( document.documentElement.contains ) {
Sizzle.contains = function( a, b ) {
return a !== b && (a.contains ? a.contains(b) : true);
};
if ( matches ) {
assert(function( div ) {
// Check to see if it's possible to do matchesSelector
// on a disconnected node (IE 9)
disconnectedMatch = matches.call( div, "div" );
} else if ( document.documentElement.compareDocumentPosition ) {
Sizzle.contains = function( a, b ) {
return !!(a.compareDocumentPosition(b) & 16);
};
// This should fail with an exception
// Gecko does not error, returns false instead
try {
matches.call( div, "[test!='']:sizzle" );
rbuggyMatches.push( matchExpr["PSEUDO"].source, matchExpr["POS"].source, "!=" );
} catch ( e ) {}
});
} else {
Sizzle.contains = function() {
return false;
};
}
// rbuggyMatches always contains :active, so no need for a length check
rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") );
Sizzle.isXML = function( elem ) {
// documentElement is verified for cases where it doesn't yet exist
// (such as loading iframes in IE - #4833)
var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
Sizzle.matchesSelector = function( elem, expr ) {
// Make sure that attribute selectors are quoted
expr = expr.replace( rattributeQuotes, "='$1']" );
return documentElement ? documentElement.nodeName !== "HTML" : false;
};
// rbuggyMatches always contains :active, so no need for an existence check
if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) {
try {
var ret = matches.call( elem, expr );
var posProcess = function( selector, context, seed ) {
var match,
tmpSet = [],
later = "",
root = context.nodeType ? [context] : context;
// IE 9's matchesSelector returns false on disconnected nodes
if ( ret || disconnectedMatch ||
// As well, disconnected nodes are said to be in a document
// fragment in IE 9
elem.document && elem.document.nodeType !== 11 ) {
return ret;
}
} catch(e) {}
}
// Position selectors must be done after the filter
// And so must :not(positional) so we move all PSEUDOs to the end
while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
later += match[0];
selector = selector.replace( Expr.match.PSEUDO, "" );
}
return Sizzle( expr, null, null, [ elem ] ).length > 0;
};
}
})();
}
selector = Expr.relative[selector] ? selector + "*" : selector;
// Deprecated
Expr.setFilters["nth"] = Expr.setFilters["eq"];
for ( var i = 0, l = root.length; i < l; i++ ) {
Sizzle( selector, root[i], tmpSet, seed );
}
// Back-compat
Expr.filters = Expr.pseudos;
return Sizzle.filter( later, tmpSet );
};
// EXPOSE
/* patch for jsdom */
return Sizzle;
/*
if ( typeof define === "function" && define.amd ) {
define(function() { return Sizzle; });
} else {
window.Sizzle = Sizzle;
}
*/
// EXPOSE
};
};

@@ -0,0 +0,0 @@ /**

@@ -0,0 +0,0 @@ Copyright (c) 2010 Elijah Insua

{
"name": "jsdom",
"version": "0.2.15",
"description": "A javascript implementation of the W3C DOM",
"version": "0.2.16",
"description": "A JavaScript implementation of the W3C DOM",
"keywords": [
"dom",
"w3c",
"javascript"
"html"
],
"maintainers": [{
"name": "Elijah Insua",
"email": "tmpvar@gmail.com",
"url": "http://tmpvar.com"
}],
"maintainers": [
{
"name": "Elijah Insua",
"email": "tmpvar@gmail.com",
"url": "http://tmpvar.com"
},
{
"name": "Domenic Denicola",
"email": "domenic@domenicdenicola.com",
"url": "http://domenicdenicola.com"
}
],
"contributors": [

@@ -57,3 +64,2 @@ {

"name": "Sam Ruby",
"email": "N/A",
"url": "http://intertwingly.net/blog/"

@@ -154,2 +160,7 @@ },

"email" : "jroberts@logitech.com"
},
{
"name" : "Chad Walker",
"email" : "chad@chad-cat-lore-eddie.com",
"url" : "https://github.com/chad3814"
}

@@ -179,3 +190,4 @@ ],

"request" : "2.x",
"cssom" : "0.2.x",
"cssom" : ">=0.2.2",
"cssstyle" : "0.2.x",
"contextify" : "0.1.x"

@@ -191,7 +203,9 @@ },

},
"engines" : { "node" : ">=0.1.9" },
"directories": {
"lib": "./lib/jsdom"
},
"scripts": {
"test": "node ./test/runner"
},
"main": "./lib/jsdom"
}
# jsdom
A javascript implementation of the W3C DOM.
A JavaScript implementation of the W3C DOM.
## Install
npm install jsdom
```bash
$ npm install jsdom
```
or
git clone http://github.com/tmpvar/jsdom.git
cd jsdom
npm link
## Human contact
see: [mailing list][]
see: [mailing list](http://groups.google.com/group/jsdom)
[mailing list]: http://groups.google.com/group/jsdom
## Easymode

@@ -30,101 +21,108 @@

// Count all of the links from the nodejs build page
var jsdom = require("jsdom");
```js
// Count all of the links from the nodejs build page
var jsdom = require("jsdom");
jsdom.env("http://nodejs.org/dist/", [
'http://code.jquery.com/jquery-1.5.min.js'
],
function(errors, window) {
console.log("there have been", window.$("a").length, "nodejs releases!");
});
jsdom.env(
"http://nodejs.org/dist/",
["http://code.jquery.com/jquery.js"],
function (errors, window) {
console.log("there have been", window.$("a").length, "nodejs releases!");
}
);
```
or with raw html
or with raw HTML
// Run some jQuery on a html fragment
var jsdom = require('jsdom');
```js
// Run some jQuery on a html fragment
var jsdom = require("jsdom");
jsdom.env('<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom\'s Homepage</a></p>', [
'http://code.jquery.com/jquery-1.5.min.js'
],
function(errors, window) {
console.log("contents of a.the-link:", window.$("a.the-link").text());
});
jsdom.env(
'<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom\'s Homepage</a></p>',
["http://code.jquery.com/jquery.js"],
function(errors, window) {
console.log("contents of a.the-link:", window.$("a.the-link").text());
}
);
```
or with a configuration object
// Print all of the news items on hackernews
var jsdom = require('jsdom');
```js
// Print all of the news items on hackernews
var jsdom = require("jsdom");
jsdom.env({
html: 'http://news.ycombinator.com/',
scripts: [
'http://code.jquery.com/jquery-1.5.min.js'
],
done: function(errors, window) {
var $ = window.$;
console.log('HN Links');
$('td.title:not(:last) a').each(function() {
console.log(' -', $(this).text());
});
}
jsdom.env({
html: "http://news.ycombinator.com/",
scripts: ["http://code.jquery.com/jquery.js"],
done: function (errors, window) {
var $ = window.$;
console.log("HN Links");
$("td.title:not(:last) a").each(function() {
console.log(" -", $(this).text());
});
}
});
```
or with raw javascript source
or with raw JavaScript source
// Print all of the news items on hackernews
var jsdom = require('jsdom');
var fs = require('fs');
var jquery = fs.readFileSync("./jquery-1.6.2.min.js").toString();
```js
// Print all of the news items on hackernews
var jsdom = require("jsdom");
var fs = require("fs");
var jquery = fs.readFileSync("./jquery.js").toString();
jsdom.env({
html: 'http://news.ycombinator.com/',
src: [
jquery
],
done: function(errors, window) {
var $ = window.$;
console.log('HN Links');
$('td.title:not(:last) a').each(function() {
console.log(' -', $(this).text());
});
}
jsdom.env({
html: "http://news.ycombinator.com/",
src: [jquery],
done: function (errors, window) {
var $ = window.$;
console.log("HN Links");
$("td.title:not(:last) a").each(function() {
console.log(" -", $(this).text());
});
}
});
```
### How it works
`jsdom.env` is built for ease of use, which is rare in the world of the DOM! Since the web has some absolutely horrible javascript on it, as of jsdom 0.2.0 `jsdom.env` will not process external resources (scripts, images, etc). If you want to process the javascript use one of the methods below (`jsdom.jsdom` or `jsdom.jQueryify`)
`jsdom.env` is built for ease of use, which is rare in the world of the DOM! Since the web has some absolutely horrible JavaScript on it, as of jsdom 0.2.0 `jsdom.env` will not process external resources (scripts, images, etc). If you want to process the JavaScript use one of the methods below (`jsdom.jsdom` or `jsdom.jQueryify`)
jsdom.env(html, [scripts], [config], callback)
```js
jsdom.env(html, [scripts], [config], callback);
```
- `html` (**required**)
May be a url, html fragment, or file
- `html` (**required**): may be a URL, HTML fragment, or file.
- `scripts` (**optional**): may contain files or URLs.
- `config` (**optional**): see below.
- `callback` (**required**): takes two arguments:
- `errors`: an array of errors
- `window`: a brand new window
- `scripts` (**optional**)
May contain files or urls
_example:_
- `callback` (**required**)
Takes 2 arguments:
- `errors` : array of errors
- `window` : a brand new window
```js
jsdom.env(html, function (errors, window) {
// free memory associated with the window
window.close();
});
```
_example:_
If you would like to specify a configuration object only:
jsdom.env(html, function(`errors`, `window`) {
// free memory associated with the window
window.close();
});
```js
jsdom.env(config);
```
If you would like to specify a configuration object
- `config.html`: see `html` above.
- `config.scripts`: see `scripts` above.
- `config.src`: an array of JavaScript strings that will be evaluated against the resulting document. Similar to `scripts`, but it accepts JavaScript instead of paths/URLs.
- `config.done`: see `callback` above.
- `config.document`:
- `referer`: the new document will have this referer
- `cookie`: manually set a cookie value, e.g. `'key=value; expires=Wed, Sep 21 2011 12:00:00 GMT; path=/'`
- `config.features` : see `Flexibility` section below. **Note**: the default feature set for jsdom.env does _not_ include fetching remote JavaScript and executing it. This is something that you will need to **carefully** enable yourself.
jsdom.env({ /* config */ })
- config.html : see `html` above
- config.scripts : see `scripts` above
- config.src : An array of javascript strings that will be evaluated against the resulting document. Similar to `scripts`, but it accepts javascript instead of paths/urls.
- config.done : see `callback` above
- config.document :
- referer : the new document will have this referer
- cookie : manually set a cookie value i.e. `'key=value; expires=Wed, Sep 21 2011 12:00:00 GMT; path=/'`
- config.features : see `Flexibility` section below. **Note**: the default feature set for jsdom.env does _not_ include fetching remote javascript and executing it. This is something that you will need to **carefully** enable yourself.
## For the hardcore

@@ -134,44 +132,47 @@

var jsdom = require("jsdom").jsdom,
doc = jsdom(markup, level, options),
window = doc.createWindow();
```js
var jsdom = require("jsdom").jsdom;
var doc = jsdom(markup, level, options);
var window = doc.createWindow();
```
- `markup` is an html/xml document to be parsed. You can also pass `null` or an undefined value to get a basic document with empty head and body tags. Document fragments are also supported (including `""`), and will behave as sanely as possible (eg. the resulting document will lack the `head`, `body` and `documentElement` properties if the corresponding elements aren't included).
- `level` is `null` (which means level3) by default, but you can pass another level if you'd like.
- `markup` is an HTML/XML document to be parsed. You can also pass `null` or an undefined value to get a basic document with empty `<head>` and `<body>` tags. Document fragments are also supported (including `""`), and will behave as sanely as possible (e.g. the resulting document will lack the `head`, `body` and `documentElement` properties if the corresponding elements aren't included).
- `level` is `null` (which means level3) by default, but you can pass another level if you'd like.
var jsdom = require('jsdom'),
doc = jsdom.jsdom('<html><body></body></html>', jsdom.level(1, 'core'))
```js
var jsdom = require("jsdom");
var doc = jsdom.jsdom("<html><body></body></html>", jsdom.level(1, "core"));
```
- `options` see the **Flexibility** section below
- `options` see the **Flexibility** section below.
### Flexibility
One of the goals of jsdom is to be as minimal and light as possible. This section details how
someone can change the behavior of `Document`s on the fly. These features are baked into
the `DOMImplementation` that every `Document` has, and may be tweaked in two ways:
One of the goals of jsdom is to be as minimal and light as possible. This section details how someone can change the behavior of `Document`s on the fly. These features are baked into the `DOMImplementation` that every `Document` has, and may be tweaked in two ways:
1. When you create a new `Document` using the jsdom builder (`require('jsdom').jsdom()`)
1. When you create a new `Document` using the jsdom builder (`require("jsdom").jsdom()`)
var jsdom = require('jsdom').jsdom,
doc = jsdom("<html><body></body></html>", null, {
features: {
FetchExternalResources : ['img']
}
});
```js
var jsdom = require("jsdom").jsdom;
var doc = jsdom("<html><body></body></html>", null, {
features: {
FetchExternalResources : ["img"]
}
});
```
Do note, that this will only affect the document that is currently being created. All other documents
will use the defaults specified below (see: Default Features)
Do note, that this will only affect the document that is currently being created. All other documents will use the defaults specified below (see: Default Features).
2. Previous to creating any documents you can modify the defaults for all future documents
2. Before creating any documents, you can modify the defaults for all future documents:
require('jsdom').defaultDocumentFeatures = {
FetchExternalResources : ['script'],
ProcessExternalResources : false,
MutationEvents : false,
QuerySelector : false
}
```js
require("jsdom").defaultDocumentFeatures = {
FetchExternalResources: ["script"],
ProcessExternalResources: false,
MutationEvents: false,
QuerySelector: false
};
```
#### Default Features

@@ -183,29 +184,37 @@

`FetchExternalResources`
_Default_: ['script']
_Allowed_: ['script', 'img', 'css', 'frame', 'link'] or false
Enables/Disables fetching files over the filesystem/http
- _Default_: `["script"]`
- _Allowed_: `["script", "img", "css", "frame", "iframe", "link"]` or `false`
Enables/disables fetching files over the file system/HTTP.
`ProcessExternalResources`
_default_: ['script']
_allowed_: ['script'] or false
Disabling this will disable script execution (currently only javascript).
- _Default_: `["script"]`
- _Allowed_: `["script"]` or `false`
Disabling this will disable script execution (currently only JavaScript).
`MutationEvents`
_default_: '2.0'
_allowed_ : '2.0' or false
- _Default_: `"2.0"`
- _Allowed_ : `"2.0"` or `false`
Initially enabled to be up to spec. Disable this if you do not need mutation events and want jsdom to be a bit more efficient.
**Note**: `ProcessExternalResources` requires this to be enabled
**Note**: `ProcessExternalResources` requires this to be enabled.
`QuerySelector`
_default_ : false
_allowed_ : true
This feature is backed by [sizzle][] but currently causes problems with some libraries. Enable this if you want `document.querySelector` and friends, but be aware that many libraries feature detect for this, and it may cause you a bit of trouble.
- _Default_ : `false`
- _Allowed_ : `true`
[sizzle]:http://sizzlejs.com/
This feature is backed by [sizzle][] but currently causes problems with some libraries. Enable this if you want `document.querySelector` and friends, but be aware that many libraries feature detect for this, and it may cause you a bit of trouble.
[sizzle]: http://sizzlejs.com/
## Canvas
jsdom includes support for using the [canvas](https://npmjs.org/package/canvas) package to extend any `<canvas>` elements with the canvas API. To make this work, you need to include canvas as a dependency in your project, as a peer of jsdom. If jsdom can find the canvas package, it will use it, but if it's not present, then `<canvas>` elements will behave like `<div>`s.
# More Examples

@@ -215,72 +224,103 @@

var jsdom = require("jsdom"),
window = jsdom.createWindow();
```js
var jsdom = require("jsdom");
var window = jsdom.createWindow();
console.log(window.document);
// output: undefined
console.log(window.document); // output: undefined
```
## Creating a document
var jsdom = require("jsdom"),
doc = new (jsdom.level(1, 'core').Document)();
console.log(doc.nodeName);
// outputs: #document
```js
var jsdom = require("jsdom");
var doc = new (jsdom.level(1, "core").Document)();
console.log(doc.nodeName); // outputs: #document
```
## Creating a browser-like BOM/DOM/Window
var jsdom = require("./lib/jsdom").jsdom,
document = jsdom("<html><head></head><body>hello world</body></html>"),
window = document.createWindow();
```js
var jsdom = require("jsdom").jsdom;
var document = jsdom("<html><head></head><body>hello world</body></html>");
var window = document.createWindow();
console.log(window.document.innerHTML);
// output: '<html><head></head><body>hello world</body></html>'
console.log(window.document.innerHTML);
// output: "<html><head></head><body>hello world</body></html>"
console.log(window.innerWidth)
// output: 1024
console.log(window.innerWidth);
// output: 1024
console.log(typeof window.document.getElementsByClassName);
// outputs: function
console.log(typeof window.document.getElementsByClassName);
// outputs: function
```
## jQueryify
var jsdom = require("jsdom"),
window = jsdom.jsdom().createWindow();
```js
var jsdom = require("jsdom");
var window = jsdom.jsdom().createWindow();
jsdom.jQueryify(window, 'http://code.jquery.com/jquery-1.4.2.min.js' , function() {
window.$('body').append('<div class="testing">Hello World, It works</div>');
console.log(window.$('.testing').text());
});
jsdom.jQueryify(window, "http://code.jquery.com/jquery.js", function () {
window.$("body").append('<div class="testing">Hello World, It works</div>');
console.log(window.$(".testing").text());
});
```
## Passing objects to scripts inside the page
```js
var jsdom = require("jsdom").jsdom;
var window = jsdom().createWindow();
window.__myObject = { foo: "bar" };
var scriptEl = window.document.createElement("script");
scriptEl.src = "anotherScript.js";
window.document.body.appendChild(scriptEl);
// anotherScript.js will have the ability to read `window.__myObject`, even
// though it originated in Node!
```
# Test Compliance:
level1/core 531/531 100%
level1/html 238/238 100%
level1/svg 527/527 100%
level2/core 283/283 100%
level2/html 687/687 100%
level2/style 4/4 100%
level2/extra 4/4 100%
level3/xpath 93/93 100%
window/index 5/5 100%
window/script 8/8 100%
window/frame 14/14 100%
sizzle/index 12/15 80%
jsdom/index 63/63 100%
--------------------------------------
TOTALS: 3/2472 failed; 99% success
TIME: 16730ms
```
level1/core 532/532 100%
level1/html 238/238 100%
level1/svg 527/527 100%
level2/core 283/283 100%
level2/html 694/694 100%
level2/style 5/5 100%
level2/extra 4/4 100%
level2/events 24/24 100%
level3/xpath 93/93 100%
window/index 5/5 100%
window/script 10/10 100%
window/frame 14/14 100%
sizzle/index 12/15 80%
jsdom/index 79/79 100%
jsonp/jsonp 1/1 100%
browser/contextifyReplacement 4/4 100%
browser/index 22/22 100%
------------------------------------------------------
TOTALS: 3/2550 failed; 99% success
```
## Running the tests
First you'll want to `npm install -g nodeunit` then `npm install --dev`
First you'll want to `npm install`. To run all the tests, use `npm test`, which just calls `node test/runner`.
Using `test/runner` you can slice and dice which tests your want to run from different levels. Usage is as follows:
Using `test/runner` directly, you can slice and dice which tests your want to run from different levels. Usage is as follows:
test/runner --help
Run the jsdom test suite
```
test/runner --help
Run the jsdom test suite
Options:
-s, --suites suites that you want to run. ie: -s level1/core,1/html,html [string]
-f, --fail-fast stop on the first failed test
-h, --help show the help
-t, --tests choose the test cases to run. ie: -t jquery
Options:
-s, --suites suites that you want to run. ie: -s level1/core,1/html,html [string]
-f, --fail-fast stop on the first failed test
-h, --help show the help
-t, --tests choose the test cases to run. ie: -t jquery
```

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc