API-CHANGE: updated jquery entwine to new version that is compatible with jQuery 1.5

This commit is contained in:
Julian Seidenberg 2011-02-24 10:03:38 +13:00
parent d045970d83
commit deb31b3bb4
30 changed files with 11882 additions and 7231 deletions

View File

@ -1,8 +1,8 @@
---
format: 1
handler:
commit: f09e97da777031a67e136945f8732890c84e3e65
commit: b0b8d4f3417db927eae24510f9a45dfe38bb7d37
branch: master
lock: false
repository_class: Piston::Git::Repository
repository_url: git://github.com/hafriedlander/jquery.entwine.git
repository_url: https://github.com/hafriedlander/jquery.entwine.git

View File

@ -6,7 +6,7 @@ FILE="dist/jquery.entwine-dist.js"
mkdir -p dist
rm dist/*.js
echo "/* jQuery.Entwine - Copyright 2009 Hamish Friedlander and SilverStripe. Version $VER. */" > $FILE
echo "/* jQuery.Entwine - Copyright 2009-2011 Hamish Friedlander and SilverStripe. Version $VER. */" > $FILE
for x in \
vendor/jquery.selector/jquery.class.js \
@ -40,4 +40,4 @@ done
# git add LICENSE
# git commit -m "Update dist to master version $VER"
# git checkout master
# git checkout master

View File

@ -1,1587 +0,0 @@
/* jQuery.Entwine - Copyright 2009 Hamish Friedlander and SilverStripe. Version . */
/* vendor/jquery.selector/jquery.class.js */
/**
* Very basic Class utility. Based on base and jquery.class.
*
* Class definition: var Foo = Base.extend({ init: function(){ Constructor }; method_name: function(){ Method } });
*
* Inheritance: var Bar = Foo.extend({ method_name: function(){ this._super(); } });
*
* new-less Constructor: new Foo(arg) <-same as-> Foo(arg)
*/
var Base;
(function(){
var marker = {}, fnTest = /xyz/.test(function(){var xyz;}) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
Base = function(){};
Base.addMethod = function(name, func) {
var parent = this._super && this._super.prototype;
if (parent && fnTest.test(func)) {
this.prototype[name] = function(){
var tmp = this._super;
this._super = parent[name];
try {
var ret = func.apply(this, arguments);
}
finally {
this._super = tmp;
}
return ret;
};
}
else this.prototype[name] = func;
};
Base.addMethods = function(props) {
for (var name in props) {
if (typeof props[name] == 'function') this.addMethod(name, props[name]);
else this.prototype[name] = props[name];
}
};
Base.subclassOf = function(parentkls) {
var kls = this;
while (kls) {
if (kls === parentkls) return true;
kls = kls._super;
}
};
// Create a new Class that inherits from this class
Base.extend = function(props) {
// The dummy class constructor
var Kls = function() {
if (arguments[0] === marker) return;
if (this instanceof Kls) {
if (this.init) this.init.apply(this, arguments);
}
else {
var ret = new Kls(marker); if (ret.init) ret.init.apply(ret, arguments); return ret;
}
};
// Add the common class variables and methods
Kls.constructor = Kls;
Kls.extend = Base.extend;
Kls.addMethod = Base.addMethod;
Kls.addMethods = Base.addMethods;
Kls.subclassOf = Base.subclassOf;
Kls._super = this;
// Attach the parent object to the inheritance chain
Kls.prototype = new this(marker);
Kls.prototype.constructor = Kls;
// Copy the properties over onto the new prototype
Kls.addMethods(props);
return Kls;
};
})();;
/* vendor/jquery.selector/jquery.selector.js */
(function($){
var tokens = {
UNICODE: /\\[0-9a-f]{1,6}(?:\r\n|[ \n\r\t\f])?/,
ESCAPE: /(?:UNICODE)|\\[^\n\r\f0-9a-f]/,
NONASCII: /[^\x00-\x7F]/,
NMSTART: /[_a-z]|(?:NONASCII)|(?:ESCAPE)/,
NMCHAR: /[_a-z0-9-]|(?:NONASCII)|(?:ESCAPE)/,
IDENT: /-?(?:NMSTART)(?:NMCHAR)*/,
NL: /\n|\r\n|\r|\f/,
STRING: /(?:STRING1)|(?:STRING2)|(?:STRINGBARE)/,
STRING1: /"(?:(?:ESCAPE)|\\(?:NL)|[^\n\r\f\"])*"/,
STRING2: /'(?:(?:ESCAPE)|\\(?:NL)|[^\n\r\f\'])*'/,
STRINGBARE: /(?:(?:ESCAPE)|\\(?:NL)|[^\n\r\f\]])*/,
FUNCTION: /(?:IDENT)\(\)/,
INTEGER: /[0-9]+/,
WITHN: /([-+])?(INTEGER)?(n)\s*(?:([-+])\s*(INTEGER))?/,
WITHOUTN: /([-+])?(INTEGER)/
};
var rx = {
not: /:not\(/,
not_end: /\)/,
tag: /((?:IDENT)|\*)/,
id: /#(IDENT)/,
cls: /\.(IDENT)/,
attr: /\[\s*(IDENT)\s*(?:([^=]?=)\s*(STRING)\s*)?\]/,
pseudo_el: /(?::(first-line|first-letter|before|after))|(?:::((?:FUNCTION)|(?:IDENT)))/,
pseudo_cls_nth: /:nth-child\(\s*(?:(?:WITHN)|(?:WITHOUTN)|(odd|even))\s*\)/,
pseudo_cls: /:(IDENT)/,
comb: /\s*(\+|~|>)\s*|\s+/,
comma: /\s*,\s*/,
important: /\s+!important\s*$/
};
/* Replace placeholders with actual regex, and mark all as case insensitive */
var token = /[A-Z][A-Z0-9]+/;
for (var k in rx) {
var m, src = rx[k].source;
while (m = src.match(token)) src = src.replace(m[0], tokens[m[0]].source);
rx[k] = new RegExp(src, 'gi');
}
/**
* A string that matches itself against regexii, and keeps track of how much of itself has been matched
*/
var ConsumableString = Base.extend({
init: function(str) {
this.str = str;
this.pos = 0;
},
match: function(rx) {
var m;
rx.lastIndex = this.pos;
if ((m = rx.exec(this.str)) && m.index == this.pos ) {
this.pos = rx.lastIndex ? rx.lastIndex : this.str.length ;
return m;
}
return null;
},
peek: function(rx) {
var m;
rx.lastIndex = this.pos;
if ((m = rx.exec(this.str)) && m.index == this.pos ) return m;
return null;
},
showpos: function() {
return this.str.slice(0,this.pos)+'<HERE>' + this.str.slice(this.pos);
},
done: function() {
return this.pos == this.str.length;
}
});
/* A base class that all Selectors inherit off */
var SelectorBase = Base.extend({});
/**
* A class representing a Simple Selector, as per the CSS3 selector spec
*/
var SimpleSelector = SelectorBase.extend({
init: function() {
this.tag = null;
this.id = null;
this.classes = [];
this.attrs = [];
this.nots = [];
this.pseudo_classes = [];
this.pseudo_els = [];
},
parse: function(selector) {
var m;
/* Pull out the initial tag first, if there is one */
if (m = selector.match(rx.tag)) this.tag = m[1];
/* Then for each selection type, try and find a match */
do {
if (m = selector.match(rx.not)) {
this.nots[this.nots.length] = SelectorsGroup().parse(selector);
if (!(m = selector.match(rx.not_end))) {
throw 'Invalid :not term in selector';
}
}
else if (m = selector.match(rx.id)) this.id = m[1];
else if (m = selector.match(rx.cls)) this.classes[this.classes.length] = m[1];
else if (m = selector.match(rx.attr)) this.attrs[this.attrs.length] = [ m[1], m[2], m[3] ];
else if (m = selector.match(rx.pseudo_el)) this.pseudo_els[this.pseudo_els.length] = m[1] || m[2];
else if (m = selector.match(rx.pseudo_cls_nth)) {
if (m[3]) {
var a = parseInt((m[1]||'')+(m[2]||'1'));
var b = parseInt((m[4]||'')+(m[5]||'0'));
}
else {
var a = m[8] ? 2 : 0;
var b = m[8] ? (4-m[8].length) : parseInt((m[6]||'')+m[7]);
}
this.pseudo_classes[this.pseudo_classes.length] = ['nth-child', [a, b]];
}
else if (m = selector.match(rx.pseudo_cls)) this.pseudo_classes[this.pseudo_classes.length] = [m[1]];
} while(m && !selector.done());
return this;
}
});
/**
* A class representing a Selector, as per the CSS3 selector spec
*/
var Selector = SelectorBase.extend({
init: function(){
this.parts = [];
},
parse: function(cons){
this.parts[this.parts.length] = SimpleSelector().parse(cons);
while (!cons.done() && !cons.peek(rx.comma) && (m = cons.match(rx.comb))) {
this.parts[this.parts.length] = m[1] || ' ';
this.parts[this.parts.length] = SimpleSelector().parse(cons);
}
return this.parts.length == 1 ? this.parts[0] : this;
}
});
/**
* A class representing a sequence of selectors, as per the CSS3 selector spec
*/
var SelectorsGroup = SelectorBase.extend({
init: function(){
this.parts = [];
},
parse: function(cons){
this.parts[this.parts.length] = Selector().parse(cons);
while (!cons.done() && (m = cons.match(rx.comma))) {
this.parts[this.parts.length] = Selector().parse(cons);
}
return this.parts.length == 1 ? this.parts[0] : this;
}
});
$.selector = function(s){
var cons = ConsumableString(s);
var res = SelectorsGroup().parse(cons);
res.selector = s;
if (!cons.done()) throw 'Could not parse selector - ' + cons.showpos() ;
else return res;
};
$.selector.SelectorBase = SelectorBase;
$.selector.SimpleSelector = SimpleSelector;
$.selector.Selector = Selector;
$.selector.SelectorsGroup = SelectorsGroup;
})(jQuery);
;
/* vendor/jquery.selector/jquery.selector.specifity.js */
(function($) {
$.selector.SimpleSelector.addMethod('specifity', function() {
if (this.spec) return this.spec;
var spec = [
this.id ? 1 : 0,
this.classes.length + this.attrs.length + this.pseudo_classes.length,
((this.tag && this.tag != '*') ? 1 : 0) + this.pseudo_els.length
];
$.each(this.nots, function(i,not){
var ns = not.specifity(); spec[0] += ns[0]; spec[1] += ns[1]; spec[2] += ns[2];
});
return this.spec = spec;
});
$.selector.Selector.addMethod('specifity', function(){
if (this.spec) return this.spec;
var spec = [0,0,0];
$.each(this.parts, function(i,part){
if (i%2) return;
var ps = part.specifity(); spec[0] += ps[0]; spec[1] += ps[1]; spec[2] += ps[2];
});
return this.spec = spec;
});
$.selector.SelectorsGroup.addMethod('specifity', function(){
if (this.spec) return this.spec;
var spec = [0,0,0];
$.each(this.parts, function(i,part){
var ps = part.specifity(); spec[0] += ps[0]; spec[1] += ps[1]; spec[2] += ps[2];
});
return this.spec = spec;
});
})(jQuery);
;
/* vendor/jquery.selector/jquery.selector.matches.js */
/*
This attempts to do the opposite of Sizzle.
Sizzle is good for finding elements for a selector, but not so good for telling if an individual element matches a selector
*/
(function($) {
/**** CAPABILITY TESTS ****/
var div = document.createElement('div');
div.innerHTML = '<form id="test"><input name="id" type="text"/></form>';
// In IE 6-7, getAttribute often does the wrong thing (returns similar to el.attr), so we need to use getAttributeNode on that browser
var getAttributeDodgy = div.firstChild.getAttribute('id') !== 'test';
// Does browser support Element.firstElementChild, Element.previousElementSibling, etc.
var hasElementTraversal = div.firstElementChild && div.firstElementChild.tagName == 'FORM';
// Does browser support Element.children
var hasChildren = div.children && div.children[0].tagName == 'FORM';
var FUNC_IN = /^\s*function\s*\([^)]*\)\s*\{/;
var FUNC_OUT = /}\s*$/;
var funcToString = function(f) {
return (''+f).replace(FUNC_IN,'').replace(FUNC_OUT,'');
};
// Can we use Function#toString ?
try {
var testFunc = function(){ return 'good'; };
if ((new Function('',funcToString(testFunc)))() != 'good') funcToString = false;
}
catch(e) { funcToString = false; console.log(e.message);/*pass*/ }
/**** INTRO ****/
var GOOD = /GOOD/g;
var BAD = /BAD/g;
var STARTS_WITH_QUOTES = /^['"]/g;
var join = function(js) {
return js.join('\n');
};
var join_complex = function(js) {
var code = new String(js.join('\n')); // String objects can have properties set. strings can't
code.complex = true;
return code;
};
/**** ATTRIBUTE ACCESSORS ****/
// Not all attribute names can be used as identifiers, so we encode any non-acceptable characters as hex
var varForAttr = function(attr) {
return '_' + attr.replace(/^[^A-Za-z]|[^A-Za-z0-9]/g, function(m){ return '_0x' + m.charCodeAt(0).toString(16) + '_'; });
};
var getAttr;
// Good browsers
if (!getAttributeDodgy) {
getAttr = function(attr){ return 'var '+varForAttr(attr)+' = el.getAttribute("'+attr+'");' ; };
}
// IE 6, 7
else {
// On IE 6 + 7, getAttribute still has to be called with DOM property mirror name, not attribute name. Map attributes to those names
var getAttrIEMap = { 'class': 'className', 'for': 'htmlFor' };
getAttr = function(attr) {
var ieattr = getAttrIEMap[attr] || attr;
return 'var '+varForAttr(attr)+' = el.getAttribute("'+ieattr+'",2) || (el.getAttributeNode("'+attr+'")||{}).nodeValue;';
};
}
/**** ATTRIBUTE COMPARITORS ****/
var attrchecks = {
'-': '!K',
'=': 'K != "V"',
'!=': 'K == "V"',
'~=': '_WS_K.indexOf(" V ") == -1',
'^=': '!K || K.indexOf("V") != 0',
'*=': '!K || K.indexOf("V") == -1',
'$=': '!K || K.substr(K.length-"V".length) != "V"'
};
/**** STATE TRACKER ****/
var State = $.selector.State = Base.extend({
init: function(){
this.reset();
},
reset: function() {
this.attrs = {}; this.wsattrs = {};
},
prev: function(){
this.reset();
if (hasElementTraversal) return 'el = el.previousElementSibling';
return 'while((el = el.previousSibling) && el.nodeType != 1) {}';
},
next: function() {
this.reset();
if (hasElementTraversal) return 'el = el.nextElementSibling';
return 'while((el = el.nextSibling) && el.nodeType != 1) {}';
},
prevLoop: function(body){
this.reset();
if (hasElementTraversal) return join([ 'while(el = el.previousElementSibling){', body]);
return join([
'while(el = el.previousSibling){',
'if (el.nodeType != 1) continue;',
body
]);
},
parent: function() {
this.reset();
return 'el = el.parentNode;';
},
parentLoop: function(body) {
this.reset();
return join([
'while((el = el.parentNode) && el.nodeType == 1){',
body,
'}'
]);
},
uses_attr: function(attr) {
if (this.attrs[attr]) return;
this.attrs[attr] = true;
return getAttr(attr);
},
uses_wsattr: function(attr) {
if (this.wsattrs[attr]) return;
this.wsattrs[attr] = true;
return join([this.uses_attr(attr), 'var _WS_'+varForAttr(attr)+' = " "+'+varForAttr(attr)+'+" ";']);
},
save: function(lbl) {
return 'var el'+lbl+' = el;';
},
restore: function(lbl) {
this.reset();
return 'el = el'+lbl+';';
}
});
/**** PSEUDO-CLASS DETAILS ****/
var pseudoclschecks = {
'first-child': join([
'var cel = el;',
'while(cel = cel.previousSibling){ if (cel.nodeType === 1) BAD; }'
]),
'last-child': join([
'var cel = el;',
'while(cel = cel.nextSibling){ if (cel.nodeType === 1) BAD; }'
]),
'nth-child': function(a,b) {
var get_i = join([
'var i = 1, cel = el;',
'while(cel = cel.previousSibling){',
'if (cel.nodeType === 1) i++;',
'}'
]);
if (a == 0) return join([
get_i,
'if (i- '+b+' != 0) BAD;'
]);
else if (b == 0 && a >= 0) return join([
get_i,
'if (i%'+a+' != 0 || i/'+a+' < 0) BAD;'
]);
else if (b == 0 && a < 0) return join([
'BAD;'
]);
else return join([
get_i,
'if ((i- '+b+')%'+a+' != 0 || (i- '+b+')/'+a+' < 0) BAD;'
]);
}
};
// Needs to refence contents of object, so must be injected after definition
pseudoclschecks['only-child'] = join([
pseudoclschecks['first-child'],
pseudoclschecks['last-child']
]);
/**** SimpleSelector ****/
$.selector.SimpleSelector.addMethod('compile', function(el) {
var js = [];
/* Check against element name */
if (this.tag && this.tag != '*') {
js[js.length] = 'if (el.tagName != "'+this.tag.toUpperCase()+'") BAD;';
}
/* Check against ID */
if (this.id) {
js[js.length] = el.uses_attr('id');
js[js.length] = 'if (_id !== "'+this.id+'") BAD;';
}
/* Build className checking variable */
if (this.classes.length) {
js[js.length] = el.uses_wsattr('class');
/* Check against class names */
$.each(this.classes, function(i, cls){
js[js.length] = 'if (_WS__class.indexOf(" '+cls+' ") == -1) BAD;';
});
}
/* Check against attributes */
$.each(this.attrs, function(i, attr){
js[js.length] = (attr[1] == '~=') ? el.uses_wsattr(attr[0]) : el.uses_attr(attr[0]);
var check = attrchecks[ attr[1] || '-' ];
check = check.replace( /K/g, varForAttr(attr[0])).replace( /V/g, attr[2] && attr[2].match(STARTS_WITH_QUOTES) ? attr[2].slice(1,-1) : attr[2] );
js[js.length] = 'if ('+check+') BAD;';
});
/* Check against nots */
$.each(this.nots, function(i, not){
var lbl = ++lbl_id;
var func = join([
'l'+lbl+':{',
not.compile(el).replace(BAD, 'break l'+lbl).replace(GOOD, 'BAD'),
'}'
]);
if (!(not instanceof $.selector.SimpleSelector)) func = join([
el.save(lbl),
func,
el.restore(lbl)
]);
js[js.length] = func;
});
/* Check against pseudo-classes */
$.each(this.pseudo_classes, function(i, pscls){
var check = pseudoclschecks[pscls[0]];
if (check) {
js[js.length] = ( typeof check == 'function' ? check.apply(this, pscls[1]) : check );
}
else if (check = $.find.selectors.filters[pscls[0]]) {
if (funcToString) {
js[js.length] = funcToString(check).replace(/elem/g,'el').replace(/return([^;]+);/,'if (!($1)) BAD;');
}
else {
js[js.length] = 'if (!$.find.selectors.filters.'+pscls[0]+'(el)) BAD;';
}
}
});
js[js.length] = 'GOOD';
/* Pass */
return join(js);
});
var lbl_id = 0;
/** Turns an compiled fragment into the first part of a combination */
function as_subexpr(f) {
if (f.complex)
return join([
'l'+(++lbl_id)+':{',
f.replace(GOOD, 'break l'+lbl_id),
'}'
]);
else
return f.replace(GOOD, '');
}
var combines = {
' ': function(el, f1, f2) {
return join_complex([
f2,
'while(true){',
el.parent(),
'if (!el || el.nodeType !== 1) BAD;',
f1.compile(el).replace(BAD, 'continue'),
'}'
]);
},
'>': function(el, f1, f2) {
return join([
f2,
el.parent(),
'if (!el || el.nodeType !== 1) BAD;',
f1.compile(el)
]);
},
'~': function(el, f1, f2) {
return join_complex([
f2,
el.prevLoop(),
f1.compile(el).replace(BAD, 'continue'),
'}',
'BAD;'
]);
},
'+': function(el, f1, f2) {
return join([
f2,
el.prev(),
'if (!el) BAD;',
f1.compile(el)
]);
}
};
$.selector.Selector.addMethod('compile', function(el) {
var l = this.parts.length;
var expr = this.parts[--l].compile(el);
while (l) {
var combinator = this.parts[--l];
expr = combines[combinator](el, this.parts[--l], as_subexpr(expr));
}
return expr;
});
$.selector.SelectorsGroup.addMethod('compile', function(el) {
var expr = [], lbl = ++lbl_id;
for (var i=0; i < this.parts.length; i++) {
expr[expr.length] = join([
i == 0 ? el.save(lbl) : el.restore(lbl),
'l'+lbl+'_'+i+':{',
this.parts[i].compile(el).replace(BAD, 'break l'+lbl+'_'+i),
'}'
]);
}
expr[expr.length] = 'BAD;';
return join(expr);
});
$.selector.SelectorBase.addMethod('matches', function(el){
this.matches = new Function('el', join([
'if (!el) return false;',
this.compile(new State()).replace(BAD, 'return false').replace(GOOD, 'return true')
]));
return this.matches(el);
});
})(jQuery);
;
/* src/jquery.focusinout.js */
(function($){
/**
* Add focusin and focusout support to bind and live for browers other than IE. Designed to be usable in a delegated fashion (like $.live)
* Copyright (c) 2007 Jörn Zaefferer
*/
$.support.focusInOut = !!($.browser.msie);
if (!$.support.focusInOut) {
// Emulate focusin and focusout by binding focus and blur in capturing mode
$.each({focus: 'focusin', blur: 'focusout'}, function(original, fix){
$.event.special[fix] = {
setup: function(){
if (!this.addEventListener) return false;
this.addEventListener(original, $.event.special[fix].handler, true);
},
teardown: function(){
if (!this.removeEventListener) return false;
this.removeEventListener(original, $.event.special[fix].handler, true);
},
handler: function(e){
arguments[0] = $.event.fix(e);
arguments[0].type = fix;
return $.event.handle.apply(this, arguments);
}
};
});
}
(function(){
//IE has some trouble with focusout with select and keyboard navigation
var activeFocus = null;
$(document)
.bind('focusin', function(e){
var target = e.realTarget || e.target;
if (activeFocus && activeFocus !== target) {
e.type = 'focusout';
$(activeFocus).trigger(e);
e.type = 'focusin';
e.target = target;
}
activeFocus = target;
})
.bind('focusout', function(e){
activeFocus = null;
});
})();
})(jQuery);;
/* src/jquery.entwine.js */
var console;
(function($) {
var namespaces = {};
$.entwine = function() {
$.fn.entwine.apply(null, arguments);
};
/**
* A couple of utility functions for accessing the store outside of this closure, and for making things
* operate in a little more easy-to-test manner
*/
$.extend($.entwine, {
/**
* Get all the namespaces. Useful for introspection? Internal interface of Namespace not guaranteed consistant
*/
namespaces: namespaces,
/**
* Remove all entwine rules
*/
clear_all_rules: function() {
// Remove proxy functions
for (var k in $.fn) { if ($.fn[k].entwine) delete $.fn[k] ; }
// Remove bound events - TODO: Make this pluggable, so this code can be moved to jquery.entwine.events.js
$(document).unbind('.entwine');
// Remove namespaces, and start over again
namespaces = $.entwine.namespaces = {};
},
WARN_LEVEL_NONE: 0,
WARN_LEVEL_IMPORTANT: 1,
WARN_LEVEL_BESTPRACTISE: 2,
/**
* Warning level. Set to a higher level to get warnings dumped to console.
*/
warningLevel: 0,
/** Utility to optionally display warning messages depending on level */
warn: function(message, level) {
if (level <= $.entwine.warningLevel && console && console.warn) {
console.warn(message);
if (console.trace) console.trace();
}
},
warn_exception: function(where, /* optional: */ on, e) {
if ($.entwine.WARN_LEVEL_IMPORTANT <= $.entwine.warningLevel && console && console.warn) {
if (arguments.length == 2) { e = on; on = null; }
if (on) console.warn('Uncaught exception',e,'in',where,'on',on);
else console.warn('Uncaught exception',e,'in',where);
if (e.stack) console.warn("Stack Trace:\n" + e.stack);
}
}
});
/** Stores a count of definitions, so that we can sort identical selectors by definition order */
var rulecount = 0;
var Rule = Base.extend({
init: function(selector, name) {
this.selector = selector;
this.specifity = selector.specifity();
this.important = 0;
this.name = name;
this.rulecount = rulecount++;
}
});
Rule.compare = function(a, b) {
var as = a.specifity, bs = b.specifity;
return (a.important - b.important) ||
(as[0] - bs[0]) ||
(as[1] - bs[1]) ||
(as[2] - bs[2]) ||
(a.rulecount - b.rulecount) ;
};
$.entwine.RuleList = function() {
var list = [];
list.addRule = function(selector, name){
var rule = Rule(selector, name);
list[list.length] = rule;
list.sort(Rule.compare);
return rule;
};
return list;
};
var handlers = [];
/**
* A Namespace holds all the information needed for adding entwine methods to a namespace (including the _null_ namespace)
*/
$.entwine.Namespace = Base.extend({
init: function(name){
if (name && !name.match(/^[A-Za-z0-9.]+$/)) $.entwine.warn('Entwine namespace '+name+' is not formatted as period seperated identifiers', $.entwine.WARN_LEVEL_BESTPRACTISE);
name = name || '__base';
this.name = name;
this.store = {};
namespaces[name] = this;
if (name == "__base") {
this.injectee = $.fn;
this.$ = $;
}
else {
// We're in a namespace, so we build a Class that subclasses the jQuery Object Class to inject namespace functions into
var subfn = function(){};
this.injectee = subfn.prototype = new $();
// And then we provide an overriding $ that returns objects of our new Class, and an overriding pushStack to catch further selection building
var bound$ = this.$ = function(a) {
// Try the simple way first
var jq = $.fn.init.apply(new subfn(), arguments);
if (jq instanceof subfn) return jq;
// That didn't return a bound object, so now we need to copy it
var rv = new subfn();
rv.selector = jq.selector; rv.context = jq.context; var i = rv.length = jq.length;
while (i--) rv[i] = jq[i];
return rv;
};
this.injectee.pushStack = function(elems, name, selector){
var ret = bound$(elems);
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
if ( name === "find" ) ret.selector = this.selector + (this.selector ? " " : "") + selector;
else if ( name ) ret.selector = this.selector + "." + name + "(" + selector + ")";
// Return the newly-formed element set
return ret;
};
// Copy static functions through from $ to this.$ so e.g. $.ajax still works
// @bug, @cantfix: Any class functions added to $ after this call won't get mirrored through
$.extend(this.$, $);
// We override entwine to inject the name of this namespace when defining blocks inside this namespace
var entwine_wrapper = this.injectee.entwine = function(spacename) {
var args = arguments;
if (!spacename || typeof spacename != 'string') { args = $.makeArray(args); args.unshift(name); }
else if (spacename.charAt(0) != '.') args[0] = name+'.'+spacename;
return $.fn.entwine.apply(this, args);
};
this.$.entwine = function() {
entwine_wrapper.apply(null, arguments);
};
for (var i = 0; i < handlers.length; i++) {
var handler = handlers[i], builder;
// Inject jQuery object method overrides
if (builder = handler.namespaceMethodOverrides) {
var overrides = builder(this);
for (var k in overrides) this.injectee[k] = overrides[k];
}
// Inject $.entwine function overrides
if (builder = handler.namespaceStaticOverrides) {
var overrides = builder(this);
for (var k in overrides) this.$.entwine[k] = overrides[k];
}
}
}
},
/**
* Returns a function that does selector matching against the function list for a function name
* Used by proxy for all calls, and by ctorProxy to handle _super calls
* @param {String} name - name of the function as passed in the construction object
* @param {String} funcprop - the property on the Rule object that gives the actual function to call
* @param {function} basefunc - the non-entwine function to use as the catch-all function at the bottom of the stack
*/
one: function(name, funcprop, basefunc) {
var namespace = this;
var funcs = this.store[name];
var one = function(el, args, i){
if (i === undefined) i = funcs.length;
while (i--) {
if (funcs[i].selector.matches(el)) {
var ret, tmp_i = el.i, tmp_f = el.f;
el.i = i; el.f = one;
try { ret = funcs[i][funcprop].apply(namespace.$(el), args); }
finally { el.i = tmp_i; el.f = tmp_f; }
return ret;
}
}
// If we didn't find a entwine-defined function, but there is a non-entwine function to use as a base, try that
if (basefunc) return basefunc.apply(namespace.$(el), args);
};
return one;
},
/**
* A proxy is a function attached to a callable object (either the base jQuery.fn or a subspace object) which handles
* finding and calling the correct function for each member of the current jQuery context
* @param {String} name - name of the function as passed in the construction object
* @param {function} basefunc - the non-entwine function to use as the catch-all function at the bottom of the stack
*/
build_proxy: function(name, basefunc) {
var one = this.one(name, 'func', basefunc);
var prxy = function() {
var rv, ctx = $(this);
var i = ctx.length;
while (i--) rv = one(ctx[i], arguments);
return rv;
};
return prxy;
},
bind_proxy: function(selector, name, func) {
var rulelist = this.store[name] || (this.store[name] = $.entwine.RuleList());
var rule = rulelist.addRule(selector, name); rule.func = func;
if (!this.injectee.hasOwnProperty(name) || !this.injectee[name].entwine) {
this.injectee[name] = this.build_proxy(name, this.injectee.hasOwnProperty(name) ? this.injectee[name] : null);
this.injectee[name].entwine = true;
}
if (!this.injectee[name].entwine) {
$.entwine.warn('Warning: Entwine function '+name+' clashes with regular jQuery function - entwine function will not be callable directly on jQuery object', $.entwine.WARN_LEVEL_IMPORTANT);
}
},
add: function(selector, data) {
// For every item in the hash, try ever method handler, until one returns true
for (var k in data) {
var v = data[k];
for (var i = 0; i < handlers.length; i++) {
if (handlers[i].bind && handlers[i].bind.call(this, selector, k, v)) break;
}
}
},
has: function(ctx, name) {
var rulelist = this.store[name];
if (!rulelist) return false;
/* We go forward this time, since low specifity is likely to knock out a bunch of elements quickly */
for (var i = 0 ; i < rulelist.length; i++) {
ctx = ctx.not(rulelist[i].selector);
if (!ctx.length) return true;
}
return false;
}
});
/**
* A handler is some javascript code that adds support for some time of key / value pair passed in the hash to the Namespace add method.
* The default handlers provided (and included by default) are event, ctor and properties
*/
$.entwine.Namespace.addHandler = function(handler) {
for (var i = 0; i < handlers.length && handlers[i].order < handler.order; i++) { /* Pass */ }
handlers.splice(i, 0, handler);
};
$.entwine.Namespace.addHandler({
order: 50,
bind: function(selector, k, v){
if ($.isFunction(v)) {
this.bind_proxy(selector, k, v);
return true;
}
}
});
$.extend($.fn, {
/**
* Main entwine function. Used for new definitions, calling into a namespace (or forcing the base namespace) and entering a using block
*
*/
entwine: function(spacename) {
var i = 0;
/* Don't actually work out selector until we try and define something on it - we might be opening a namespace on an function-traveresed object
which have non-standard selectors like .parents(.foo).slice(0,1) */
var selector = null;
/* By default we operator on the base namespace */
var namespace = namespaces.__base || $.entwine.Namespace();
/* If the first argument is a string, then it's the name of a namespace. Look it up */
if (typeof spacename == 'string') {
if (spacename.charAt('0') == '.') spacename = spacename.substr(1);
if (spacename) namespace = namespaces[spacename] || $.entwine.Namespace(spacename);
i=1;
}
/* All remaining arguments should either be using blocks or definition hashs */
while (i < arguments.length) {
var res = arguments[i++];
// If it's a function, call it - either it's a using block or it's a namespaced entwine definition
if ($.isFunction(res)) {
if (res.length != 1) $.entwine.warn('Function block inside entwine definition does not take $ argument properly', $.entwine.WARN_LEVEL_IMPORTANT);
res = res.call(namespace.$(this), namespace.$);
}
// If we have a entwine definition hash, inject it into namespace
if (res) {
if (selector === null) selector = this.selector ? $.selector(this.selector) : false;
if (selector) namespace.add(selector, res);
else $.entwine.warn('Entwine block given to entwine call without selector. Make sure you call $(selector).entwine when defining blocks', $.entwine.WARN_LEVEL_IMPORTANT);
}
}
/* Finally, return the jQuery object 'this' refers to, wrapped in the new namespace */
return namespace.$(this);
},
/**
* Calls the next most specific version of the current entwine method
*/
_super: function(){
var rv, i = this.length;
while (i--) {
var el = this[0];
rv = el.f(el, arguments, el.i);
}
return rv;
}
});
})(jQuery);
;
/* src/jquery.entwine.dommaybechanged.js */
(function($){
/** What to call to run a function 'soon'. Normally setTimeout, but for syncronous mode we override so soon === now */
var runSoon = window.setTimeout;
/** The timer handle for the asyncronous matching call */
var check_id = null;
/** Fire the change event. Only fires on the document node, so bind to that */
var triggerEvent = function() {
$(document).triggerHandler('DOMMaybeChanged');
check_id = null;
};
$.extend($.entwine, {
/**
* Make onmatch and onunmatch work in synchronous mode - that is, new elements will be detected immediately after
* the DOM manipulation that made them match. This is only really useful for during testing, since it's pretty slow
* (otherwise we'd make it the default).
*/
synchronous_mode: function() {
if (check_id) clearTimeout(check_id); check_id = null;
runSoon = function(func, delay){ func.call(this); return null; };
},
/**
* Trigger onmatch and onunmatch now - usefull for after DOM manipulation by methods other than through jQuery.
* Called automatically on document.ready
*/
triggerMatching: function() {
matching();
}
});
function registerMutateFunction() {
$.each(arguments, function(i,func){
var old = $.fn[func];
$.fn[func] = function() {
var rv = old.apply(this, arguments);
if (!check_id) check_id = runSoon(triggerEvent, 100);
return rv;
};
});
}
function registerSetterGetterFunction() {
$.each(arguments, function(i,func){
var old = $.fn[func];
$.fn[func] = function(a, b) {
var rv = old.apply(this, arguments);
if (!check_id && (b !== undefined || typeof a != 'string')) check_id = runSoon(triggerEvent, 100);
return rv;
};
});
}
// Register core DOM manipulation methods
registerMutateFunction('append', 'prepend', 'after', 'before', 'wrap', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove');
registerSetterGetterFunction('attr');
// And on DOM ready, trigger matching once
$(function(){ triggerEvent(); });
})(jQuery);;
/* src/jquery.entwine.events.js */
(function($) {
/* If we are any browser other than IE or Safari, we don't have to do anything special to handle
* onchange delegation */
$.support.bubblingChange = !($.browser.msie || $.browser.safari);
/* Return true if node b is the same as, or is a descendant of, node a */
if (document.compareDocumentPosition) {
var is_or_contains = function(a, b) {
return a && b && (a == b || !!(a.compareDocumentPosition(b) & 16));
};
}
else {
var is_or_contains = function(a, b) {
return a && b && (a == b || (a.contains ? a.contains(b) : true));
};
}
/* Add the methods to handle event binding to the Namespace class */
$.entwine.Namespace.addMethods({
build_event_proxy: function(name) {
var one = this.one(name, 'func');
var prxy = function(e, data) {
// For events that do not bubble we manually trigger delegation (see delegate_submit below)
// If this event is a manual trigger, the event we actually want to bubble is attached as a property of the passed event
e = e.delegatedEvent || e;
var el = e.target;
while (el && el.nodeType == 1 && !e.isPropagationStopped()) {
var ret = one(el, arguments);
if (ret !== undefined) e.result = ret;
if (ret === false) { e.preventDefault(); e.stopPropagation(); }
el = el.parentNode;
}
};
return prxy;
},
build_mouseenterleave_proxy: function(name) {
var one = this.one(name, 'func');
var prxy = function(e) {
var el = e.target;
var rel = e.relatedTarget;
while (el && el.nodeType == 1 && !e.isPropagationStopped()) {
/* We know el contained target. If it also contains relatedTarget then we didn't mouseenter / leave. What's more, every ancestor will also
contan el and rel, and so we can just stop bubbling */
if (is_or_contains(el, rel)) break;
var ret = one(el, arguments);
if (ret !== undefined) e.result = ret;
if (ret === false) { e.preventDefault(); e.stopPropagation(); }
el = el.parentNode;
}
};
return prxy;
},
build_change_proxy: function(name) {
var one = this.one(name, 'func');
var prxy = function(e) {
var el = e.target;
// If this is a keydown event, only worry about the enter key, since browsers only trigger onchange on enter or focus loss
if (e.type === 'keydown' && e.keyCode !== 13) return;
// Make sure this is event is for an input type we're interested in
if (el.tagName !== 'INPUT' && el.tagName !== 'TEXTAREA' && el.tagName !== 'SELECT') return;
var $el = $(el), nowVal, oldVal = $el.data('changeVal');
// Detect changes on checkboxes & radiobuttons, which have different value logic. We don't use el.value, since el is part
// of a set, and we only want to raise onchange once for a single user action.
if (el.type == 'checkbox' || el.type == 'radio') {
if (!el.disabled && e.type === 'click') {
nowVal = el.checked;
// If radio, we get two changes - the activation, and the deactivation. We only want to fire one change though
if ((el.type === 'checkbox' || nowVal === true) && oldVal !== nowVal) e.type = 'change';
}
}
// Detect changes on other input types. In this case value is OK.
else {
nowVal = el.value;
if (oldVal !== undefined && oldVal !== nowVal) e.type = 'change';
}
// Save the current value for next time
if (nowVal !== undefined) $el.data('changeVal', nowVal);
// And if we decided that a change happened, do the actual triggering
if (e.type == 'change') {
while (el && el.nodeType == 1 && !e.isPropagationStopped()) {
var ret = one(el, arguments);
if (ret !== undefined) e.result = ret;
if (ret === false) { e.preventDefault(); e.stopPropagation(); }
el = el.parentNode;
}
}
};
return prxy;
},
bind_event: function(selector, name, func, event) {
var funcs = this.store[name] || (this.store[name] = $.entwine.RuleList()) ;
var proxies = funcs.proxies || (funcs.proxies = {});
var rule = funcs.addRule(selector, name); rule.func = func;
if (!proxies[name]) {
switch (name) {
case 'onmouseenter':
proxies[name] = this.build_mouseenterleave_proxy(name);
event = 'mouseover';
break;
case 'onmouseleave':
proxies[name] = this.build_mouseenterleave_proxy(name);
event = 'mouseout';
break;
case 'onchange':
if (!$.support.bubblingChange) {
proxies[name] = this.build_change_proxy(name);
event = 'click focusin focusout keydown';
}
break;
case 'onsubmit':
event = 'delegatedSubmit';
break;
case 'onfocus':
case 'onblur':
$.entwine.warn('Event '+event+' not supported - using focusin / focusout instead', $.entwine.WARN_LEVEL_IMPORTANT);
}
// If none of the special handlers created a proxy, use the generic proxy
if (!proxies[name]) proxies[name] = this.build_event_proxy(name);
$(document).bind(event+'.entwine', proxies[name]);
}
}
});
$.entwine.Namespace.addHandler({
order: 40,
bind: function(selector, k, v){
var match, event;
if ($.isFunction(v) && (match = k.match(/^on(.*)/))) {
event = match[1];
this.bind_event(selector, k, v, event);
return true;
}
}
});
// Find all forms and bind onsubmit to trigger on the document too.
// This is the only event that can't be grabbed via delegation
var form_binding_cache = $([]); // A cache for already-handled form elements
var delegate_submit = function(e, data){
var delegationEvent = $.Event('delegatedSubmit'); delegationEvent.delegatedEvent = e;
return $(document).trigger(delegationEvent, data);
};
$(document).bind('DOMMaybeChanged', function(){
var forms = $('form');
// Only bind to forms we haven't processed yet
forms.not(form_binding_cache).bind('submit', delegate_submit);
// Then remember the current set of forms
form_binding_cache = forms;
});
})(jQuery);
;
/* src/jquery.entwine.ctors.js */
(function($) {
/* Add the methods to handle constructor & destructor binding to the Namespace class */
$.entwine.Namespace.addMethods({
bind_condesc: function(selector, name, func) {
var ctors = this.store.ctors || (this.store.ctors = $.entwine.RuleList()) ;
var rule;
for (var i = 0 ; i < ctors.length; i++) {
if (ctors[i].selector.selector == selector.selector) {
rule = ctors[i]; break;
}
}
if (!rule) {
rule = ctors.addRule(selector, 'ctors');
}
rule[name] = func;
if (!ctors[name+'proxy']) {
var one = this.one('ctors', name);
var namespace = this;
var proxy = function(els, i, func) {
var j = els.length;
while (j--) {
var el = els[j];
var tmp_i = el.i, tmp_f = el.f;
el.i = i; el.f = one;
try { func.call(namespace.$(el)); }
catch(e) { $.entwine.warn_exception(name, el, e); }
finally { el.i = tmp_i; el.f = tmp_f; }
}
};
ctors[name+'proxy'] = proxy;
}
}
});
$.entwine.Namespace.addHandler({
order: 30,
bind: function(selector, k, v) {
if ($.isFunction(v) && (k == 'onmatch' || k == 'onunmatch')) {
this.bind_condesc(selector, k, v);
return true;
}
}
});
/**
* Finds all the elements that now match a different rule (or have been removed) and call onmatch on onunmatch as appropriate
*
* Because this has to scan the DOM, and is therefore fairly slow, this is normally triggered off a short timeout, so that
* a series of DOM manipulations will only trigger this once.
*
* The downside of this is that things like:
* $('#foo').addClass('tabs'); $('#foo').tabFunctionBar();
* won't work.
*/
$(document).bind('DOMMaybeChanged', function(){
// For every namespace
for (var k in $.entwine.namespaces) {
// That has constructors or destructors
var ctors = $.entwine.namespaces[k].store.ctors;
if (ctors) {
// Keep a record of elements that have matched already
var matched = $([]), add, rem, res, rule, sel, ctor, dtor;
// Stepping through each selector from most to least specific
var j = ctors.length;
while (j--) {
// Build some quick-access variables
rule = ctors[j];
sel = rule.selector.selector;
ctor = rule.onmatch;
dtor = rule.onunmatch;
// Get the list of elements that match this selector, that haven't yet matched a more specific selector
res = add = $(sel).not(matched);
// If this selector has a list of elements it matched against last time
if (rule.cache) {
// Find the ones that are extra this time
add = res.not(rule.cache);
if (dtor) {
// Find the ones that are gone this time
rem = rule.cache.not(res);
// And call the destructor on them
if (rem.length) ctors.onunmatchproxy(rem, j, dtor);
}
}
// Call the constructor on the newly matched ones
if (add.length && ctor) ctors.onmatchproxy(add, j, ctor);
// Add these matched ones to the list tracking all elements matched so far
matched = matched.add(res);
// And remember this list of matching elements again this selector, so next matching we can find the unmatched ones
ctors[j].cache = res;
}
}
}
});
})(jQuery);
;
/* src/jquery.entwine.properties.js */
(function($) {
var entwine_prepend = '__entwine!';
var getEntwineData = function(el, namespace, property) {
return el.data(entwine_prepend + namespace + '!' + property);
};
var setEntwineData = function(el, namespace, property, value) {
return el.data(entwine_prepend + namespace + '!' + property, value);
};
var getEntwineDataAsHash = function(el, namespace) {
var hash = {};
var id = jQuery.data(el[0]);
var matchstr = entwine_prepend + namespace + '!';
var matchlen = matchstr.length;
var cache = jQuery.cache[id];
for (var k in cache) {
if (k.substr(0,matchlen) == matchstr) hash[k.substr(matchlen)] = cache[k];
}
return hash;
};
var setEntwineDataFromHash = function(el, namespace, hash) {
for (var k in hash) setEntwineData(namespace, k, hash[k]);
};
var entwineData = function(el, namespace, args) {
switch (args.length) {
case 0:
return getEntwineDataAsHash(el, namespace);
case 1:
if (typeof args[0] == 'string') return getEntwineData(el, namespace, args[0]);
else return setEntwineDataFromHash(el, namespace, args[0]);
default:
return setEntwineData(el, namespace, args[0], args[1]);
}
};
$.extend($.fn, {
entwineData: function() {
return entwineData(this, '__base', arguments);
}
});
$.entwine.Namespace.addHandler({
order: 60,
bind: function(selector, k, v) {
if (k.charAt(0) != k.charAt(0).toUpperCase()) $.entwine.warn('Entwine property '+k+' does not start with a capital letter', $.entwine.WARN_LEVEL_BESTPRACTISE);
// Create the getters and setters
var getterName = 'get'+k;
var setterName = 'set'+k;
this.bind_proxy(selector, getterName, function() { return this.entwineData(k) || v ; });
this.bind_proxy(selector, setterName, function(v){ return this.entwineData(k, v); });
// Get the get and set proxies we just created
var getter = this.injectee[getterName];
var setter = this.injectee[setterName];
// And bind in the jQuery-style accessor
this.bind_proxy(selector, k, function(v){ return (arguments.length == 1 ? setter : getter).call(this, v) ; });
return true;
},
namespaceMethodOverrides: function(namespace){
return {
entwineData: function() {
return entwineData(this, namespace.name, arguments);
}
};
}
});
})(jQuery);
;
/* src/jquery.entwine.legacy.js */
(function($) {
// Adds back concrete methods for backwards compatibility
$.concrete = $.entwine;
$.fn.concrete = $.fn.entwine;
$.fn.concreteData = $.fn.entwineData;
// Use addHandler to hack in the namespace.$.concrete equivilent to the namespace.$.entwine namespace-injection
$.entwine.Namespace.addHandler({
order: 100,
bind: function(selector, k, v) { return false; },
namespaceMethodOverrides: function(namespace){
namespace.$.concrete = namespace.$.entwine;
namespace.injectee.concrete = namespace.injectee.entwine;
namespace.injectee.concreteData = namespace.injectee.entwineData;
return {};
}
});
})(jQuery);
;

View File

@ -0,0 +1 @@
jquery.entwine-dist.js

View File

@ -1,4 +1,4 @@
/* jQuery.Entwine - Copyright 2009 Hamish Friedlander and SilverStripe. Version . */
/* jQuery.Entwine - Copyright 2009-2011 Hamish Friedlander and SilverStripe. Version . */
/* vendor/jquery.selector/jquery.class.js */
@ -774,7 +774,7 @@ var console;
*/
clear_all_rules: function() {
// Remove proxy functions
for (var k in $.fn) { if ($.fn[k].entwine) delete $.fn[k] ; }
for (var k in $.fn) { if ($.fn[k].isentwinemethod) delete $.fn[k]; }
// Remove bound events - TODO: Make this pluggable, so this code can be moved to jquery.entwine.events.js
$(document).unbind('.entwine');
// Remove namespaces, and start over again
@ -870,38 +870,48 @@ var console;
}
else {
// We're in a namespace, so we build a Class that subclasses the jQuery Object Class to inject namespace functions into
var subfn = function(){};
this.injectee = subfn.prototype = new $();
// And then we provide an overriding $ that returns objects of our new Class, and an overriding pushStack to catch further selection building
var bound$ = this.$ = function(a) {
// Try the simple way first
var jq = $.fn.init.apply(new subfn(), arguments);
if (jq instanceof subfn) return jq;
// jQuery 1.5 already provides a nice way to subclass, so use it
if ($.sub) {
this.$ = $.sub();
this.injectee = this.$.prototype;
}
// For jQuery < 1.5 we have to do it ourselves
else {
var subfn = function(){};
this.injectee = subfn.prototype = new $;
// And then we provide an overriding $ that returns objects of our new Class, and an overriding pushStack to catch further selection building
var bound$ = this.$ = function(a) {
// Try the simple way first
var jq = $.fn.init.apply(new subfn(), arguments);
if (jq instanceof subfn) return jq;
// That didn't return a bound object, so now we need to copy it
var rv = new subfn();
rv.selector = jq.selector; rv.context = jq.context; var i = rv.length = jq.length;
while (i--) rv[i] = jq[i];
return rv;
};
this.injectee.pushStack = function(elems, name, selector){
var ret = bound$(elems);
// That didn't return a bound object, so now we need to copy it
var rv = new subfn();
rv.selector = jq.selector; rv.context = jq.context; var i = rv.length = jq.length;
while (i--) rv[i] = jq[i];
return rv;
};
this.injectee.pushStack = function(elems, name, selector){
var ret = bound$(elems);
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
if ( name === "find" ) ret.selector = this.selector + (this.selector ? " " : "") + selector;
else if ( name ) ret.selector = this.selector + "." + name + "(" + selector + ")";
if ( name === "find" ) ret.selector = this.selector + (this.selector ? " " : "") + selector;
else if ( name ) ret.selector = this.selector + "." + name + "(" + selector + ")";
// Return the newly-formed element set
return ret;
};
// Return the newly-formed element set
return ret;
};
// Copy static functions through from $ to this.$ so e.g. $.ajax still works
// @bug, @cantfix: Any class functions added to $ after this call won't get mirrored through
$.extend(this.$, $);
// Copy static functions through from $ to this.$ so e.g. $.ajax still works
// @bug, @cantfix: Any class functions added to $ after this call won't get mirrored through
$.extend(this.$, $);
}
// We override entwine to inject the name of this namespace when defining blocks inside this namespace
var entwine_wrapper = this.injectee.entwine = function(spacename) {
@ -989,12 +999,12 @@ var console;
var rule = rulelist.addRule(selector, name); rule.func = func;
if (!this.injectee.hasOwnProperty(name) || !this.injectee[name].entwine) {
if (!this.injectee.hasOwnProperty(name) || !this.injectee[name].isentwinemethod) {
this.injectee[name] = this.build_proxy(name, this.injectee.hasOwnProperty(name) ? this.injectee[name] : null);
this.injectee[name].entwine = true;
this.injectee[name].isentwinemethod = true;
}
if (!this.injectee[name].entwine) {
if (!this.injectee[name].isentwinemethod) {
$.entwine.warn('Warning: Entwine function '+name+' clashes with regular jQuery function - entwine function will not be callable directly on jQuery object', $.entwine.WARN_LEVEL_IMPORTANT);
}
},

View File

@ -0,0 +1,42 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Test Runner</title>
<link rel="stylesheet" type="text/css" href="../vendor/jasmine-1.0.1/jasmine.css">
<script type="text/javascript" src="../vendor/jasmine-1.0.1/jasmine.js"></script>
<script type="text/javascript" src="../vendor/jasmine-1.0.1/jasmine-html.js"></script>
<script type="text/javascript" src="../vendor/jasmine-dom/jasmine-dom-matchers.js"></script>
<script type="text/javascript" src="../vendor/jasmine-dom/jasmine-dom-fixtures.js"></script>
<!-- include source files here... -->
<script src="../vendor/jquery-1.5.js"></script>
<script src="../vendor/jquery.selector/jquery.class.js"></script>
<script src="../vendor/jquery.selector/jquery.selector.js"></script>
<script src="../vendor/jquery.selector/jquery.selector.specifity.js"></script>
<script src="../vendor/jquery.selector/jquery.selector.matches.js"></script>
<script src="../src/jquery.entwine.js"></script>
<script src="../src/jquery.entwine.dommaybechanged.js"></script>
<script src="../src/jquery.entwine.events.js"></script>
<script src="../src/jquery.entwine.ctors.js"></script>
<script src="../src/jquery.entwine.properties.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="spec.entwine.basics.js"></script>
<script type="text/javascript" src="spec.entwine.ctors.js"></script>
<script type="text/javascript" src="spec.entwine.events.js"></script>
<script type="text/javascript" src="spec.entwine.namespaces.js"></script>
<script type="text/javascript" src="spec.entwine.properties.js"></script>
<script type="text/javascript" src="spec.entwine.super.js"></script>
</head>
<body>
<script type="text/javascript">
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
jasmine.getEnv().execute();
</script>
</body>
</html>

View File

@ -1,30 +0,0 @@
<html>
<head>
<!-- spec-dist is the same as spec, but runs on the distribution version of the library, to make sure no problems were introduced during building -->
<link type="text/css" rel="stylesheet" href="../../vendor/jspec/lib/jspec.css" />
<script src="../../vendor/jquery-1.3.2.js"></script>
<script src="../../vendor/jspec/lib/jspec.js"></script>
<script src="../../vendor/jspec/lib/jspec.jquery.js"></script>
<script src="../../dist/jquery.entwine-dist.js"></script>
<script>
function runSuites() {
JSpec
.exec('spec.concrete.basics.js')
.exec('spec.concrete.namespaces.js')
.exec('spec.concrete.super.js')
.exec('spec.concrete.events.js')
.exec('spec.concrete.ctors.js')
.exec('spec.concrete.properties.js')
.run()
.report()
}
</script>
</head>
<body class="jspec" onLoad="runSuites();">
<div id="jspec-top"><h2 id="jspec-title">JSpec <em><script>document.write(JSpec.version)</script></em></h2></div>
<div id="jspec"><div class="loading"></div></div>
<div id="jspec-bottom"></div>
</body>
</html>

View File

@ -1,85 +0,0 @@
describe 'Concrete'
describe 'Basics'
before
$.concrete.warningLevel = $.concrete.WARN_LEVEL_BESTPRACTISE;
$('body').append('<div id="dom_test"></div>');
end
after
$('#dom_test').remove();
end
before_each
$.concrete.clear_all_rules();
$('#dom_test').html('<div id="a" class="a b c" data-fieldtype="foo"></div><div id="b" class="c d e"></div>');
end
it 'can attach and call a base function'
$('#a').concrete({
foo: function(){return this.attr('id');}
});
$('.a').foo().should.equal 'a'
end
it 'can attach and call a base function on a selector using a data attribute selection'
$('[data-fieldtype=foo]').concrete({
foo: function(){return this.attr('id');}
});
$('.a').foo().should.equal 'a'
end
it 'can attach and call several base functions'
$('#a').concrete({
foo: function(){return 'foo_' + this.attr('id');},
bar: function(){return 'bar_' + this.attr('id');}
});
$('.a').foo().should.equal 'foo_a'
$('.a').bar().should.equal 'bar_a'
end
it 'can attach and call a namespaced function'
$.concrete('bar', function($){
$('#a').concrete({
foo: function(){return this.attr('id');}
});
});
$('.a').concrete('bar').foo().should.equal 'a'
end
it 'can attach and call a nested namespaced function'
$.concrete('qux.baz.bar', function($){
$('#a').concrete({
foo: function(){return this.attr('id');}
});
});
$('.a').concrete('qux.baz.bar').foo().should.equal 'a'
end
it 'can call two functions on two elements'
var res = []
$('#a').concrete({
foo: function(){res.push(this.attr('id'));}
});
$('#b.c').concrete({
foo: function(){res.push(this.attr('id'));}
});
$('#dom_test div').foo();
res.should.eql ['b', 'a']
end
it 'can call two namespaced functions on two elements'
var res = []
$.concrete('bar', function($){
$('#a').concrete({
foo: function(){res.push(this.attr('id'));}
});
$('#b.c').concrete({
foo: function(){res.push(this.attr('id'));}
});
});
$('#dom_test div').concrete('bar').foo();
res.should.eql ['b', 'a']
end
end
end

View File

@ -1,68 +0,0 @@
describe 'Concrete'
describe 'Ctors'
before
$('body').append('<div id="dom_test"></div>')
end
after
$('#dom_test').remove()
end
before_each
$.concrete.synchronous_mode();
$.concrete.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c"></div>')
end
it 'calls onmatch when new element created'
var a = false;
$('#b').concrete({onmatch: function(){a = true;} });
a.should.be_false
$('#a').after('<div id="b"></div>');
a.should.be_true
end
it 'calls onunmatch when new element deleted'
var a = 0;
$('#b').concrete({onmatch: function(){a = 1;}, onunmatch: function(){a = 2;} });
a.should.equal 0
$('#a').after('<div id="b"></div>');
a.should.equal 1
$('#b').remove();
a.should.equal 2
end
it 'calls onmatch when ruleset matches after class added'
var a = 0;
$('#a.foo').concrete({onmatch: function(){a = 1;} });
a.should.equal 0
$('#a').addClass('foo');
a.should.equal 1
end
it 'calls onmatch in both direct and namespaced onmatch, does not call less specific onmatch'
var a = 0, b=0, c=0, d=0;
$('.foo').concrete({onmatch: function(){a = 1;}})
$('.foo').concrete('bar', function($){return{onmatch: function(){b = 1;}}})
$('#a.foo').concrete({onmatch: function(){c = 1;}})
$('#a.foo').concrete('bar', function($){return{onmatch: function(){d = 1}}})
[a, b, c, d].should.eql [0, 0, 0, 0]
$('#a').addClass('foo');
[a, b, c, d].should.eql [0, 0, 1, 1]
end
it 'calls onmatch in both direct and namespaced onmatch, super works as expected'
var a = 0, b=0, c=0, d=0;
$('.foo').concrete({onmatch: function(){a += 1;}})
$('.foo').concrete('bar', function($){return{onmatch: function(){b += 1;}}})
$('#a.foo').concrete({onmatch: function(){this._super(); c = 1; this._super();}})
$('#a.foo').concrete('bar', function($){return{onmatch: function(){this._super(); d = 1; this._super();}}})
[a, b, c, d].should.eql [0, 0, 0, 0]
$('#a').addClass('foo');
[a, b, c, d].should.eql [2, 2, 1, 1]
end
end
end

View File

@ -1,112 +0,0 @@
describe 'Concrete'
describe 'Events'
before
$('body').append('<div id="dom_test"></div>')
end
after
$('#dom_test').remove()
end
before_each
$.concrete.synchronous_mode();
$.concrete.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c"></div>')
end
it 'calls onfoo when foo triggered'
var a = 0;
$('#a').concrete({onfoo: function(){a = 1;} });
a.should.equal 0
$('#a').trigger('foo');
a.should.equal 1
end
it 'only calls most specific onfoo when foo triggered'
var a = 0, b = 0;
$('#a.a').concrete({onfoo: function(){a = 1;} });
$('#a').concrete({onfoo: function(){b = 1;} });
a.should.equal 0
b.should.equal 0
$('#a').trigger('foo');
a.should.equal 1
b.should.equal 0
end
it 'calls namespaced onfoo when foo triggered'
var a = 0;
$('#a').concrete('bar', function($){return{onfoo: function(){a = 1;} }});
a.should.equal 0
$('#a').trigger('foo');
a.should.equal 1
end
it 'calls most specific namespaced onfoo and most specific non-namespaced onfoo when foo triggered'
var a = 0, b = 0, c = 0, d = 0;
$('#a.a').concrete({onfoo: function(){a = 1;} });
$('#a').concrete({onfoo: function(){b = 1;} });
$('#a.a').concrete('bar', function($){return{onfoo: function(){c = 1;} }});
$('#a').concrete('bar', function($){return{onfoo: function(){d = 1;} }});
[a, b, c, d].should.eql [0, 0, 0, 0]
$('#a').trigger('foo');
[a, b, c, d].should.eql [1, 0, 1, 0]
end
it 'calls up correctly on _super'
var a = 0, b = 0;
$('#a').concrete({onfoo: function(){a += 1;} });
$('#a.a').concrete({onfoo: function(){this._super(); b += 1; this._super();} });
[a, b].should.eql [0, 0]
$('#a').trigger('foo')
[a, b].should.eql [2, 1]
end
it 'passes event object'
var event;
$('#a').concrete({onfoo: function(e){event = e;} });
$('#a').trigger('foo');
event.should.have_prop 'type', 'foo'
$(event.target).should.have_attr 'id', 'a'
end
it 'delegates submit events to forms'
var a = 0;
$('<form class="foo" action="javascript:undefined">').appendTo('#dom_test');
$('.foo').concrete({onsubmit: function(e, d){a = 1;} });
a.should.eql 0
$('.foo').trigger('submit');
a.should.eql 1
end
describe 'can pass event data'
it 'on custom events'
var data;
$('#a').concrete({onfoo: function(e, d){data = d;} });
$('#a').trigger('foo', {cheese: 'burger'});
data.cheese.should.eql 'burger'
end
it 'on normal events'
var data;
$('#a').concrete({onclick: function(e, d){data = d;} });
$('#a').trigger('click', {finger: 'left'});
data.finger.should.eql 'left'
end
it 'on submit'
var data;
$('<form class="foo" action="javascript:undefined">').appendTo('#dom_test');
$('.foo').concrete({onsubmit: function(e, d){data = d; return false;} })
$('.foo').trigger('submit', {cheese: 'burger'});
data.cheese.should.eql 'burger'
end
end
end
end

View File

@ -1,246 +0,0 @@
describe 'Concrete'
describe 'Namespaces'
before
$('body').append('<div id="dom_test"></div>')
end
after
$('#dom_test').remove()
end
before_each
$.concrete.synchronous_mode();
$.concrete.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c"></div><div id="b" class="c d e"></div>')
end
it 'namespaced functions work (single definition mode)'
$('#a').concrete('bar', function($){return{
bar: function(){return 'a';}
}})
$('#a').concrete('bar').bar().should.equal 'a'
end
it 'namespaced functions work (block definition mode)'
$.concrete('zap', function($){
$('#a').concrete({
bar: function(){return 'a';}
})
});
$('#a').concrete('zap').bar().should.equal 'a'
end
it 'double-namespaced functions work (block definition mode)'
$.concrete('zap', function($){
$.concrete('pow', function($){
$('#a').concrete({
bar: function(){return 'a';}
})
})
})
$('#a').concrete('zap.pow').bar().should.equal 'a'
end
it 'revert to base namespacing work (block definition mode)'
$.concrete('zap', function($){
$.concrete('.pow', function($){
$('#a').concrete({
bar: function(){return 'a';}
})
})
})
$('#a').concrete('pow').bar().should.equal 'a'
end
it 'internal to namespace, will look up functions in namespace before in base'
var res = []
$('#a').concrete({
foo: function(){res.push(1);},
bar: function(){res.push(2); this.foo();}
})
$('#a').concrete('bar', function($){return{
foo: function(){res.push(3);},
bar: function(){res.push(4); $(this).foo();}
}})
$('#dom_test div').bar();
res.should.eql [2, 1]
$('#dom_test div').concrete('bar').bar();
res.should.eql [2, 1, 4, 3]
end
it 'internal to namespace, will look up functions in namespace before in base, even in closure'
var res = []
$('#a').concrete({
foo: function(){res.push(1);},
bar: function(){res.push(2); this.foo();}
})
$('#a').concrete('bar', function($){return{
foo: function(){res.push(3);},
bar: function(){res.push(4); $('#a').each(function(){ $(this).foo(); })}
}})
$('#dom_test div').bar();
res.should.eql [2, 1]
$('#dom_test div').concrete('bar').bar();
res.should.eql [2, 1, 4, 3]
end
it 'internal to namespace, will look up functions in namespace before in base, even in onmatch'
var res = []
$('#a').concrete({
foo: function(){res.push(1);},
bar: function(){res.push(2); this.foo();}
})
$('#a').concrete('bar', function($){return{
foo: function(){res.push(3);}
}})
$('#a.d').concrete('bar', function($){return{
onmatch: function(){res.push(4); this.foo();}
}})
$('#dom_test div').bar();
res.should.eql [2, 1]
$('#a').addClass('d');
res.should.eql [2, 1, 4, 3]
end
it 'internal to namespace, will look up functions in base when not present in namespace'
var res = []
$('#a').concrete({
foo: function(){res.push(1);}
})
$('#a').concrete('bar', function($){return{
bar: function(){res.push(2); this.foo();}
}})
$('#dom_test div').concrete('bar').bar();
res.should.eql [2, 1]
end
it 'internal to namespace, will not look up functions in base if present in namespace, even when not applicable to selector'
var res = []
$('#a').concrete('bar', function($){return{
foo: function(){this.bar();}
}})
$('#a').concrete({
bar: function(){res.push(1);}
})
$('span').concrete('bar', function($){return{
bar: function(){res.push(2);}
}})
$('#a').concrete('bar').foo()
res.should.eql []
end
it 'internal to namespace, can be directed to base namespace'
var res = []
$('#a').concrete({
foo: function(){res.push(1);},
bar: function(){res.push(2); this.foo();}
})
$('#a').concrete('bar', function($){return{
foo: function(){res.push(3);},
bar: function(){res.push(4); this.foo(); this.concrete('.').foo();}
}})
$('#dom_test div').bar();
res.should.eql [2, 1]
$('#dom_test div').concrete('bar').bar();
res.should.eql [2, 1, 4, 3, 1]
end
it 'internal to namespace, will look up functions in namespace called the same as a regular jQuery base function'
var res = []
$('#a').concrete('bar', function($){return{
load: function(){res.push(1);},
bar: function(){res.push(2); this.load();}
}})
$('#dom_test div').concrete('bar').bar();
res.should.eql [2, 1]
end
it 'internal to namespace, can be directed to regular jQuery base function'
var res = []
$.fn.testy = function(){ res.push(1); }
$('#a').concrete('bar', function($){return{
testy: function(){res.push(3);},
bar: function(){res.push(2); this.concrete('.').testy();}
}})
$('#dom_test div').concrete('bar').bar();
res.should.eql [2, 1]
end
it 'internal to namespace, can be directed to sub namespace'
var res = []
$.concrete('zap', function($){
$('#a').concrete({
foo: function(){ res.push(1); this.concrete('pow').bar(); }
})
$.concrete('pow', function($){
$('#a').concrete({
bar: function(){ res.push(2); }
})
})
})
$('#dom_test div').concrete('zap').foo();
res.should.eql [1, 2]
end
it 'internal to namespace, can be directed to unrelated namespace'
var res = []
$.concrete('zap', function($){
$('#a').concrete({
foo: function(){ res.push(1); this.concrete('.pow').bar(); }
})
$.concrete('pow', function($){
$('#a').concrete({
bar: function(){ res.push(2); }
})
})
})
$.concrete('pow', function($){
$('#a').concrete({
bar: function(){ res.push(3); }
})
})
$('#dom_test div').concrete('zap').foo();
res.should.eql [1, 3]
end
it 'a function passed out of a namespace will remember its namespace'
var res = []
var func = function(func) {
func.call($('#a, #b'));
}
$('#a, #b').concrete('bar', function($){return{
zap: function(){res.push($(this).attr('id'));},
bar: function(){res.push(2); func(this.zap);}
}})
$('#dom_test #a').concrete('bar').bar();
res.should.eql [2, 'b', 'a']
end
it 'using block functions'
var res = []
$('#a').concrete({
foo: function(){res.push(1);}
})
$('#a').concrete('bar', function($){return{
foo: function(){res.push(3);}
}})
$('#dom_test div').foo();
res.should.eql [1]
$('#dom_test div').concrete('bar', function($){
$(this).foo();
})
res.should.eql [1, 3]
end
end
end

View File

@ -1,102 +0,0 @@
describe 'Concrete'
describe 'Properties'
before
$('body').append('<div id="dom_test"></div>')
end
after
$('#dom_test').remove()
end
before_each
$.concrete.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c"></div><div id="b" class="b c"></div>')
end
it 'can define and get a basic property'
$('#a').concrete({
Foo: null
});
$('.a').getFoo().should.be_null
end
it 'can define and set a basic property'
$('#a').concrete({
Foo: null
});
$('.a').setFoo(1);
$('.a').getFoo().should.equal 1
end
it 'can define a default value'
$('#a').concrete({
Foo: 1
});
$('.a').getFoo().should.equal 1
end
it 'should manage proprties in namespaces without clashing'
$('#a').concrete({
Foo: 1
});
$.concrete('test', function($){
$('#a').concrete({
Foo: 2
});
});
$('.a').getFoo().should.equal 1
$('.a').concrete('test').getFoo().should.equal 2
$('.a').setFoo(4);
$('.a').concrete('test').setFoo(8);
$('.a').getFoo().should.equal 4
$('.a').concrete('test').getFoo().should.equal 8
end
it 'should manage directly setting proprties in namespaces without clashing'
$('#a').concrete({
Foo: null
});
$.concrete('test', function($){
$('#a').concrete({
Foo: null
});
});
$('.a').concreteData('Foo', 4);
$('.a').concrete('test').concreteData('Foo', 8);
$('.a').concreteData('Foo').should.equal 4
$('.a').concrete('test').concreteData('Foo').should.equal 8
end
describe 'jQuery style accessors'
it 'can define and get a basic property'
$('#a').concrete({
Foo: null
});
$('.a').Foo().should.be_null
end
it 'can define and set a basic property'
$('#a').concrete({
Foo: null
});
$('.a').Foo(1);
$('.a').Foo().should.equal 1
end
it 'can define a default value'
$('#a').concrete({
Foo: 1
});
$('.a').Foo().should.equal 1
end
end
end
end

View File

@ -1,66 +0,0 @@
describe 'Concrete'
describe 'Super'
before
$('body').append('<div id="dom_test"></div>')
end
after
$('#dom_test').remove()
end
before_each
$.concrete.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c">Foo</div><div id="b" class="c d e">Bar</div>')
end
it 'can call the super function'
var a = 1;
$('#a').concrete({
foo: function(){a *= 2;}
});
$('#a.a').concrete({
foo: function(){a += 2; this._super();}
});
$('#a').foo();
a.should.equal 6
end
it 'super to a non-existant class should be ignored'
var a = 1;
$('#a').concrete({
foo: function(){a *= 2; this._super();}
});
$('#a.a').concrete({
foo: function(){a += 2; this._super();}
});
$('#a').foo();
a.should.equal 6
end
it 'can call super from two different functions without screwing up what super points to'
var list = [];
$('#a').concrete({
foo: function(){ list.push('foo'); this.bar(); },
bar: function(){ list.push('bar'); }
});
$('#a.a').concrete({
foo: function(){ list.push('foo2'); this._super(); list.push('foo2'); this._super(); },
bar: function(){ list.push('bar2'); this._super(); }
});
$('#a').foo();
list.should.eql [ 'foo2', 'foo', 'bar2', 'bar', 'foo2', 'foo', 'bar2', 'bar' ]
end
it 'can override (and call via super) a non-concrete jquery function'
var a = 1
$('#a').concrete({
text: function(){ a = this._super(); }
});
$('#a').text();
a.should.equal 'Foo'
$('#b').text().should.equal 'Bar'
end
end
end

View File

@ -1,39 +0,0 @@
<html>
<head>
<link type="text/css" rel="stylesheet" href="../../vendor/jspec/lib/jspec.css" />
<script src="../../vendor/jquery-1.3.2.js"></script>
<script src="../../vendor/jspec/lib/jspec.js"></script>
<script src="../../vendor/jspec/lib/jspec.jquery.js"></script>
<script src="../../vendor/jquery.selector/jquery.class.js"></script>
<script src="../../vendor/jquery.selector/jquery.selector.js"></script>
<script src="../../vendor/jquery.selector/jquery.selector.specifity.js"></script>
<script src="../../vendor/jquery.selector/jquery.selector.matches.js"></script>
<script src="../../src/jquery.entwine.js"></script>
<script src="../../src/jquery.entwine.dommaybechanged.js"></script>
<script src="../../src/jquery.entwine.events.js"></script>
<script src="../../src/jquery.entwine.ctors.js"></script>
<script src="../../src/jquery.entwine.properties.js"></script>
<script src="../../src/jquery.entwine.legacy.js"></script>
<script>
function runSuites() {
JSpec
.exec('spec.concrete.basics.js')
.exec('spec.concrete.namespaces.js')
.exec('spec.concrete.super.js')
.exec('spec.concrete.events.js')
.exec('spec.concrete.ctors.js')
.exec('spec.concrete.properties.js')
.run()
.report()
}
</script>
</head>
<body class="jspec" onLoad="runSuites();">
<div id="jspec-top"><h2 id="jspec-title">JSpec <em><script>document.write(JSpec.version)</script></em></h2></div>
<div id="jspec"><div class="loading"></div></div>
<div id="jspec-bottom"></div>
</body>
</html>

View File

@ -1,30 +0,0 @@
<html>
<head>
<!-- spec-dist is the same as spec, but runs on the distribution version of the library, to make sure no problems were introduced during building -->
<link type="text/css" rel="stylesheet" href="../vendor/jspec/lib/jspec.css" />
<script src="../vendor/jquery-1.3.2.js"></script>
<script src="../vendor/jspec/lib/jspec.js"></script>
<script src="../vendor/jspec/lib/jspec.jquery.js"></script>
<script src="../dist/jquery.entwine-dist.js"></script>
<script>
function runSuites() {
JSpec
.exec('spec.entwine.basics.js')
.exec('spec.entwine.namespaces.js')
.exec('spec.entwine.super.js')
.exec('spec.entwine.events.js')
.exec('spec.entwine.ctors.js')
.exec('spec.entwine.properties.js')
.run()
.report()
}
</script>
</head>
<body class="jspec" onLoad="runSuites();">
<div id="jspec-top"><h2 id="jspec-title">JSpec <em><script>document.write(JSpec.version)</script></em></h2></div>
<div id="jspec"><div class="loading"></div></div>
<div id="jspec-bottom"></div>
</body>
</html>

View File

@ -1,61 +1,63 @@
describe 'Entwine'
describe 'Basics'
before
$.entwine.warningLevel = $.entwine.WARN_LEVEL_BESTPRACTISE;
$('body').append('<div id="dom_test"></div>');
end
after
$('#dom_test').remove();
end
describe( 'Entwine', function() {
before_each
beforeEach(function() {
$.entwine.warningLevel = $.entwine.WARN_LEVEL_BESTPRACTISE;
$('body').append('<div id="dom_test"></div>');
});
afterEach(function() {
$('#dom_test').remove();
});
describe( 'Basics', function() {
beforeEach(function() {
$.entwine.clear_all_rules();
$('#dom_test').html('<div id="a" class="a b c" data-fieldtype="foo"></div><div id="b" class="c d e"></div>');
end
});
it 'can attach and call a base function'
it( 'can attach and call a base function', function() {
$('#a').entwine({
foo: function(){return this.attr('id');}
});
$('.a').foo().should.equal 'a'
end
expect($('.a').foo()).toEqual('a');
});
it 'can attach and call a base function on a selector using a data attribute selection'
it( 'can attach and call a base function on a selector using a data attribute selection', function() {
$('[data-fieldtype=foo]').entwine({
foo: function(){return this.attr('id');}
});
$('.a').foo().should.equal 'a'
end
it 'can attach and call several base functions'
expect($('.a').foo()).toEqual('a') ;
});
it( 'can attach and call several base functions', function() {
$('#a').entwine({
foo: function(){return 'foo_' + this.attr('id');},
bar: function(){return 'bar_' + this.attr('id');}
});
$('.a').foo().should.equal 'foo_a'
$('.a').bar().should.equal 'bar_a'
end
it 'can attach and call a namespaced function'
expect($('.a').foo()).toEqual( 'foo_a');
expect($('.a').bar()).toEqual( 'bar_a');
});
it( 'can attach and call a namespaced function', function() {
$.entwine('bar', function($){
$('#a').entwine({
foo: function(){return this.attr('id');}
});
});
$('.a').entwine('bar').foo().should.equal 'a'
end
it 'can attach and call a nested namespaced function'
expect($('.a').entwine('bar').foo()).toEqual( 'a');
});
it( 'can attach and call a nested namespaced function', function() {
$.entwine('qux.baz.bar', function($){
$('#a').entwine({
foo: function(){return this.attr('id');}
});
});
$('.a').entwine('qux.baz.bar').foo().should.equal 'a'
end
it 'can call two functions on two elements'
expect($('.a').entwine('qux.baz.bar').foo()).toEqual( 'a');
});
it( 'can call two functions on two elements', function() {
var res = []
$('#a').entwine({
foo: function(){res.push(this.attr('id'));}
@ -64,10 +66,10 @@ describe 'Entwine'
foo: function(){res.push(this.attr('id'));}
});
$('#dom_test div').foo();
res.should.eql ['b', 'a']
end
it 'can call two namespaced functions on two elements'
expect(res).toEqual( ['b', 'a']);
});
it( 'can call two namespaced functions on two elements', function() {
var res = []
$.entwine('bar', function($){
$('#a').entwine({
@ -78,8 +80,7 @@ describe 'Entwine'
});
});
$('#dom_test div').entwine('bar').foo();
res.should.eql ['b', 'a']
end
end
end
expect(res).toEqual( ['b', 'a']);
});
});
});

View File

@ -1,68 +1,68 @@
describe 'Entwine'
describe 'Ctors'
before
$('body').append('<div id="dom_test"></div>')
end
describe( 'Entwine', function() {
after
$('#dom_test').remove()
end
before_each
beforeEach(function() {
$('body').append('<div id="dom_test"></div>')
});
afterEach(function() {
$('#dom_test').remove()
});
describe( 'Ctors', function() {
beforeEach(function() {
$.entwine.synchronous_mode();
$.entwine.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c"></div>')
end
it 'calls onmatch when new element created'
});
it( 'calls onmatch when new element created', function() {
var a = false;
$('#b').entwine({onmatch: function(){a = true;} });
a.should.be_false
expect(a).toBeFalsy();
$('#a').after('<div id="b"></div>');
a.should.be_true
end
it 'calls onunmatch when new element deleted'
expect(a).toBeTruthy();
});
it( 'calls onunmatch when new element deleted', function() {
var a = 0;
$('#b').entwine({onmatch: function(){a = 1;}, onunmatch: function(){a = 2;} });
a.should.equal 0
expect(a).toEqual( 0);
$('#a').after('<div id="b"></div>');
a.should.equal 1
expect(a).toEqual( 1);
$('#b').remove();
a.should.equal 2
end
it 'calls onmatch when ruleset matches after class added'
expect(a).toEqual( 2);
});
it( 'calls onmatch when ruleset matches after class added', function() {
var a = 0;
$('#a.foo').entwine({onmatch: function(){a = 1;} });
a.should.equal 0
expect(a).toEqual(0);
$('#a').addClass('foo');
a.should.equal 1
end
it 'calls onmatch in both direct and namespaced onmatch, does not call less specific onmatch'
expect(a).toEqual( 1);
});
it( 'calls onmatch in both direct and namespaced onmatch, does not call less specific onmatch', function() {
var a = 0, b=0, c=0, d=0;
$('.foo').entwine({onmatch: function(){a = 1;}})
$('.foo').entwine('bar', function($){return{onmatch: function(){b = 1;}}})
$('.foo').entwine('bar', function($){return{onmatch: function(){b = 1;}}})
$('#a.foo').entwine({onmatch: function(){c = 1;}})
$('#a.foo').entwine('bar', function($){return{onmatch: function(){d = 1}}})
[a, b, c, d].should.eql [0, 0, 0, 0]
$('#a.foo').entwine('bar', function($){return{onmatch: function(){d = 1}}})
expect([a, b, c, d]).toEqual( [0, 0, 0, 0]);
$('#a').addClass('foo');
[a, b, c, d].should.eql [0, 0, 1, 1]
end
it 'calls onmatch in both direct and namespaced onmatch, super works as expected'
expect([a, b, c, d]).toEqual( [0, 0, 1, 1]);
});
it( 'calls onmatch in both direct and namespaced onmatch, super works as expected', function() {
var a = 0, b=0, c=0, d=0;
$('.foo').entwine({onmatch: function(){a += 1;}})
$('.foo').entwine('bar', function($){return{onmatch: function(){b += 1;}}})
$('.foo').entwine('bar', function($){return{onmatch: function(){b += 1;}}})
$('#a.foo').entwine({onmatch: function(){this._super(); c = 1; this._super();}})
$('#a.foo').entwine('bar', function($){return{onmatch: function(){this._super(); d = 1; this._super();}}})
[a, b, c, d].should.eql [0, 0, 0, 0]
$('#a.foo').entwine('bar', function($){return{onmatch: function(){this._super(); d = 1; this._super();}}})
expect([a, b, c, d]).toEqual( [0, 0, 0, 0]);
$('#a').addClass('foo');
[a, b, c, d].should.eql [2, 2, 1, 1]
end
end
end
expect([a, b, c, d]).toEqual( [2, 2, 1, 1]);
});
});
});

View File

@ -1,112 +1,116 @@
describe 'Entwine'
describe 'Events'
describe( 'Entwine', function() {
before
$('body').append('<div id="dom_test"></div>')
end
after
$('#dom_test').remove()
end
before_each
beforeEach(function() {
$('body').append('<div id="dom_test"></div>')
});
afterEach(function() {
$('#dom_test').remove()
});
describe( 'Events', function() {
beforeEach(function() {
$.entwine.synchronous_mode();
$.entwine.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c"></div>')
end
it 'calls onfoo when foo triggered'
});
it( 'calls onfoo when foo triggered', function() {
var a = 0;
$('#a').entwine({onfoo: function(){a = 1;} });
a.should.equal 0
expect(a).toEqual(0);
$('#a').trigger('foo');
a.should.equal 1
end
it 'only calls most specific onfoo when foo triggered'
expect(a).toEqual( 1);
});
it( 'only calls most specific onfoo when foo triggered', function() {
var a = 0, b = 0;
$('#a.a').entwine({onfoo: function(){a = 1;} });
$('#a').entwine({onfoo: function(){b = 1;} });
a.should.equal 0
b.should.equal 0
expect(a).toEqual( 0);
expect(b).toEqual( 0);
$('#a').trigger('foo');
a.should.equal 1
b.should.equal 0
end
it 'calls namespaced onfoo when foo triggered'
expect(a).toEqual( 1);
expect(b).toEqual( 0);
});
it( 'calls namespaced onfoo when foo triggered', function() {
var a = 0;
$('#a').entwine('bar', function($){return{onfoo: function(){a = 1;} }});
a.should.equal 0
expect(a).toEqual( 0);
$('#a').trigger('foo');
a.should.equal 1
end
it 'calls most specific namespaced onfoo and most specific non-namespaced onfoo when foo triggered'
expect(a).toEqual( 1);
});
it( 'calls most specific namespaced onfoo and most specific non-namespaced onfoo when foo triggered', function() {
var a = 0, b = 0, c = 0, d = 0;
$('#a.a').entwine({onfoo: function(){a = 1;} });
$('#a').entwine({onfoo: function(){b = 1;} });
$('#a.a').entwine('bar', function($){return{onfoo: function(){c = 1;} }});
$('#a').entwine('bar', function($){return{onfoo: function(){d = 1;} }});
[a, b, c, d].should.eql [0, 0, 0, 0]
expect([a, b, c, d]).toEqual( [0, 0, 0, 0] );
$('#a').trigger('foo');
[a, b, c, d].should.eql [1, 0, 1, 0]
end
it 'calls up correctly on _super'
expect([a, b, c, d]).toEqual( [1, 0, 1, 0]);
});
it( 'calls up correctly on _super', function() {
var a = 0, b = 0;
$('#a').entwine({onfoo: function(){a += 1;} });
$('#a.a').entwine({onfoo: function(){this._super(); b += 1; this._super();} });
[a, b].should.eql [0, 0]
expect([a, b]).toEqual( [0, 0]);
$('#a').trigger('foo')
[a, b].should.eql [2, 1]
end
it 'passes event object'
expect([a, b]).toEqual( [2, 1]);
});
it( 'passes event object', function() {
var event;
$('#a').entwine({onfoo: function(e){event = e;} });
$('#a').trigger('foo');
event.should.have_prop 'type', 'foo'
$(event.target).should.have_attr 'id', 'a'
end
it 'delegates submit events to forms'
expect(event.type).toBeDefined();
expect(event.type).toEqual('foo');
expect(event.target).toHaveAttr( 'id', 'a');
});
it( 'delegates submit events to forms', function() {
var a = 0;
$('<form class="foo" action="javascript:undefined">').appendTo('#dom_test');
$('.foo').entwine({onsubmit: function(e, d){a = 1;} });
a.should.eql 0
expect(a).toEqual( 0);
$('.foo').trigger('submit');
a.should.eql 1
end
describe 'can pass event data'
it 'on custom events'
expect(a).toEqual( 1);
});
describe( 'can pass event data', function() {
it( 'on custom events', function() {
var data;
$('#a').entwine({onfoo: function(e, d){data = d;} });
$('#a').trigger('foo', {cheese: 'burger'});
data.cheese.should.eql 'burger'
end
expect(data.cheese).toEqual( 'burger');
});
it 'on normal events'
it( 'on normal events', function() {
var data;
$('#a').entwine({onclick: function(e, d){data = d;} });
$('#a').trigger('click', {finger: 'left'});
data.finger.should.eql 'left'
end
it 'on submit'
expect(data.finger).toEqual( 'left');
});
it( 'on submit', function() {
var data;
$('<form class="foo" action="javascript:undefined">').appendTo('#dom_test');
$('.foo').entwine({onsubmit: function(e, d){data = d; return false;} })
$('.foo').trigger('submit', {cheese: 'burger'});
data.cheese.should.eql 'burger'
end
end
end
end
expect(data.cheese).toEqual( 'burger');
});
});
});
});

View File

@ -1,36 +1,38 @@
describe 'Entwine'
describe 'Namespaces'
before
$('body').append('<div id="dom_test"></div>')
end
after
$('#dom_test').remove()
end
describe( 'Entwine', function() {
before_each
beforeEach(function() {
$('body').append('<div id="dom_test"></div>')
});
afterEach(function() {
$('#dom_test').remove()
});
describe( 'Namespaces', function() {
beforeEach(function() {
$.entwine.synchronous_mode();
$.entwine.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c"></div><div id="b" class="c d e"></div>')
end
it 'namespaced functions work (single definition mode)'
});
it( 'namespaced functions work (single definition mode)', function() {
$('#a').entwine('bar', function($){return{
bar: function(){return 'a';}
}})
$('#a').entwine('bar').bar().should.equal 'a'
end
expect($('#a').entwine('bar').bar()).toEqual( 'a');
});
it 'namespaced functions work (block definition mode)'
it( 'namespaced functions work (block definition mode)', function() {
$.entwine('zap', function($){
$('#a').entwine({
bar: function(){return 'a';}
})
});
$('#a').entwine('zap').bar().should.equal 'a'
end
it 'double-namespaced functions work (block definition mode)'
expect($('#a').entwine('zap').bar()).toEqual( 'a');
});
it( 'double-namespaced functions work (block definition mode)', function() {
$.entwine('zap', function($){
$.entwine('pow', function($){
$('#a').entwine({
@ -38,10 +40,10 @@ describe 'Entwine'
})
})
})
$('#a').entwine('zap.pow').bar().should.equal 'a'
end
expect($('#a').entwine('zap.pow').bar()).toEqual( 'a');
})
it 'revert to base namespacing work (block definition mode)'
it( 'revert to base namespacing work (block definition mode)', function() {
$.entwine('zap', function($){
$.entwine('.pow', function($){
$('#a').entwine({
@ -49,10 +51,10 @@ describe 'Entwine'
})
})
})
$('#a').entwine('pow').bar().should.equal 'a'
end
expect($('#a').entwine('pow').bar()).toEqual( 'a');
});
it 'internal to namespace, will look up functions in namespace before in base'
it( 'internal to namespace, will look up functions in namespace before in base', function() {
var res = []
$('#a').entwine({
foo: function(){res.push(1);},
@ -64,12 +66,12 @@ describe 'Entwine'
}})
$('#dom_test div').bar();
res.should.eql [2, 1]
expect(res).toEqual( [2, 1]);
$('#dom_test div').entwine('bar').bar();
res.should.eql [2, 1, 4, 3]
end
it 'internal to namespace, will look up functions in namespace before in base, even in closure'
expect(res).toEqual( [2, 1, 4, 3]);
});
it( 'internal to namespace, will look up functions in namespace before in base, even in closure', function() {
var res = []
$('#a').entwine({
foo: function(){res.push(1);},
@ -81,12 +83,12 @@ describe 'Entwine'
}})
$('#dom_test div').bar();
res.should.eql [2, 1]
expect(res).toEqual( [2, 1]);
$('#dom_test div').entwine('bar').bar();
res.should.eql [2, 1, 4, 3]
end
it 'internal to namespace, will look up functions in namespace before in base, even in onmatch'
expect(res).toEqual( [2, 1, 4, 3]);
});
it( 'internal to namespace, will look up functions in namespace before in base, even in onmatch', function() {
var res = []
$('#a').entwine({
foo: function(){res.push(1);},
@ -100,13 +102,13 @@ describe 'Entwine'
}})
$('#dom_test div').bar();
res.should.eql [2, 1]
expect(res).toEqual( [2, 1]);
$('#a').addClass('d');
res.should.eql [2, 1, 4, 3]
end
it 'internal to namespace, will look up functions in base when not present in namespace'
expect(res).toEqual( [2, 1, 4, 3]);
});
it( 'internal to namespace, will look up functions in base when not present in namespace', function() {
var res = []
$('#a').entwine({
foo: function(){res.push(1);}
@ -115,10 +117,10 @@ describe 'Entwine'
bar: function(){res.push(2); this.foo();}
}})
$('#dom_test div').entwine('bar').bar();
res.should.eql [2, 1]
end
expect(res).toEqual( [2, 1]);
});
it 'internal to namespace, will not look up functions in base if present in namespace, even when not applicable to selector'
it( 'internal to namespace, will not look up functions in base if present in namespace, even when not applicable to selector', function() {
var res = []
$('#a').entwine('bar', function($){return{
foo: function(){this.bar();}
@ -131,10 +133,10 @@ describe 'Entwine'
}})
$('#a').entwine('bar').foo()
res.should.eql []
end
expect(res).toEqual( []);
});
it 'internal to namespace, can be directed to base namespace'
it( 'internal to namespace, can be directed to base namespace', function() {
var res = []
$('#a').entwine({
foo: function(){res.push(1);},
@ -145,22 +147,22 @@ describe 'Entwine'
bar: function(){res.push(4); this.foo(); this.entwine('.').foo();}
}})
$('#dom_test div').bar();
res.should.eql [2, 1]
expect(res).toEqual( [2, 1]);
$('#dom_test div').entwine('bar').bar();
res.should.eql [2, 1, 4, 3, 1]
end
expect(res).toEqual( [2, 1, 4, 3, 1]);
});
it 'internal to namespace, will look up functions in namespace called the same as a regular jQuery base function'
it( 'internal to namespace, will look up functions in namespace called the same as a regular jQuery base function', function() {
var res = []
$('#a').entwine('bar', function($){return{
load: function(){res.push(1);},
bar: function(){res.push(2); this.load();}
}})
$('#dom_test div').entwine('bar').bar();
res.should.eql [2, 1]
end
expect(res).toEqual( [2, 1]);
});
it 'internal to namespace, can be directed to regular jQuery base function'
it( 'internal to namespace, can be directed to regular jQuery base function', function() {
var res = []
$.fn.testy = function(){ res.push(1); }
$('#a').entwine('bar', function($){return{
@ -168,10 +170,10 @@ describe 'Entwine'
bar: function(){res.push(2); this.entwine('.').testy();}
}})
$('#dom_test div').entwine('bar').bar();
res.should.eql [2, 1]
end
it 'internal to namespace, can be directed to sub namespace'
expect(res).toEqual( [2, 1]);
});
it( 'internal to namespace, can be directed to sub namespace', function() {
var res = []
$.entwine('zap', function($){
$('#a').entwine({
@ -185,10 +187,10 @@ describe 'Entwine'
})
})
$('#dom_test div').entwine('zap').foo();
res.should.eql [1, 2]
end
expect(res).toEqual( [1, 2]);
});
it 'internal to namespace, can be directed to unrelated namespace'
it( 'internal to namespace, can be directed to unrelated namespace', function() {
var res = []
$.entwine('zap', function($){
$('#a').entwine({
@ -208,10 +210,10 @@ describe 'Entwine'
})
$('#dom_test div').entwine('zap').foo();
res.should.eql [1, 3]
end
expect(res).toEqual( [1, 3]);
});
it 'a function passed out of a namespace will remember its namespace'
it( 'a function passed out of a namespace will remember its namespace', function() {
var res = []
var func = function(func) {
func.call($('#a, #b'));
@ -221,10 +223,10 @@ describe 'Entwine'
bar: function(){res.push(2); func(this.zap);}
}})
$('#dom_test #a').entwine('bar').bar();
res.should.eql [2, 'b', 'a']
end
expect(res).toEqual( [2, 'b', 'a']);
});
it 'using block functions'
it( 'using block functions', function() {
var res = []
$('#a').entwine({
foo: function(){res.push(1);}
@ -234,13 +236,14 @@ describe 'Entwine'
}})
$('#dom_test div').foo();
res.should.eql [1]
expect(res).toEqual( [1]);
$('#dom_test div').entwine('bar', function($){
$(this).foo();
})
res.should.eql [1, 3]
end
expect(res).toEqual( [1, 3]);
});
end
end
});
});

View File

@ -1,102 +1,88 @@
describe 'Entwine'
describe 'Properties'
before
$('body').append('<div id="dom_test"></div>')
end
after
$('#dom_test').remove()
end
before_each
$.entwine.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c"></div><div id="b" class="b c"></div>')
end
it 'can define and get a basic property'
$('#a').entwine({
Foo: null
});
$('.a').getFoo().should.be_null
end
it 'can define and set a basic property'
$('#a').entwine({
Foo: null
});
$('.a').setFoo(1);
$('.a').getFoo().should.equal 1
end
it 'can define a default value'
$('#a').entwine({
Foo: 1
});
$('.a').getFoo().should.equal 1
end
it 'should manage proprties in namespaces without clashing'
$('#a').entwine({
Foo: 1
});
$.entwine('test', function($){
$('#a').entwine({
Foo: 2
});
});
$('.a').getFoo().should.equal 1
$('.a').entwine('test').getFoo().should.equal 2
$('.a').setFoo(4);
$('.a').entwine('test').setFoo(8);
$('.a').getFoo().should.equal 4
$('.a').entwine('test').getFoo().should.equal 8
end
it 'should manage directly setting proprties in namespaces without clashing'
$('#a').entwine({
Foo: null
});
$.entwine('test', function($){
$('#a').entwine({
Foo: null
});
});
$('.a').entwineData('Foo', 4);
$('.a').entwine('test').entwineData('Foo', 8);
$('.a').entwineData('Foo').should.equal 4
$('.a').entwine('test').entwineData('Foo').should.equal 8
end
describe('Entwine', function() {
describe 'jQuery style accessors'
it 'can define and get a basic property'
$('#a').entwine({
Foo: null
beforeEach(function() {
$('body').append('<div id="dom_test"></div>')
});
afterEach(function() {
$('#dom_test').remove()
});
describe('Properties', function() {
beforeEach(function() {
$.entwine.clear_all_rules();
$('#dom_test').html('<div id="a" class="a b c"></div><div id="b" class="b c"></div>');
});
$('.a').Foo().should.be_null
end
it 'can define and set a basic property'
$('#a').entwine({
Foo: null
it('can define and get a basic property', function() {
$('#a').entwine({
Foo: null
});
expect($('.a').getFoo()).toBeNull();
});
$('.a').Foo(1);
$('.a').Foo().should.equal 1
end
it 'can define a default value'
$('#a').entwine({
Foo: 1
it('can define and set a basic property', function() {
$('#a').entwine({
Foo: null
});
$('.a').setFoo(1);
expect($('.a').getFoo()).toEqual(1)
});
$('.a').Foo().should.equal 1
end
end
end
end
it('can define a default value', function() {
$('#a').entwine({
Foo: 1
});
expect($('.a').getFoo()).toEqual(1);
});
it('should manage proprties in namespaces without clashing', function() {
$('#a').entwine({
Foo: 1
});
$.entwine('test', function($) {
$('#a').entwine({
Foo: 2
});
});
expect($('.a').getFoo()).toEqual(1);
expect($('.a').entwine('test').getFoo()).toEqual(2)
$('.a').setFoo(4);
$('.a').entwine('test').setFoo(8);
expect($('.a').getFoo()).toEqual(4)
expect($('.a').entwine('test').getFoo()).toEqual(8)
});
it('should manage directly setting proprties in namespaces without clashing', function() {
$('#a').entwine({
Foo: null
});
$.entwine('test', function($) {
$('#a').entwine({
Foo: null
});
});
$('.a').entwineData('Foo', 4);
$('.a').entwine('test').entwineData('Foo', 8);
expect($('.a').entwineData('Foo')).toEqual(4) ;
expect($('.a').entwine('test').entwineData('Foo')).toEqual(8);
});
describe('jQuery style accessors', function() {
it('can define and get a basic property', function() {
$('#a').entwine({
Foo: null
});
expect($('.a').Foo()).toBeNull();
});
it('can define and set a basic property', function() {
$('#a').entwine({
Foo: null
});
$('.a').Foo(1);
expect($('.a').Foo()).toEqual(1)
});
it('can define a default value', function() {
$('#a').entwine({
Foo: 1
});
expect($('.a').Foo()).toEqual(1)
});
});
});
});

View File

@ -1,66 +1,88 @@
describe 'Entwine'
describe 'Super'
before
$('body').append('<div id="dom_test"></div>')
end
after
$('#dom_test').remove()
end
describe('Entwine', function() {
before_each
$.entwine.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c">Foo</div><div id="b" class="c d e">Bar</div>')
end
it 'can call the super function'
var a = 1;
$('#a').entwine({
foo: function(){a *= 2;}
});
$('#a.a').entwine({
foo: function(){a += 2; this._super();}
});
$('#a').foo();
a.should.equal 6
end
it 'super to a non-existant class should be ignored'
var a = 1;
$('#a').entwine({
foo: function(){a *= 2; this._super();}
});
$('#a.a').entwine({
foo: function(){a += 2; this._super();}
});
$('#a').foo();
a.should.equal 6
end
it 'can call super from two different functions without screwing up what super points to'
var list = [];
$('#a').entwine({
foo: function(){ list.push('foo'); this.bar(); },
bar: function(){ list.push('bar'); }
});
$('#a.a').entwine({
foo: function(){ list.push('foo2'); this._super(); list.push('foo2'); this._super(); },
bar: function(){ list.push('bar2'); this._super(); }
});
$('#a').foo();
list.should.eql [ 'foo2', 'foo', 'bar2', 'bar', 'foo2', 'foo', 'bar2', 'bar' ]
end
it 'can override (and call via super) a non-entwine jquery function'
var a = 1
$('#a').entwine({
text: function(){ a = this._super(); }
});
$('#a').text();
a.should.equal 'Foo'
$('#b').text().should.equal 'Bar'
end
end
end
beforeEach(function() {
$('body').append('<div id="dom_test"></div>')
});
afterEach(function() {
$('#dom_test').remove()
});
describe('Super', function() {
beforeEach(function() {
$.entwine.clear_all_rules()
$('#dom_test').html('<div id="a" class="a b c">Foo</div><div id="b" class="c d e">Bar</div>')
});
it('can call the super function', function() {
var a = 1;
$('#a').entwine({
foo: function() {
a *= 2;
}
});
$('#a.a').entwine({
foo: function() {
a += 2;
this._super();
}
});
$('#a').foo();
expect(a).toEqual(6)
});
it('super to a non-existant class should be ignored', function() {
var a = 1;
$('#a').entwine({
foo: function() {
a *= 2;
this._super();
}
});
$('#a.a').entwine({
foo: function() {
a += 2;
this._super();
}
});
$('#a').foo();
expect(a).toEqual(6)
});
it('can call super from two different functions without screwing up what super points to', function() {
var list = [];
$('#a').entwine({
foo: function() {
list.push('foo');
this.bar();
},
bar: function() {
list.push('bar');
}
});
$('#a.a').entwine({
foo: function() {
list.push('foo2');
this._super();
list.push('foo2');
this._super();
},
bar: function() {
list.push('bar2');
this._super();
}
});
$('#a').foo();
expect(list).toEqual(['foo2', 'foo', 'bar2', 'bar', 'foo2', 'foo', 'bar2', 'bar'])
});
it('can override (and call via super) a non-entwine jquery function', function() {
var a = 1
$('#a').entwine({
text: function() {
a = this._super();
}
});
$('#a').text();
expect(a).toEqual('Foo')
expect($('#b').text()).toEqual('Bar')
});
});
});

View File

@ -1,38 +0,0 @@
<html>
<head>
<link type="text/css" rel="stylesheet" href="../vendor/jspec/lib/jspec.css" />
<script src="../vendor/jquery-1.3.2.js"></script>
<script src="../vendor/jspec/lib/jspec.js"></script>
<script src="../vendor/jspec/lib/jspec.jquery.js"></script>
<script src="../vendor/jquery.selector/jquery.class.js"></script>
<script src="../vendor/jquery.selector/jquery.selector.js"></script>
<script src="../vendor/jquery.selector/jquery.selector.specifity.js"></script>
<script src="../vendor/jquery.selector/jquery.selector.matches.js"></script>
<script src="../src/jquery.entwine.js"></script>
<script src="../src/jquery.entwine.dommaybechanged.js"></script>
<script src="../src/jquery.entwine.events.js"></script>
<script src="../src/jquery.entwine.ctors.js"></script>
<script src="../src/jquery.entwine.properties.js"></script>
<script>
function runSuites() {
JSpec
.exec('spec.entwine.basics.js')
.exec('spec.entwine.namespaces.js')
.exec('spec.entwine.super.js')
.exec('spec.entwine.events.js')
.exec('spec.entwine.ctors.js')
.exec('spec.entwine.properties.js')
.run()
.report()
}
</script>
</head>
<body class="jspec" onLoad="runSuites();">
<div id="jspec-top"><h2 id="jspec-title">JSpec <em><script>document.write(JSpec.version)</script></em></h2></div>
<div id="jspec"><div class="loading"></div></div>
<div id="jspec-bottom"></div>
</body>
</html>

View File

@ -23,7 +23,7 @@ var console;
*/
clear_all_rules: function() {
// Remove proxy functions
for (var k in $.fn) { if ($.fn[k].entwine) delete $.fn[k] ; }
for (var k in $.fn) { if ($.fn[k].isentwinemethod) delete $.fn[k]; }
// Remove bound events - TODO: Make this pluggable, so this code can be moved to jquery.entwine.events.js
$(document).unbind('.entwine');
// Remove namespaces, and start over again
@ -119,38 +119,48 @@ var console;
}
else {
// We're in a namespace, so we build a Class that subclasses the jQuery Object Class to inject namespace functions into
var subfn = function(){};
this.injectee = subfn.prototype = new $();
// And then we provide an overriding $ that returns objects of our new Class, and an overriding pushStack to catch further selection building
var bound$ = this.$ = function(a) {
// Try the simple way first
var jq = $.fn.init.apply(new subfn(), arguments);
if (jq instanceof subfn) return jq;
// jQuery 1.5 already provides a nice way to subclass, so use it
if ($.sub) {
this.$ = $.sub();
this.injectee = this.$.prototype;
}
// For jQuery < 1.5 we have to do it ourselves
else {
var subfn = function(){};
this.injectee = subfn.prototype = new $;
// And then we provide an overriding $ that returns objects of our new Class, and an overriding pushStack to catch further selection building
var bound$ = this.$ = function(a) {
// Try the simple way first
var jq = $.fn.init.apply(new subfn(), arguments);
if (jq instanceof subfn) return jq;
// That didn't return a bound object, so now we need to copy it
var rv = new subfn();
rv.selector = jq.selector; rv.context = jq.context; var i = rv.length = jq.length;
while (i--) rv[i] = jq[i];
return rv;
};
this.injectee.pushStack = function(elems, name, selector){
var ret = bound$(elems);
// That didn't return a bound object, so now we need to copy it
var rv = new subfn();
rv.selector = jq.selector; rv.context = jq.context; var i = rv.length = jq.length;
while (i--) rv[i] = jq[i];
return rv;
};
this.injectee.pushStack = function(elems, name, selector){
var ret = bound$(elems);
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
if ( name === "find" ) ret.selector = this.selector + (this.selector ? " " : "") + selector;
else if ( name ) ret.selector = this.selector + "." + name + "(" + selector + ")";
if ( name === "find" ) ret.selector = this.selector + (this.selector ? " " : "") + selector;
else if ( name ) ret.selector = this.selector + "." + name + "(" + selector + ")";
// Return the newly-formed element set
return ret;
};
// Return the newly-formed element set
return ret;
};
// Copy static functions through from $ to this.$ so e.g. $.ajax still works
// @bug, @cantfix: Any class functions added to $ after this call won't get mirrored through
$.extend(this.$, $);
// Copy static functions through from $ to this.$ so e.g. $.ajax still works
// @bug, @cantfix: Any class functions added to $ after this call won't get mirrored through
$.extend(this.$, $);
}
// We override entwine to inject the name of this namespace when defining blocks inside this namespace
var entwine_wrapper = this.injectee.entwine = function(spacename) {
@ -238,12 +248,12 @@ var console;
var rule = rulelist.addRule(selector, name); rule.func = func;
if (!this.injectee.hasOwnProperty(name) || !this.injectee[name].entwine) {
if (!this.injectee.hasOwnProperty(name) || !this.injectee[name].isentwinemethod) {
this.injectee[name] = this.build_proxy(name, this.injectee.hasOwnProperty(name) ? this.injectee[name] : null);
this.injectee[name].entwine = true;
this.injectee[name].isentwinemethod = true;
}
if (!this.injectee[name].entwine) {
if (!this.injectee[name].isentwinemethod) {
$.entwine.warn('Warning: Entwine function '+name+' clashes with regular jQuery function - entwine function will not be callable directly on jQuery object', $.entwine.WARN_LEVEL_IMPORTANT);
}
},

View File

@ -0,0 +1,20 @@
Copyright (c) 2008-2010 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,188 @@
jasmine.TrivialReporter = function(doc) {
this.document = doc || document;
this.suiteDivs = {};
this.logRunningSpecs = false;
};
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
var el = document.createElement(type);
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else {
if (child) { el.appendChild(child); }
}
}
for (var attr in attrs) {
if (attr == "className") {
el[attr] = attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}
return el;
};
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
var showPassed, showSkipped;
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
this.createDom('div', { className: 'banner' },
this.createDom('div', { className: 'logo' },
this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"),
this.createDom('span', { className: 'version' }, runner.env.versionString())),
this.createDom('div', { className: 'options' },
"Show ",
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
)
),
this.runnerDiv = this.createDom('div', { className: 'runner running' },
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
);
this.document.body.appendChild(this.outerDiv);
var suites = runner.suites();
for (var i = 0; i < suites.length; i++) {
var suite = suites[i];
var suiteDiv = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
this.suiteDivs[suite.id] = suiteDiv;
var parentDiv = this.outerDiv;
if (suite.parentSuite) {
parentDiv = this.suiteDivs[suite.parentSuite.id];
}
parentDiv.appendChild(suiteDiv);
}
this.startedAt = new Date();
var self = this;
showPassed.onclick = function(evt) {
if (showPassed.checked) {
self.outerDiv.className += ' show-passed';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
}
};
showSkipped.onclick = function(evt) {
if (showSkipped.checked) {
self.outerDiv.className += ' show-skipped';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
}
};
};
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
var results = runner.results();
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
this.runnerDiv.setAttribute("class", className);
//do it twice for IE
this.runnerDiv.setAttribute("className", className);
var specs = runner.specs();
var specCount = 0;
for (var i = 0; i < specs.length; i++) {
if (this.specFilter(specs[i])) {
specCount++;
}
}
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
};
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
var results = suite.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.totalCount == 0) { // todo: change this to check results.skipped
status = 'skipped';
}
this.suiteDivs[suite.id].className += " " + status;
};
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
if (this.logRunningSpecs) {
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
}
};
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
var results = spec.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.skipped) {
status = 'skipped';
}
var specDiv = this.createDom('div', { className: 'spec ' + status },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(spec.getFullName()),
title: spec.getFullName()
}, spec.description));
var resultItems = results.getItems();
var messagesDiv = this.createDom('div', { className: 'messages' });
for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i];
if (result.type == 'log') {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
} else if (result.type == 'expect' && result.passed && !result.passed()) {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
if (result.trace.stack) {
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
}
}
}
if (messagesDiv.childNodes.length > 0) {
specDiv.appendChild(messagesDiv);
}
this.suiteDivs[spec.suite.id].appendChild(specDiv);
};
jasmine.TrivialReporter.prototype.log = function() {
var console = jasmine.getGlobal().console;
if (console && console.log) {
if (console.log.apply) {
console.log.apply(console, arguments);
} else {
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
}
}
};
jasmine.TrivialReporter.prototype.getLocation = function() {
return this.document.location;
};
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
var paramMap = {};
var params = this.getLocation().search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
}
if (!paramMap["spec"]) return true;
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
};

View File

@ -0,0 +1,166 @@
body {
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
}
.jasmine_reporter a:visited, .jasmine_reporter a {
color: #303;
}
.jasmine_reporter a:hover, .jasmine_reporter a:active {
color: blue;
}
.run_spec {
float:right;
padding-right: 5px;
font-size: .8em;
text-decoration: none;
}
.jasmine_reporter {
margin: 0 5px;
}
.banner {
color: #303;
background-color: #fef;
padding: 5px;
}
.logo {
float: left;
font-size: 1.1em;
padding-left: 5px;
}
.logo .version {
font-size: .6em;
padding-left: 1em;
}
.runner.running {
background-color: yellow;
}
.options {
text-align: right;
font-size: .8em;
}
.suite {
border: 1px outset gray;
margin: 5px 0;
padding-left: 1em;
}
.suite .suite {
margin: 5px;
}
.suite.passed {
background-color: #dfd;
}
.suite.failed {
background-color: #fdd;
}
.spec {
margin: 5px;
padding-left: 1em;
clear: both;
}
.spec.failed, .spec.passed, .spec.skipped {
padding-bottom: 5px;
border: 1px solid gray;
}
.spec.failed {
background-color: #fbb;
border-color: red;
}
.spec.passed {
background-color: #bfb;
border-color: green;
}
.spec.skipped {
background-color: #bbb;
}
.messages {
border-left: 1px dashed gray;
padding-left: 1em;
padding-right: 1em;
}
.passed {
background-color: #cfc;
display: none;
}
.failed {
background-color: #fbb;
}
.skipped {
color: #777;
background-color: #eee;
display: none;
}
/*.resultMessage {*/
/*white-space: pre;*/
/*}*/
.resultMessage span.result {
display: block;
line-height: 2em;
color: black;
}
.resultMessage .mismatch {
color: black;
}
.stackTrace {
white-space: pre;
font-size: .8em;
margin-left: 10px;
max-height: 5em;
overflow: auto;
border: 1px inset red;
padding: 1em;
background: #eef;
}
.finished-at {
padding-left: 1em;
font-size: .6em;
}
.show-passed .passed,
.show-skipped .skipped {
display: block;
}
#jasmine_content {
position:fixed;
right: 100%;
}
.runner {
border: 1px solid gray;
display: block;
margin: 5px 0;
padding: 2px 0 2px 10px;
}

View File

@ -0,0 +1,2421 @@
/**
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
*
* @namespace
*/
var jasmine = {};
/**
* @private
*/
jasmine.unimplementedMethod_ = function() {
throw new Error("unimplemented method");
};
/**
* Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
* a plain old variable and may be redefined by somebody else.
*
* @private
*/
jasmine.undefined = jasmine.___undefined___;
/**
* Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
*
*/
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
/**
* Default timeout interval in milliseconds for waitsFor() blocks.
*/
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
jasmine.getGlobal = function() {
function getGlobal() {
return this;
}
return getGlobal();
};
/**
* Allows for bound functions to be compared. Internal use only.
*
* @ignore
* @private
* @param base {Object} bound 'this' for the function
* @param name {Function} function to find
*/
jasmine.bindOriginal_ = function(base, name) {
var original = base[name];
if (original.apply) {
return function() {
return original.apply(base, arguments);
};
} else {
// IE support
return jasmine.getGlobal()[name];
}
};
jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
jasmine.MessageResult = function(values) {
this.type = 'log';
this.values = values;
this.trace = new Error(); // todo: test better
};
jasmine.MessageResult.prototype.toString = function() {
var text = "";
for(var i = 0; i < this.values.length; i++) {
if (i > 0) text += " ";
if (jasmine.isString_(this.values[i])) {
text += this.values[i];
} else {
text += jasmine.pp(this.values[i]);
}
}
return text;
};
jasmine.ExpectationResult = function(params) {
this.type = 'expect';
this.matcherName = params.matcherName;
this.passed_ = params.passed;
this.expected = params.expected;
this.actual = params.actual;
this.message = this.passed_ ? 'Passed.' : params.message;
this.trace = this.passed_ ? '' : new Error(this.message);
};
jasmine.ExpectationResult.prototype.toString = function () {
return this.message;
};
jasmine.ExpectationResult.prototype.passed = function () {
return this.passed_;
};
/**
* Getter for the Jasmine environment. Ensures one gets created
*/
jasmine.getEnv = function() {
return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
};
/**
* @ignore
* @private
* @param value
* @returns {Boolean}
*/
jasmine.isArray_ = function(value) {
return jasmine.isA_("Array", value);
};
/**
* @ignore
* @private
* @param value
* @returns {Boolean}
*/
jasmine.isString_ = function(value) {
return jasmine.isA_("String", value);
};
/**
* @ignore
* @private
* @param value
* @returns {Boolean}
*/
jasmine.isNumber_ = function(value) {
return jasmine.isA_("Number", value);
};
/**
* @ignore
* @private
* @param {String} typeName
* @param value
* @returns {Boolean}
*/
jasmine.isA_ = function(typeName, value) {
return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
};
/**
* Pretty printer for expecations. Takes any object and turns it into a human-readable string.
*
* @param value {Object} an object to be outputted
* @returns {String}
*/
jasmine.pp = function(value) {
var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
stringPrettyPrinter.format(value);
return stringPrettyPrinter.string;
};
/**
* Returns true if the object is a DOM Node.
*
* @param {Object} obj object to check
* @returns {Boolean}
*/
jasmine.isDomNode = function(obj) {
return obj['nodeType'] > 0;
};
/**
* Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
*
* @example
* // don't care about which function is passed in, as long as it's a function
* expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
*
* @param {Class} clazz
* @returns matchable object of the type clazz
*/
jasmine.any = function(clazz) {
return new jasmine.Matchers.Any(clazz);
};
/**
* Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
*
* Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
* expectation syntax. Spies can be checked if they were called or not and what the calling params were.
*
* A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
*
* Spies are torn down at the end of every spec.
*
* Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
*
* @example
* // a stub
* var myStub = jasmine.createSpy('myStub'); // can be used anywhere
*
* // spy example
* var foo = {
* not: function(bool) { return !bool; }
* }
*
* // actual foo.not will not be called, execution stops
* spyOn(foo, 'not');
// foo.not spied upon, execution will continue to implementation
* spyOn(foo, 'not').andCallThrough();
*
* // fake example
* var foo = {
* not: function(bool) { return !bool; }
* }
*
* // foo.not(val) will return val
* spyOn(foo, 'not').andCallFake(function(value) {return value;});
*
* // mock example
* foo.not(7 == 7);
* expect(foo.not).toHaveBeenCalled();
* expect(foo.not).toHaveBeenCalledWith(true);
*
* @constructor
* @see spyOn, jasmine.createSpy, jasmine.createSpyObj
* @param {String} name
*/
jasmine.Spy = function(name) {
/**
* The name of the spy, if provided.
*/
this.identity = name || 'unknown';
/**
* Is this Object a spy?
*/
this.isSpy = true;
/**
* The actual function this spy stubs.
*/
this.plan = function() {
};
/**
* Tracking of the most recent call to the spy.
* @example
* var mySpy = jasmine.createSpy('foo');
* mySpy(1, 2);
* mySpy.mostRecentCall.args = [1, 2];
*/
this.mostRecentCall = {};
/**
* Holds arguments for each call to the spy, indexed by call count
* @example
* var mySpy = jasmine.createSpy('foo');
* mySpy(1, 2);
* mySpy(7, 8);
* mySpy.mostRecentCall.args = [7, 8];
* mySpy.argsForCall[0] = [1, 2];
* mySpy.argsForCall[1] = [7, 8];
*/
this.argsForCall = [];
this.calls = [];
};
/**
* Tells a spy to call through to the actual implemenatation.
*
* @example
* var foo = {
* bar: function() { // do some stuff }
* }
*
* // defining a spy on an existing property: foo.bar
* spyOn(foo, 'bar').andCallThrough();
*/
jasmine.Spy.prototype.andCallThrough = function() {
this.plan = this.originalValue;
return this;
};
/**
* For setting the return value of a spy.
*
* @example
* // defining a spy from scratch: foo() returns 'baz'
* var foo = jasmine.createSpy('spy on foo').andReturn('baz');
*
* // defining a spy on an existing property: foo.bar() returns 'baz'
* spyOn(foo, 'bar').andReturn('baz');
*
* @param {Object} value
*/
jasmine.Spy.prototype.andReturn = function(value) {
this.plan = function() {
return value;
};
return this;
};
/**
* For throwing an exception when a spy is called.
*
* @example
* // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
* var foo = jasmine.createSpy('spy on foo').andThrow('baz');
*
* // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
* spyOn(foo, 'bar').andThrow('baz');
*
* @param {String} exceptionMsg
*/
jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
this.plan = function() {
throw exceptionMsg;
};
return this;
};
/**
* Calls an alternate implementation when a spy is called.
*
* @example
* var baz = function() {
* // do some stuff, return something
* }
* // defining a spy from scratch: foo() calls the function baz
* var foo = jasmine.createSpy('spy on foo').andCall(baz);
*
* // defining a spy on an existing property: foo.bar() calls an anonymnous function
* spyOn(foo, 'bar').andCall(function() { return 'baz';} );
*
* @param {Function} fakeFunc
*/
jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
this.plan = fakeFunc;
return this;
};
/**
* Resets all of a spy's the tracking variables so that it can be used again.
*
* @example
* spyOn(foo, 'bar');
*
* foo.bar();
*
* expect(foo.bar.callCount).toEqual(1);
*
* foo.bar.reset();
*
* expect(foo.bar.callCount).toEqual(0);
*/
jasmine.Spy.prototype.reset = function() {
this.wasCalled = false;
this.callCount = 0;
this.argsForCall = [];
this.calls = [];
this.mostRecentCall = {};
};
jasmine.createSpy = function(name) {
var spyObj = function() {
spyObj.wasCalled = true;
spyObj.callCount++;
var args = jasmine.util.argsToArray(arguments);
spyObj.mostRecentCall.object = this;
spyObj.mostRecentCall.args = args;
spyObj.argsForCall.push(args);
spyObj.calls.push({object: this, args: args});
return spyObj.plan.apply(this, arguments);
};
var spy = new jasmine.Spy(name);
for (var prop in spy) {
spyObj[prop] = spy[prop];
}
spyObj.reset();
return spyObj;
};
/**
* Determines whether an object is a spy.
*
* @param {jasmine.Spy|Object} putativeSpy
* @returns {Boolean}
*/
jasmine.isSpy = function(putativeSpy) {
return putativeSpy && putativeSpy.isSpy;
};
/**
* Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
* large in one call.
*
* @param {String} baseName name of spy class
* @param {Array} methodNames array of names of methods to make spies
*/
jasmine.createSpyObj = function(baseName, methodNames) {
if (!jasmine.isArray_(methodNames) || methodNames.length == 0) {
throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
}
var obj = {};
for (var i = 0; i < methodNames.length; i++) {
obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
}
return obj;
};
/**
* All parameters are pretty-printed and concatenated together, then written to the current spec's output.
*
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
*/
jasmine.log = function() {
var spec = jasmine.getEnv().currentSpec;
spec.log.apply(spec, arguments);
};
/**
* Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
*
* @example
* // spy example
* var foo = {
* not: function(bool) { return !bool; }
* }
* spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
*
* @see jasmine.createSpy
* @param obj
* @param methodName
* @returns a Jasmine spy that can be chained with all spy methods
*/
var spyOn = function(obj, methodName) {
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
};
/**
* Creates a Jasmine spec that will be added to the current suite.
*
* // TODO: pending tests
*
* @example
* it('should be true', function() {
* expect(true).toEqual(true);
* });
*
* @param {String} desc description of this specification
* @param {Function} func defines the preconditions and expectations of the spec
*/
var it = function(desc, func) {
return jasmine.getEnv().it(desc, func);
};
/**
* Creates a <em>disabled</em> Jasmine spec.
*
* A convenience method that allows existing specs to be disabled temporarily during development.
*
* @param {String} desc description of this specification
* @param {Function} func defines the preconditions and expectations of the spec
*/
var xit = function(desc, func) {
return jasmine.getEnv().xit(desc, func);
};
/**
* Starts a chain for a Jasmine expectation.
*
* It is passed an Object that is the actual value and should chain to one of the many
* jasmine.Matchers functions.
*
* @param {Object} actual Actual value to test against and expected value
*/
var expect = function(actual) {
return jasmine.getEnv().currentSpec.expect(actual);
};
/**
* Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
*
* @param {Function} func Function that defines part of a jasmine spec.
*/
var runs = function(func) {
jasmine.getEnv().currentSpec.runs(func);
};
/**
* Waits a fixed time period before moving to the next block.
*
* @deprecated Use waitsFor() instead
* @param {Number} timeout milliseconds to wait
*/
var waits = function(timeout) {
jasmine.getEnv().currentSpec.waits(timeout);
};
/**
* Waits for the latchFunction to return true before proceeding to the next block.
*
* @param {Function} latchFunction
* @param {String} optional_timeoutMessage
* @param {Number} optional_timeout
*/
var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
};
/**
* A function that is called before each spec in a suite.
*
* Used for spec setup, including validating assumptions.
*
* @param {Function} beforeEachFunction
*/
var beforeEach = function(beforeEachFunction) {
jasmine.getEnv().beforeEach(beforeEachFunction);
};
/**
* A function that is called after each spec in a suite.
*
* Used for restoring any state that is hijacked during spec execution.
*
* @param {Function} afterEachFunction
*/
var afterEach = function(afterEachFunction) {
jasmine.getEnv().afterEach(afterEachFunction);
};
/**
* Defines a suite of specifications.
*
* Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
* are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
* of setup in some tests.
*
* @example
* // TODO: a simple suite
*
* // TODO: a simple suite with a nested describe block
*
* @param {String} description A string, usually the class under test.
* @param {Function} specDefinitions function that defines several specs.
*/
var describe = function(description, specDefinitions) {
return jasmine.getEnv().describe(description, specDefinitions);
};
/**
* Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
*
* @param {String} description A string, usually the class under test.
* @param {Function} specDefinitions function that defines several specs.
*/
var xdescribe = function(description, specDefinitions) {
return jasmine.getEnv().xdescribe(description, specDefinitions);
};
// Provide the XMLHttpRequest class for IE 5.x-6.x:
jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
try {
return new ActiveXObject("Msxml2.XMLHTTP.6.0");
} catch(e) {
}
try {
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
} catch(e) {
}
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
}
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
}
throw new Error("This browser does not support XMLHttpRequest.");
} : XMLHttpRequest;
/**
* @namespace
*/
jasmine.util = {};
/**
* Declare that a child class inherit it's prototype from the parent class.
*
* @private
* @param {Function} childClass
* @param {Function} parentClass
*/
jasmine.util.inherit = function(childClass, parentClass) {
/**
* @private
*/
var subclass = function() {
};
subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass;
};
jasmine.util.formatException = function(e) {
var lineNumber;
if (e.line) {
lineNumber = e.line;
}
else if (e.lineNumber) {
lineNumber = e.lineNumber;
}
var file;
if (e.sourceURL) {
file = e.sourceURL;
}
else if (e.fileName) {
file = e.fileName;
}
var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
if (file && lineNumber) {
message += ' in ' + file + ' (line ' + lineNumber + ')';
}
return message;
};
jasmine.util.htmlEscape = function(str) {
if (!str) return str;
return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
};
jasmine.util.argsToArray = function(args) {
var arrayOfArgs = [];
for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
return arrayOfArgs;
};
jasmine.util.extend = function(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;
};
/**
* Environment for Jasmine
*
* @constructor
*/
jasmine.Env = function() {
this.currentSpec = null;
this.currentSuite = null;
this.currentRunner_ = new jasmine.Runner(this);
this.reporter = new jasmine.MultiReporter();
this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
this.lastUpdate = 0;
this.specFilter = function() {
return true;
};
this.nextSpecId_ = 0;
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
// wrap matchers
this.matchersClass = function() {
jasmine.Matchers.apply(this, arguments);
};
jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
};
jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
jasmine.Env.prototype.setInterval = jasmine.setInterval;
jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
/**
* @returns an object containing jasmine version build info, if set.
*/
jasmine.Env.prototype.version = function () {
if (jasmine.version_) {
return jasmine.version_;
} else {
throw new Error('Version not set');
}
};
/**
* @returns string containing jasmine version build info, if set.
*/
jasmine.Env.prototype.versionString = function() {
if (jasmine.version_) {
var version = this.version();
return version.major + "." + version.minor + "." + version.build + " revision " + version.revision;
} else {
return "version unknown";
}
};
/**
* @returns a sequential integer starting at 0
*/
jasmine.Env.prototype.nextSpecId = function () {
return this.nextSpecId_++;
};
/**
* @returns a sequential integer starting at 0
*/
jasmine.Env.prototype.nextSuiteId = function () {
return this.nextSuiteId_++;
};
/**
* Register a reporter to receive status updates from Jasmine.
* @param {jasmine.Reporter} reporter An object which will receive status updates.
*/
jasmine.Env.prototype.addReporter = function(reporter) {
this.reporter.addReporter(reporter);
};
jasmine.Env.prototype.execute = function() {
this.currentRunner_.execute();
};
jasmine.Env.prototype.describe = function(description, specDefinitions) {
var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
var parentSuite = this.currentSuite;
if (parentSuite) {
parentSuite.add(suite);
} else {
this.currentRunner_.add(suite);
}
this.currentSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch(e) {
declarationError = e;
}
this.currentSuite = parentSuite;
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
return suite;
};
jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
if (this.currentSuite) {
this.currentSuite.beforeEach(beforeEachFunction);
} else {
this.currentRunner_.beforeEach(beforeEachFunction);
}
};
jasmine.Env.prototype.currentRunner = function () {
return this.currentRunner_;
};
jasmine.Env.prototype.afterEach = function(afterEachFunction) {
if (this.currentSuite) {
this.currentSuite.afterEach(afterEachFunction);
} else {
this.currentRunner_.afterEach(afterEachFunction);
}
};
jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
return {
execute: function() {
}
};
};
jasmine.Env.prototype.it = function(description, func) {
var spec = new jasmine.Spec(this, this.currentSuite, description);
this.currentSuite.add(spec);
this.currentSpec = spec;
if (func) {
spec.runs(func);
}
return spec;
};
jasmine.Env.prototype.xit = function(desc, func) {
return {
id: this.nextSpecId(),
runs: function() {
}
};
};
jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
return true;
}
a.__Jasmine_been_here_before__ = b;
b.__Jasmine_been_here_before__ = a;
var hasKey = function(obj, keyName) {
return obj != null && obj[keyName] !== jasmine.undefined;
};
for (var property in b) {
if (!hasKey(a, property) && hasKey(b, property)) {
mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
}
}
for (property in a) {
if (!hasKey(b, property) && hasKey(a, property)) {
mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
}
}
for (property in b) {
if (property == '__Jasmine_been_here_before__') continue;
if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
}
}
if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
mismatchValues.push("arrays were not the same length");
}
delete a.__Jasmine_been_here_before__;
delete b.__Jasmine_been_here_before__;
return (mismatchKeys.length == 0 && mismatchValues.length == 0);
};
jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
for (var i = 0; i < this.equalityTesters_.length; i++) {
var equalityTester = this.equalityTesters_[i];
var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
if (result !== jasmine.undefined) return result;
}
if (a === b) return true;
if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
return (a == jasmine.undefined && b == jasmine.undefined);
}
if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
return a === b;
}
if (a instanceof Date && b instanceof Date) {
return a.getTime() == b.getTime();
}
if (a instanceof jasmine.Matchers.Any) {
return a.matches(b);
}
if (b instanceof jasmine.Matchers.Any) {
return b.matches(a);
}
if (jasmine.isString_(a) && jasmine.isString_(b)) {
return (a == b);
}
if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
return (a == b);
}
if (typeof a === "object" && typeof b === "object") {
return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
}
//Straight check
return (a === b);
};
jasmine.Env.prototype.contains_ = function(haystack, needle) {
if (jasmine.isArray_(haystack)) {
for (var i = 0; i < haystack.length; i++) {
if (this.equals_(haystack[i], needle)) return true;
}
return false;
}
return haystack.indexOf(needle) >= 0;
};
jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
this.equalityTesters_.push(equalityTester);
};
/** No-op base class for Jasmine reporters.
*
* @constructor
*/
jasmine.Reporter = function() {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportSpecResults = function(spec) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.log = function(str) {
};
/**
* Blocks are functions with executable code that make up a spec.
*
* @constructor
* @param {jasmine.Env} env
* @param {Function} func
* @param {jasmine.Spec} spec
*/
jasmine.Block = function(env, func, spec) {
this.env = env;
this.func = func;
this.spec = spec;
};
jasmine.Block.prototype.execute = function(onComplete) {
try {
this.func.apply(this.spec);
} catch (e) {
this.spec.fail(e);
}
onComplete();
};
/** JavaScript API reporter.
*
* @constructor
*/
jasmine.JsApiReporter = function() {
this.started = false;
this.finished = false;
this.suites_ = [];
this.results_ = {};
};
jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
this.started = true;
var suites = runner.topLevelSuites();
for (var i = 0; i < suites.length; i++) {
var suite = suites[i];
this.suites_.push(this.summarize_(suite));
}
};
jasmine.JsApiReporter.prototype.suites = function() {
return this.suites_;
};
jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
var isSuite = suiteOrSpec instanceof jasmine.Suite;
var summary = {
id: suiteOrSpec.id,
name: suiteOrSpec.description,
type: isSuite ? 'suite' : 'spec',
children: []
};
if (isSuite) {
var children = suiteOrSpec.children();
for (var i = 0; i < children.length; i++) {
summary.children.push(this.summarize_(children[i]));
}
}
return summary;
};
jasmine.JsApiReporter.prototype.results = function() {
return this.results_;
};
jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
return this.results_[specId];
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
this.finished = true;
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
this.results_[spec.id] = {
messages: spec.results().getItems(),
result: spec.results().failedCount > 0 ? "failed" : "passed"
};
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.log = function(str) {
};
jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
var results = {};
for (var i = 0; i < specIds.length; i++) {
var specId = specIds[i];
results[specId] = this.summarizeResult_(this.results_[specId]);
}
return results;
};
jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
var summaryMessages = [];
var messagesLength = result.messages.length;
for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
var resultMessage = result.messages[messageIndex];
summaryMessages.push({
text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
passed: resultMessage.passed ? resultMessage.passed() : true,
type: resultMessage.type,
message: resultMessage.message,
trace: {
stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
}
});
}
return {
result : result.result,
messages : summaryMessages
};
};
/**
* @constructor
* @param {jasmine.Env} env
* @param actual
* @param {jasmine.Spec} spec
*/
jasmine.Matchers = function(env, actual, spec, opt_isNot) {
this.env = env;
this.actual = actual;
this.spec = spec;
this.isNot = opt_isNot || false;
this.reportWasCalled_ = false;
};
// todo: @deprecated as of Jasmine 0.11, remove soon [xw]
jasmine.Matchers.pp = function(str) {
throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
};
// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
jasmine.Matchers.prototype.report = function(result, failing_message, details) {
throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
};
jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
for (var methodName in prototype) {
if (methodName == 'report') continue;
var orig = prototype[methodName];
matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
}
};
jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
return function() {
var matcherArgs = jasmine.util.argsToArray(arguments);
var result = matcherFunction.apply(this, arguments);
if (this.isNot) {
result = !result;
}
if (this.reportWasCalled_) return result;
var message;
if (!result) {
if (this.message) {
message = this.message.apply(this, arguments);
if (jasmine.isArray_(message)) {
message = message[this.isNot ? 1 : 0];
}
} else {
var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
if (matcherArgs.length > 0) {
for (var i = 0; i < matcherArgs.length; i++) {
if (i > 0) message += ",";
message += " " + jasmine.pp(matcherArgs[i]);
}
}
message += ".";
}
}
var expectationResult = new jasmine.ExpectationResult({
matcherName: matcherName,
passed: result,
expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
actual: this.actual,
message: message
});
this.spec.addMatcherResult(expectationResult);
return jasmine.undefined;
};
};
/**
* toBe: compares the actual to the expected using ===
* @param expected
*/
jasmine.Matchers.prototype.toBe = function(expected) {
return this.actual === expected;
};
/**
* toNotBe: compares the actual to the expected using !==
* @param expected
* @deprecated as of 1.0. Use not.toBe() instead.
*/
jasmine.Matchers.prototype.toNotBe = function(expected) {
return this.actual !== expected;
};
/**
* toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
*
* @param expected
*/
jasmine.Matchers.prototype.toEqual = function(expected) {
return this.env.equals_(this.actual, expected);
};
/**
* toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
* @param expected
* @deprecated as of 1.0. Use not.toNotEqual() instead.
*/
jasmine.Matchers.prototype.toNotEqual = function(expected) {
return !this.env.equals_(this.actual, expected);
};
/**
* Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
* a pattern or a String.
*
* @param expected
*/
jasmine.Matchers.prototype.toMatch = function(expected) {
return new RegExp(expected).test(this.actual);
};
/**
* Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
* @param expected
* @deprecated as of 1.0. Use not.toMatch() instead.
*/
jasmine.Matchers.prototype.toNotMatch = function(expected) {
return !(new RegExp(expected).test(this.actual));
};
/**
* Matcher that compares the actual to jasmine.undefined.
*/
jasmine.Matchers.prototype.toBeDefined = function() {
return (this.actual !== jasmine.undefined);
};
/**
* Matcher that compares the actual to jasmine.undefined.
*/
jasmine.Matchers.prototype.toBeUndefined = function() {
return (this.actual === jasmine.undefined);
};
/**
* Matcher that compares the actual to null.
*/
jasmine.Matchers.prototype.toBeNull = function() {
return (this.actual === null);
};
/**
* Matcher that boolean not-nots the actual.
*/
jasmine.Matchers.prototype.toBeTruthy = function() {
return !!this.actual;
};
/**
* Matcher that boolean nots the actual.
*/
jasmine.Matchers.prototype.toBeFalsy = function() {
return !this.actual;
};
/**
* Matcher that checks to see if the actual, a Jasmine spy, was called.
*/
jasmine.Matchers.prototype.toHaveBeenCalled = function() {
if (arguments.length > 0) {
throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
}
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
return [
"Expected spy " + this.actual.identity + " to have been called.",
"Expected spy " + this.actual.identity + " not to have been called."
];
};
return this.actual.wasCalled;
};
/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
/**
* Matcher that checks to see if the actual, a Jasmine spy, was not called.
*
* @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
*/
jasmine.Matchers.prototype.wasNotCalled = function() {
if (arguments.length > 0) {
throw new Error('wasNotCalled does not take arguments');
}
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
return [
"Expected spy " + this.actual.identity + " to not have been called.",
"Expected spy " + this.actual.identity + " to have been called."
];
};
return !this.actual.wasCalled;
};
/**
* Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
*
* @example
*
*/
jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
var expectedArgs = jasmine.util.argsToArray(arguments);
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
if (this.actual.callCount == 0) {
// todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
return [
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
];
} else {
return [
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
];
}
};
return this.env.contains_(this.actual.argsForCall, expectedArgs);
};
/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
jasmine.Matchers.prototype.wasNotCalledWith = function() {
var expectedArgs = jasmine.util.argsToArray(arguments);
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
return [
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
]
};
return !this.env.contains_(this.actual.argsForCall, expectedArgs);
};
/**
* Matcher that checks that the expected item is an element in the actual Array.
*
* @param {Object} expected
*/
jasmine.Matchers.prototype.toContain = function(expected) {
return this.env.contains_(this.actual, expected);
};
/**
* Matcher that checks that the expected item is NOT an element in the actual Array.
*
* @param {Object} expected
* @deprecated as of 1.0. Use not.toNotContain() instead.
*/
jasmine.Matchers.prototype.toNotContain = function(expected) {
return !this.env.contains_(this.actual, expected);
};
jasmine.Matchers.prototype.toBeLessThan = function(expected) {
return this.actual < expected;
};
jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
return this.actual > expected;
};
/**
* Matcher that checks that the expected exception was thrown by the actual.
*
* @param {String} expected
*/
jasmine.Matchers.prototype.toThrow = function(expected) {
var result = false;
var exception;
if (typeof this.actual != 'function') {
throw new Error('Actual is not a function');
}
try {
this.actual();
} catch (e) {
exception = e;
}
if (exception) {
result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
}
var not = this.isNot ? "not " : "";
this.message = function() {
if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' ');
} else {
return "Expected function to throw an exception.";
}
};
return result;
};
jasmine.Matchers.Any = function(expectedClass) {
this.expectedClass = expectedClass;
};
jasmine.Matchers.Any.prototype.matches = function(other) {
if (this.expectedClass == String) {
return typeof other == 'string' || other instanceof String;
}
if (this.expectedClass == Number) {
return typeof other == 'number' || other instanceof Number;
}
if (this.expectedClass == Function) {
return typeof other == 'function' || other instanceof Function;
}
if (this.expectedClass == Object) {
return typeof other == 'object';
}
return other instanceof this.expectedClass;
};
jasmine.Matchers.Any.prototype.toString = function() {
return '<jasmine.any(' + this.expectedClass + ')>';
};
/**
* @constructor
*/
jasmine.MultiReporter = function() {
this.subReporters_ = [];
};
jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
jasmine.MultiReporter.prototype.addReporter = function(reporter) {
this.subReporters_.push(reporter);
};
(function() {
var functionNames = [
"reportRunnerStarting",
"reportRunnerResults",
"reportSuiteResults",
"reportSpecStarting",
"reportSpecResults",
"log"
];
for (var i = 0; i < functionNames.length; i++) {
var functionName = functionNames[i];
jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
return function() {
for (var j = 0; j < this.subReporters_.length; j++) {
var subReporter = this.subReporters_[j];
if (subReporter[functionName]) {
subReporter[functionName].apply(subReporter, arguments);
}
}
};
})(functionName);
}
})();
/**
* Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
*
* @constructor
*/
jasmine.NestedResults = function() {
/**
* The total count of results
*/
this.totalCount = 0;
/**
* Number of passed results
*/
this.passedCount = 0;
/**
* Number of failed results
*/
this.failedCount = 0;
/**
* Was this suite/spec skipped?
*/
this.skipped = false;
/**
* @ignore
*/
this.items_ = [];
};
/**
* Roll up the result counts.
*
* @param result
*/
jasmine.NestedResults.prototype.rollupCounts = function(result) {
this.totalCount += result.totalCount;
this.passedCount += result.passedCount;
this.failedCount += result.failedCount;
};
/**
* Adds a log message.
* @param values Array of message parts which will be concatenated later.
*/
jasmine.NestedResults.prototype.log = function(values) {
this.items_.push(new jasmine.MessageResult(values));
};
/**
* Getter for the results: message & results.
*/
jasmine.NestedResults.prototype.getItems = function() {
return this.items_;
};
/**
* Adds a result, tracking counts (total, passed, & failed)
* @param {jasmine.ExpectationResult|jasmine.NestedResults} result
*/
jasmine.NestedResults.prototype.addResult = function(result) {
if (result.type != 'log') {
if (result.items_) {
this.rollupCounts(result);
} else {
this.totalCount++;
if (result.passed()) {
this.passedCount++;
} else {
this.failedCount++;
}
}
}
this.items_.push(result);
};
/**
* @returns {Boolean} True if <b>everything</b> below passed
*/
jasmine.NestedResults.prototype.passed = function() {
return this.passedCount === this.totalCount;
};
/**
* Base class for pretty printing for expectation results.
*/
jasmine.PrettyPrinter = function() {
this.ppNestLevel_ = 0;
};
/**
* Formats a value in a nice, human-readable string.
*
* @param value
*/
jasmine.PrettyPrinter.prototype.format = function(value) {
if (this.ppNestLevel_ > 40) {
throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
}
this.ppNestLevel_++;
try {
if (value === jasmine.undefined) {
this.emitScalar('undefined');
} else if (value === null) {
this.emitScalar('null');
} else if (value === jasmine.getGlobal()) {
this.emitScalar('<global>');
} else if (value instanceof jasmine.Matchers.Any) {
this.emitScalar(value.toString());
} else if (typeof value === 'string') {
this.emitString(value);
} else if (jasmine.isSpy(value)) {
this.emitScalar("spy on " + value.identity);
} else if (value instanceof RegExp) {
this.emitScalar(value.toString());
} else if (typeof value === 'function') {
this.emitScalar('Function');
} else if (typeof value.nodeType === 'number') {
this.emitScalar('HTMLNode');
} else if (value instanceof Date) {
this.emitScalar('Date(' + value + ')');
} else if (value.__Jasmine_been_here_before__) {
this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
} else if (jasmine.isArray_(value) || typeof value == 'object') {
value.__Jasmine_been_here_before__ = true;
if (jasmine.isArray_(value)) {
this.emitArray(value);
} else {
this.emitObject(value);
}
delete value.__Jasmine_been_here_before__;
} else {
this.emitScalar(value.toString());
}
} finally {
this.ppNestLevel_--;
}
};
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
if (property == '__Jasmine_been_here_before__') continue;
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false);
}
};
jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
jasmine.StringPrettyPrinter = function() {
jasmine.PrettyPrinter.call(this);
this.string = '';
};
jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
this.append(value);
};
jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
this.append("'" + value + "'");
};
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
this.append('[ ');
for (var i = 0; i < array.length; i++) {
if (i > 0) {
this.append(', ');
}
this.format(array[i]);
}
this.append(' ]');
};
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
var self = this;
this.append('{ ');
var first = true;
this.iterateObject(obj, function(property, isGetter) {
if (first) {
first = false;
} else {
self.append(', ');
}
self.append(property);
self.append(' : ');
if (isGetter) {
self.append('<getter>');
} else {
self.format(obj[property]);
}
});
this.append(' }');
};
jasmine.StringPrettyPrinter.prototype.append = function(value) {
this.string += value;
};
jasmine.Queue = function(env) {
this.env = env;
this.blocks = [];
this.running = false;
this.index = 0;
this.offset = 0;
this.abort = false;
};
jasmine.Queue.prototype.addBefore = function(block) {
this.blocks.unshift(block);
};
jasmine.Queue.prototype.add = function(block) {
this.blocks.push(block);
};
jasmine.Queue.prototype.insertNext = function(block) {
this.blocks.splice((this.index + this.offset + 1), 0, block);
this.offset++;
};
jasmine.Queue.prototype.start = function(onComplete) {
this.running = true;
this.onComplete = onComplete;
this.next_();
};
jasmine.Queue.prototype.isRunning = function() {
return this.running;
};
jasmine.Queue.LOOP_DONT_RECURSE = true;
jasmine.Queue.prototype.next_ = function() {
var self = this;
var goAgain = true;
while (goAgain) {
goAgain = false;
if (self.index < self.blocks.length && !this.abort) {
var calledSynchronously = true;
var completedSynchronously = false;
var onComplete = function () {
if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
completedSynchronously = true;
return;
}
if (self.blocks[self.index].abort) {
self.abort = true;
}
self.offset = 0;
self.index++;
var now = new Date().getTime();
if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
self.env.lastUpdate = now;
self.env.setTimeout(function() {
self.next_();
}, 0);
} else {
if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
goAgain = true;
} else {
self.next_();
}
}
};
self.blocks[self.index].execute(onComplete);
calledSynchronously = false;
if (completedSynchronously) {
onComplete();
}
} else {
self.running = false;
if (self.onComplete) {
self.onComplete();
}
}
}
};
jasmine.Queue.prototype.results = function() {
var results = new jasmine.NestedResults();
for (var i = 0; i < this.blocks.length; i++) {
if (this.blocks[i].results) {
results.addResult(this.blocks[i].results());
}
}
return results;
};
/**
* Runner
*
* @constructor
* @param {jasmine.Env} env
*/
jasmine.Runner = function(env) {
var self = this;
self.env = env;
self.queue = new jasmine.Queue(env);
self.before_ = [];
self.after_ = [];
self.suites_ = [];
};
jasmine.Runner.prototype.execute = function() {
var self = this;
if (self.env.reporter.reportRunnerStarting) {
self.env.reporter.reportRunnerStarting(this);
}
self.queue.start(function () {
self.finishCallback();
});
};
jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
beforeEachFunction.typeName = 'beforeEach';
this.before_.splice(0,0,beforeEachFunction);
};
jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
afterEachFunction.typeName = 'afterEach';
this.after_.splice(0,0,afterEachFunction);
};
jasmine.Runner.prototype.finishCallback = function() {
this.env.reporter.reportRunnerResults(this);
};
jasmine.Runner.prototype.addSuite = function(suite) {
this.suites_.push(suite);
};
jasmine.Runner.prototype.add = function(block) {
if (block instanceof jasmine.Suite) {
this.addSuite(block);
}
this.queue.add(block);
};
jasmine.Runner.prototype.specs = function () {
var suites = this.suites();
var specs = [];
for (var i = 0; i < suites.length; i++) {
specs = specs.concat(suites[i].specs());
}
return specs;
};
jasmine.Runner.prototype.suites = function() {
return this.suites_;
};
jasmine.Runner.prototype.topLevelSuites = function() {
var topLevelSuites = [];
for (var i = 0; i < this.suites_.length; i++) {
if (!this.suites_[i].parentSuite) {
topLevelSuites.push(this.suites_[i]);
}
}
return topLevelSuites;
};
jasmine.Runner.prototype.results = function() {
return this.queue.results();
};
/**
* Internal representation of a Jasmine specification, or test.
*
* @constructor
* @param {jasmine.Env} env
* @param {jasmine.Suite} suite
* @param {String} description
*/
jasmine.Spec = function(env, suite, description) {
if (!env) {
throw new Error('jasmine.Env() required');
}
if (!suite) {
throw new Error('jasmine.Suite() required');
}
var spec = this;
spec.id = env.nextSpecId ? env.nextSpecId() : null;
spec.env = env;
spec.suite = suite;
spec.description = description;
spec.queue = new jasmine.Queue(env);
spec.afterCallbacks = [];
spec.spies_ = [];
spec.results_ = new jasmine.NestedResults();
spec.results_.description = description;
spec.matchersClass = null;
};
jasmine.Spec.prototype.getFullName = function() {
return this.suite.getFullName() + ' ' + this.description + '.';
};
jasmine.Spec.prototype.results = function() {
return this.results_;
};
/**
* All parameters are pretty-printed and concatenated together, then written to the spec's output.
*
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
*/
jasmine.Spec.prototype.log = function() {
return this.results_.log(arguments);
};
jasmine.Spec.prototype.runs = function (func) {
var block = new jasmine.Block(this.env, func, this);
this.addToQueue(block);
return this;
};
jasmine.Spec.prototype.addToQueue = function (block) {
if (this.queue.isRunning()) {
this.queue.insertNext(block);
} else {
this.queue.add(block);
}
};
/**
* @param {jasmine.ExpectationResult} result
*/
jasmine.Spec.prototype.addMatcherResult = function(result) {
this.results_.addResult(result);
};
jasmine.Spec.prototype.expect = function(actual) {
var positive = new (this.getMatchersClass_())(this.env, actual, this);
positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
return positive;
};
/**
* Waits a fixed time period before moving to the next block.
*
* @deprecated Use waitsFor() instead
* @param {Number} timeout milliseconds to wait
*/
jasmine.Spec.prototype.waits = function(timeout) {
var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
this.addToQueue(waitsFunc);
return this;
};
/**
* Waits for the latchFunction to return true before proceeding to the next block.
*
* @param {Function} latchFunction
* @param {String} optional_timeoutMessage
* @param {Number} optional_timeout
*/
jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
var latchFunction_ = null;
var optional_timeoutMessage_ = null;
var optional_timeout_ = null;
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
switch (typeof arg) {
case 'function':
latchFunction_ = arg;
break;
case 'string':
optional_timeoutMessage_ = arg;
break;
case 'number':
optional_timeout_ = arg;
break;
}
}
var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
this.addToQueue(waitsForFunc);
return this;
};
jasmine.Spec.prototype.fail = function (e) {
var expectationResult = new jasmine.ExpectationResult({
passed: false,
message: e ? jasmine.util.formatException(e) : 'Exception'
});
this.results_.addResult(expectationResult);
};
jasmine.Spec.prototype.getMatchersClass_ = function() {
return this.matchersClass || this.env.matchersClass;
};
jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
var parent = this.getMatchersClass_();
var newMatchersClass = function() {
parent.apply(this, arguments);
};
jasmine.util.inherit(newMatchersClass, parent);
jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
this.matchersClass = newMatchersClass;
};
jasmine.Spec.prototype.finishCallback = function() {
this.env.reporter.reportSpecResults(this);
};
jasmine.Spec.prototype.finish = function(onComplete) {
this.removeAllSpies();
this.finishCallback();
if (onComplete) {
onComplete();
}
};
jasmine.Spec.prototype.after = function(doAfter) {
if (this.queue.isRunning()) {
this.queue.add(new jasmine.Block(this.env, doAfter, this));
} else {
this.afterCallbacks.unshift(doAfter);
}
};
jasmine.Spec.prototype.execute = function(onComplete) {
var spec = this;
if (!spec.env.specFilter(spec)) {
spec.results_.skipped = true;
spec.finish(onComplete);
return;
}
this.env.reporter.reportSpecStarting(this);
spec.env.currentSpec = spec;
spec.addBeforesAndAftersToQueue();
spec.queue.start(function () {
spec.finish(onComplete);
});
};
jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
var runner = this.env.currentRunner();
var i;
for (var suite = this.suite; suite; suite = suite.parentSuite) {
for (i = 0; i < suite.before_.length; i++) {
this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
}
}
for (i = 0; i < runner.before_.length; i++) {
this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
}
for (i = 0; i < this.afterCallbacks.length; i++) {
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
}
for (suite = this.suite; suite; suite = suite.parentSuite) {
for (i = 0; i < suite.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
}
}
for (i = 0; i < runner.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
}
};
jasmine.Spec.prototype.explodes = function() {
throw 'explodes function should not have been called';
};
jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
if (obj == jasmine.undefined) {
throw "spyOn could not find an object to spy upon for " + methodName + "()";
}
if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
throw methodName + '() method does not exist';
}
if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
throw new Error(methodName + ' has already been spied upon');
}
var spyObj = jasmine.createSpy(methodName);
this.spies_.push(spyObj);
spyObj.baseObj = obj;
spyObj.methodName = methodName;
spyObj.originalValue = obj[methodName];
obj[methodName] = spyObj;
return spyObj;
};
jasmine.Spec.prototype.removeAllSpies = function() {
for (var i = 0; i < this.spies_.length; i++) {
var spy = this.spies_[i];
spy.baseObj[spy.methodName] = spy.originalValue;
}
this.spies_ = [];
};
/**
* Internal representation of a Jasmine suite.
*
* @constructor
* @param {jasmine.Env} env
* @param {String} description
* @param {Function} specDefinitions
* @param {jasmine.Suite} parentSuite
*/
jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
var self = this;
self.id = env.nextSuiteId ? env.nextSuiteId() : null;
self.description = description;
self.queue = new jasmine.Queue(env);
self.parentSuite = parentSuite;
self.env = env;
self.before_ = [];
self.after_ = [];
self.children_ = [];
self.suites_ = [];
self.specs_ = [];
};
jasmine.Suite.prototype.getFullName = function() {
var fullName = this.description;
for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
fullName = parentSuite.description + ' ' + fullName;
}
return fullName;
};
jasmine.Suite.prototype.finish = function(onComplete) {
this.env.reporter.reportSuiteResults(this);
this.finished = true;
if (typeof(onComplete) == 'function') {
onComplete();
}
};
jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
beforeEachFunction.typeName = 'beforeEach';
this.before_.unshift(beforeEachFunction);
};
jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
afterEachFunction.typeName = 'afterEach';
this.after_.unshift(afterEachFunction);
};
jasmine.Suite.prototype.results = function() {
return this.queue.results();
};
jasmine.Suite.prototype.add = function(suiteOrSpec) {
this.children_.push(suiteOrSpec);
if (suiteOrSpec instanceof jasmine.Suite) {
this.suites_.push(suiteOrSpec);
this.env.currentRunner().addSuite(suiteOrSpec);
} else {
this.specs_.push(suiteOrSpec);
}
this.queue.add(suiteOrSpec);
};
jasmine.Suite.prototype.specs = function() {
return this.specs_;
};
jasmine.Suite.prototype.suites = function() {
return this.suites_;
};
jasmine.Suite.prototype.children = function() {
return this.children_;
};
jasmine.Suite.prototype.execute = function(onComplete) {
var self = this;
this.queue.start(function () {
self.finish(onComplete);
});
};
jasmine.WaitsBlock = function(env, timeout, spec) {
this.timeout = timeout;
jasmine.Block.call(this, env, null, spec);
};
jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
jasmine.WaitsBlock.prototype.execute = function (onComplete) {
this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
this.env.setTimeout(function () {
onComplete();
}, this.timeout);
};
/**
* A block which waits for some condition to become true, with timeout.
*
* @constructor
* @extends jasmine.Block
* @param {jasmine.Env} env The Jasmine environment.
* @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
* @param {Function} latchFunction A function which returns true when the desired condition has been met.
* @param {String} message The message to display if the desired condition hasn't been met within the given time period.
* @param {jasmine.Spec} spec The Jasmine spec.
*/
jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
this.timeout = timeout || env.defaultTimeoutInterval;
this.latchFunction = latchFunction;
this.message = message;
this.totalTimeSpentWaitingForLatch = 0;
jasmine.Block.call(this, env, null, spec);
};
jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
var latchFunctionResult;
try {
latchFunctionResult = this.latchFunction.apply(this.spec);
} catch (e) {
this.spec.fail(e);
onComplete();
return;
}
if (latchFunctionResult) {
onComplete();
} else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
this.spec.fail({
name: 'timeout',
message: message
});
this.abort = true;
onComplete();
} else {
this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
var self = this;
this.env.setTimeout(function() {
self.execute(onComplete);
}, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
}
};
// Mock setTimeout, clearTimeout
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
jasmine.FakeTimer = function() {
this.reset();
var self = this;
self.setTimeout = function(funcToCall, millis) {
self.timeoutsMade++;
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
return self.timeoutsMade;
};
self.setInterval = function(funcToCall, millis) {
self.timeoutsMade++;
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
return self.timeoutsMade;
};
self.clearTimeout = function(timeoutKey) {
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
};
self.clearInterval = function(timeoutKey) {
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
};
};
jasmine.FakeTimer.prototype.reset = function() {
this.timeoutsMade = 0;
this.scheduledFunctions = {};
this.nowMillis = 0;
};
jasmine.FakeTimer.prototype.tick = function(millis) {
var oldMillis = this.nowMillis;
var newMillis = oldMillis + millis;
this.runFunctionsWithinRange(oldMillis, newMillis);
this.nowMillis = newMillis;
};
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
var scheduledFunc;
var funcsToRun = [];
for (var timeoutKey in this.scheduledFunctions) {
scheduledFunc = this.scheduledFunctions[timeoutKey];
if (scheduledFunc != jasmine.undefined &&
scheduledFunc.runAtMillis >= oldMillis &&
scheduledFunc.runAtMillis <= nowMillis) {
funcsToRun.push(scheduledFunc);
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
}
}
if (funcsToRun.length > 0) {
funcsToRun.sort(function(a, b) {
return a.runAtMillis - b.runAtMillis;
});
for (var i = 0; i < funcsToRun.length; ++i) {
try {
var funcToRun = funcsToRun[i];
this.nowMillis = funcToRun.runAtMillis;
funcToRun.funcToCall();
if (funcToRun.recurring) {
this.scheduleFunction(funcToRun.timeoutKey,
funcToRun.funcToCall,
funcToRun.millis,
true);
}
} catch(e) {
}
}
this.runFunctionsWithinRange(oldMillis, nowMillis);
}
};
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
this.scheduledFunctions[timeoutKey] = {
runAtMillis: this.nowMillis + millis,
funcToCall: funcToCall,
recurring: recurring,
timeoutKey: timeoutKey,
millis: millis
};
};
/**
* @namespace
*/
jasmine.Clock = {
defaultFakeTimer: new jasmine.FakeTimer(),
reset: function() {
jasmine.Clock.assertInstalled();
jasmine.Clock.defaultFakeTimer.reset();
},
tick: function(millis) {
jasmine.Clock.assertInstalled();
jasmine.Clock.defaultFakeTimer.tick(millis);
},
runFunctionsWithinRange: function(oldMillis, nowMillis) {
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
},
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
},
useMock: function() {
if (!jasmine.Clock.isInstalled()) {
var spec = jasmine.getEnv().currentSpec;
spec.after(jasmine.Clock.uninstallMock);
jasmine.Clock.installMock();
}
},
installMock: function() {
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
},
uninstallMock: function() {
jasmine.Clock.assertInstalled();
jasmine.Clock.installed = jasmine.Clock.real;
},
real: {
setTimeout: jasmine.getGlobal().setTimeout,
clearTimeout: jasmine.getGlobal().clearTimeout,
setInterval: jasmine.getGlobal().setInterval,
clearInterval: jasmine.getGlobal().clearInterval
},
assertInstalled: function() {
if (!jasmine.Clock.isInstalled()) {
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
}
},
isInstalled: function() {
return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
},
installed: null
};
jasmine.Clock.installed = jasmine.Clock.real;
//else for IE support
jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
if (jasmine.Clock.installed.setTimeout.apply) {
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
} else {
return jasmine.Clock.installed.setTimeout(funcToCall, millis);
}
};
jasmine.getGlobal().setInterval = function(funcToCall, millis) {
if (jasmine.Clock.installed.setInterval.apply) {
return jasmine.Clock.installed.setInterval.apply(this, arguments);
} else {
return jasmine.Clock.installed.setInterval(funcToCall, millis);
}
};
jasmine.getGlobal().clearTimeout = function(timeoutKey) {
if (jasmine.Clock.installed.clearTimeout.apply) {
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
} else {
return jasmine.Clock.installed.clearTimeout(timeoutKey);
}
};
jasmine.getGlobal().clearInterval = function(timeoutKey) {
if (jasmine.Clock.installed.clearTimeout.apply) {
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
} else {
return jasmine.Clock.installed.clearInterval(timeoutKey);
}
};
jasmine.version_= {
"major": 1,
"minor": 0,
"build": 1,
"revision": 1286311016
};

View File

@ -0,0 +1,175 @@
/*jsl:declare jasmine*/
function readFixtures()
{
return jasmine.getFixtures()._proxyCallTo('read', arguments);
}
function loadFixtures()
{
jasmine.getFixtures()._proxyCallTo('load', arguments);
}
function setFixtures(html)
{
jasmine.getFixtures().set(html);
}
function sandbox(attributes)
{
return jasmine.getFixtures().sandbox(attributes);
}
jasmine.getFixtures = function()
{
return jasmine._currentFixtures = jasmine._currentFixtures || new jasmine.Fixtures();
}
jasmine.Fixtures = function()
{
this.containerId = 'jasmine-fixtures';
this._fixturesCache = {};
}
jasmine.Fixtures.XHR= window.XMLHttpRequest || (function(){
var progIdCandidates= ['Msxml2.XMLHTTP.4.0', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP'];
var len= progIdCandidates.length;
var progId;
var xhr;
function ConstructXhr()
{
return new window.ActiveXObject(ConstructXhr.progId);
}
while (len--)
{
try
{
progId= progIdCandidates[len];
xhr= new window.ActiveXObject(progId);
// ActiveXObject constructor throws an exception
// if the component isn't available.
xhr= null;
ConstructXhr.progId= progId;
return ConstructXhr;
}
catch (e)
{
// Ignore the error
}
}
throw new Error('No XMLHttpRequest implementation found');
})();
jasmine.Fixtures.prototype= {
set: function(html)
{
this.cleanUp();
this._createContainer(html);
},
load: function()
{
this.cleanUp();
this._createContainer(this.read.apply(this, arguments));
},
read: function()
{
var htmlChunks = [];
var fixtureUrls = arguments;
for (var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++)
htmlChunks.push(this._getFixtureHtml(fixtureUrls[urlIndex]));
return htmlChunks.join('');
},
clearCache: function()
{
this._fixturesCache = {};
},
cleanUp: function()
{
var container= document.getElementById(this.containerId);
if (container)
container.parentNode.removeChild(container);
},
sandbox: function(attributes)
{
var attributesToSet = attributes || {};
var sandbox= document.createElement('div');
sandbox.id= 'sandbox';
if ("string"===typeof(attributes))
{
sandbox.innerHTML= attributes;
if (1===sandbox.childNodes.length && 1===sandbox.firstChild.nodeType)
{
sandbox= sandbox.firstChild;
if (!sandbox.id)
sandbox.id= 'sandbox';
}
return sandbox;
}
for (var attr in attributesToSet)
sandbox.setAttribute(attr, attributesToSet[attr]);
return sandbox;
},
_createContainer: function(html)
{
var container = document.createElement('div');
container.id= this.containerId;
if (html && html.nodeType===1)
container.appendChild(html);
else
container.innerHTML= html;
document.body.appendChild(container);
},
_getFixtureHtml: function(url)
{
if (void(0)===this._fixturesCache[url])
this._loadFixtureIntoCache(url);
return this._fixturesCache[url];
},
_loadFixtureIntoCache: function(url)
{
var self= this;
var xhr= new jasmine.Fixtures.XHR();
xhr.open('GET', url, true);
xhr.onreadystatechange= function()
{
if (4!==xhr.readyState)
return;
var status= xhr.status;
var succeeded= 0===status || (status>=200 && status<300) || 304==status;
if (!succeeded)
throw new Error('Failed to load resource: status=' + status + ' url=' + url);
self._fixturesCache[url]= xhr.responseText;
xhr.onreadystatechange= null;
xhr= null;
}
xhr.send(null);
},
_proxyCallTo: function(methodName, passedArguments)
{
return this[methodName].apply(this, passedArguments);
}
};

View File

@ -0,0 +1,205 @@
/*jsl:declare jasmine*/
/*jsl:declare Sizzle*/
/*jsl:declare Prototype*/
/*jsl:declare jQuery*/
jasmine.DOM = {};
jasmine.DOM.browserTagCaseIndependentHtml = function(html)
{
var div= document.createElement('div');
div.innerHTML= html;
return div.innerHTML;
}
jasmine.DOM.elementToString = function(element)
{
var div= document.createElement('div');
div.appendChild(element.cloneNode(true));
return div.innerHTML;
}
jasmine.DOM.trim= function(string)
{
var str= string.replace(/^\s+/, '');
for (var i = str.length - 1; i > 0; --i)
if (/\S/.test(str.charAt(i)))
{
str = str.substring(0, i + 1);
break;
}
return str;
}
jasmine.DOM.slice= function(arrayLike, startIndex)
{
return [].slice.call(arrayLike, startIndex||0);
}
jasmine.DOM.uniqueId= 1;
jasmine.DOM.assignId= function(element)
{
return element.id || (element.id=('jasmine_id_' + jasmine.DOM.uniqueId++));
};
/**
jasmine.DOM.queryAll(selector[, scope]) -> array
*/
jasmine.DOM.queryAll= (function(){
if ('undefined'!==typeof(Sizzle))
return Sizzle;
if ('undefined'!==typeof(Prototype))
return function(selector, node)
{
return Element.getElementsBySelector(node||document, selector);
};
if ('undefined'!==typeof(jQuery))
return function(selector, node)
{
var result= jQuery(selector, node);
var nodes= [];
var len= result.length;
for (var i=0; i<len; ++i)
nodes.push(result[i]);
return nodes;
};
if (document.querySelectorAll)
return function(selector, node)
{
if (!node)
node= document;
else if (node!==document)
selector = ['#', jasmine.DOM.assignId(node), ' ', selector].join('');
return jasmine.DOM.slice(node.querySelectorAll(selector));
};
throw new Error("Can't determine selector engine...");
})();
jasmine.DOM.matchers = {};
(function(){
var matchers = {
toHaveClass: function(className)
{
var classes= jasmine.DOM.trim(this.actual.className).split(" ");
return -1!==classes.indexOf(className);
},
toBeVisible: function()
{
return (this.actual.offsetWidth!==0 || this.actual.offsetHeight!==0);
},
toBeHidden: function()
{
return (0===this.actual.offsetWidth && 0===this.actual.offsetHeight);
},
toBeSelected: function()
{
return this.actual.selected;
},
toBeChecked: function()
{
return this.actual.checked;
},
toBeEmpty: function()
{
return !this.actual.firstChild;
},
toExist: function()
{
return !!this.actual;
},
toHaveAttr: function(attributeName, expectedAttributeValue)
{
if (!this.actual.hasAttribute(attributeName))
return false;
return comparePropertyValues(this.actual.getAttribute(attributeName), expectedAttributeValue);
},
toHaveId: function(id)
{
return this.actual.id===id;
},
toHaveHtml: function(html)
{
return this.actual.innerHTML === jasmine.DOM.browserTagCaseIndependentHtml(html);
},
toHaveText: function(text)
{
return (this.actual.textContent||this.actual.innerText) === text;
},
toHaveValue: function(value)
{
return this.actual.value === value;
},
toMatchSelector: function(selector)
{
// This isn't efficient
var nodes= jasmine.DOM.queryAll(selector);
return -1!==nodes.indexOf(this.actual);
},
toContain: function(selector)
{
var nodes= jasmine.DOM.queryAll(selector, this.actual);
return nodes.length > 0;
}
};
function comparePropertyValues(actualValue, expectedValue)
{
if (void(0) === expectedValue)
return void(0) !== actualValue;
return actualValue == expectedValue;
}
function bindMatcher(methodName)
{
var originalMatcher = jasmine.Matchers.prototype[methodName];
jasmine.DOM.matchers[methodName] = function()
{
// If the actual value is a DOM node...
if (this.actual && this.actual.nodeType)
{
var result = matchers[methodName].apply(this, arguments);
this.actual = jasmine.DOM.elementToString(this.actual);
return result;
}
if (originalMatcher)
return originalMatcher.apply(this, arguments);
return false;
}
}
for (var methodName in matchers)
bindMatcher(methodName);
})();
beforeEach(function() {
this.addMatchers(jasmine.DOM.matchers);
});
afterEach(function() {
jasmine.getFixtures().cleanUp();
});

View File

@ -1,4376 +0,0 @@
/*!
* jQuery JavaScript Library v1.3.2
* http://jquery.com/
*
* Copyright (c) 2009 John Resig
* Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License
*
* Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
* Revision: 6246
*/
(function(){
var
// Will speed up references to window, and allows munging its name.
window = this,
// Will speed up references to undefined, and allows munging its name.
undefined,
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$,
jQuery = window.jQuery = window.$ = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context );
},
// A simple way to check for HTML strings or ID strings
// (both of which we optimize for)
quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
// Is it a simple selector
isSimple = /^.[^:#\[\.,]*$/;
jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {
// Make sure that a selection was provided
selector = selector || document;
// Handle $(DOMElement)
if ( selector.nodeType ) {
this[0] = selector;
this.length = 1;
this.context = selector;
return this;
}
// Handle HTML strings
if ( typeof selector === "string" ) {
// Are we dealing with HTML string or an ID?
var match = quickExpr.exec( selector );
// Verify a match, and that no context was specified for #id
if ( match && (match[1] || !context) ) {
// HANDLE: $(html) -> $(array)
if ( match[1] )
selector = jQuery.clean( [ match[1] ], context );
// HANDLE: $("#id")
else {
var elem = document.getElementById( match[3] );
// Handle the case where IE and Opera return items
// by name instead of ID
if ( elem && elem.id != match[3] )
return jQuery().find( selector );
// Otherwise, we inject the element directly into the jQuery object
var ret = jQuery( elem || [] );
ret.context = document;
ret.selector = selector;
return ret;
}
// HANDLE: $(expr, [context])
// (which is just equivalent to: $(content).find(expr)
} else
return jQuery( context ).find( selector );
// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) )
return jQuery( document ).ready( selector );
// Make sure that old selector state is passed along
if ( selector.selector && selector.context ) {
this.selector = selector.selector;
this.context = selector.context;
}
return this.setArray(jQuery.isArray( selector ) ?
selector :
jQuery.makeArray(selector));
},
// Start with an empty selector
selector: "",
// The current version of jQuery being used
jquery: "1.3.2",
// The number of elements contained in the matched element set
size: function() {
return this.length;
},
// Get the Nth element in the matched element set OR
// Get the whole matched element set as a clean array
get: function( num ) {
return num === undefined ?
// Return a 'clean' array
Array.prototype.slice.call( this ) :
// Return just the object
this[ num ];
},
// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
// Build a new jQuery matched element set
var ret = jQuery( elems );
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
if ( name === "find" )
ret.selector = this.selector + (this.selector ? " " : "") + selector;
else if ( name )
ret.selector = this.selector + "." + name + "(" + selector + ")";
// Return the newly-formed element set
return ret;
},
// Force the current matched set of elements to become
// the specified array of elements (destroying the stack in the process)
// You should use pushStack() in order to do this, but maintain the stack
setArray: function( elems ) {
// Resetting the length to 0, then using the native Array push
// is a super-fast way to populate an object with array-like properties
this.length = 0;
Array.prototype.push.apply( this, elems );
return this;
},
// Execute a callback for every element in the matched set.
// (You can seed the arguments with an array of args, but this is
// only used internally.)
each: function( callback, args ) {
return jQuery.each( this, callback, args );
},
// Determine the position of an element within
// the matched set of elements
index: function( elem ) {
// Locate the position of the desired element
return jQuery.inArray(
// If it receives a jQuery object, the first element is used
elem && elem.jquery ? elem[0] : elem
, this );
},
attr: function( name, value, type ) {
var options = name;
// Look for the case where we're accessing a style value
if ( typeof name === "string" )
if ( value === undefined )
return this[0] && jQuery[ type || "attr" ]( this[0], name );
else {
options = {};
options[ name ] = value;
}
// Check to see if we're setting style values
return this.each(function(i){
// Set all the styles
for ( name in options )
jQuery.attr(
type ?
this.style :
this,
name, jQuery.prop( this, options[ name ], type, i, name )
);
});
},
css: function( key, value ) {
// ignore negative width and height values
if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
value = undefined;
return this.attr( key, value, "curCSS" );
},
text: function( text ) {
if ( typeof text !== "object" && text != null )
return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
var ret = "";
jQuery.each( text || this, function(){
jQuery.each( this.childNodes, function(){
if ( this.nodeType != 8 )
ret += this.nodeType != 1 ?
this.nodeValue :
jQuery.fn.text( [ this ] );
});
});
return ret;
},
wrapAll: function( html ) {
if ( this[0] ) {
// The elements to wrap the target around
var wrap = jQuery( html, this[0].ownerDocument ).clone();
if ( this[0].parentNode )
wrap.insertBefore( this[0] );
wrap.map(function(){
var elem = this;
while ( elem.firstChild )
elem = elem.firstChild;
return elem;
}).append(this);
}
return this;
},
wrapInner: function( html ) {
return this.each(function(){
jQuery( this ).contents().wrapAll( html );
});
},
wrap: function( html ) {
return this.each(function(){
jQuery( this ).wrapAll( html );
});
},
append: function() {
return this.domManip(arguments, true, function(elem){
if (this.nodeType == 1)
this.appendChild( elem );
});
},
prepend: function() {
return this.domManip(arguments, true, function(elem){
if (this.nodeType == 1)
this.insertBefore( elem, this.firstChild );
});
},
before: function() {
return this.domManip(arguments, false, function(elem){
this.parentNode.insertBefore( elem, this );
});
},
after: function() {
return this.domManip(arguments, false, function(elem){
this.parentNode.insertBefore( elem, this.nextSibling );
});
},
end: function() {
return this.prevObject || jQuery( [] );
},
// For internal use only.
// Behaves like an Array's method, not like a jQuery method.
push: [].push,
sort: [].sort,
splice: [].splice,
find: function( selector ) {
if ( this.length === 1 ) {
var ret = this.pushStack( [], "find", selector );
ret.length = 0;
jQuery.find( selector, this[0], ret );
return ret;
} else {
return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
return jQuery.find( selector, elem );
})), "find", selector );
}
},
clone: function( events ) {
// Do the clone
var ret = this.map(function(){
if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
// IE copies events bound via attachEvent when
// using cloneNode. Calling detachEvent on the
// clone will also remove the events from the orignal
// In order to get around this, we use innerHTML.
// Unfortunately, this means some modifications to
// attributes in IE that are actually only stored
// as properties will not be copied (such as the
// the name attribute on an input).
var html = this.outerHTML;
if ( !html ) {
var div = this.ownerDocument.createElement("div");
div.appendChild( this.cloneNode(true) );
html = div.innerHTML;
}
return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
} else
return this.cloneNode(true);
});
// Copy the events from the original to the clone
if ( events === true ) {
var orig = this.find("*").andSelf(), i = 0;
ret.find("*").andSelf().each(function(){
if ( this.nodeName !== orig[i].nodeName )
return;
var events = jQuery.data( orig[i], "events" );
for ( var type in events ) {
for ( var handler in events[ type ] ) {
jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
}
}
i++;
});
}
// Return the cloned set
return ret;
},
filter: function( selector ) {
return this.pushStack(
jQuery.isFunction( selector ) &&
jQuery.grep(this, function(elem, i){
return selector.call( elem, i );
}) ||
jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
return elem.nodeType === 1;
}) ), "filter", selector );
},
closest: function( selector ) {
var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
closer = 0;
return this.map(function(){
var cur = this;
while ( cur && cur.ownerDocument ) {
if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
jQuery.data(cur, "closest", closer);
return cur;
}
cur = cur.parentNode;
closer++;
}
});
},
not: function( selector ) {
if ( typeof selector === "string" )
// test special case where just one selector is passed in
if ( isSimple.test( selector ) )
return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
else
selector = jQuery.multiFilter( selector, this );
var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
return this.filter(function() {
return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
});
},
add: function( selector ) {
return this.pushStack( jQuery.unique( jQuery.merge(
this.get(),
typeof selector === "string" ?
jQuery( selector ) :
jQuery.makeArray( selector )
)));
},
is: function( selector ) {
return !!selector && jQuery.multiFilter( selector, this ).length > 0;
},
hasClass: function( selector ) {
return !!selector && this.is( "." + selector );
},
val: function( value ) {
if ( value === undefined ) {
var elem = this[0];
if ( elem ) {
if( jQuery.nodeName( elem, 'option' ) )
return (elem.attributes.value || {}).specified ? elem.value : elem.text;
// We need to handle select boxes special
if ( jQuery.nodeName( elem, "select" ) ) {
var index = elem.selectedIndex,
values = [],
options = elem.options,
one = elem.type == "select-one";
// Nothing was selected
if ( index < 0 )
return null;
// Loop through all the selected options
for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
var option = options[ i ];
if ( option.selected ) {
// Get the specifc value for the option
value = jQuery(option).val();
// We don't need an array for one selects
if ( one )
return value;
// Multi-Selects return an array
values.push( value );
}
}
return values;
}
// Everything else, we just grab the value
return (elem.value || "").replace(/\r/g, "");
}
return undefined;
}
if ( typeof value === "number" )
value += '';
return this.each(function(){
if ( this.nodeType != 1 )
return;
if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
this.checked = (jQuery.inArray(this.value, value) >= 0 ||
jQuery.inArray(this.name, value) >= 0);
else if ( jQuery.nodeName( this, "select" ) ) {
var values = jQuery.makeArray(value);
jQuery( "option", this ).each(function(){
this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
jQuery.inArray( this.text, values ) >= 0);
});
if ( !values.length )
this.selectedIndex = -1;
} else
this.value = value;
});
},
html: function( value ) {
return value === undefined ?
(this[0] ?
this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
null) :
this.empty().append( value );
},
replaceWith: function( value ) {
return this.after( value ).remove();
},
eq: function( i ) {
return this.slice( i, +i + 1 );
},
slice: function() {
return this.pushStack( Array.prototype.slice.apply( this, arguments ),
"slice", Array.prototype.slice.call(arguments).join(",") );
},
map: function( callback ) {
return this.pushStack( jQuery.map(this, function(elem, i){
return callback.call( elem, i, elem );
}));
},
andSelf: function() {
return this.add( this.prevObject );
},
domManip: function( args, table, callback ) {
if ( this[0] ) {
var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
first = fragment.firstChild;
if ( first )
for ( var i = 0, l = this.length; i < l; i++ )
callback.call( root(this[i], first), this.length > 1 || i > 0 ?
fragment.cloneNode(true) : fragment );
if ( scripts )
jQuery.each( scripts, evalScript );
}
return this;
function root( elem, cur ) {
return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
(elem.getElementsByTagName("tbody")[0] ||
elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
elem;
}
}
};
// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;
function evalScript( i, elem ) {
if ( elem.src )
jQuery.ajax({
url: elem.src,
async: false,
dataType: "script"
});
else
jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
if ( elem.parentNode )
elem.parentNode.removeChild( elem );
}
function now(){
return +new Date;
}
jQuery.extend = jQuery.fn.extend = function() {
// copy reference to target object
var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) )
target = {};
// extend jQuery itself if only one argument is passed
if ( length == i ) {
target = this;
--i;
}
for ( ; i < length; i++ )
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null )
// Extend the base object
for ( var name in options ) {
var src = target[ name ], copy = options[ name ];
// Prevent never-ending loop
if ( target === copy )
continue;
// Recurse if we're merging object values
if ( deep && copy && typeof copy === "object" && !copy.nodeType )
target[ name ] = jQuery.extend( deep,
// Never move original objects, clone them
src || ( copy.length != null ? [ ] : { } )
, copy );
// Don't bring in undefined values
else if ( copy !== undefined )
target[ name ] = copy;
}
// Return the modified object
return target;
};
// exclude the following css properties to add px
var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
// cache defaultView
defaultView = document.defaultView || {},
toString = Object.prototype.toString;
jQuery.extend({
noConflict: function( deep ) {
window.$ = _$;
if ( deep )
window.jQuery = _jQuery;
return jQuery;
},
// See test/unit/core.js for details concerning isFunction.
// Since version 1.3, DOM methods and functions like alert
// aren't supported. They return false on IE (#2968).
isFunction: function( obj ) {
return toString.call(obj) === "[object Function]";
},
isArray: function( obj ) {
return toString.call(obj) === "[object Array]";
},
// check if an element is in a (or is an) XML document
isXMLDoc: function( elem ) {
return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
!!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
},
// Evalulates a script in a global context
globalEval: function( data ) {
if ( data && /\S/.test(data) ) {
// Inspired by code by Andrea Giammarchi
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
var head = document.getElementsByTagName("head")[0] || document.documentElement,
script = document.createElement("script");
script.type = "text/javascript";
if ( jQuery.support.scriptEval )
script.appendChild( document.createTextNode( data ) );
else
script.text = data;
// Use insertBefore instead of appendChild to circumvent an IE6 bug.
// This arises when a base node is used (#2709).
head.insertBefore( script, head.firstChild );
head.removeChild( script );
}
},
nodeName: function( elem, name ) {
return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
},
// args is for internal usage only
each: function( object, callback, args ) {
var name, i = 0, length = object.length;
if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break;
} else
for ( ; i < length; )
if ( callback.apply( object[ i++ ], args ) === false )
break;
// A special, fast, case for the most common use of each
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
}
return object;
},
prop: function( elem, value, type, i, name ) {
// Handle executable functions
if ( jQuery.isFunction( value ) )
value = value.call( elem, i );
// Handle passing in a number to a CSS property
return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
value + "px" :
value;
},
className: {
// internal only, use addClass("class")
add: function( elem, classNames ) {
jQuery.each((classNames || "").split(/\s+/), function(i, className){
if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
elem.className += (elem.className ? " " : "") + className;
});
},
// internal only, use removeClass("class")
remove: function( elem, classNames ) {
if (elem.nodeType == 1)
elem.className = classNames !== undefined ?
jQuery.grep(elem.className.split(/\s+/), function(className){
return !jQuery.className.has( classNames, className );
}).join(" ") :
"";
},
// internal only, use hasClass("class")
has: function( elem, className ) {
return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
}
},
// A method for quickly swapping in/out CSS properties to get correct calculations
swap: function( elem, options, callback ) {
var old = {};
// Remember the old values, and insert the new ones
for ( var name in options ) {
old[ name ] = elem.style[ name ];
elem.style[ name ] = options[ name ];
}
callback.call( elem );
// Revert the old values
for ( var name in options )
elem.style[ name ] = old[ name ];
},
css: function( elem, name, force, extra ) {
if ( name == "width" || name == "height" ) {
var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
function getWH() {
val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
if ( extra === "border" )
return;
jQuery.each( which, function() {
if ( !extra )
val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
if ( extra === "margin" )
val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
else
val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
});
}
if ( elem.offsetWidth !== 0 )
getWH();
else
jQuery.swap( elem, props, getWH );
return Math.max(0, Math.round(val));
}
return jQuery.curCSS( elem, name, force );
},
curCSS: function( elem, name, force ) {
var ret, style = elem.style;
// We need to handle opacity special in IE
if ( name == "opacity" && !jQuery.support.opacity ) {
ret = jQuery.attr( style, "opacity" );
return ret == "" ?
"1" :
ret;
}
// Make sure we're using the right name for getting the float value
if ( name.match( /float/i ) )
name = styleFloat;
if ( !force && style && style[ name ] )
ret = style[ name ];
else if ( defaultView.getComputedStyle ) {
// Only "float" is needed here
if ( name.match( /float/i ) )
name = "float";
name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
var computedStyle = defaultView.getComputedStyle( elem, null );
if ( computedStyle )
ret = computedStyle.getPropertyValue( name );
// We should always get a number back from opacity
if ( name == "opacity" && ret == "" )
ret = "1";
} else if ( elem.currentStyle ) {
var camelCase = name.replace(/\-(\w)/g, function(all, letter){
return letter.toUpperCase();
});
ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
// From the awesome hack by Dean Edwards
// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
// If we're not dealing with a regular pixel number
// but a number that has a weird ending, we need to convert it to pixels
if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
// Remember the original values
var left = style.left, rsLeft = elem.runtimeStyle.left;
// Put in the new values to get a computed value out
elem.runtimeStyle.left = elem.currentStyle.left;
style.left = ret || 0;
ret = style.pixelLeft + "px";
// Revert the changed values
style.left = left;
elem.runtimeStyle.left = rsLeft;
}
}
return ret;
},
clean: function( elems, context, fragment ) {
context = context || document;
// !context.createElement fails in IE with an error but returns typeof 'object'
if ( typeof context.createElement === "undefined" )
context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
// If a single string is passed in and it's a single tag
// just do a createElement and skip the rest
if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
if ( match )
return [ context.createElement( match[1] ) ];
}
var ret = [], scripts = [], div = context.createElement("div");
jQuery.each(elems, function(i, elem){
if ( typeof elem === "number" )
elem += '';
if ( !elem )
return;
// Convert html string into DOM nodes
if ( typeof elem === "string" ) {
// Fix "XHTML"-style tags in all browsers
elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
all :
front + "></" + tag + ">";
});
// Trim whitespace, otherwise indexOf won't work as expected
var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
var wrap =
// option or optgroup
!tags.indexOf("<opt") &&
[ 1, "<select multiple='multiple'>", "</select>" ] ||
!tags.indexOf("<leg") &&
[ 1, "<fieldset>", "</fieldset>" ] ||
tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
[ 1, "<table>", "</table>" ] ||
!tags.indexOf("<tr") &&
[ 2, "<table><tbody>", "</tbody></table>" ] ||
// <thead> matched above
(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
!tags.indexOf("<col") &&
[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
// IE can't serialize <link> and <script> tags normally
!jQuery.support.htmlSerialize &&
[ 1, "div<div>", "</div>" ] ||
[ 0, "", "" ];
// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];
// Move to the right depth
while ( wrap[0]-- )
div = div.lastChild;
// Remove IE's autoinserted <tbody> from table fragments
if ( !jQuery.support.tbody ) {
// String was a <table>, *may* have spurious <tbody>
var hasBody = /<tbody/i.test(elem),
tbody = !tags.indexOf("<table") && !hasBody ?
div.firstChild && div.firstChild.childNodes :
// String was a bare <thead> or <tfoot>
wrap[1] == "<table>" && !hasBody ?
div.childNodes :
[];
for ( var j = tbody.length - 1; j >= 0 ; --j )
if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
tbody[ j ].parentNode.removeChild( tbody[ j ] );
}
// IE completely kills leading whitespace when innerHTML is used
if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
elem = jQuery.makeArray( div.childNodes );
}
if ( elem.nodeType )
ret.push( elem );
else
ret = jQuery.merge( ret, elem );
});
if ( fragment ) {
for ( var i = 0; ret[i]; i++ ) {
if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
} else {
if ( ret[i].nodeType === 1 )
ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
fragment.appendChild( ret[i] );
}
}
return scripts;
}
return ret;
},
attr: function( elem, name, value ) {
// don't set attributes on text and comment nodes
if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
return undefined;
var notxml = !jQuery.isXMLDoc( elem ),
// Whether we are setting (or getting)
set = value !== undefined;
// Try to normalize/fix the name
name = notxml && jQuery.props[ name ] || name;
// Only do all the following if this is a node (faster for style)
// IE elem.getAttribute passes even for style
if ( elem.tagName ) {
// These attributes require special treatment
var special = /href|src|style/.test( name );
// Safari mis-reports the default selected property of a hidden option
// Accessing the parent's selectedIndex property fixes it
if ( name == "selected" && elem.parentNode )
elem.parentNode.selectedIndex;
// If applicable, access the attribute via the DOM 0 way
if ( name in elem && notxml && !special ) {
if ( set ){
// We can't allow the type property to be changed (since it causes problems in IE)
if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
throw "type property can't be changed";
elem[ name ] = value;
}
// browsers index elements by id/name on forms, give priority to attributes.
if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
return elem.getAttributeNode( name ).nodeValue;
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
if ( name == "tabIndex" ) {
var attributeNode = elem.getAttributeNode( "tabIndex" );
return attributeNode && attributeNode.specified
? attributeNode.value
: elem.nodeName.match(/(button|input|object|select|textarea)/i)
? 0
: elem.nodeName.match(/^(a|area)$/i) && elem.href
? 0
: undefined;
}
return elem[ name ];
}
if ( !jQuery.support.style && notxml && name == "style" )
return jQuery.attr( elem.style, "cssText", value );
if ( set )
// convert the value to a string (all browsers do this but IE) see #1070
elem.setAttribute( name, "" + value );
var attr = !jQuery.support.hrefNormalized && notxml && special
// Some attributes require a special call on IE
? elem.getAttribute( name, 2 )
: elem.getAttribute( name );
// Non-existent attributes return null, we normalize to undefined
return attr === null ? undefined : attr;
}
// elem is actually elem.style ... set the style
// IE uses filters for opacity
if ( !jQuery.support.opacity && name == "opacity" ) {
if ( set ) {
// IE has trouble with opacity if it does not have layout
// Force it by setting the zoom level
elem.zoom = 1;
// Set the alpha filter to set the opacity
elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
(parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
}
return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
"";
}
name = name.replace(/-([a-z])/ig, function(all, letter){
return letter.toUpperCase();
});
if ( set )
elem[ name ] = value;
return elem[ name ];
},
trim: function( text ) {
return (text || "").replace( /^\s+|\s+$/g, "" );
},
makeArray: function( array ) {
var ret = [];
if( array != null ){
var i = array.length;
// The window, strings (and functions) also have 'length'
if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
ret[0] = array;
else
while( i )
ret[--i] = array[i];
}
return ret;
},
inArray: function( elem, array ) {
for ( var i = 0, length = array.length; i < length; i++ )
// Use === because on IE, window == document
if ( array[ i ] === elem )
return i;
return -1;
},
merge: function( first, second ) {
// We have to loop this way because IE & Opera overwrite the length
// expando of getElementsByTagName
var i = 0, elem, pos = first.length;
// Also, we need to make sure that the correct elements are being returned
// (IE returns comment nodes in a '*' query)
if ( !jQuery.support.getAll ) {
while ( (elem = second[ i++ ]) != null )
if ( elem.nodeType != 8 )
first[ pos++ ] = elem;
} else
while ( (elem = second[ i++ ]) != null )
first[ pos++ ] = elem;
return first;
},
unique: function( array ) {
var ret = [], done = {};
try {
for ( var i = 0, length = array.length; i < length; i++ ) {
var id = jQuery.data( array[ i ] );
if ( !done[ id ] ) {
done[ id ] = true;
ret.push( array[ i ] );
}
}
} catch( e ) {
ret = array;
}
return ret;
},
grep: function( elems, callback, inv ) {
var ret = [];
// Go through the array, only saving the items
// that pass the validator function
for ( var i = 0, length = elems.length; i < length; i++ )
if ( !inv != !callback( elems[ i ], i ) )
ret.push( elems[ i ] );
return ret;
},
map: function( elems, callback ) {
var ret = [];
// Go through the array, translating each of the items to their
// new value (or values).
for ( var i = 0, length = elems.length; i < length; i++ ) {
var value = callback( elems[ i ], i );
if ( value != null )
ret[ ret.length ] = value;
}
return ret.concat.apply( [], ret );
}
});
// Use of jQuery.browser is deprecated.
// It's included for backwards compatibility and plugins,
// although they should work to migrate away.
var userAgent = navigator.userAgent.toLowerCase();
// Figure out what browser is being used
jQuery.browser = {
version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
safari: /webkit/.test( userAgent ),
opera: /opera/.test( userAgent ),
msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
};
jQuery.each({
parent: function(elem){return elem.parentNode;},
parents: function(elem){return jQuery.dir(elem,"parentNode");},
next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
children: function(elem){return jQuery.sibling(elem.firstChild);},
contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
}, function(name, fn){
jQuery.fn[ name ] = function( selector ) {
var ret = jQuery.map( this, fn );
if ( selector && typeof selector == "string" )
ret = jQuery.multiFilter( selector, ret );
return this.pushStack( jQuery.unique( ret ), name, selector );
};
});
jQuery.each({
appendTo: "append",
prependTo: "prepend",
insertBefore: "before",
insertAfter: "after",
replaceAll: "replaceWith"
}, function(name, original){
jQuery.fn[ name ] = function( selector ) {
var ret = [], insert = jQuery( selector );
for ( var i = 0, l = insert.length; i < l; i++ ) {
var elems = (i > 0 ? this.clone(true) : this).get();
jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
ret = ret.concat( elems );
}
return this.pushStack( ret, name, selector );
};
});
jQuery.each({
removeAttr: function( name ) {
jQuery.attr( this, name, "" );
if (this.nodeType == 1)
this.removeAttribute( name );
},
addClass: function( classNames ) {
jQuery.className.add( this, classNames );
},
removeClass: function( classNames ) {
jQuery.className.remove( this, classNames );
},
toggleClass: function( classNames, state ) {
if( typeof state !== "boolean" )
state = !jQuery.className.has( this, classNames );
jQuery.className[ state ? "add" : "remove" ]( this, classNames );
},
remove: function( selector ) {
if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
// Prevent memory leaks
jQuery( "*", this ).add([this]).each(function(){
jQuery.event.remove(this);
jQuery.removeData(this);
});
if (this.parentNode)
this.parentNode.removeChild( this );
}
},
empty: function() {
// Remove element nodes and prevent memory leaks
jQuery(this).children().remove();
// Remove any remaining nodes
while ( this.firstChild )
this.removeChild( this.firstChild );
}
}, function(name, fn){
jQuery.fn[ name ] = function(){
return this.each( fn, arguments );
};
});
// Helper function used by the dimensions and offset modules
function num(elem, prop) {
return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
}
var expando = "jQuery" + now(), uuid = 0, windowData = {};
jQuery.extend({
cache: {},
data: function( elem, name, data ) {
elem = elem == window ?
windowData :
elem;
var id = elem[ expando ];
// Compute a unique ID for the element
if ( !id )
id = elem[ expando ] = ++uuid;
// Only generate the data cache if we're
// trying to access or manipulate it
if ( name && !jQuery.cache[ id ] )
jQuery.cache[ id ] = {};
// Prevent overriding the named cache with undefined values
if ( data !== undefined )
jQuery.cache[ id ][ name ] = data;
// Return the named cache data, or the ID for the element
return name ?
jQuery.cache[ id ][ name ] :
id;
},
removeData: function( elem, name ) {
elem = elem == window ?
windowData :
elem;
var id = elem[ expando ];
// If we want to remove a specific section of the element's data
if ( name ) {
if ( jQuery.cache[ id ] ) {
// Remove the section of cache data
delete jQuery.cache[ id ][ name ];
// If we've removed all the data, remove the element's cache
name = "";
for ( name in jQuery.cache[ id ] )
break;
if ( !name )
jQuery.removeData( elem );
}
// Otherwise, we want to remove all of the element's data
} else {
// Clean up the element expando
try {
delete elem[ expando ];
} catch(e){
// IE has trouble directly removing the expando
// but it's ok with using removeAttribute
if ( elem.removeAttribute )
elem.removeAttribute( expando );
}
// Completely remove the data cache
delete jQuery.cache[ id ];
}
},
queue: function( elem, type, data ) {
if ( elem ){
type = (type || "fx") + "queue";
var q = jQuery.data( elem, type );
if ( !q || jQuery.isArray(data) )
q = jQuery.data( elem, type, jQuery.makeArray(data) );
else if( data )
q.push( data );
}
return q;
},
dequeue: function( elem, type ){
var queue = jQuery.queue( elem, type ),
fn = queue.shift();
if( !type || type === "fx" )
fn = queue[0];
if( fn !== undefined )
fn.call(elem);
}
});
jQuery.fn.extend({
data: function( key, value ){
var parts = key.split(".");
parts[1] = parts[1] ? "." + parts[1] : "";
if ( value === undefined ) {
var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
if ( data === undefined && this.length )
data = jQuery.data( this[0], key );
return data === undefined && parts[1] ?
this.data( parts[0] ) :
data;
} else
return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
jQuery.data( this, key, value );
});
},
removeData: function( key ){
return this.each(function(){
jQuery.removeData( this, key );
});
},
queue: function(type, data){
if ( typeof type !== "string" ) {
data = type;
type = "fx";
}
if ( data === undefined )
return jQuery.queue( this[0], type );
return this.each(function(){
var queue = jQuery.queue( this, type, data );
if( type == "fx" && queue.length == 1 )
queue[0].call(this);
});
},
dequeue: function(type){
return this.each(function(){
jQuery.dequeue( this, type );
});
}
});/*!
* Sizzle CSS Selector Engine - v0.9.3
* Copyright 2009, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
* More information: http://sizzlejs.com/
*/
(function(){
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
done = 0,
toString = Object.prototype.toString;
var Sizzle = function(selector, context, results, seed) {
results = results || [];
context = context || document;
if ( context.nodeType !== 1 && context.nodeType !== 9 )
return [];
if ( !selector || typeof selector !== "string" ) {
return results;
}
var parts = [], m, set, checkSet, check, mode, extra, prune = true;
// Reset the position of the chunker regexp (start from head)
chunker.lastIndex = 0;
while ( (m = chunker.exec(selector)) !== null ) {
parts.push( m[1] );
if ( m[2] ) {
extra = RegExp.rightContext;
break;
}
}
if ( parts.length > 1 && origPOS.exec( selector ) ) {
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
set = posProcess( parts[0] + parts[1], context );
} else {
set = Expr.relative[ parts[0] ] ?
[ context ] :
Sizzle( parts.shift(), context );
while ( parts.length ) {
selector = parts.shift();
if ( Expr.relative[ selector ] )
selector += parts.shift();
set = posProcess( selector, set );
}
}
} else {
var ret = seed ?
{ expr: parts.pop(), set: makeArray(seed) } :
Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
set = Sizzle.filter( ret.expr, ret.set );
if ( parts.length > 0 ) {
checkSet = makeArray(set);
} else {
prune = false;
}
while ( parts.length ) {
var cur = parts.pop(), pop = cur;
if ( !Expr.relative[ cur ] ) {
cur = "";
} else {
pop = parts.pop();
}
if ( pop == null ) {
pop = context;
}
Expr.relative[ cur ]( checkSet, pop, isXML(context) );
}
}
if ( !checkSet ) {
checkSet = set;
}
if ( !checkSet ) {
throw "Syntax error, unrecognized expression: " + (cur || selector);
}
if ( toString.call(checkSet) === "[object Array]" ) {
if ( !prune ) {
results.push.apply( results, checkSet );
} else if ( context.nodeType === 1 ) {
for ( var i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
results.push( set[i] );
}
}
} else {
for ( var i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
results.push( set[i] );
}
}
}
} else {
makeArray( checkSet, results );
}
if ( extra ) {
Sizzle( extra, context, results, seed );
if ( sortOrder ) {
hasDuplicate = false;
results.sort(sortOrder);
if ( hasDuplicate ) {
for ( var i = 1; i < results.length; i++ ) {
if ( results[i] === results[i-1] ) {
results.splice(i--, 1);
}
}
}
}
}
return results;
};
Sizzle.matches = function(expr, set){
return Sizzle(expr, null, null, set);
};
Sizzle.find = function(expr, context, isXML){
var set, match;
if ( !expr ) {
return [];
}
for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
var type = Expr.order[i], match;
if ( (match = Expr.match[ type ].exec( expr )) ) {
var left = RegExp.leftContext;
if ( left.substr( left.length - 1 ) !== "\\" ) {
match[1] = (match[1] || "").replace(/\\/g, "");
set = Expr.find[ type ]( match, context, isXML );
if ( set != null ) {
expr = expr.replace( Expr.match[ type ], "" );
break;
}
}
}
}
if ( !set ) {
set = context.getElementsByTagName("*");
}
return {set: set, expr: expr};
};
Sizzle.filter = function(expr, set, inplace, not){
var old = expr, result = [], curLoop = set, match, anyFound,
isXMLFilter = set && set[0] && isXML(set[0]);
while ( expr && set.length ) {
for ( var type in Expr.filter ) {
if ( (match = Expr.match[ type ].exec( expr )) != null ) {
var filter = Expr.filter[ type ], found, item;
anyFound = false;
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 ( var i = 0; (item = curLoop[i]) != null; i++ ) {
if ( item ) {
found = filter( item, match, i, curLoop );
var pass = not ^ !!found;
if ( inplace && found != null ) {
if ( pass ) {
anyFound = true;
} else {
curLoop[i] = false;
}
} else if ( pass ) {
result.push( item );
anyFound = true;
}
}
}
}
if ( found !== undefined ) {
if ( !inplace ) {
curLoop = result;
}
expr = expr.replace( Expr.match[ type ], "" );
if ( !anyFound ) {
return [];
}
break;
}
}
}
// Improper expression
if ( expr == old ) {
if ( anyFound == null ) {
throw "Syntax error, unrecognized expression: " + expr;
} else {
break;
}
}
old = expr;
}
return curLoop;
};
var Expr = Sizzle.selectors = {
order: [ "ID", "NAME", "TAG" ],
match: {
ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
},
attrMap: {
"class": "className",
"for": "htmlFor"
},
attrHandle: {
href: function(elem){
return elem.getAttribute("href");
}
},
relative: {
"+": function(checkSet, part, isXML){
var isPartStr = typeof part === "string",
isTag = isPartStr && !/\W/.test(part),
isPartStrNotTag = isPartStr && !isTag;
if ( isTag && !isXML ) {
part = part.toUpperCase();
}
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
if ( (elem = checkSet[i]) ) {
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
elem || false :
elem === part;
}
}
if ( isPartStrNotTag ) {
Sizzle.filter( part, checkSet, true );
}
},
">": function(checkSet, part, isXML){
var isPartStr = typeof part === "string";
if ( isPartStr && !/\W/.test(part) ) {
part = isXML ? part : part.toUpperCase();
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
var parent = elem.parentNode;
checkSet[i] = parent.nodeName === part ? parent : false;
}
}
} else {
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
checkSet[i] = isPartStr ?
elem.parentNode :
elem.parentNode === part;
}
}
if ( isPartStr ) {
Sizzle.filter( part, checkSet, true );
}
}
},
"": function(checkSet, part, isXML){
var doneName = done++, checkFn = dirCheck;
if ( !part.match(/\W/) ) {
var nodeCheck = part = isXML ? part : part.toUpperCase();
checkFn = dirNodeCheck;
}
checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
},
"~": function(checkSet, part, isXML){
var doneName = done++, checkFn = dirCheck;
if ( typeof part === "string" && !part.match(/\W/) ) {
var nodeCheck = part = isXML ? part : part.toUpperCase();
checkFn = dirNodeCheck;
}
checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
}
},
find: {
ID: function(match, context, isXML){
if ( typeof context.getElementById !== "undefined" && !isXML ) {
var m = context.getElementById(match[1]);
return m ? [m] : [];
}
},
NAME: function(match, context, isXML){
if ( typeof context.getElementsByName !== "undefined" ) {
var ret = [], results = context.getElementsByName(match[1]);
for ( var i = 0, l = results.length; i < l; i++ ) {
if ( results[i].getAttribute("name") === match[1] ) {
ret.push( results[i] );
}
}
return ret.length === 0 ? null : ret;
}
},
TAG: function(match, context){
return context.getElementsByTagName(match[1]);
}
},
preFilter: {
CLASS: function(match, curLoop, inplace, result, not, isXML){
match = " " + match[1].replace(/\\/g, "") + " ";
if ( isXML ) {
return match;
}
for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
if ( elem ) {
if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
if ( !inplace )
result.push( elem );
} else if ( inplace ) {
curLoop[i] = false;
}
}
}
return false;
},
ID: function(match){
return match[1].replace(/\\/g, "");
},
TAG: function(match, curLoop){
for ( var i = 0; curLoop[i] === false; i++ ){}
return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
},
CHILD: function(match){
if ( match[1] == "nth" ) {
// 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]);
// calculate the numbers (first)n+(last) including if they are negative
match[2] = (test[1] + (test[2] || 1)) - 0;
match[3] = test[3] - 0;
}
// TODO: Move to normal caching system
match[0] = done++;
return match;
},
ATTR: function(match, curLoop, inplace, result, not, isXML){
var name = match[1].replace(/\\/g, "");
if ( !isXML && Expr.attrMap[name] ) {
match[1] = Expr.attrMap[name];
}
if ( match[2] === "~=" ) {
match[4] = " " + match[4] + " ";
}
return match;
},
PSEUDO: function(match, curLoop, inplace, result, not){
if ( match[1] === "not" ) {
// If we're dealing with a complex expression, or a simple one
if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
match[3] = Sizzle(match[3], null, null, curLoop);
} else {
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
if ( !inplace ) {
result.push.apply( result, ret );
}
return false;
}
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
return true;
}
return match;
},
POS: function(match){
match.unshift( true );
return match;
}
},
filters: {
enabled: function(elem){
return elem.disabled === false && elem.type !== "hidden";
},
disabled: function(elem){
return elem.disabled === true;
},
checked: function(elem){
return elem.checked === true;
},
selected: function(elem){
// Accessing this property makes selected-by-default
// options in Safari work properly
elem.parentNode.selectedIndex;
return elem.selected === true;
},
parent: function(elem){
return !!elem.firstChild;
},
empty: function(elem){
return !elem.firstChild;
},
has: function(elem, i, match){
return !!Sizzle( match[3], elem ).length;
},
header: function(elem){
return /h\d/i.test( elem.nodeName );
},
text: function(elem){
return "text" === elem.type;
},
radio: function(elem){
return "radio" === elem.type;
},
checkbox: function(elem){
return "checkbox" === elem.type;
},
file: function(elem){
return "file" === elem.type;
},
password: function(elem){
return "password" === elem.type;
},
submit: function(elem){
return "submit" === elem.type;
},
image: function(elem){
return "image" === elem.type;
},
reset: function(elem){
return "reset" === elem.type;
},
button: function(elem){
return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
},
input: function(elem){
return /input|select|textarea|button/i.test(elem.nodeName);
}
},
setFilters: {
first: function(elem, i){
return i === 0;
},
last: function(elem, i, match, array){
return i === array.length - 1;
},
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 || "").indexOf(match[3]) >= 0;
} else if ( name === "not" ) {
var not = match[3];
for ( var i = 0, l = not.length; i < l; i++ ) {
if ( not[i] === elem ) {
return false;
}
}
return true;
}
},
CHILD: function(elem, match){
var 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;
case 'last':
while (node = node.nextSibling) {
if ( node.nodeType === 1 ) return false;
}
return true;
case 'nth':
var first = match[2], last = match[3];
if ( first == 1 && last == 0 ) {
return true;
}
var doneName = match[0],
parent = elem.parentNode;
if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
var count = 0;
for ( node = parent.firstChild; node; node = node.nextSibling ) {
if ( node.nodeType === 1 ) {
node.nodeIndex = ++count;
}
}
parent.sizcache = doneName;
}
var diff = elem.nodeIndex - last;
if ( first == 0 ) {
return diff == 0;
} else {
return ( diff % first == 0 && diff / first >= 0 );
}
}
},
ID: function(elem, match){
return elem.nodeType === 1 && elem.getAttribute("id") === match;
},
TAG: function(elem, match){
return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
},
CLASS: function(elem, match){
return (" " + (elem.className || elem.getAttribute("class")) + " ")
.indexOf( match ) > -1;
},
ATTR: function(elem, match){
var name = match[1],
result = 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 === "=" ?
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 );
}
}
}
};
var origPOS = Expr.match.POS;
for ( var type in Expr.match ) {
Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
}
var makeArray = function(array, results) {
array = Array.prototype.slice.call( array );
if ( results ) {
results.push.apply( results, array );
return results;
}
return array;
};
// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
try {
Array.prototype.slice.call( document.documentElement.childNodes );
// Provide a fallback method if it does not work
} catch(e){
makeArray = function(array, results) {
var ret = results || [];
if ( toString.call(array) === "[object Array]" ) {
Array.prototype.push.apply( ret, array );
} else {
if ( typeof array.length === "number" ) {
for ( var i = 0, l = array.length; i < l; i++ ) {
ret.push( array[i] );
}
} else {
for ( var i = 0; array[i]; i++ ) {
ret.push( array[i] );
}
}
}
return ret;
};
}
var sortOrder;
if ( document.documentElement.compareDocumentPosition ) {
sortOrder = function( a, b ) {
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
if ( ret === 0 ) {
hasDuplicate = true;
}
return ret;
};
} else if ( "sourceIndex" in document.documentElement ) {
sortOrder = function( a, b ) {
var ret = a.sourceIndex - b.sourceIndex;
if ( ret === 0 ) {
hasDuplicate = true;
}
return ret;
};
} else if ( document.createRange ) {
sortOrder = function( a, b ) {
var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
aRange.selectNode(a);
aRange.collapse(true);
bRange.selectNode(b);
bRange.collapse(true);
var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
if ( ret === 0 ) {
hasDuplicate = true;
}
return ret;
};
}
// 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("form"),
id = "script" + (new Date).getTime();
form.innerHTML = "<input name='" + id + "'/>";
// Inject it into the root element, check its status, and remove it quickly
var root = document.documentElement;
root.insertBefore( form, root.firstChild );
// 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]);
return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
}
};
Expr.filter.ID = function(elem, match){
var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
return elem.nodeType === 1 && node && node.nodeValue === match;
};
}
root.removeChild( form );
})();
(function(){
// Check to see if the browser returns only elements
// when doing getElementsByTagName("*")
// Create a fake element
var div = document.createElement("div");
div.appendChild( document.createComment("") );
// Make sure no comments are found
if ( div.getElementsByTagName("*").length > 0 ) {
Expr.find.TAG = function(match, context){
var results = context.getElementsByTagName(match[1]);
// Filter out possible comments
if ( match[1] === "*" ) {
var tmp = [];
for ( var i = 0; results[i]; i++ ) {
if ( results[i].nodeType === 1 ) {
tmp.push( results[i] );
}
}
results = tmp;
}
return results;
};
}
// Check to see if an attribute returns normalized href attributes
div.innerHTML = "<a href='#'></a>";
if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
div.firstChild.getAttribute("href") !== "#" ) {
Expr.attrHandle.href = function(elem){
return elem.getAttribute("href", 2);
};
}
})();
if ( document.querySelectorAll ) (function(){
var oldSizzle = Sizzle, div = document.createElement("div");
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;
}
Sizzle = function(query, context, extra, seed){
context = context || document;
// Only use querySelectorAll on non-XML documents
// (ID selectors don't work in non-HTML documents)
if ( !seed && context.nodeType === 9 && !isXML(context) ) {
try {
return makeArray( context.querySelectorAll(query), extra );
} catch(e){}
}
return oldSizzle(query, context, extra, seed);
};
Sizzle.find = oldSizzle.find;
Sizzle.filter = oldSizzle.filter;
Sizzle.selectors = oldSizzle.selectors;
Sizzle.matches = oldSizzle.matches;
})();
if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
var div = document.createElement("div");
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
// Opera can't find a second classname (in 9.6)
if ( div.getElementsByClassName("e").length === 0 )
return;
// Safari caches class attributes, doesn't catch changes (in 3.2)
div.lastChild.className = "e";
if ( div.getElementsByClassName("e").length === 1 )
return;
Expr.order.splice(1, 0, "CLASS");
Expr.find.CLASS = function(match, context, isXML) {
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
return context.getElementsByClassName(match[1]);
}
};
})();
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
var sibDir = dir == "previousSibling" && !isXML;
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
if ( sibDir && elem.nodeType === 1 ){
elem.sizcache = doneName;
elem.sizset = i;
}
elem = elem[dir];
var match = false;
while ( elem ) {
if ( elem.sizcache === doneName ) {
match = checkSet[elem.sizset];
break;
}
if ( elem.nodeType === 1 && !isXML ){
elem.sizcache = doneName;
elem.sizset = i;
}
if ( elem.nodeName === cur ) {
match = elem;
break;
}
elem = elem[dir];
}
checkSet[i] = match;
}
}
}
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
var sibDir = dir == "previousSibling" && !isXML;
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
if ( sibDir && elem.nodeType === 1 ) {
elem.sizcache = doneName;
elem.sizset = i;
}
elem = elem[dir];
var match = false;
while ( elem ) {
if ( elem.sizcache === doneName ) {
match = checkSet[elem.sizset];
break;
}
if ( elem.nodeType === 1 ) {
if ( !isXML ) {
elem.sizcache = doneName;
elem.sizset = i;
}
if ( typeof cur !== "string" ) {
if ( elem === cur ) {
match = true;
break;
}
} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
match = elem;
break;
}
}
elem = elem[dir];
}
checkSet[i] = match;
}
}
}
var contains = document.compareDocumentPosition ? function(a, b){
return a.compareDocumentPosition(b) & 16;
} : function(a, b){
return a !== b && (a.contains ? a.contains(b) : true);
};
var isXML = function(elem){
return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
!!elem.ownerDocument && isXML( elem.ownerDocument );
};
var posProcess = function(selector, context){
var tmpSet = [], later = "", match,
root = context.nodeType ? [context] : context;
// 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, "" );
}
selector = Expr.relative[selector] ? selector + "*" : selector;
for ( var i = 0, l = root.length; i < l; i++ ) {
Sizzle( selector, root[i], tmpSet );
}
return Sizzle.filter( later, tmpSet );
};
// EXPOSE
jQuery.find = Sizzle;
jQuery.filter = Sizzle.filter;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;
Sizzle.selectors.filters.hidden = function(elem){
return elem.offsetWidth === 0 || elem.offsetHeight === 0;
};
Sizzle.selectors.filters.visible = function(elem){
return elem.offsetWidth > 0 || elem.offsetHeight > 0;
};
Sizzle.selectors.filters.animated = function(elem){
return jQuery.grep(jQuery.timers, function(fn){
return elem === fn.elem;
}).length;
};
jQuery.multiFilter = function( expr, elems, not ) {
if ( not ) {
expr = ":not(" + expr + ")";
}
return Sizzle.matches(expr, elems);
};
jQuery.dir = function( elem, dir ){
var matched = [], cur = elem[dir];
while ( cur && cur != document ) {
if ( cur.nodeType == 1 )
matched.push( cur );
cur = cur[dir];
}
return matched;
};
jQuery.nth = function(cur, result, dir, elem){
result = result || 1;
var num = 0;
for ( ; cur; cur = cur[dir] )
if ( cur.nodeType == 1 && ++num == result )
break;
return cur;
};
jQuery.sibling = function(n, elem){
var r = [];
for ( ; n; n = n.nextSibling ) {
if ( n.nodeType == 1 && n != elem )
r.push( n );
}
return r;
};
return;
window.Sizzle = Sizzle;
})();
/*
* A number of helper functions used for managing events.
* Many of the ideas behind this code originated from
* Dean Edwards' addEvent library.
*/
jQuery.event = {
// Bind an event to an element
// Original by Dean Edwards
add: function(elem, types, handler, data) {
if ( elem.nodeType == 3 || elem.nodeType == 8 )
return;
// For whatever reason, IE has trouble passing the window object
// around, causing it to be cloned in the process
if ( elem.setInterval && elem != window )
elem = window;
// Make sure that the function being executed has a unique ID
if ( !handler.guid )
handler.guid = this.guid++;
// if data is passed, bind to handler
if ( data !== undefined ) {
// Create temporary function pointer to original handler
var fn = handler;
// Create unique handler function, wrapped around original handler
handler = this.proxy( fn );
// Store data in unique handler
handler.data = data;
}
// Init the element's event structure
var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
// Handle the second event of a trigger and when
// an event is called after a page has unloaded
return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
jQuery.event.handle.apply(arguments.callee.elem, arguments) :
undefined;
});
// Add elem as a property of the handle function
// This is to prevent a memory leak with non-native
// event in IE.
handle.elem = elem;
// Handle multiple events separated by a space
// jQuery(...).bind("mouseover mouseout", fn);
jQuery.each(types.split(/\s+/), function(index, type) {
// Namespaced event handlers
var namespaces = type.split(".");
type = namespaces.shift();
handler.type = namespaces.slice().sort().join(".");
// Get the current list of functions bound to this event
var handlers = events[type];
if ( jQuery.event.specialAll[type] )
jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
// Init the event handler queue
if (!handlers) {
handlers = events[type] = {};
// Check for a special event handler
// Only use addEventListener/attachEvent if the special
// events handler returns false
if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
// Bind the global event handler to the element
if (elem.addEventListener)
elem.addEventListener(type, handle, false);
else if (elem.attachEvent)
elem.attachEvent("on" + type, handle);
}
}
// Add the function to the element's handler list
handlers[handler.guid] = handler;
// Keep track of which events have been used, for global triggering
jQuery.event.global[type] = true;
});
// Nullify elem to prevent memory leaks in IE
elem = null;
},
guid: 1,
global: {},
// Detach an event or set of events from an element
remove: function(elem, types, handler) {
// don't do events on text and comment nodes
if ( elem.nodeType == 3 || elem.nodeType == 8 )
return;
var events = jQuery.data(elem, "events"), ret, index;
if ( events ) {
// Unbind all events for the element
if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
for ( var type in events )
this.remove( elem, type + (types || "") );
else {
// types is actually an event object here
if ( types.type ) {
handler = types.handler;
types = types.type;
}
// Handle multiple events seperated by a space
// jQuery(...).unbind("mouseover mouseout", fn);
jQuery.each(types.split(/\s+/), function(index, type){
// Namespaced event handlers
var namespaces = type.split(".");
type = namespaces.shift();
var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
if ( events[type] ) {
// remove the given handler for the given type
if ( handler )
delete events[type][handler.guid];
// remove all handlers for the given type
else
for ( var handle in events[type] )
// Handle the removal of namespaced events
if ( namespace.test(events[type][handle].type) )
delete events[type][handle];
if ( jQuery.event.specialAll[type] )
jQuery.event.specialAll[type].teardown.call(elem, namespaces);
// remove generic event handler if no more handlers exist
for ( ret in events[type] ) break;
if ( !ret ) {
if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
if (elem.removeEventListener)
elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
else if (elem.detachEvent)
elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
}
ret = null;
delete events[type];
}
}
});
}
// Remove the expando if it's no longer used
for ( ret in events ) break;
if ( !ret ) {
var handle = jQuery.data( elem, "handle" );
if ( handle ) handle.elem = null;
jQuery.removeData( elem, "events" );
jQuery.removeData( elem, "handle" );
}
}
},
// bubbling is internal
trigger: function( event, data, elem, bubbling ) {
// Event object or event type
var type = event.type || event;
if( !bubbling ){
event = typeof event === "object" ?
// jQuery.Event object
event[expando] ? event :
// Object literal
jQuery.extend( jQuery.Event(type), event ) :
// Just the event type (string)
jQuery.Event(type);
if ( type.indexOf("!") >= 0 ) {
event.type = type = type.slice(0, -1);
event.exclusive = true;
}
// Handle a global trigger
if ( !elem ) {
// Don't bubble custom events when global (to avoid too much overhead)
event.stopPropagation();
// Only trigger if we've ever bound an event for it
if ( this.global[type] )
jQuery.each( jQuery.cache, function(){
if ( this.events && this.events[type] )
jQuery.event.trigger( event, data, this.handle.elem );
});
}
// Handle triggering a single element
// don't do events on text and comment nodes
if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
return undefined;
// Clean up in case it is reused
event.result = undefined;
event.target = elem;
// Clone the incoming data, if any
data = jQuery.makeArray(data);
data.unshift( event );
}
event.currentTarget = elem;
// Trigger the event, it is assumed that "handle" is a function
var handle = jQuery.data(elem, "handle");
if ( handle )
handle.apply( elem, data );
// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
event.result = false;
// Trigger the native events (except for clicks on links)
if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
this.triggered = true;
try {
elem[ type ]();
// prevent IE from throwing an error for some hidden elements
} catch (e) {}
}
this.triggered = false;
if ( !event.isPropagationStopped() ) {
var parent = elem.parentNode || elem.ownerDocument;
if ( parent )
jQuery.event.trigger(event, data, parent, true);
}
},
handle: function(event) {
// returned undefined or false
var all, handlers;
event = arguments[0] = jQuery.event.fix( event || window.event );
event.currentTarget = this;
// Namespaced event handlers
var namespaces = event.type.split(".");
event.type = namespaces.shift();
// Cache this now, all = true means, any handler
all = !namespaces.length && !event.exclusive;
var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
handlers = ( jQuery.data(this, "events") || {} )[event.type];
for ( var j in handlers ) {
var handler = handlers[j];
// Filter the functions by class
if ( all || namespace.test(handler.type) ) {
// Pass in a reference to the handler function itself
// So that we can later remove it
event.handler = handler;
event.data = handler.data;
var ret = handler.apply(this, arguments);
if( ret !== undefined ){
event.result = ret;
if ( ret === false ) {
event.preventDefault();
event.stopPropagation();
}
}
if( event.isImmediatePropagationStopped() )
break;
}
}
},
props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix: function(event) {
if ( event[expando] )
return event;
// store a copy of the original event object
// and "clone" to set read-only properties
var originalEvent = event;
event = jQuery.Event( originalEvent );
for ( var i = this.props.length, prop; i; ){
prop = this.props[ --i ];
event[ prop ] = originalEvent[ prop ];
}
// Fix target property, if necessary
if ( !event.target )
event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
// check if target is a textnode (safari)
if ( event.target.nodeType == 3 )
event.target = event.target.parentNode;
// Add relatedTarget, if necessary
if ( !event.relatedTarget && event.fromElement )
event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
// Calculate pageX/Y if missing and clientX/Y available
if ( event.pageX == null && event.clientX != null ) {
var doc = document.documentElement, body = document.body;
event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
}
// Add which for key events
if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
event.which = event.charCode || event.keyCode;
// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
if ( !event.metaKey && event.ctrlKey )
event.metaKey = event.ctrlKey;
// Add which for click: 1 == left; 2 == middle; 3 == right
// Note: button is not normalized, so don't use it
if ( !event.which && event.button )
event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
return event;
},
proxy: function( fn, proxy ){
proxy = proxy || function(){ return fn.apply(this, arguments); };
// Set the guid of unique handler to the same of original handler, so it can be removed
proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
// So proxy can be declared as an argument
return proxy;
},
special: {
ready: {
// Make sure the ready event is setup
setup: bindReady,
teardown: function() {}
}
},
specialAll: {
live: {
setup: function( selector, namespaces ){
jQuery.event.add( this, namespaces[0], liveHandler );
},
teardown: function( namespaces ){
if ( namespaces.length ) {
var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
jQuery.each( (jQuery.data(this, "events").live || {}), function(){
if ( name.test(this.type) )
remove++;
});
if ( remove < 1 )
jQuery.event.remove( this, namespaces[0], liveHandler );
}
}
}
}
};
jQuery.Event = function( src ){
// Allow instantiation without the 'new' keyword
if( !this.preventDefault )
return new jQuery.Event(src);
// Event object
if( src && src.type ){
this.originalEvent = src;
this.type = src.type;
// Event type
}else
this.type = src;
// timeStamp is buggy for some events on Firefox(#3843)
// So we won't rely on the native value
this.timeStamp = now();
// Mark it as fixed
this[expando] = true;
};
function returnFalse(){
return false;
}
function returnTrue(){
return true;
}
// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
preventDefault: function() {
this.isDefaultPrevented = returnTrue;
var e = this.originalEvent;
if( !e )
return;
// if preventDefault exists run it on the original event
if (e.preventDefault)
e.preventDefault();
// otherwise set the returnValue property of the original event to false (IE)
e.returnValue = false;
},
stopPropagation: function() {
this.isPropagationStopped = returnTrue;
var e = this.originalEvent;
if( !e )
return;
// if stopPropagation exists run it on the original event
if (e.stopPropagation)
e.stopPropagation();
// otherwise set the cancelBubble property of the original event to true (IE)
e.cancelBubble = true;
},
stopImmediatePropagation:function(){
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
},
isDefaultPrevented: returnFalse,
isPropagationStopped: returnFalse,
isImmediatePropagationStopped: returnFalse
};
// Checks if an event happened on an element within another element
// Used in jQuery.event.special.mouseenter and mouseleave handlers
var withinElement = function(event) {
// Check if mouse(over|out) are still within the same parent element
var parent = event.relatedTarget;
// Traverse up the tree
while ( parent && parent != this )
try { parent = parent.parentNode; }
catch(e) { parent = this; }
if( parent != this ){
// set the correct event type
event.type = event.data;
// handle event if we actually just moused on to a non sub-element
jQuery.event.handle.apply( this, arguments );
}
};
jQuery.each({
mouseover: 'mouseenter',
mouseout: 'mouseleave'
}, function( orig, fix ){
jQuery.event.special[ fix ] = {
setup: function(){
jQuery.event.add( this, orig, withinElement, fix );
},
teardown: function(){
jQuery.event.remove( this, orig, withinElement );
}
};
});
jQuery.fn.extend({
bind: function( type, data, fn ) {
return type == "unload" ? this.one(type, data, fn) : this.each(function(){
jQuery.event.add( this, type, fn || data, fn && data );
});
},
one: function( type, data, fn ) {
var one = jQuery.event.proxy( fn || data, function(event) {
jQuery(this).unbind(event, one);
return (fn || data).apply( this, arguments );
});
return this.each(function(){
jQuery.event.add( this, type, one, fn && data);
});
},
unbind: function( type, fn ) {
return this.each(function(){
jQuery.event.remove( this, type, fn );
});
},
trigger: function( type, data ) {
return this.each(function(){
jQuery.event.trigger( type, data, this );
});
},
triggerHandler: function( type, data ) {
if( this[0] ){
var event = jQuery.Event(type);
event.preventDefault();
event.stopPropagation();
jQuery.event.trigger( event, data, this[0] );
return event.result;
}
},
toggle: function( fn ) {
// Save reference to arguments for access in closure
var args = arguments, i = 1;
// link all the functions, so any of them can unbind this click handler
while( i < args.length )
jQuery.event.proxy( fn, args[i++] );
return this.click( jQuery.event.proxy( fn, function(event) {
// Figure out which function to execute
this.lastToggle = ( this.lastToggle || 0 ) % i;
// Make sure that clicks stop
event.preventDefault();
// and execute the function
return args[ this.lastToggle++ ].apply( this, arguments ) || false;
}));
},
hover: function(fnOver, fnOut) {
return this.mouseenter(fnOver).mouseleave(fnOut);
},
ready: function(fn) {
// Attach the listeners
bindReady();
// If the DOM is already ready
if ( jQuery.isReady )
// Execute the function immediately
fn.call( document, jQuery );
// Otherwise, remember the function for later
else
// Add the function to the wait list
jQuery.readyList.push( fn );
return this;
},
live: function( type, fn ){
var proxy = jQuery.event.proxy( fn );
proxy.guid += this.selector + type;
jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
return this;
},
die: function( type, fn ){
jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
return this;
}
});
function liveHandler( event ){
var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
stop = true,
elems = [];
jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
if ( check.test(fn.type) ) {
var elem = jQuery(event.target).closest(fn.data)[0];
if ( elem )
elems.push({ elem: elem, fn: fn });
}
});
elems.sort(function(a,b) {
return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
});
jQuery.each(elems, function(){
if ( this.fn.call(this.elem, event, this.fn.data) === false )
return (stop = false);
});
return stop;
}
function liveConvert(type, selector){
return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
}
jQuery.extend({
isReady: false,
readyList: [],
// Handle when the DOM is ready
ready: function() {
// Make sure that the DOM is not already loaded
if ( !jQuery.isReady ) {
// Remember that the DOM is ready
jQuery.isReady = true;
// If there are functions bound, to execute
if ( jQuery.readyList ) {
// Execute all of them
jQuery.each( jQuery.readyList, function(){
this.call( document, jQuery );
});
// Reset the list of functions
jQuery.readyList = null;
}
// Trigger any bound ready events
jQuery(document).triggerHandler("ready");
}
}
});
var readyBound = false;
function bindReady(){
if ( readyBound ) return;
readyBound = true;
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", function(){
document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
jQuery.ready();
}, false );
// If IE event model is used
} else if ( document.attachEvent ) {
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent("onreadystatechange", function(){
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", arguments.callee );
jQuery.ready();
}
});
// If IE and not an iframe
// continually check to see if the document is ready
if ( document.documentElement.doScroll && window == window.top ) (function(){
if ( jQuery.isReady ) return;
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch( error ) {
setTimeout( arguments.callee, 0 );
return;
}
// and execute any waiting functions
jQuery.ready();
})();
}
// A fallback to window.onload, that will always work
jQuery.event.add( window, "load", jQuery.ready );
}
jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
"mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
"change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
// Handle event binding
jQuery.fn[name] = function(fn){
return fn ? this.bind(name, fn) : this.trigger(name);
};
});
// Prevent memory leaks in IE
// And prevent errors on refresh with events like mouseover in other browsers
// Window isn't included so as not to unbind existing unload events
jQuery( window ).bind( 'unload', function(){
for ( var id in jQuery.cache )
// Skip the window
if ( id != 1 && jQuery.cache[ id ].handle )
jQuery.event.remove( jQuery.cache[ id ].handle.elem );
});
(function(){
jQuery.support = {};
var root = document.documentElement,
script = document.createElement("script"),
div = document.createElement("div"),
id = "script" + (new Date).getTime();
div.style.display = "none";
div.innerHTML = ' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
var all = div.getElementsByTagName("*"),
a = div.getElementsByTagName("a")[0];
// Can't get basic test support
if ( !all || !all.length || !a ) {
return;
}
jQuery.support = {
// IE strips leading whitespace when .innerHTML is used
leadingWhitespace: div.firstChild.nodeType == 3,
// Make sure that tbody elements aren't automatically inserted
// IE will insert them into empty tables
tbody: !div.getElementsByTagName("tbody").length,
// Make sure that you can get all elements in an <object> element
// IE 7 always returns no results
objectAll: !!div.getElementsByTagName("object")[0]
.getElementsByTagName("*").length,
// Make sure that link elements get serialized correctly by innerHTML
// This requires a wrapper element in IE
htmlSerialize: !!div.getElementsByTagName("link").length,
// Get the style information from getAttribute
// (IE uses .cssText insted)
style: /red/.test( a.getAttribute("style") ),
// Make sure that URLs aren't manipulated
// (IE normalizes it by default)
hrefNormalized: a.getAttribute("href") === "/a",
// Make sure that element opacity exists
// (IE uses filter instead)
opacity: a.style.opacity === "0.5",
// Verify style float existence
// (IE uses styleFloat instead of cssFloat)
cssFloat: !!a.style.cssFloat,
// Will be defined later
scriptEval: false,
noCloneEvent: true,
boxModel: null
};
script.type = "text/javascript";
try {
script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
} catch(e){}
root.insertBefore( script, root.firstChild );
// Make sure that the execution of code works by injecting a script
// tag with appendChild/createTextNode
// (IE doesn't support this, fails, and uses .text instead)
if ( window[ id ] ) {
jQuery.support.scriptEval = true;
delete window[ id ];
}
root.removeChild( script );
if ( div.attachEvent && div.fireEvent ) {
div.attachEvent("onclick", function(){
// Cloning a node shouldn't copy over any
// bound event handlers (IE does this)
jQuery.support.noCloneEvent = false;
div.detachEvent("onclick", arguments.callee);
});
div.cloneNode(true).fireEvent("onclick");
}
// Figure out if the W3C box model works as expected
// document.body must exist before we can do this
jQuery(function(){
var div = document.createElement("div");
div.style.width = div.style.paddingLeft = "1px";
document.body.appendChild( div );
jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
document.body.removeChild( div ).style.display = 'none';
});
})();
var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
jQuery.props = {
"for": "htmlFor",
"class": "className",
"float": styleFloat,
cssFloat: styleFloat,
styleFloat: styleFloat,
readonly: "readOnly",
maxlength: "maxLength",
cellspacing: "cellSpacing",
rowspan: "rowSpan",
tabindex: "tabIndex"
};
jQuery.fn.extend({
// Keep a copy of the old load
_load: jQuery.fn.load,
load: function( url, params, callback ) {
if ( typeof url !== "string" )
return this._load( url );
var off = url.indexOf(" ");
if ( off >= 0 ) {
var selector = url.slice(off, url.length);
url = url.slice(0, off);
}
// Default to a GET request
var type = "GET";
// If the second parameter was provided
if ( params )
// If it's a function
if ( jQuery.isFunction( params ) ) {
// We assume that it's the callback
callback = params;
params = null;
// Otherwise, build a param string
} else if( typeof params === "object" ) {
params = jQuery.param( params );
type = "POST";
}
var self = this;
// Request the remote document
jQuery.ajax({
url: url,
type: type,
dataType: "html",
data: params,
complete: function(res, status){
// If successful, inject the HTML into all the matched elements
if ( status == "success" || status == "notmodified" )
// See if a selector was specified
self.html( selector ?
// Create a dummy div to hold the results
jQuery("<div/>")
// inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE
.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
// Locate the specified elements
.find(selector) :
// If not, just inject the full result
res.responseText );
if( callback )
self.each( callback, [res.responseText, status, res] );
}
});
return this;
},
serialize: function() {
return jQuery.param(this.serializeArray());
},
serializeArray: function() {
return this.map(function(){
return this.elements ? jQuery.makeArray(this.elements) : this;
})
.filter(function(){
return this.name && !this.disabled &&
(this.checked || /select|textarea/i.test(this.nodeName) ||
/text|hidden|password|search/i.test(this.type));
})
.map(function(i, elem){
var val = jQuery(this).val();
return val == null ? null :
jQuery.isArray(val) ?
jQuery.map( val, function(val, i){
return {name: elem.name, value: val};
}) :
{name: elem.name, value: val};
}).get();
}
});
// Attach a bunch of functions for handling common AJAX events
jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
jQuery.fn[o] = function(f){
return this.bind(o, f);
};
});
var jsc = now();
jQuery.extend({
get: function( url, data, callback, type ) {
// shift arguments if data argument was ommited
if ( jQuery.isFunction( data ) ) {
callback = data;
data = null;
}
return jQuery.ajax({
type: "GET",
url: url,
data: data,
success: callback,
dataType: type
});
},
getScript: function( url, callback ) {
return jQuery.get(url, null, callback, "script");
},
getJSON: function( url, data, callback ) {
return jQuery.get(url, data, callback, "json");
},
post: function( url, data, callback, type ) {
if ( jQuery.isFunction( data ) ) {
callback = data;
data = {};
}
return jQuery.ajax({
type: "POST",
url: url,
data: data,
success: callback,
dataType: type
});
},
ajaxSetup: function( settings ) {
jQuery.extend( jQuery.ajaxSettings, settings );
},
ajaxSettings: {
url: location.href,
global: true,
type: "GET",
contentType: "application/x-www-form-urlencoded",
processData: true,
async: true,
/*
timeout: 0,
data: null,
username: null,
password: null,
*/
// Create the request object; Microsoft failed to properly
// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
// This function can be overriden by calling jQuery.ajaxSetup
xhr:function(){
return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
},
accepts: {
xml: "application/xml, text/xml",
html: "text/html",
script: "text/javascript, application/javascript",
json: "application/json, text/javascript",
text: "text/plain",
_default: "*/*"
}
},
// Last-Modified header cache for next request
lastModified: {},
ajax: function( s ) {
// Extend the settings, but re-extend 's' so that it can be
// checked again later (in the test suite, specifically)
s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
var jsonp, jsre = /=\?(&|$)/g, status, data,
type = s.type.toUpperCase();
// convert data if not already a string
if ( s.data && s.processData && typeof s.data !== "string" )
s.data = jQuery.param(s.data);
// Handle JSONP Parameter Callbacks
if ( s.dataType == "jsonp" ) {
if ( type == "GET" ) {
if ( !s.url.match(jsre) )
s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
} else if ( !s.data || !s.data.match(jsre) )
s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
s.dataType = "json";
}
// Build temporary JSONP function
if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
jsonp = "jsonp" + jsc++;
// Replace the =? sequence both in the query string and the data
if ( s.data )
s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
s.url = s.url.replace(jsre, "=" + jsonp + "$1");
// We need to make sure
// that a JSONP style response is executed properly
s.dataType = "script";
// Handle JSONP-style loading
window[ jsonp ] = function(tmp){
data = tmp;
success();
complete();
// Garbage collect
window[ jsonp ] = undefined;
try{ delete window[ jsonp ]; } catch(e){}
if ( head )
head.removeChild( script );
};
}
if ( s.dataType == "script" && s.cache == null )
s.cache = false;
if ( s.cache === false && type == "GET" ) {
var ts = now();
// try replacing _= if it is there
var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
// if nothing was replaced, add timestamp to the end
s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
}
// If data is available, append data to url for get requests
if ( s.data && type == "GET" ) {
s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
// IE likes to send both get and post data, prevent this
s.data = null;
}
// Watch for a new set of requests
if ( s.global && ! jQuery.active++ )
jQuery.event.trigger( "ajaxStart" );
// Matches an absolute URL, and saves the domain
var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
// If we're requesting a remote document
// and trying to load JSON or Script with a GET
if ( s.dataType == "script" && type == "GET" && parts
&& ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = s.url;
if (s.scriptCharset)
script.charset = s.scriptCharset;
// Handle Script loading
if ( !jsonp ) {
var done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function(){
if ( !done && (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") ) {
done = true;
success();
complete();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
head.removeChild( script );
}
};
}
head.appendChild(script);
// We handle everything using the script element injection
return undefined;
}
var requestDone = false;
// Create the request object
var xhr = s.xhr();
// Open the socket
// Passing null username, generates a login popup on Opera (#2865)
if( s.username )
xhr.open(type, s.url, s.async, s.username, s.password);
else
xhr.open(type, s.url, s.async);
// Need an extra try/catch for cross domain requests in Firefox 3
try {
// Set the correct header, if data is being sent
if ( s.data )
xhr.setRequestHeader("Content-Type", s.contentType);
// Set the If-Modified-Since header, if ifModified mode.
if ( s.ifModified )
xhr.setRequestHeader("If-Modified-Since",
jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
// Set header so the called script knows that it's an XMLHttpRequest
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
// Set the Accepts header for the server, depending on the dataType
xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
s.accepts[ s.dataType ] + ", */*" :
s.accepts._default );
} catch(e){}
// Allow custom headers/mimetypes and early abort
if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
// Handle the global AJAX counter
if ( s.global && ! --jQuery.active )
jQuery.event.trigger( "ajaxStop" );
// close opended socket
xhr.abort();
return false;
}
if ( s.global )
jQuery.event.trigger("ajaxSend", [xhr, s]);
// Wait for a response to come back
var onreadystatechange = function(isTimeout){
// The request was aborted, clear the interval and decrement jQuery.active
if (xhr.readyState == 0) {
if (ival) {
// clear poll interval
clearInterval(ival);
ival = null;
// Handle the global AJAX counter
if ( s.global && ! --jQuery.active )
jQuery.event.trigger( "ajaxStop" );
}
// The transfer is complete and the data is available, or the request timed out
} else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
requestDone = true;
// clear poll interval
if (ival) {
clearInterval(ival);
ival = null;
}
status = isTimeout == "timeout" ? "timeout" :
!jQuery.httpSuccess( xhr ) ? "error" :
s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
"success";
if ( status == "success" ) {
// Watch for, and catch, XML document parse errors
try {
// process the data (runs the xml through httpData regardless of callback)
data = jQuery.httpData( xhr, s.dataType, s );
} catch(e) {
status = "parsererror";
}
}
// Make sure that the request was successful or notmodified
if ( status == "success" ) {
// Cache Last-Modified header, if ifModified mode.
var modRes;
try {
modRes = xhr.getResponseHeader("Last-Modified");
} catch(e) {} // swallow exception thrown by FF if header is not available
if ( s.ifModified && modRes )
jQuery.lastModified[s.url] = modRes;
// JSONP handles its own success callback
if ( !jsonp )
success();
} else
jQuery.handleError(s, xhr, status);
// Fire the complete handlers
complete();
if ( isTimeout )
xhr.abort();
// Stop memory leaks
if ( s.async )
xhr = null;
}
};
if ( s.async ) {
// don't attach the handler to the request, just poll it instead
var ival = setInterval(onreadystatechange, 13);
// Timeout checker
if ( s.timeout > 0 )
setTimeout(function(){
// Check to see if the request is still happening
if ( xhr && !requestDone )
onreadystatechange( "timeout" );
}, s.timeout);
}
// Send the data
try {
xhr.send(s.data);
} catch(e) {
jQuery.handleError(s, xhr, null, e);
}
// firefox 1.5 doesn't fire statechange for sync requests
if ( !s.async )
onreadystatechange();
function success(){
// If a local callback was specified, fire it and pass it the data
if ( s.success )
s.success( data, status );
// Fire the global callback
if ( s.global )
jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
}
function complete(){
// Process result
if ( s.complete )
s.complete(xhr, status);
// The request was completed
if ( s.global )
jQuery.event.trigger( "ajaxComplete", [xhr, s] );
// Handle the global AJAX counter
if ( s.global && ! --jQuery.active )
jQuery.event.trigger( "ajaxStop" );
}
// return XMLHttpRequest to allow aborting the request etc.
return xhr;
},
handleError: function( s, xhr, status, e ) {
// If a local callback was specified, fire it
if ( s.error ) s.error( xhr, status, e );
// Fire the global callback
if ( s.global )
jQuery.event.trigger( "ajaxError", [xhr, s, e] );
},
// Counter for holding the number of active queries
active: 0,
// Determines if an XMLHttpRequest was successful or not
httpSuccess: function( xhr ) {
try {
// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
return !xhr.status && location.protocol == "file:" ||
( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
} catch(e){}
return false;
},
// Determines if an XMLHttpRequest returns NotModified
httpNotModified: function( xhr, url ) {
try {
var xhrRes = xhr.getResponseHeader("Last-Modified");
// Firefox always returns 200. check Last-Modified date
return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
} catch(e){}
return false;
},
httpData: function( xhr, type, s ) {
var ct = xhr.getResponseHeader("content-type"),
xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
data = xml ? xhr.responseXML : xhr.responseText;
if ( xml && data.documentElement.tagName == "parsererror" )
throw "parsererror";
// Allow a pre-filtering function to sanitize the response
// s != null is checked to keep backwards compatibility
if( s && s.dataFilter )
data = s.dataFilter( data, type );
// The filter can actually parse the response
if( typeof data === "string" ){
// If the type is "script", eval it in global context
if ( type == "script" )
jQuery.globalEval( data );
// Get the JavaScript object, if JSON is used.
if ( type == "json" )
data = window["eval"]("(" + data + ")");
}
return data;
},
// Serialize an array of form elements or a set of
// key/values into a query string
param: function( a ) {
var s = [ ];
function add( key, value ){
s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
};
// If an array was passed in, assume that it is an array
// of form elements
if ( jQuery.isArray(a) || a.jquery )
// Serialize the form elements
jQuery.each( a, function(){
add( this.name, this.value );
});
// Otherwise, assume that it's an object of key/value pairs
else
// Serialize the key/values
for ( var j in a )
// If the value is an array then the key names need to be repeated
if ( jQuery.isArray(a[j]) )
jQuery.each( a[j], function(){
add( j, this );
});
else
add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
// Return the resulting serialization
return s.join("&").replace(/%20/g, "+");
}
});
var elemdisplay = {},
timerId,
fxAttrs = [
// height animations
[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
// width animations
[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
// opacity animations
[ "opacity" ]
];
function genFx( type, num ){
var obj = {};
jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
obj[ this ] = type;
});
return obj;
}
jQuery.fn.extend({
show: function(speed,callback){
if ( speed ) {
return this.animate( genFx("show", 3), speed, callback);
} else {
for ( var i = 0, l = this.length; i < l; i++ ){
var old = jQuery.data(this[i], "olddisplay");
this[i].style.display = old || "";
if ( jQuery.css(this[i], "display") === "none" ) {
var tagName = this[i].tagName, display;
if ( elemdisplay[ tagName ] ) {
display = elemdisplay[ tagName ];
} else {
var elem = jQuery("<" + tagName + " />").appendTo("body");
display = elem.css("display");
if ( display === "none" )
display = "block";
elem.remove();
elemdisplay[ tagName ] = display;
}
jQuery.data(this[i], "olddisplay", display);
}
}
// Set the display of the elements in a second loop
// to avoid the constant reflow
for ( var i = 0, l = this.length; i < l; i++ ){
this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
}
return this;
}
},
hide: function(speed,callback){
if ( speed ) {
return this.animate( genFx("hide", 3), speed, callback);
} else {
for ( var i = 0, l = this.length; i < l; i++ ){
var old = jQuery.data(this[i], "olddisplay");
if ( !old && old !== "none" )
jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
}
// Set the display of the elements in a second loop
// to avoid the constant reflow
for ( var i = 0, l = this.length; i < l; i++ ){
this[i].style.display = "none";
}
return this;
}
},
// Save the old toggle function
_toggle: jQuery.fn.toggle,
toggle: function( fn, fn2 ){
var bool = typeof fn === "boolean";
return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
this._toggle.apply( this, arguments ) :
fn == null || bool ?
this.each(function(){
var state = bool ? fn : jQuery(this).is(":hidden");
jQuery(this)[ state ? "show" : "hide" ]();
}) :
this.animate(genFx("toggle", 3), fn, fn2);
},
fadeTo: function(speed,to,callback){
return this.animate({opacity: to}, speed, callback);
},
animate: function( prop, speed, easing, callback ) {
var optall = jQuery.speed(speed, easing, callback);
return this[ optall.queue === false ? "each" : "queue" ](function(){
var opt = jQuery.extend({}, optall), p,
hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
self = this;
for ( p in prop ) {
if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
return opt.complete.call(this);
if ( ( p == "height" || p == "width" ) && this.style ) {
// Store display property
opt.display = jQuery.css(this, "display");
// Make sure that nothing sneaks out
opt.overflow = this.style.overflow;
}
}
if ( opt.overflow != null )
this.style.overflow = "hidden";
opt.curAnim = jQuery.extend({}, prop);
jQuery.each( prop, function(name, val){
var e = new jQuery.fx( self, opt, name );
if ( /toggle|show|hide/.test(val) )
e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
else {
var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
start = e.cur(true) || 0;
if ( parts ) {
var end = parseFloat(parts[2]),
unit = parts[3] || "px";
// We need to compute starting value
if ( unit != "px" ) {
self.style[ name ] = (end || 1) + unit;
start = ((end || 1) / e.cur(true)) * start;
self.style[ name ] = start + unit;
}
// If a +=/-= token was provided, we're doing a relative animation
if ( parts[1] )
end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
e.custom( start, end, unit );
} else
e.custom( start, val, "" );
}
});
// For JS strict compliance
return true;
});
},
stop: function(clearQueue, gotoEnd){
var timers = jQuery.timers;
if (clearQueue)
this.queue([]);
this.each(function(){
// go in reverse order so anything added to the queue during the loop is ignored
for ( var i = timers.length - 1; i >= 0; i-- )
if ( timers[i].elem == this ) {
if (gotoEnd)
// force the next step to be the last
timers[i](true);
timers.splice(i, 1);
}
});
// start the next in the queue if the last step wasn't forced
if (!gotoEnd)
this.dequeue();
return this;
}
});
// Generate shortcuts for custom animations
jQuery.each({
slideDown: genFx("show", 1),
slideUp: genFx("hide", 1),
slideToggle: genFx("toggle", 1),
fadeIn: { opacity: "show" },
fadeOut: { opacity: "hide" }
}, function( name, props ){
jQuery.fn[ name ] = function( speed, callback ){
return this.animate( props, speed, callback );
};
});
jQuery.extend({
speed: function(speed, easing, fn) {
var opt = typeof speed === "object" ? speed : {
complete: fn || !fn && easing ||
jQuery.isFunction( speed ) && speed,
duration: speed,
easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
};
opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
// Queueing
opt.old = opt.complete;
opt.complete = function(){
if ( opt.queue !== false )
jQuery(this).dequeue();
if ( jQuery.isFunction( opt.old ) )
opt.old.call( this );
};
return opt;
},
easing: {
linear: function( p, n, firstNum, diff ) {
return firstNum + diff * p;
},
swing: function( p, n, firstNum, diff ) {
return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
}
},
timers: [],
fx: function( elem, options, prop ){
this.options = options;
this.elem = elem;
this.prop = prop;
if ( !options.orig )
options.orig = {};
}
});
jQuery.fx.prototype = {
// Simple function for setting a style value
update: function(){
if ( this.options.step )
this.options.step.call( this.elem, this.now, this );
(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
// Set display property to block for height/width animations
if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
this.elem.style.display = "block";
},
// Get the current size
cur: function(force){
if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
return this.elem[ this.prop ];
var r = parseFloat(jQuery.css(this.elem, this.prop, force));
return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
},
// Start an animation from one number to another
custom: function(from, to, unit){
this.startTime = now();
this.start = from;
this.end = to;
this.unit = unit || this.unit || "px";
this.now = this.start;
this.pos = this.state = 0;
var self = this;
function t(gotoEnd){
return self.step(gotoEnd);
}
t.elem = this.elem;
if ( t() && jQuery.timers.push(t) && !timerId ) {
timerId = setInterval(function(){
var timers = jQuery.timers;
for ( var i = 0; i < timers.length; i++ )
if ( !timers[i]() )
timers.splice(i--, 1);
if ( !timers.length ) {
clearInterval( timerId );
timerId = undefined;
}
}, 13);
}
},
// Simple 'show' function
show: function(){
// Remember where we started, so that we can go back to it later
this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
this.options.show = true;
// Begin the animation
// Make sure that we start at a small width/height to avoid any
// flash of content
this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
// Start by showing the element
jQuery(this.elem).show();
},
// Simple 'hide' function
hide: function(){
// Remember where we started, so that we can go back to it later
this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
this.options.hide = true;
// Begin the animation
this.custom(this.cur(), 0);
},
// Each step of an animation
step: function(gotoEnd){
var t = now();
if ( gotoEnd || t >= this.options.duration + this.startTime ) {
this.now = this.end;
this.pos = this.state = 1;
this.update();
this.options.curAnim[ this.prop ] = true;
var done = true;
for ( var i in this.options.curAnim )
if ( this.options.curAnim[i] !== true )
done = false;
if ( done ) {
if ( this.options.display != null ) {
// Reset the overflow
this.elem.style.overflow = this.options.overflow;
// Reset the display
this.elem.style.display = this.options.display;
if ( jQuery.css(this.elem, "display") == "none" )
this.elem.style.display = "block";
}
// Hide the element if the "hide" operation was done
if ( this.options.hide )
jQuery(this.elem).hide();
// Reset the properties, if the item has been hidden or shown
if ( this.options.hide || this.options.show )
for ( var p in this.options.curAnim )
jQuery.attr(this.elem.style, p, this.options.orig[p]);
// Execute the complete function
this.options.complete.call( this.elem );
}
return false;
} else {
var n = t - this.startTime;
this.state = n / this.options.duration;
// Perform the easing function, defaults to swing
this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
this.now = this.start + ((this.end - this.start) * this.pos);
// Perform the next step of the animation
this.update();
}
return true;
}
};
jQuery.extend( jQuery.fx, {
speeds:{
slow: 600,
fast: 200,
// Default speed
_default: 400
},
step: {
opacity: function(fx){
jQuery.attr(fx.elem.style, "opacity", fx.now);
},
_default: function(fx){
if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
fx.elem.style[ fx.prop ] = fx.now + fx.unit;
else
fx.elem[ fx.prop ] = fx.now;
}
}
});
if ( document.documentElement["getBoundingClientRect"] )
jQuery.fn.offset = function() {
if ( !this[0] ) return { top: 0, left: 0 };
if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
return { top: top, left: left };
};
else
jQuery.fn.offset = function() {
if ( !this[0] ) return { top: 0, left: 0 };
if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
jQuery.offset.initialized || jQuery.offset.initialize();
var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
body = doc.body, defaultView = doc.defaultView,
prevComputedStyle = defaultView.getComputedStyle(elem, null),
top = elem.offsetTop, left = elem.offsetLeft;
while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
computedStyle = defaultView.getComputedStyle(elem, null);
top -= elem.scrollTop, left -= elem.scrollLeft;
if ( elem === offsetParent ) {
top += elem.offsetTop, left += elem.offsetLeft;
if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
top += parseInt( computedStyle.borderTopWidth, 10) || 0,
left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
}
if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
top += parseInt( computedStyle.borderTopWidth, 10) || 0,
left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
prevComputedStyle = computedStyle;
}
if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
top += body.offsetTop,
left += body.offsetLeft;
if ( prevComputedStyle.position === "fixed" )
top += Math.max(docElem.scrollTop, body.scrollTop),
left += Math.max(docElem.scrollLeft, body.scrollLeft);
return { top: top, left: left };
};
jQuery.offset = {
initialize: function() {
if ( this.initialized ) return;
var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
for ( prop in rules ) container.style[prop] = rules[prop];
container.innerHTML = html;
body.insertBefore(container, body.firstChild);
innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
body.style.marginTop = '1px';
this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
body.style.marginTop = bodyMarginTop;
body.removeChild(container);
this.initialized = true;
},
bodyOffset: function(body) {
jQuery.offset.initialized || jQuery.offset.initialize();
var top = body.offsetTop, left = body.offsetLeft;
if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0,
left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
return { top: top, left: left };
}
};
jQuery.fn.extend({
position: function() {
var left = 0, top = 0, results;
if ( this[0] ) {
// Get *real* offsetParent
var offsetParent = this.offsetParent(),
// Get correct offsets
offset = this.offset(),
parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
// Subtract element margins
// note: when an element has margin: auto the offsetLeft and marginLeft
// are the same in Safari causing offset.left to incorrectly be 0
offset.top -= num( this, 'marginTop' );
offset.left -= num( this, 'marginLeft' );
// Add offsetParent borders
parentOffset.top += num( offsetParent, 'borderTopWidth' );
parentOffset.left += num( offsetParent, 'borderLeftWidth' );
// Subtract the two offsets
results = {
top: offset.top - parentOffset.top,
left: offset.left - parentOffset.left
};
}
return results;
},
offsetParent: function() {
var offsetParent = this[0].offsetParent || document.body;
while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
offsetParent = offsetParent.offsetParent;
return jQuery(offsetParent);
}
});
// Create scrollLeft and scrollTop methods
jQuery.each( ['Left', 'Top'], function(i, name) {
var method = 'scroll' + name;
jQuery.fn[ method ] = function(val) {
if (!this[0]) return null;
return val !== undefined ?
// Set the scroll offset
this.each(function() {
this == window || this == document ?
window.scrollTo(
!i ? val : jQuery(window).scrollLeft(),
i ? val : jQuery(window).scrollTop()
) :
this[ method ] = val;
}) :
// Return the scroll offset
this[0] == window || this[0] == document ?
self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
jQuery.boxModel && document.documentElement[ method ] ||
document.body[ method ] :
this[0][ method ];
};
});
// Create innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height", "Width" ], function(i, name){
var tl = i ? "Left" : "Top", // top or left
br = i ? "Right" : "Bottom", // bottom or right
lower = name.toLowerCase();
// innerHeight and innerWidth
jQuery.fn["inner" + name] = function(){
return this[0] ?
jQuery.css( this[0], lower, false, "padding" ) :
null;
};
// outerHeight and outerWidth
jQuery.fn["outer" + name] = function(margin) {
return this[0] ?
jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
null;
};
var type = name.toLowerCase();
jQuery.fn[ type ] = function( size ) {
// Get window width or height
return this[0] == window ?
// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
document.body[ "client" + name ] :
// Get document width or height
this[0] == document ?
// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
Math.max(
document.documentElement["client" + name],
document.body["scroll" + name], document.documentElement["scroll" + name],
document.body["offset" + name], document.documentElement["offset" + name]
) :
// Get or set width or height on the element
size === undefined ?
// Get width or height on the element
(this.length ? jQuery.css( this[0], type ) : null) :
// Set the width or height on the element (default to pixels if value is unitless)
this.css( type, typeof size === "string" ? size : size + "px" );
};
});
})();

View File

@ -0,0 +1,8176 @@
/*!
* jQuery JavaScript Library v1.5
* http://jquery.com/
*
* Copyright 2011, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2011, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Mon Jan 31 08:31:29 2011 -0500
*/
(function( window, undefined ) {
// Use the correct document accordingly with window argument (sandbox)
var document = window.document;
var jQuery = (function() {
// Define a local copy of jQuery
var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
},
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$,
// A central reference to the root jQuery(document)
rootjQuery,
// A simple way to check for HTML strings or ID strings
// (both of which we optimize for)
quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
// Check if a string has a non-whitespace character in it
rnotwhite = /\S/,
// Used for trimming whitespace
trimLeft = /^\s+/,
trimRight = /\s+$/,
// Check for digits
rdigit = /\d/,
// Match a standalone tag
rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
// JSON RegExp
rvalidchars = /^[\],:{}\s]*$/,
rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
// Useragent RegExp
rwebkit = /(webkit)[ \/]([\w.]+)/,
ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
rmsie = /(msie) ([\w.]+)/,
rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
// Keep a UserAgent string for use with jQuery.browser
userAgent = navigator.userAgent,
// For matching the engine and version of the browser
browserMatch,
// Has the ready events already been bound?
readyBound = false,
// The deferred used on DOM ready
readyList,
// Promise methods
promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
// The ready event handler
DOMContentLoaded,
// Save a reference to some core methods
toString = Object.prototype.toString,
hasOwn = Object.prototype.hasOwnProperty,
push = Array.prototype.push,
slice = Array.prototype.slice,
trim = String.prototype.trim,
indexOf = Array.prototype.indexOf,
// [[Class]] -> type pairs
class2type = {};
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
var match, elem, ret, doc;
// Handle $(""), $(null), or $(undefined)
if ( !selector ) {
return this;
}
// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
// The body element only exists once, optimize finding it
if ( selector === "body" && !context && document.body ) {
this.context = document;
this[0] = document.body;
this.selector = "body";
this.length = 1;
return this;
}
// Handle HTML strings
if ( typeof selector === "string" ) {
// Are we dealing with HTML string or an ID?
match = quickExpr.exec( selector );
// Verify a match, and that no context was specified for #id
if ( match && (match[1] || !context) ) {
// HANDLE: $(html) -> $(array)
if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
doc = (context ? context.ownerDocument || context : document);
// If a single string is passed in and it's a single tag
// just do a createElement and skip the rest
ret = rsingleTag.exec( selector );
if ( ret ) {
if ( jQuery.isPlainObject( context ) ) {
selector = [ document.createElement( ret[1] ) ];
jQuery.fn.attr.call( selector, context, true );
} else {
selector = [ doc.createElement( ret[1] ) ];
}
} else {
ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
}
return jQuery.merge( this, selector );
// HANDLE: $("#id")
} else {
elem = document.getElementById( match[2] );
// 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[2] ) {
return rootjQuery.find( selector );
}
// Otherwise, we inject the element directly into the jQuery object
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
// HANDLE: $(expr, $(...))
} else if ( !context || context.jquery ) {
return (context || rootjQuery).find( selector );
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
return this.constructor( context ).find( selector );
}
// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
if (selector.selector !== undefined) {
this.selector = selector.selector;
this.context = selector.context;
}
return jQuery.makeArray( selector, this );
},
// Start with an empty selector
selector: "",
// The current version of jQuery being used
jquery: "1.5",
// The default length of a jQuery object is 0
length: 0,
// The number of elements contained in the matched element set
size: function() {
return this.length;
},
toArray: function() {
return slice.call( this, 0 );
},
// Get the Nth element in the matched element set OR
// Get the whole matched element set as a clean array
get: function( num ) {
return num == null ?
// Return a 'clean' array
this.toArray() :
// Return just the object
( num < 0 ? this[ this.length + num ] : this[ num ] );
},
// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
// Build a new jQuery matched element set
var ret = this.constructor();
if ( jQuery.isArray( elems ) ) {
push.apply( ret, elems );
} else {
jQuery.merge( ret, elems );
}
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
if ( name === "find" ) {
ret.selector = this.selector + (this.selector ? " " : "") + selector;
} else if ( name ) {
ret.selector = this.selector + "." + name + "(" + selector + ")";
}
// Return the newly-formed element set
return ret;
},
// Execute a callback for every element in the matched set.
// (You can seed the arguments with an array of args, but this is
// only used internally.)
each: function( callback, args ) {
return jQuery.each( this, callback, args );
},
ready: function( fn ) {
// Attach the listeners
jQuery.bindReady();
// Add the callback
readyList.done( fn );
return this;
},
eq: function( i ) {
return i === -1 ?
this.slice( i ) :
this.slice( i, +i + 1 );
},
first: function() {
return this.eq( 0 );
},
last: function() {
return this.eq( -1 );
},
slice: function() {
return this.pushStack( slice.apply( this, arguments ),
"slice", slice.call(arguments).join(",") );
},
map: function( callback ) {
return this.pushStack( jQuery.map(this, function( elem, i ) {
return callback.call( elem, i, elem );
}));
},
end: function() {
return this.prevObject || this.constructor(null);
},
// For internal use only.
// Behaves like an Array's method, not like a jQuery method.
push: push,
sort: [].sort,
splice: [].splice
};
// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// extend jQuery itself if only one argument is passed
if ( length === i ) {
target = this;
--i;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
jQuery.extend({
noConflict: function( deep ) {
window.$ = _$;
if ( deep ) {
window.jQuery = _jQuery;
}
return jQuery;
},
// Is the DOM ready to be used? Set to true once it occurs.
isReady: false,
// A counter to track how many items to wait for before
// the ready event fires. See #6781
readyWait: 1,
// Handle when the DOM is ready
ready: function( wait ) {
// A third-party is pushing the ready event forwards
if ( wait === true ) {
jQuery.readyWait--;
}
// Make sure that the DOM is not already loaded
if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( !document.body ) {
return setTimeout( jQuery.ready, 1 );
}
// Remember that the DOM is ready
jQuery.isReady = true;
// If a normal DOM Ready event fired, decrement, and wait if need be
if ( wait !== true && --jQuery.readyWait > 0 ) {
return;
}
// If there are functions bound, to execute
readyList.resolveWith( document, [ jQuery ] );
// Trigger any bound ready events
if ( jQuery.fn.trigger ) {
jQuery( document ).trigger( "ready" ).unbind( "ready" );
}
}
},
bindReady: function() {
if ( readyBound ) {
return;
}
readyBound = true;
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
return setTimeout( jQuery.ready, 1 );
}
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window.onload, that will always work
window.addEventListener( "load", jQuery.ready, false );
// If IE event model is used
} else if ( document.attachEvent ) {
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent("onreadystatechange", DOMContentLoaded);
// A fallback to window.onload, that will always work
window.attachEvent( "onload", jQuery.ready );
// If IE and not a frame
// continually check to see if the document is ready
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
},
// See test/unit/core.js for details concerning isFunction.
// Since version 1.3, DOM methods and functions like alert
// aren't supported. They return false on IE (#2968).
isFunction: function( obj ) {
return jQuery.type(obj) === "function";
},
isArray: Array.isArray || function( obj ) {
return jQuery.type(obj) === "array";
},
// A crude way of determining if an object is a window
isWindow: function( obj ) {
return obj && typeof obj === "object" && "setInterval" in obj;
},
isNaN: function( obj ) {
return obj == null || !rdigit.test( obj ) || isNaN( obj );
},
type: function( obj ) {
return obj == null ?
String( obj ) :
class2type[ toString.call(obj) ] || "object";
},
isPlainObject: function( obj ) {
// Must be an Object.
// Because of IE, we also have to check the presence of the constructor property.
// Make sure that DOM nodes and window objects don't pass through, as well
if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
return false;
}
// Not own constructor property must be Object
if ( obj.constructor &&
!hasOwn.call(obj, "constructor") &&
!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for ( key in obj ) {}
return key === undefined || hasOwn.call( obj, key );
},
isEmptyObject: function( obj ) {
for ( var name in obj ) {
return false;
}
return true;
},
error: function( msg ) {
throw msg;
},
parseJSON: function( data ) {
if ( typeof data !== "string" || !data ) {
return null;
}
// Make sure leading/trailing whitespace is removed (IE can't handle it)
data = jQuery.trim( data );
// Make sure the incoming data is actual JSON
// Logic borrowed from http://json.org/json2.js
if ( rvalidchars.test(data.replace(rvalidescape, "@")
.replace(rvalidtokens, "]")
.replace(rvalidbraces, "")) ) {
// Try to use the native JSON parser first
return window.JSON && window.JSON.parse ?
window.JSON.parse( data ) :
(new Function("return " + data))();
} else {
jQuery.error( "Invalid JSON: " + data );
}
},
// Cross-browser xml parsing
// (xml & tmp used internally)
parseXML: function( data , xml , tmp ) {
if ( window.DOMParser ) { // Standard
tmp = new DOMParser();
xml = tmp.parseFromString( data , "text/xml" );
} else { // IE
xml = new ActiveXObject( "Microsoft.XMLDOM" );
xml.async = "false";
xml.loadXML( data );
}
tmp = xml.documentElement;
if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
jQuery.error( "Invalid XML: " + data );
}
return xml;
},
noop: function() {},
// Evalulates a script in a global context
globalEval: function( data ) {
if ( data && rnotwhite.test(data) ) {
// Inspired by code by Andrea Giammarchi
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
var head = document.getElementsByTagName("head")[0] || document.documentElement,
script = document.createElement("script");
script.type = "text/javascript";
if ( jQuery.support.scriptEval() ) {
script.appendChild( document.createTextNode( data ) );
} else {
script.text = data;
}
// Use insertBefore instead of appendChild to circumvent an IE6 bug.
// This arises when a base node is used (#2709).
head.insertBefore( script, head.firstChild );
head.removeChild( script );
}
},
nodeName: function( elem, name ) {
return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
},
// args is for internal usage only
each: function( object, callback, args ) {
var name, i = 0,
length = object.length,
isObj = length === undefined || jQuery.isFunction(object);
if ( args ) {
if ( isObj ) {
for ( name in object ) {
if ( callback.apply( object[ name ], args ) === false ) {
break;
}
}
} else {
for ( ; i < length; ) {
if ( callback.apply( object[ i++ ], args ) === false ) {
break;
}
}
}
// A special, fast, case for the most common use of each
} else {
if ( isObj ) {
for ( name in object ) {
if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
break;
}
}
} else {
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
}
}
return object;
},
// Use native String.trim function wherever possible
trim: trim ?
function( text ) {
return text == null ?
"" :
trim.call( text );
} :
// Otherwise use our own trimming functionality
function( text ) {
return text == null ?
"" :
text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
},
// results is for internal usage only
makeArray: function( array, results ) {
var ret = results || [];
if ( array != null ) {
// The window, strings (and functions) also have 'length'
// The extra typeof function check is to prevent crashes
// in Safari 2 (See: #3039)
// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
var type = jQuery.type(array);
if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
push.call( ret, array );
} else {
jQuery.merge( ret, array );
}
}
return ret;
},
inArray: function( elem, array ) {
if ( array.indexOf ) {
return array.indexOf( elem );
}
for ( var i = 0, length = array.length; i < length; i++ ) {
if ( array[ i ] === elem ) {
return i;
}
}
return -1;
},
merge: function( first, second ) {
var i = first.length,
j = 0;
if ( typeof second.length === "number" ) {
for ( var l = second.length; j < l; j++ ) {
first[ i++ ] = second[ j ];
}
} else {
while ( second[j] !== undefined ) {
first[ i++ ] = second[ j++ ];
}
}
first.length = i;
return first;
},
grep: function( elems, callback, inv ) {
var ret = [], retVal;
inv = !!inv;
// Go through the array, only saving the items
// that pass the validator function
for ( var i = 0, length = elems.length; i < length; i++ ) {
retVal = !!callback( elems[ i ], i );
if ( inv !== retVal ) {
ret.push( elems[ i ] );
}
}
return ret;
},
// arg is for internal usage only
map: function( elems, callback, arg ) {
var ret = [], value;
// Go through the array, translating each of the items to their
// new value (or values).
for ( var i = 0, length = elems.length; i < length; i++ ) {
value = callback( elems[ i ], i, arg );
if ( value != null ) {
ret[ ret.length ] = value;
}
}
// Flatten any nested arrays
return ret.concat.apply( [], ret );
},
// A global GUID counter for objects
guid: 1,
proxy: function( fn, proxy, thisObject ) {
if ( arguments.length === 2 ) {
if ( typeof proxy === "string" ) {
thisObject = fn;
fn = thisObject[ proxy ];
proxy = undefined;
} else if ( proxy && !jQuery.isFunction( proxy ) ) {
thisObject = proxy;
proxy = undefined;
}
}
if ( !proxy && fn ) {
proxy = function() {
return fn.apply( thisObject || this, arguments );
};
}
// Set the guid of unique handler to the same of original handler, so it can be removed
if ( fn ) {
proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
}
// So proxy can be declared as an argument
return proxy;
},
// Mutifunctional method to get and set values to a collection
// The value/s can be optionally by executed if its a function
access: function( elems, key, value, exec, fn, pass ) {
var length = elems.length;
// Setting many attributes
if ( typeof key === "object" ) {
for ( var k in key ) {
jQuery.access( elems, k, key[k], exec, fn, value );
}
return elems;
}
// Setting one attribute
if ( value !== undefined ) {
// Optionally, function values get executed if exec is true
exec = !pass && exec && jQuery.isFunction(value);
for ( var i = 0; i < length; i++ ) {
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
}
return elems;
}
// Getting an attribute
return length ? fn( elems[0], key ) : undefined;
},
now: function() {
return (new Date()).getTime();
},
// Create a simple deferred (one callbacks list)
_Deferred: function() {
var // callbacks list
callbacks = [],
// stored [ context , args ]
fired,
// to avoid firing when already doing so
firing,
// flag to know if the deferred has been cancelled
cancelled,
// the deferred itself
deferred = {
// done( f1, f2, ...)
done: function() {
if ( !cancelled ) {
var args = arguments,
i,
length,
elem,
type,
_fired;
if ( fired ) {
_fired = fired;
fired = 0;
}
for ( i = 0, length = args.length; i < length; i++ ) {
elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
deferred.done.apply( deferred, elem );
} else if ( type === "function" ) {
callbacks.push( elem );
}
}
if ( _fired ) {
deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
}
}
return this;
},
// resolve with given context and args
resolveWith: function( context, args ) {
if ( !cancelled && !fired && !firing ) {
firing = 1;
try {
while( callbacks[ 0 ] ) {
callbacks.shift().apply( context, args );
}
}
finally {
fired = [ context, args ];
firing = 0;
}
}
return this;
},
// resolve with this as context and given arguments
resolve: function() {
deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments );
return this;
},
// Has this deferred been resolved?
isResolved: function() {
return !!( firing || fired );
},
// Cancel
cancel: function() {
cancelled = 1;
callbacks = [];
return this;
}
};
return deferred;
},
// Full fledged deferred (two callbacks list)
Deferred: function( func ) {
var deferred = jQuery._Deferred(),
failDeferred = jQuery._Deferred(),
promise;
// Add errorDeferred methods, then and promise
jQuery.extend( deferred, {
then: function( doneCallbacks, failCallbacks ) {
deferred.done( doneCallbacks ).fail( failCallbacks );
return this;
},
fail: failDeferred.done,
rejectWith: failDeferred.resolveWith,
reject: failDeferred.resolve,
isRejected: failDeferred.isResolved,
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj , i /* internal */ ) {
if ( obj == null ) {
if ( promise ) {
return promise;
}
promise = obj = {};
}
i = promiseMethods.length;
while( i-- ) {
obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ];
}
return obj;
}
} );
// Make sure only one callback list will be used
deferred.then( failDeferred.cancel, deferred.cancel );
// Unexpose cancel
delete deferred.cancel;
// Call given func if any
if ( func ) {
func.call( deferred, deferred );
}
return deferred;
},
// Deferred helper
when: function( object ) {
var args = arguments,
length = args.length,
deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ?
object :
jQuery.Deferred(),
promise = deferred.promise(),
resolveArray;
if ( length > 1 ) {
resolveArray = new Array( length );
jQuery.each( args, function( index, element ) {
jQuery.when( element ).then( function( value ) {
resolveArray[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value;
if( ! --length ) {
deferred.resolveWith( promise, resolveArray );
}
}, deferred.reject );
} );
} else if ( deferred !== object ) {
deferred.resolve( object );
}
return promise;
},
// Use of jQuery.browser is frowned upon.
// More details: http://docs.jquery.com/Utilities/jQuery.browser
uaMatch: function( ua ) {
ua = ua.toLowerCase();
var match = rwebkit.exec( ua ) ||
ropera.exec( ua ) ||
rmsie.exec( ua ) ||
ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
[];
return { browser: match[1] || "", version: match[2] || "0" };
},
sub: function() {
function jQuerySubclass( selector, context ) {
return new jQuerySubclass.fn.init( selector, context );
}
jQuery.extend( true, jQuerySubclass, this );
jQuerySubclass.superclass = this;
jQuerySubclass.fn = jQuerySubclass.prototype = this();
jQuerySubclass.fn.constructor = jQuerySubclass;
jQuerySubclass.subclass = this.subclass;
jQuerySubclass.fn.init = function init( selector, context ) {
if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) {
context = jQuerySubclass(context);
}
return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass );
};
jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;
var rootjQuerySubclass = jQuerySubclass(document);
return jQuerySubclass;
},
browser: {}
});
// Create readyList deferred
readyList = jQuery._Deferred();
// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
browserMatch = jQuery.uaMatch( userAgent );
if ( browserMatch.browser ) {
jQuery.browser[ browserMatch.browser ] = true;
jQuery.browser.version = browserMatch.version;
}
// Deprecated, use jQuery.browser.webkit instead
if ( jQuery.browser.webkit ) {
jQuery.browser.safari = true;
}
if ( indexOf ) {
jQuery.inArray = function( elem, array ) {
return indexOf.call( array, elem );
};
}
// IE doesn't match non-breaking spaces with \s
if ( rnotwhite.test( "\xA0" ) ) {
trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/;
}
// All jQuery objects should point back to these
rootjQuery = jQuery(document);
// Cleanup functions for the document ready method
if ( document.addEventListener ) {
DOMContentLoaded = function() {
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
jQuery.ready();
};
} else if ( document.attachEvent ) {
DOMContentLoaded = function() {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", DOMContentLoaded );
jQuery.ready();
}
};
}
// The DOM ready check for Internet Explorer
function doScrollCheck() {
if ( jQuery.isReady ) {
return;
}
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
}
// and execute any waiting functions
jQuery.ready();
}
// Expose jQuery to the global object
return (window.jQuery = window.$ = jQuery);
})();
(function() {
jQuery.support = {};
var div = document.createElement("div");
div.style.display = "none";
div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var all = div.getElementsByTagName("*"),
a = div.getElementsByTagName("a")[0],
select = document.createElement("select"),
opt = select.appendChild( document.createElement("option") );
// Can't get basic test support
if ( !all || !all.length || !a ) {
return;
}
jQuery.support = {
// IE strips leading whitespace when .innerHTML is used
leadingWhitespace: div.firstChild.nodeType === 3,
// Make sure that tbody elements aren't automatically inserted
// IE will insert them into empty tables
tbody: !div.getElementsByTagName("tbody").length,
// Make sure that link elements get serialized correctly by innerHTML
// This requires a wrapper element in IE
htmlSerialize: !!div.getElementsByTagName("link").length,
// Get the style information from getAttribute
// (IE uses .cssText insted)
style: /red/.test( a.getAttribute("style") ),
// Make sure that URLs aren't manipulated
// (IE normalizes it by default)
hrefNormalized: a.getAttribute("href") === "/a",
// Make sure that element opacity exists
// (IE uses filter instead)
// Use a regex to work around a WebKit issue. See #5145
opacity: /^0.55$/.test( a.style.opacity ),
// Verify style float existence
// (IE uses styleFloat instead of cssFloat)
cssFloat: !!a.style.cssFloat,
// Make sure that if no value is specified for a checkbox
// that it defaults to "on".
// (WebKit defaults to "" instead)
checkOn: div.getElementsByTagName("input")[0].value === "on",
// Make sure that a selected-by-default option has a working selected property.
// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
optSelected: opt.selected,
// Will be defined later
deleteExpando: true,
optDisabled: false,
checkClone: false,
_scriptEval: null,
noCloneEvent: true,
boxModel: null,
inlineBlockNeedsLayout: false,
shrinkWrapBlocks: false,
reliableHiddenOffsets: true
};
// Make sure that the options inside disabled selects aren't marked as disabled
// (WebKit marks them as diabled)
select.disabled = true;
jQuery.support.optDisabled = !opt.disabled;
jQuery.support.scriptEval = function() {
if ( jQuery.support._scriptEval === null ) {
var root = document.documentElement,
script = document.createElement("script"),
id = "script" + jQuery.now();
script.type = "text/javascript";
try {
script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
} catch(e) {}
root.insertBefore( script, root.firstChild );
// Make sure that the execution of code works by injecting a script
// tag with appendChild/createTextNode
// (IE doesn't support this, fails, and uses .text instead)
if ( window[ id ] ) {
jQuery.support._scriptEval = true;
delete window[ id ];
} else {
jQuery.support._scriptEval = false;
}
root.removeChild( script );
// release memory in IE
root = script = id = null;
}
return jQuery.support._scriptEval;
};
// Test to see if it's possible to delete an expando from an element
// Fails in Internet Explorer
try {
delete div.test;
} catch(e) {
jQuery.support.deleteExpando = false;
}
if ( div.attachEvent && div.fireEvent ) {
div.attachEvent("onclick", function click() {
// Cloning a node shouldn't copy over any
// bound event handlers (IE does this)
jQuery.support.noCloneEvent = false;
div.detachEvent("onclick", click);
});
div.cloneNode(true).fireEvent("onclick");
}
div = document.createElement("div");
div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
var fragment = document.createDocumentFragment();
fragment.appendChild( div.firstChild );
// WebKit doesn't clone checked state correctly in fragments
jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
// Figure out if the W3C box model works as expected
// document.body must exist before we can do this
jQuery(function() {
var div = document.createElement("div"),
body = document.getElementsByTagName("body")[0];
// Frameset documents with no body should not run this code
if ( !body ) {
return;
}
div.style.width = div.style.paddingLeft = "1px";
body.appendChild( div );
jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
if ( "zoom" in div.style ) {
// Check if natively block-level elements act like inline-block
// elements when setting their display to 'inline' and giving
// them layout
// (IE < 8 does this)
div.style.display = "inline";
div.style.zoom = 1;
jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;
// Check if elements with layout shrink-wrap their children
// (IE 6 does this)
div.style.display = "";
div.innerHTML = "<div style='width:4px;'></div>";
jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
}
div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
var tds = div.getElementsByTagName("td");
// Check if table cells still have offsetWidth/Height when they are set
// to display:none and there are still other visible table cells in a
// table row; if so, offsetWidth/Height are not reliable for use when
// determining if an element has been hidden directly using
// display:none (it is still safe to use offsets if a parent element is
// hidden; don safety goggles and see bug #4512 for more information).
// (only IE 8 fails this test)
jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;
tds[0].style.display = "";
tds[1].style.display = "none";
// Check if empty table cells still have offsetWidth/Height
// (IE < 8 fail this test)
jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
div.innerHTML = "";
body.removeChild( div ).style.display = "none";
div = tds = null;
});
// Technique from Juriy Zaytsev
// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
var eventSupported = function( eventName ) {
var el = document.createElement("div");
eventName = "on" + eventName;
// We only care about the case where non-standard event systems
// are used, namely in IE. Short-circuiting here helps us to
// avoid an eval call (in setAttribute) which can cause CSP
// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
if ( !el.attachEvent ) {
return true;
}
var isSupported = (eventName in el);
if ( !isSupported ) {
el.setAttribute(eventName, "return;");
isSupported = typeof el[eventName] === "function";
}
el = null;
return isSupported;
};
jQuery.support.submitBubbles = eventSupported("submit");
jQuery.support.changeBubbles = eventSupported("change");
// release memory in IE
div = all = a = null;
})();
var rbrace = /^(?:\{.*\}|\[.*\])$/;
jQuery.extend({
cache: {},
// Please use with caution
uuid: 0,
// Unique for each copy of jQuery on the page
// Non-digits removed to match rinlinejQuery
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
// The following elements throw uncatchable exceptions if you
// attempt to add expando properties to them.
noData: {
"embed": true,
// Ban all objects except for Flash (which handle expandos)
"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
"applet": true
},
hasData: function( elem ) {
elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
return !!elem && !jQuery.isEmptyObject(elem);
},
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) {
return;
}
var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
// We have to handle DOM nodes and JS objects differently because IE6-7
// can't GC object references properly across the DOM-JS boundary
isNode = elem.nodeType,
// Only DOM nodes need the global jQuery cache; JS object data is
// attached directly to the object so GC can occur automatically
cache = isNode ? jQuery.cache : elem,
// Only defining an ID for JS objects if its cache already exists allows
// the code to shortcut on the same path as a DOM node with no cache
id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
// Avoid doing any more work than we need to when trying to get data on an
// object that has no data at all
if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
return;
}
if ( !id ) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if ( isNode ) {
elem[ jQuery.expando ] = id = ++jQuery.uuid;
} else {
id = jQuery.expando;
}
}
if ( !cache[ id ] ) {
cache[ id ] = {};
}
// An object can be passed to jQuery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache
if ( typeof name === "object" ) {
if ( pvt ) {
cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
} else {
cache[ id ] = jQuery.extend(cache[ id ], name);
}
}
thisCache = cache[ id ];
// Internal jQuery data is stored in a separate object inside the object's data
// cache in order to avoid key collisions between internal data and user-defined
// data
if ( pvt ) {
if ( !thisCache[ internalKey ] ) {
thisCache[ internalKey ] = {};
}
thisCache = thisCache[ internalKey ];
}
if ( data !== undefined ) {
thisCache[ name ] = data;
}
// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
// not attempt to inspect the internal events object using jQuery.data, as this
// internal data object is undocumented and subject to change.
if ( name === "events" && !thisCache[name] ) {
return thisCache[ internalKey ] && thisCache[ internalKey ].events;
}
return getByName ? thisCache[ name ] : thisCache;
},
removeData: function( elem, name, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) {
return;
}
var internalKey = jQuery.expando, isNode = elem.nodeType,
// See jQuery.data for more information
cache = isNode ? jQuery.cache : elem,
// See jQuery.data for more information
id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
// If there is already no cache entry for this object, there is no
// purpose in continuing
if ( !cache[ id ] ) {
return;
}
if ( name ) {
var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
if ( thisCache ) {
delete thisCache[ name ];
// If there is no data left in the cache, we want to continue
// and let the cache object itself get destroyed
if ( !jQuery.isEmptyObject(thisCache) ) {
return;
}
}
}
// See jQuery.data for more information
if ( pvt ) {
delete cache[ id ][ internalKey ];
// Don't destroy the parent cache unless the internal data object
// had been the only thing left in it
if ( !jQuery.isEmptyObject(cache[ id ]) ) {
return;
}
}
var internalCache = cache[ id ][ internalKey ];
// Browsers that fail expando deletion also refuse to delete expandos on
// the window, but it will allow it on all other JS objects; other browsers
// don't care
if ( jQuery.support.deleteExpando || cache != window ) {
delete cache[ id ];
} else {
cache[ id ] = null;
}
// We destroyed the entire user cache at once because it's faster than
// iterating through each key, but we need to continue to persist internal
// data if it existed
if ( internalCache ) {
cache[ id ] = {};
cache[ id ][ internalKey ] = internalCache;
// Otherwise, we need to eliminate the expando on the node to avoid
// false lookups in the cache for entries that no longer exist
} else if ( isNode ) {
// IE does not allow us to delete expando properties from nodes,
// nor does it have a removeAttribute function on Document nodes;
// we must handle all of these cases
if ( jQuery.support.deleteExpando ) {
delete elem[ jQuery.expando ];
} else if ( elem.removeAttribute ) {
elem.removeAttribute( jQuery.expando );
} else {
elem[ jQuery.expando ] = null;
}
}
},
// For internal use only.
_data: function( elem, name, data ) {
return jQuery.data( elem, name, data, true );
},
// A method for determining if a DOM node can handle the data expando
acceptData: function( elem ) {
if ( elem.nodeName ) {
var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
if ( match ) {
return !(match === true || elem.getAttribute("classid") !== match);
}
}
return true;
}
});
jQuery.fn.extend({
data: function( key, value ) {
var data = null;
if ( typeof key === "undefined" ) {
if ( this.length ) {
data = jQuery.data( this[0] );
if ( this[0].nodeType === 1 ) {
var attr = this[0].attributes, name;
for ( var i = 0, l = attr.length; i < l; i++ ) {
name = attr[i].name;
if ( name.indexOf( "data-" ) === 0 ) {
name = name.substr( 5 );
dataAttr( this[0], name, data[ name ] );
}
}
}
}
return data;
} else if ( typeof key === "object" ) {
return this.each(function() {
jQuery.data( this, key );
});
}
var parts = key.split(".");
parts[1] = parts[1] ? "." + parts[1] : "";
if ( value === undefined ) {
data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
// Try to fetch any internally stored data first
if ( data === undefined && this.length ) {
data = jQuery.data( this[0], key );
data = dataAttr( this[0], key, data );
}
return data === undefined && parts[1] ?
this.data( parts[0] ) :
data;
} else {
return this.each(function() {
var $this = jQuery( this ),
args = [ parts[0], value ];
$this.triggerHandler( "setData" + parts[1] + "!", args );
jQuery.data( this, key, value );
$this.triggerHandler( "changeData" + parts[1] + "!", args );
});
}
},
removeData: function( key ) {
return this.each(function() {
jQuery.removeData( this, key );
});
}
});
function dataAttr( elem, key, data ) {
// If nothing was found internally, try to fetch any
// data from the HTML5 data-* attribute
if ( data === undefined && elem.nodeType === 1 ) {
data = elem.getAttribute( "data-" + key );
if ( typeof data === "string" ) {
try {
data = data === "true" ? true :
data === "false" ? false :
data === "null" ? null :
!jQuery.isNaN( data ) ? parseFloat( data ) :
rbrace.test( data ) ? jQuery.parseJSON( data ) :
data;
} catch( e ) {}
// Make sure we set the data so it isn't changed later
jQuery.data( elem, key, data );
} else {
data = undefined;
}
}
return data;
}
jQuery.extend({
queue: function( elem, type, data ) {
if ( !elem ) {
return;
}
type = (type || "fx") + "queue";
var q = jQuery._data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup
if ( !data ) {
return q || [];
}
if ( !q || jQuery.isArray(data) ) {
q = jQuery._data( elem, type, jQuery.makeArray(data) );
} else {
q.push( data );
}
return q;
},
dequeue: function( elem, type ) {
type = type || "fx";
var queue = jQuery.queue( elem, type ),
fn = queue.shift();
// If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
if ( type === "fx" ) {
queue.unshift("inprogress");
}
fn.call(elem, function() {
jQuery.dequeue(elem, type);
});
}
if ( !queue.length ) {
jQuery.removeData( elem, type + "queue", true );
}
}
});
jQuery.fn.extend({
queue: function( type, data ) {
if ( typeof type !== "string" ) {
data = type;
type = "fx";
}
if ( data === undefined ) {
return jQuery.queue( this[0], type );
}
return this.each(function( i ) {
var queue = jQuery.queue( this, type, data );
if ( type === "fx" && queue[0] !== "inprogress" ) {
jQuery.dequeue( this, type );
}
});
},
dequeue: function( type ) {
return this.each(function() {
jQuery.dequeue( this, type );
});
},
// Based off of the plugin by Clint Helfers, with permission.
// http://blindsignals.com/index.php/2009/07/jquery-delay/
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
type = type || "fx";
return this.queue( type, function() {
var elem = this;
setTimeout(function() {
jQuery.dequeue( elem, type );
}, time );
});
},
clearQueue: function( type ) {
return this.queue( type || "fx", [] );
}
});
var rclass = /[\n\t\r]/g,
rspaces = /\s+/,
rreturn = /\r/g,
rspecialurl = /^(?:href|src|style)$/,
rtype = /^(?:button|input)$/i,
rfocusable = /^(?:button|input|object|select|textarea)$/i,
rclickable = /^a(?:rea)?$/i,
rradiocheck = /^(?:radio|checkbox)$/i;
jQuery.props = {
"for": "htmlFor",
"class": "className",
readonly: "readOnly",
maxlength: "maxLength",
cellspacing: "cellSpacing",
rowspan: "rowSpan",
colspan: "colSpan",
tabindex: "tabIndex",
usemap: "useMap",
frameborder: "frameBorder"
};
jQuery.fn.extend({
attr: function( name, value ) {
return jQuery.access( this, name, value, true, jQuery.attr );
},
removeAttr: function( name, fn ) {
return this.each(function(){
jQuery.attr( this, name, "" );
if ( this.nodeType === 1 ) {
this.removeAttribute( name );
}
});
},
addClass: function( value ) {
if ( jQuery.isFunction(value) ) {
return this.each(function(i) {
var self = jQuery(this);
self.addClass( value.call(this, i, self.attr("class")) );
});
}
if ( value && typeof value === "string" ) {
var classNames = (value || "").split( rspaces );
for ( var i = 0, l = this.length; i < l; i++ ) {
var elem = this[i];
if ( elem.nodeType === 1 ) {
if ( !elem.className ) {
elem.className = value;
} else {
var className = " " + elem.className + " ",
setClass = elem.className;
for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
setClass += " " + classNames[c];
}
}
elem.className = jQuery.trim( setClass );
}
}
}
}
return this;
},
removeClass: function( value ) {
if ( jQuery.isFunction(value) ) {
return this.each(function(i) {
var self = jQuery(this);
self.removeClass( value.call(this, i, self.attr("class")) );
});
}
if ( (value && typeof value === "string") || value === undefined ) {
var classNames = (value || "").split( rspaces );
for ( var i = 0, l = this.length; i < l; i++ ) {
var elem = this[i];
if ( elem.nodeType === 1 && elem.className ) {
if ( value ) {
var className = (" " + elem.className + " ").replace(rclass, " ");
for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
className = className.replace(" " + classNames[c] + " ", " ");
}
elem.className = jQuery.trim( className );
} else {
elem.className = "";
}
}
}
}
return this;
},
toggleClass: function( value, stateVal ) {
var type = typeof value,
isBool = typeof stateVal === "boolean";
if ( jQuery.isFunction( value ) ) {
return this.each(function(i) {
var self = jQuery(this);
self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
});
}
return this.each(function() {
if ( type === "string" ) {
// toggle individual class names
var className,
i = 0,
self = jQuery( this ),
state = stateVal,
classNames = value.split( rspaces );
while ( (className = classNames[ i++ ]) ) {
// check each className given, space seperated list
state = isBool ? state : !self.hasClass( className );
self[ state ? "addClass" : "removeClass" ]( className );
}
} else if ( type === "undefined" || type === "boolean" ) {
if ( this.className ) {
// store className if set
jQuery._data( this, "__className__", this.className );
}
// toggle whole className
this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
}
});
},
hasClass: function( selector ) {
var className = " " + selector + " ";
for ( var i = 0, l = this.length; i < l; i++ ) {
if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
return true;
}
}
return false;
},
val: function( value ) {
if ( !arguments.length ) {
var elem = this[0];
if ( elem ) {
if ( jQuery.nodeName( elem, "option" ) ) {
// attributes.value is undefined in Blackberry 4.7 but
// uses .value. See #6932
var val = elem.attributes.value;
return !val || val.specified ? elem.value : elem.text;
}
// We need to handle select boxes special
if ( jQuery.nodeName( elem, "select" ) ) {
var index = elem.selectedIndex,
values = [],
options = elem.options,
one = elem.type === "select-one";
// Nothing was selected
if ( index < 0 ) {
return null;
}
// Loop through all the selected options
for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
var option = options[ i ];
// Don't return options that are disabled or in a disabled optgroup
if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
// Get the specific value for the option
value = jQuery(option).val();
// We don't need an array for one selects
if ( one ) {
return value;
}
// Multi-Selects return an array
values.push( value );
}
}
return values;
}
// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
return elem.getAttribute("value") === null ? "on" : elem.value;
}
// Everything else, we just grab the value
return (elem.value || "").replace(rreturn, "");
}
return undefined;
}
var isFunction = jQuery.isFunction(value);
return this.each(function(i) {
var self = jQuery(this), val = value;
if ( this.nodeType !== 1 ) {
return;
}
if ( isFunction ) {
val = value.call(this, i, self.val());
}
// Treat null/undefined as ""; convert numbers to string
if ( val == null ) {
val = "";
} else if ( typeof val === "number" ) {
val += "";
} else if ( jQuery.isArray(val) ) {
val = jQuery.map(val, function (value) {
return value == null ? "" : value + "";
});
}
if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
this.checked = jQuery.inArray( self.val(), val ) >= 0;
} else if ( jQuery.nodeName( this, "select" ) ) {
var values = jQuery.makeArray(val);
jQuery( "option", this ).each(function() {
this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
});
if ( !values.length ) {
this.selectedIndex = -1;
}
} else {
this.value = val;
}
});
}
});
jQuery.extend({
attrFn: {
val: true,
css: true,
html: true,
text: true,
data: true,
width: true,
height: true,
offset: true
},
attr: function( elem, name, value, pass ) {
// don't get/set attributes on text, comment and attribute nodes
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) {
return undefined;
}
if ( pass && name in jQuery.attrFn ) {
return jQuery(elem)[name](value);
}
var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
// Whether we are setting (or getting)
set = value !== undefined;
// Try to normalize/fix the name
name = notxml && jQuery.props[ name ] || name;
// Only do all the following if this is a node (faster for style)
if ( elem.nodeType === 1 ) {
// These attributes require special treatment
var special = rspecialurl.test( name );
// Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
if ( name === "selected" && !jQuery.support.optSelected ) {
var parent = elem.parentNode;
if ( parent ) {
parent.selectedIndex;
// Make sure that it also works with optgroups, see #5701
if ( parent.parentNode ) {
parent.parentNode.selectedIndex;
}
}
}
// If applicable, access the attribute via the DOM 0 way
// 'in' checks fail in Blackberry 4.7 #6931
if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) {
if ( set ) {
// We can't allow the type property to be changed (since it causes problems in IE)
if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
jQuery.error( "type property can't be changed" );
}
if ( value === null ) {
if ( elem.nodeType === 1 ) {
elem.removeAttribute( name );
}
} else {
elem[ name ] = value;
}
}
// browsers index elements by id/name on forms, give priority to attributes.
if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
return elem.getAttributeNode( name ).nodeValue;
}
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
if ( name === "tabIndex" ) {
var attributeNode = elem.getAttributeNode( "tabIndex" );
return attributeNode && attributeNode.specified ?
attributeNode.value :
rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
0 :
undefined;
}
return elem[ name ];
}
if ( !jQuery.support.style && notxml && name === "style" ) {
if ( set ) {
elem.style.cssText = "" + value;
}
return elem.style.cssText;
}
if ( set ) {
// convert the value to a string (all browsers do this but IE) see #1070
elem.setAttribute( name, "" + value );
}
// Ensure that missing attributes return undefined
// Blackberry 4.7 returns "" from getAttribute #6938
if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {
return undefined;
}
var attr = !jQuery.support.hrefNormalized && notxml && special ?
// Some attributes require a special call on IE
elem.getAttribute( name, 2 ) :
elem.getAttribute( name );
// Non-existent attributes return null, we normalize to undefined
return attr === null ? undefined : attr;
}
// Handle everything which isn't a DOM element node
if ( set ) {
elem[ name ] = value;
}
return elem[ name ];
}
});
var rnamespaces = /\.(.*)$/,
rformElems = /^(?:textarea|input|select)$/i,
rperiod = /\./g,
rspace = / /g,
rescape = /[^\w\s.|`]/g,
fcleanup = function( nm ) {
return nm.replace(rescape, "\\$&");
},
eventKey = "events";
/*
* A number of helper functions used for managing events.
* Many of the ideas behind this code originated from
* Dean Edwards' addEvent library.
*/
jQuery.event = {
// Bind an event to an element
// Original by Dean Edwards
add: function( elem, types, handler, data ) {
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return;
}
// For whatever reason, IE has trouble passing the window object
// around, causing it to be cloned in the process
if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
elem = window;
}
if ( handler === false ) {
handler = returnFalse;
} else if ( !handler ) {
// Fixes bug #7229. Fix recommended by jdalton
return;
}
var handleObjIn, handleObj;
if ( handler.handler ) {
handleObjIn = handler;
handler = handleObjIn.handler;
}
// Make sure that the function being executed has a unique ID
if ( !handler.guid ) {
handler.guid = jQuery.guid++;
}
// Init the element's event structure
var elemData = jQuery._data( elem );
// If no elemData is found then we must be trying to bind to one of the
// banned noData elements
if ( !elemData ) {
return;
}
var events = elemData[ eventKey ],
eventHandle = elemData.handle;
if ( typeof events === "function" ) {
// On plain objects events is a fn that holds the the data
// which prevents this data from being JSON serialized
// the function does not need to be called, it just contains the data
eventHandle = events.handle;
events = events.events;
} else if ( !events ) {
if ( !elem.nodeType ) {
// On plain objects, create a fn that acts as the holder
// of the values to avoid JSON serialization of event data
elemData[ eventKey ] = elemData = function(){};
}
elemData.events = events = {};
}
if ( !eventHandle ) {
elemData.handle = eventHandle = function() {
// Handle the second event of a trigger and when
// an event is called after a page has unloaded
return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
jQuery.event.handle.apply( eventHandle.elem, arguments ) :
undefined;
};
}
// Add elem as a property of the handle function
// This is to prevent a memory leak with non-native events in IE.
eventHandle.elem = elem;
// Handle multiple events separated by a space
// jQuery(...).bind("mouseover mouseout", fn);
types = types.split(" ");
var type, i = 0, namespaces;
while ( (type = types[ i++ ]) ) {
handleObj = handleObjIn ?
jQuery.extend({}, handleObjIn) :
{ handler: handler, data: data };
// Namespaced event handlers
if ( type.indexOf(".") > -1 ) {
namespaces = type.split(".");
type = namespaces.shift();
handleObj.namespace = namespaces.slice(0).sort().join(".");
} else {
namespaces = [];
handleObj.namespace = "";
}
handleObj.type = type;
if ( !handleObj.guid ) {
handleObj.guid = handler.guid;
}
// Get the current list of functions bound to this event
var handlers = events[ type ],
special = jQuery.event.special[ type ] || {};
// Init the event handler queue
if ( !handlers ) {
handlers = events[ type ] = [];
// Check for a special event handler
// Only use addEventListener/attachEvent if the special
// events handler returns false
if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
// Bind the global event handler to the element
if ( elem.addEventListener ) {
elem.addEventListener( type, eventHandle, false );
} else if ( elem.attachEvent ) {
elem.attachEvent( "on" + type, eventHandle );
}
}
}
if ( special.add ) {
special.add.call( elem, handleObj );
if ( !handleObj.handler.guid ) {
handleObj.handler.guid = handler.guid;
}
}
// Add the function to the element's handler list
handlers.push( handleObj );
// Keep track of which events have been used, for global triggering
jQuery.event.global[ type ] = true;
}
// Nullify elem to prevent memory leaks in IE
elem = null;
},
global: {},
// Detach an event or set of events from an element
remove: function( elem, types, handler, pos ) {
// don't do events on text and comment nodes
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return;
}
if ( handler === false ) {
handler = returnFalse;
}
var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
events = elemData && elemData[ eventKey ];
if ( !elemData || !events ) {
return;
}
if ( typeof events === "function" ) {
elemData = events;
events = events.events;
}
// types is actually an event object here
if ( types && types.type ) {
handler = types.handler;
types = types.type;
}
// Unbind all events for the element
if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
types = types || "";
for ( type in events ) {
jQuery.event.remove( elem, type + types );
}
return;
}
// Handle multiple events separated by a space
// jQuery(...).unbind("mouseover mouseout", fn);
types = types.split(" ");
while ( (type = types[ i++ ]) ) {
origType = type;
handleObj = null;
all = type.indexOf(".") < 0;
namespaces = [];
if ( !all ) {
// Namespaced event handlers
namespaces = type.split(".");
type = namespaces.shift();
namespace = new RegExp("(^|\\.)" +
jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
}
eventType = events[ type ];
if ( !eventType ) {
continue;
}
if ( !handler ) {
for ( j = 0; j < eventType.length; j++ ) {
handleObj = eventType[ j ];
if ( all || namespace.test( handleObj.namespace ) ) {
jQuery.event.remove( elem, origType, handleObj.handler, j );
eventType.splice( j--, 1 );
}
}
continue;
}
special = jQuery.event.special[ type ] || {};
for ( j = pos || 0; j < eventType.length; j++ ) {
handleObj = eventType[ j ];
if ( handler.guid === handleObj.guid ) {
// remove the given handler for the given type
if ( all || namespace.test( handleObj.namespace ) ) {
if ( pos == null ) {
eventType.splice( j--, 1 );
}
if ( special.remove ) {
special.remove.call( elem, handleObj );
}
}
if ( pos != null ) {
break;
}
}
}
// remove generic event handler if no more handlers exist
if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
jQuery.removeEvent( elem, type, elemData.handle );
}
ret = null;
delete events[ type ];
}
}
// Remove the expando if it's no longer used
if ( jQuery.isEmptyObject( events ) ) {
var handle = elemData.handle;
if ( handle ) {
handle.elem = null;
}
delete elemData.events;
delete elemData.handle;
if ( typeof elemData === "function" ) {
jQuery.removeData( elem, eventKey, true );
} else if ( jQuery.isEmptyObject( elemData ) ) {
jQuery.removeData( elem, undefined, true );
}
}
},
// bubbling is internal
trigger: function( event, data, elem /*, bubbling */ ) {
// Event object or event type
var type = event.type || event,
bubbling = arguments[3];
if ( !bubbling ) {
event = typeof event === "object" ?
// jQuery.Event object
event[ jQuery.expando ] ? event :
// Object literal
jQuery.extend( jQuery.Event(type), event ) :
// Just the event type (string)
jQuery.Event(type);
if ( type.indexOf("!") >= 0 ) {
event.type = type = type.slice(0, -1);
event.exclusive = true;
}
// Handle a global trigger
if ( !elem ) {
// Don't bubble custom events when global (to avoid too much overhead)
event.stopPropagation();
// Only trigger if we've ever bound an event for it
if ( jQuery.event.global[ type ] ) {
// XXX This code smells terrible. event.js should not be directly
// inspecting the data cache
jQuery.each( jQuery.cache, function() {
// internalKey variable is just used to make it easier to find
// and potentially change this stuff later; currently it just
// points to jQuery.expando
var internalKey = jQuery.expando,
internalCache = this[ internalKey ];
if ( internalCache && internalCache.events && internalCache.events[type] ) {
jQuery.event.trigger( event, data, internalCache.handle.elem );
}
});
}
}
// Handle triggering a single element
// don't do events on text and comment nodes
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
return undefined;
}
// Clean up in case it is reused
event.result = undefined;
event.target = elem;
// Clone the incoming data, if any
data = jQuery.makeArray( data );
data.unshift( event );
}
event.currentTarget = elem;
// Trigger the event, it is assumed that "handle" is a function
var handle = elem.nodeType ?
jQuery._data( elem, "handle" ) :
(jQuery._data( elem, eventKey ) || {}).handle;
if ( handle ) {
handle.apply( elem, data );
}
var parent = elem.parentNode || elem.ownerDocument;
// Trigger an inline bound script
try {
if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
event.result = false;
event.preventDefault();
}
}
// prevent IE from throwing an error for some elements with some event types, see #3533
} catch (inlineError) {}
if ( !event.isPropagationStopped() && parent ) {
jQuery.event.trigger( event, data, parent, true );
} else if ( !event.isDefaultPrevented() ) {
var old,
target = event.target,
targetType = type.replace( rnamespaces, "" ),
isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
special = jQuery.event.special[ targetType ] || {};
if ( (!special._default || special._default.call( elem, event ) === false) &&
!isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
try {
if ( target[ targetType ] ) {
// Make sure that we don't accidentally re-trigger the onFOO events
old = target[ "on" + targetType ];
if ( old ) {
target[ "on" + targetType ] = null;
}
jQuery.event.triggered = true;
target[ targetType ]();
}
// prevent IE from throwing an error for some elements with some event types, see #3533
} catch (triggerError) {}
if ( old ) {
target[ "on" + targetType ] = old;
}
jQuery.event.triggered = false;
}
}
},
handle: function( event ) {
var all, handlers, namespaces, namespace_re, events,
namespace_sort = [],
args = jQuery.makeArray( arguments );
event = args[0] = jQuery.event.fix( event || window.event );
event.currentTarget = this;
// Namespaced event handlers
all = event.type.indexOf(".") < 0 && !event.exclusive;
if ( !all ) {
namespaces = event.type.split(".");
event.type = namespaces.shift();
namespace_sort = namespaces.slice(0).sort();
namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
}
event.namespace = event.namespace || namespace_sort.join(".");
events = jQuery._data(this, eventKey);
if ( typeof events === "function" ) {
events = events.events;
}
handlers = (events || {})[ event.type ];
if ( events && handlers ) {
// Clone the handlers to prevent manipulation
handlers = handlers.slice(0);
for ( var j = 0, l = handlers.length; j < l; j++ ) {
var handleObj = handlers[ j ];
// Filter the functions by class
if ( all || namespace_re.test( handleObj.namespace ) ) {
// Pass in a reference to the handler function itself
// So that we can later remove it
event.handler = handleObj.handler;
event.data = handleObj.data;
event.handleObj = handleObj;
var ret = handleObj.handler.apply( this, args );
if ( ret !== undefined ) {
event.result = ret;
if ( ret === false ) {
event.preventDefault();
event.stopPropagation();
}
}
if ( event.isImmediatePropagationStopped() ) {
break;
}
}
}
}
return event.result;
},
props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix: function( event ) {
if ( event[ jQuery.expando ] ) {
return event;
}
// store a copy of the original event object
// and "clone" to set read-only properties
var originalEvent = event;
event = jQuery.Event( originalEvent );
for ( var i = this.props.length, prop; i; ) {
prop = this.props[ --i ];
event[ prop ] = originalEvent[ prop ];
}
// Fix target property, if necessary
if ( !event.target ) {
// Fixes #1925 where srcElement might not be defined either
event.target = event.srcElement || document;
}
// check if target is a textnode (safari)
if ( event.target.nodeType === 3 ) {
event.target = event.target.parentNode;
}
// Add relatedTarget, if necessary
if ( !event.relatedTarget && event.fromElement ) {
event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
}
// Calculate pageX/Y if missing and clientX/Y available
if ( event.pageX == null && event.clientX != null ) {
var doc = document.documentElement,
body = document.body;
event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
}
// Add which for key events
if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
event.which = event.charCode != null ? event.charCode : event.keyCode;
}
// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
if ( !event.metaKey && event.ctrlKey ) {
event.metaKey = event.ctrlKey;
}
// Add which for click: 1 === left; 2 === middle; 3 === right
// Note: button is not normalized, so don't use it
if ( !event.which && event.button !== undefined ) {
event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
}
return event;
},
// Deprecated, use jQuery.guid instead
guid: 1E8,
// Deprecated, use jQuery.proxy instead
proxy: jQuery.proxy,
special: {
ready: {
// Make sure the ready event is setup
setup: jQuery.bindReady,
teardown: jQuery.noop
},
live: {
add: function( handleObj ) {
jQuery.event.add( this,
liveConvert( handleObj.origType, handleObj.selector ),
jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
},
remove: function( handleObj ) {
jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
}
},
beforeunload: {
setup: function( data, namespaces, eventHandle ) {
// We only want to do this special case on windows
if ( jQuery.isWindow( this ) ) {
this.onbeforeunload = eventHandle;
}
},
teardown: function( namespaces, eventHandle ) {
if ( this.onbeforeunload === eventHandle ) {
this.onbeforeunload = null;
}
}
}
}
};
jQuery.removeEvent = document.removeEventListener ?
function( elem, type, handle ) {
if ( elem.removeEventListener ) {
elem.removeEventListener( type, handle, false );
}
} :
function( elem, type, handle ) {
if ( elem.detachEvent ) {
elem.detachEvent( "on" + type, handle );
}
};
jQuery.Event = function( src ) {
// Allow instantiation without the 'new' keyword
if ( !this.preventDefault ) {
return new jQuery.Event( src );
}
// Event object
if ( src && src.type ) {
this.originalEvent = src;
this.type = src.type;
// Events bubbling up the document may have been marked as prevented
// by a handler lower down the tree; reflect the correct value.
this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
// Event type
} else {
this.type = src;
}
// timeStamp is buggy for some events on Firefox(#3843)
// So we won't rely on the native value
this.timeStamp = jQuery.now();
// Mark it as fixed
this[ jQuery.expando ] = true;
};
function returnFalse() {
return false;
}
function returnTrue() {
return true;
}
// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
preventDefault: function() {
this.isDefaultPrevented = returnTrue;
var e = this.originalEvent;
if ( !e ) {
return;
}
// if preventDefault exists run it on the original event
if ( e.preventDefault ) {
e.preventDefault();
// otherwise set the returnValue property of the original event to false (IE)
} else {
e.returnValue = false;
}
},
stopPropagation: function() {
this.isPropagationStopped = returnTrue;
var e = this.originalEvent;
if ( !e ) {
return;
}
// if stopPropagation exists run it on the original event
if ( e.stopPropagation ) {
e.stopPropagation();
}
// otherwise set the cancelBubble property of the original event to true (IE)
e.cancelBubble = true;
},
stopImmediatePropagation: function() {
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
},
isDefaultPrevented: returnFalse,
isPropagationStopped: returnFalse,
isImmediatePropagationStopped: returnFalse
};
// Checks if an event happened on an element within another element
// Used in jQuery.event.special.mouseenter and mouseleave handlers
var withinElement = function( event ) {
// Check if mouse(over|out) are still within the same parent element
var parent = event.relatedTarget;
// Firefox sometimes assigns relatedTarget a XUL element
// which we cannot access the parentNode property of
try {
// Traverse up the tree
while ( parent && parent !== this ) {
parent = parent.parentNode;
}
if ( parent !== this ) {
// set the correct event type
event.type = event.data;
// handle event if we actually just moused on to a non sub-element
jQuery.event.handle.apply( this, arguments );
}
// assuming we've left the element since we most likely mousedover a xul element
} catch(e) { }
},
// In case of event delegation, we only need to rename the event.type,
// liveHandler will take care of the rest.
delegate = function( event ) {
event.type = event.data;
jQuery.event.handle.apply( this, arguments );
};
// Create mouseenter and mouseleave events
jQuery.each({
mouseenter: "mouseover",
mouseleave: "mouseout"
}, function( orig, fix ) {
jQuery.event.special[ orig ] = {
setup: function( data ) {
jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
},
teardown: function( data ) {
jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
}
};
});
// submit delegation
if ( !jQuery.support.submitBubbles ) {
jQuery.event.special.submit = {
setup: function( data, namespaces ) {
if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
jQuery.event.add(this, "click.specialSubmit", function( e ) {
var elem = e.target,
type = elem.type;
if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
e.liveFired = undefined;
return trigger( "submit", this, arguments );
}
});
jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
var elem = e.target,
type = elem.type;
if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
e.liveFired = undefined;
return trigger( "submit", this, arguments );
}
});
} else {
return false;
}
},
teardown: function( namespaces ) {
jQuery.event.remove( this, ".specialSubmit" );
}
};
}
// change delegation, happens here so we have bind.
if ( !jQuery.support.changeBubbles ) {
var changeFilters,
getVal = function( elem ) {
var type = elem.type, val = elem.value;
if ( type === "radio" || type === "checkbox" ) {
val = elem.checked;
} else if ( type === "select-multiple" ) {
val = elem.selectedIndex > -1 ?
jQuery.map( elem.options, function( elem ) {
return elem.selected;
}).join("-") :
"";
} else if ( elem.nodeName.toLowerCase() === "select" ) {
val = elem.selectedIndex;
}
return val;
},
testChange = function testChange( e ) {
var elem = e.target, data, val;
if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
return;
}
data = jQuery._data( elem, "_change_data" );
val = getVal(elem);
// the current data will be also retrieved by beforeactivate
if ( e.type !== "focusout" || elem.type !== "radio" ) {
jQuery._data( elem, "_change_data", val );
}
if ( data === undefined || val === data ) {
return;
}
if ( data != null || val ) {
e.type = "change";
e.liveFired = undefined;
return jQuery.event.trigger( e, arguments[1], elem );
}
};
jQuery.event.special.change = {
filters: {
focusout: testChange,
beforedeactivate: testChange,
click: function( e ) {
var elem = e.target, type = elem.type;
if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
return testChange.call( this, e );
}
},
// Change has to be called before submit
// Keydown will be called before keypress, which is used in submit-event delegation
keydown: function( e ) {
var elem = e.target, type = elem.type;
if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
type === "select-multiple" ) {
return testChange.call( this, e );
}
},
// Beforeactivate happens also before the previous element is blurred
// with this event you can't trigger a change event, but you can store
// information
beforeactivate: function( e ) {
var elem = e.target;
jQuery._data( elem, "_change_data", getVal(elem) );
}
},
setup: function( data, namespaces ) {
if ( this.type === "file" ) {
return false;
}
for ( var type in changeFilters ) {
jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
}
return rformElems.test( this.nodeName );
},
teardown: function( namespaces ) {
jQuery.event.remove( this, ".specialChange" );
return rformElems.test( this.nodeName );
}
};
changeFilters = jQuery.event.special.change.filters;
// Handle when the input is .focus()'d
changeFilters.focus = changeFilters.beforeactivate;
}
function trigger( type, elem, args ) {
args[0].type = type;
return jQuery.event.handle.apply( elem, args );
}
// Create "bubbling" focus and blur events
if ( document.addEventListener ) {
jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
jQuery.event.special[ fix ] = {
setup: function() {
this.addEventListener( orig, handler, true );
},
teardown: function() {
this.removeEventListener( orig, handler, true );
}
};
function handler( e ) {
e = jQuery.event.fix( e );
e.type = fix;
return jQuery.event.handle.call( this, e );
}
});
}
jQuery.each(["bind", "one"], function( i, name ) {
jQuery.fn[ name ] = function( type, data, fn ) {
// Handle object literals
if ( typeof type === "object" ) {
for ( var key in type ) {
this[ name ](key, data, type[key], fn);
}
return this;
}
if ( jQuery.isFunction( data ) || data === false ) {
fn = data;
data = undefined;
}
var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
jQuery( this ).unbind( event, handler );
return fn.apply( this, arguments );
}) : fn;
if ( type === "unload" && name !== "one" ) {
this.one( type, data, fn );
} else {
for ( var i = 0, l = this.length; i < l; i++ ) {
jQuery.event.add( this[i], type, handler, data );
}
}
return this;
};
});
jQuery.fn.extend({
unbind: function( type, fn ) {
// Handle object literals
if ( typeof type === "object" && !type.preventDefault ) {
for ( var key in type ) {
this.unbind(key, type[key]);
}
} else {
for ( var i = 0, l = this.length; i < l; i++ ) {
jQuery.event.remove( this[i], type, fn );
}
}
return this;
},
delegate: function( selector, types, data, fn ) {
return this.live( types, data, fn, selector );
},
undelegate: function( selector, types, fn ) {
if ( arguments.length === 0 ) {
return this.unbind( "live" );
} else {
return this.die( types, null, fn, selector );
}
},
trigger: function( type, data ) {
return this.each(function() {
jQuery.event.trigger( type, data, this );
});
},
triggerHandler: function( type, data ) {
if ( this[0] ) {
var event = jQuery.Event( type );
event.preventDefault();
event.stopPropagation();
jQuery.event.trigger( event, data, this[0] );
return event.result;
}
},
toggle: function( fn ) {
// Save reference to arguments for access in closure
var args = arguments,
i = 1;
// link all the functions, so any of them can unbind this click handler
while ( i < args.length ) {
jQuery.proxy( fn, args[ i++ ] );
}
return this.click( jQuery.proxy( fn, function( event ) {
// Figure out which function to execute
var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
// Make sure that clicks stop
event.preventDefault();
// and execute the function
return args[ lastToggle ].apply( this, arguments ) || false;
}));
},
hover: function( fnOver, fnOut ) {
return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
}
});
var liveMap = {
focus: "focusin",
blur: "focusout",
mouseenter: "mouseover",
mouseleave: "mouseout"
};
jQuery.each(["live", "die"], function( i, name ) {
jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
var type, i = 0, match, namespaces, preType,
selector = origSelector || this.selector,
context = origSelector ? this : jQuery( this.context );
if ( typeof types === "object" && !types.preventDefault ) {
for ( var key in types ) {
context[ name ]( key, data, types[key], selector );
}
return this;
}
if ( jQuery.isFunction( data ) ) {
fn = data;
data = undefined;
}
types = (types || "").split(" ");
while ( (type = types[ i++ ]) != null ) {
match = rnamespaces.exec( type );
namespaces = "";
if ( match ) {
namespaces = match[0];
type = type.replace( rnamespaces, "" );
}
if ( type === "hover" ) {
types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
continue;
}
preType = type;
if ( type === "focus" || type === "blur" ) {
types.push( liveMap[ type ] + namespaces );
type = type + namespaces;
} else {
type = (liveMap[ type ] || type) + namespaces;
}
if ( name === "live" ) {
// bind live handler
for ( var j = 0, l = context.length; j < l; j++ ) {
jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
}
} else {
// unbind live handler
context.unbind( "live." + liveConvert( type, selector ), fn );
}
}
return this;
};
});
function liveHandler( event ) {
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
elems = [],
selectors = [],
events = jQuery._data( this, eventKey );
if ( typeof events === "function" ) {
events = events.events;
}
// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
return;
}
if ( event.namespace ) {
namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
}
event.liveFired = this;
var live = events.live.slice(0);
for ( j = 0; j < live.length; j++ ) {
handleObj = live[j];
if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
selectors.push( handleObj.selector );
} else {
live.splice( j--, 1 );
}
}
match = jQuery( event.target ).closest( selectors, event.currentTarget );
for ( i = 0, l = match.length; i < l; i++ ) {
close = match[i];
for ( j = 0; j < live.length; j++ ) {
handleObj = live[j];
if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
elem = close.elem;
related = null;
// Those two events require additional checking
if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
event.type = handleObj.preType;
related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
}
if ( !related || related !== elem ) {
elems.push({ elem: elem, handleObj: handleObj, level: close.level });
}
}
}
}
for ( i = 0, l = elems.length; i < l; i++ ) {
match = elems[i];
if ( maxLevel && match.level > maxLevel ) {
break;
}
event.currentTarget = match.elem;
event.data = match.handleObj.data;
event.handleObj = match.handleObj;
ret = match.handleObj.origHandler.apply( match.elem, arguments );
if ( ret === false || event.isPropagationStopped() ) {
maxLevel = match.level;
if ( ret === false ) {
stop = false;
}
if ( event.isImmediatePropagationStopped() ) {
break;
}
}
}
return stop;
}
function liveConvert( type, selector ) {
return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
}
jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup error").split(" "), function( i, name ) {
// Handle event binding
jQuery.fn[ name ] = function( data, fn ) {
if ( fn == null ) {
fn = data;
data = null;
}
return arguments.length > 0 ?
this.bind( name, data, fn ) :
this.trigger( name );
};
if ( jQuery.attrFn ) {
jQuery.attrFn[ name ] = true;
}
});
/*!
* Sizzle CSS Selector Engine
* Copyright 2011, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
* More information: http://sizzlejs.com/
*/
(function(){
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
done = 0,
toString = Object.prototype.toString,
hasDuplicate = false,
baseHasDuplicate = true;
// 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;
});
var Sizzle = function( selector, context, results, seed ) {
results = results || [];
context = context || document;
var origContext = context;
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
return [];
}
if ( !selector || typeof selector !== "string" ) {
return results;
}
var m, set, checkSet, extra, ret, cur, pop, i,
prune = true,
contextXML = Sizzle.isXML( context ),
parts = [],
soFar = selector;
// Reset the position of the chunker regexp (start from head)
do {
chunker.exec( "" );
m = chunker.exec( soFar );
if ( m ) {
soFar = m[3];
parts.push( m[1] );
if ( m[2] ) {
extra = m[3];
break;
}
}
} while ( m );
if ( parts.length > 1 && origPOS.exec( selector ) ) {
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
set = posProcess( parts[0] + parts[1], context );
} else {
set = Expr.relative[ parts[0] ] ?
[ context ] :
Sizzle( parts.shift(), context );
while ( parts.length ) {
selector = parts.shift();
if ( Expr.relative[ selector ] ) {
selector += parts.shift();
}
set = posProcess( selector, set );
}
}
} 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]) ) {
ret = Sizzle.find( parts.shift(), context, contextXML );
context = ret.expr ?
Sizzle.filter( ret.expr, ret.set )[0] :
ret.set[0];
}
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 );
set = ret.expr ?
Sizzle.filter( ret.expr, ret.set ) :
ret.set;
if ( parts.length > 0 ) {
checkSet = makeArray( set );
} else {
prune = false;
}
while ( parts.length ) {
cur = parts.pop();
pop = cur;
if ( !Expr.relative[ cur ] ) {
cur = "";
} else {
pop = parts.pop();
}
if ( pop == null ) {
pop = context;
}
Expr.relative[ cur ]( checkSet, pop, contextXML );
}
} else {
checkSet = parts = [];
}
}
if ( !checkSet ) {
checkSet = set;
}
if ( !checkSet ) {
Sizzle.error( cur || selector );
}
if ( toString.call(checkSet) === "[object Array]" ) {
if ( !prune ) {
results.push.apply( results, checkSet );
} 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] );
}
}
} else {
for ( i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
results.push( set[i] );
}
}
}
} 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 );
}
}
}
}
return results;
};
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;
if ( !expr ) {
return [];
}
for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
var match,
type = Expr.order[i];
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
var left = match[1];
match.splice( 1, 1 );
if ( left.substr( left.length - 1 ) !== "\\" ) {
match[1] = (match[1] || "").replace(/\\/g, "");
set = Expr.find[ type ]( match, context, isXML );
if ( set != null ) {
expr = expr.replace( Expr.match[ type ], "" );
break;
}
}
}
}
if ( !set ) {
set = typeof context.getElementsByTagName !== "undefined" ?
context.getElementsByTagName( "*" ) :
[];
}
return { set: set, expr: expr };
};
Sizzle.filter = function( expr, set, inplace, not ) {
var match, anyFound,
old = expr,
result = [],
curLoop = set,
isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
while ( expr && set.length ) {
for ( var type in Expr.filter ) {
if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
var found, item,
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 ( var i = 0; (item = curLoop[i]) != null; i++ ) {
if ( item ) {
found = filter( item, match, i, curLoop );
var pass = not ^ !!found;
if ( inplace && found != null ) {
if ( pass ) {
anyFound = true;
} else {
curLoop[i] = false;
}
} else if ( pass ) {
result.push( item );
anyFound = true;
}
}
}
}
if ( found !== undefined ) {
if ( !inplace ) {
curLoop = result;
}
expr = expr.replace( Expr.match[ type ], "" );
if ( !anyFound ) {
return [];
}
break;
}
}
}
// Improper expression
if ( expr === old ) {
if ( anyFound == null ) {
Sizzle.error( expr );
} else {
break;
}
}
old = expr;
}
return curLoop;
};
Sizzle.error = function( msg ) {
throw "Syntax error, unrecognized expression: " + msg;
};
var Expr = Sizzle.selectors = {
order: [ "ID", "NAME", "TAG" ],
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\))?/
},
leftMatch: {},
attrMap: {
"class": "className",
"for": "htmlFor"
},
attrHandle: {
href: function( elem ) {
return elem.getAttribute( "href" );
}
},
relative: {
"+": function(checkSet, part){
var isPartStr = typeof part === "string",
isTag = isPartStr && !/\W/.test( part ),
isPartStrNotTag = isPartStr && !isTag;
if ( isTag ) {
part = part.toLowerCase();
}
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
if ( (elem = checkSet[i]) ) {
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
elem || false :
elem === part;
}
}
if ( isPartStrNotTag ) {
Sizzle.filter( part, checkSet, true );
}
},
">": function( checkSet, part ) {
var elem,
isPartStr = typeof part === "string",
i = 0,
l = checkSet.length;
if ( isPartStr && !/\W/.test( part ) ) {
part = part.toLowerCase();
for ( ; i < l; i++ ) {
elem = checkSet[i];
if ( elem ) {
var parent = elem.parentNode;
checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
}
}
} else {
for ( ; i < l; i++ ) {
elem = checkSet[i];
if ( elem ) {
checkSet[i] = isPartStr ?
elem.parentNode :
elem.parentNode === part;
}
}
if ( isPartStr ) {
Sizzle.filter( part, checkSet, true );
}
}
},
"": function(checkSet, part, isXML){
var nodeCheck,
doneName = done++,
checkFn = dirCheck;
if ( typeof part === "string" && !/\W/.test(part) ) {
part = part.toLowerCase();
nodeCheck = part;
checkFn = dirNodeCheck;
}
checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
},
"~": function( checkSet, part, isXML ) {
var nodeCheck,
doneName = done++,
checkFn = dirCheck;
if ( typeof part === "string" && !/\W/.test( part ) ) {
part = part.toLowerCase();
nodeCheck = part;
checkFn = dirNodeCheck;
}
checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
}
},
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] : [];
}
},
NAME: function( match, context ) {
if ( typeof context.getElementsByName !== "undefined" ) {
var ret = [],
results = context.getElementsByName( match[1] );
for ( var i = 0, l = results.length; i < l; i++ ) {
if ( results[i].getAttribute("name") === match[1] ) {
ret.push( results[i] );
}
}
return ret.length === 0 ? null : ret;
}
},
TAG: function( match, context ) {
if ( typeof context.getElementsByTagName !== "undefined" ) {
return context.getElementsByTagName( match[1] );
}
}
},
preFilter: {
CLASS: function( match, curLoop, inplace, result, not, isXML ) {
match = " " + match[1].replace(/\\/g, "") + " ";
if ( isXML ) {
return match;
}
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 );
}
} else if ( inplace ) {
curLoop[i] = false;
}
}
}
return false;
},
ID: function( match ) {
return match[1].replace(/\\/g, "");
},
TAG: function( match, curLoop ) {
return match[1].toLowerCase();
},
CHILD: function( match ) {
if ( match[1] === "nth" ) {
if ( !match[2] ) {
Sizzle.error( match[0] );
}
match[2] = match[2].replace(/^\+|\s*/g, '');
// 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]);
// 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] );
}
// TODO: Move to normal caching system
match[0] = done++;
return match;
},
ATTR: function( match, curLoop, inplace, result, not, isXML ) {
var name = match[1] = match[1].replace(/\\/g, "");
if ( !isXML && Expr.attrMap[name] ) {
match[1] = Expr.attrMap[name];
}
// Handle if an un-quoted value was used
match[4] = ( match[4] || match[5] || "" ).replace(/\\/g, "");
if ( match[2] === "~=" ) {
match[4] = " " + match[4] + " ";
}
return match;
},
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);
} else {
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
if ( !inplace ) {
result.push.apply( result, ret );
}
return false;
}
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
return true;
}
return match;
},
POS: function( match ) {
match.unshift( true );
return match;
}
},
filters: {
enabled: function( elem ) {
return elem.disabled === false && elem.type !== "hidden";
},
disabled: function( elem ) {
return elem.disabled === true;
},
checked: function( elem ) {
return elem.checked === true;
},
selected: function( elem ) {
// Accessing this property makes selected-by-default
// options in Safari work properly
elem.parentNode.selectedIndex;
return elem.selected === true;
},
parent: function( elem ) {
return !!elem.firstChild;
},
empty: function( elem ) {
return !elem.firstChild;
},
has: function( elem, i, match ) {
return !!Sizzle( match[3], elem ).length;
},
header: function( elem ) {
return (/h\d/i).test( elem.nodeName );
},
text: function( elem ) {
return "text" === elem.type;
},
radio: function( elem ) {
return "radio" === elem.type;
},
checkbox: function( elem ) {
return "checkbox" === elem.type;
},
file: function( elem ) {
return "file" === elem.type;
},
password: function( elem ) {
return "password" === elem.type;
},
submit: function( elem ) {
return "submit" === elem.type;
},
image: function( elem ) {
return "image" === elem.type;
},
reset: function( elem ) {
return "reset" === elem.type;
},
button: function( elem ) {
return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
},
input: function( elem ) {
return (/input|select|textarea|button/i).test( elem.nodeName );
}
},
setFilters: {
first: function( elem, i ) {
return i === 0;
},
last: function( elem, i, match, array ) {
return i === array.length - 1;
},
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 || Sizzle.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 );
}
},
CHILD: function( elem, match ) {
var 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;
case "last":
while ( (node = node.nextSibling) ) {
if ( node.nodeType === 1 ) {
return false;
}
}
return true;
case "nth":
var first = match[2],
last = match[3];
if ( first === 1 && last === 0 ) {
return true;
}
var doneName = match[0],
parent = elem.parentNode;
if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
var count = 0;
for ( node = parent.firstChild; node; node = node.nextSibling ) {
if ( node.nodeType === 1 ) {
node.nodeIndex = ++count;
}
}
parent.sizcache = doneName;
}
var diff = elem.nodeIndex - last;
if ( first === 0 ) {
return diff === 0;
} else {
return ( diff % first === 0 && diff / first >= 0 );
}
}
},
ID: function( elem, match ) {
return elem.nodeType === 1 && elem.getAttribute("id") === match;
},
TAG: function( elem, match ) {
return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
},
CLASS: function( elem, match ) {
return (" " + (elem.className || elem.getAttribute("class")) + " ")
.indexOf( match ) > -1;
},
ATTR: function( elem, match ) {
var name = match[1],
result = 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 === "=" ?
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 );
}
}
}
};
var origPOS = Expr.match.POS,
fescape = function(all, num){
return "\\" + (num - 0 + 1);
};
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) );
}
var makeArray = function( array, results ) {
array = Array.prototype.slice.call( array, 0 );
if ( results ) {
results.push.apply( results, array );
return results;
}
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;
};
}
var sortOrder, siblingCheck;
if ( document.documentElement.compareDocumentPosition ) {
sortOrder = function( a, b ) {
if ( a === b ) {
hasDuplicate = true;
return 0;
}
if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
return a.compareDocumentPosition ? -1 : 1;
}
return a.compareDocumentPosition(b) & 4 ? -1 : 1;
};
} else {
sortOrder = function( a, b ) {
var al, bl,
ap = [],
bp = [],
aup = a.parentNode,
bup = b.parentNode,
cur = aup;
// The nodes are identical, we can exit early
if ( a === b ) {
hasDuplicate = true;
return 0;
// If the nodes are siblings (or identical) we can do a quick check
} else if ( aup === bup ) {
return siblingCheck( a, b );
// If no parents were found then the nodes are disconnected
} else if ( !aup ) {
return -1;
} else if ( !bup ) {
return 1;
}
// Otherwise they're somewhere else in the tree so we need
// to build up a full list of the parentNodes for comparison
while ( cur ) {
ap.unshift( cur );
cur = cur.parentNode;
}
cur = bup;
while ( cur ) {
bp.unshift( cur );
cur = cur.parentNode;
}
al = ap.length;
bl = bp.length;
// Start walking down the tree looking for a discrepancy
for ( var i = 0; i < al && i < bl; i++ ) {
if ( ap[i] !== bp[i] ) {
return siblingCheck( ap[i], bp[i] );
}
}
// We ended someplace up the tree so do a sibling check
return i === al ?
siblingCheck( a, bp[i], -1 ) :
siblingCheck( ap[i], b, 1 );
};
siblingCheck = function( a, b, ret ) {
if ( a === b ) {
return ret;
}
var cur = a.nextSibling;
while ( cur ) {
if ( cur === b ) {
return -1;
}
cur = cur.nextSibling;
}
return 1;
};
}
// Utility function for retreiving the text value of an array of DOM nodes
Sizzle.getText = function( elems ) {
var ret = "", elem;
for ( var i = 0; elems[i]; i++ ) {
elem = elems[i];
// Get the text from text nodes and CDATA nodes
if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
ret += elem.nodeValue;
// Traverse everything else, except comment nodes
} else if ( elem.nodeType !== 8 ) {
ret += Sizzle.getText( elem.childNodes );
}
}
return ret;
};
// 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;
form.innerHTML = "<a name='" + id + "'/>";
// Inject it into the root element, check its status, and remove it quickly
root.insertBefore( form, root.firstChild );
// 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]);
return m ?
m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
[m] :
undefined :
[];
}
};
Expr.filter.ID = function( elem, match ) {
var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
return elem.nodeType === 1 && node && node.nodeValue === match;
};
}
root.removeChild( form );
// release memory in IE
root = form = null;
})();
(function(){
// Check to see if the browser returns only elements
// when doing getElementsByTagName("*")
// Create a fake element
var div = document.createElement("div");
div.appendChild( document.createComment("") );
// Make sure no comments are found
if ( div.getElementsByTagName("*").length > 0 ) {
Expr.find.TAG = function( match, context ) {
var results = context.getElementsByTagName( match[1] );
// Filter out possible comments
if ( match[1] === "*" ) {
var tmp = [];
for ( var i = 0; results[i]; i++ ) {
if ( results[i].nodeType === 1 ) {
tmp.push( results[i] );
}
}
results = tmp;
}
return results;
};
}
// Check to see if an attribute returns normalized href attributes
div.innerHTML = "<a href='#'></a>";
if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
div.firstChild.getAttribute("href") !== "#" ) {
Expr.attrHandle.href = function( elem ) {
return elem.getAttribute( "href", 2 );
};
}
// release memory in IE
div = null;
})();
if ( document.querySelectorAll ) {
(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;
}
Sizzle = function( query, context, extra, seed ) {
context = context || document;
// 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 );
if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
// Speed-up: Sizzle("TAG")
if ( match[1] ) {
return makeArray( context.getElementsByTagName( query ), extra );
// Speed-up: Sizzle(".CLASS")
} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
return makeArray( context.getElementsByClassName( match[2] ), extra );
}
}
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 );
// Speed-up: Sizzle("#ID")
} else if ( match && match[3] ) {
var elem = context.getElementById( match[3] );
// 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 );
}
} else {
return makeArray( [], extra );
}
}
try {
return makeArray( context.querySelectorAll(query), extra );
} 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 old = context.getAttribute( "id" ),
nid = old || id,
hasParent = context.parentNode,
relativeHierarchySelector = /^\s*[+~]/.test( query );
if ( !old ) {
context.setAttribute( "id", nid );
} else {
nid = nid.replace( /'/g, "\\$&" );
}
if ( relativeHierarchySelector && hasParent ) {
context = context.parentNode;
}
try {
if ( !relativeHierarchySelector || hasParent ) {
return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
}
} catch(pseudoError) {
} finally {
if ( !old ) {
context.removeAttribute( "id" );
}
}
}
}
return oldSizzle(query, context, extra, seed);
};
for ( var prop in oldSizzle ) {
Sizzle[ prop ] = oldSizzle[ prop ];
}
// release memory in IE
div = null;
})();
}
(function(){
var html = document.documentElement,
matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,
pseudoWorks = false;
try {
// This should fail with an exception
// Gecko does not error, returns false instead
matches.call( document.documentElement, "[test!='']:sizzle" );
} catch( pseudoError ) {
pseudoWorks = true;
}
if ( matches ) {
Sizzle.matchesSelector = function( node, expr ) {
// Make sure that attribute selectors are quoted
expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
if ( !Sizzle.isXML( node ) ) {
try {
if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
return matches.call( node, expr );
}
} catch(e) {}
}
return Sizzle(expr, null, null, [node]).length > 0;
};
}
})();
(function(){
var div = document.createElement("div");
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
// 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;
}
// Safari caches class attributes, doesn't catch changes (in 3.2)
div.lastChild.className = "e";
if ( div.getElementsByClassName("e").length === 1 ) {
return;
}
Expr.order.splice(1, 0, "CLASS");
Expr.find.CLASS = function( match, context, isXML ) {
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
return context.getElementsByClassName(match[1]);
}
};
// release memory in IE
div = null;
})();
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
var match = false;
elem = elem[dir];
while ( elem ) {
if ( elem.sizcache === doneName ) {
match = checkSet[elem.sizset];
break;
}
if ( elem.nodeType === 1 && !isXML ){
elem.sizcache = doneName;
elem.sizset = i;
}
if ( elem.nodeName.toLowerCase() === cur ) {
match = elem;
break;
}
elem = elem[dir];
}
checkSet[i] = match;
}
}
}
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
var match = false;
elem = elem[dir];
while ( elem ) {
if ( elem.sizcache === doneName ) {
match = checkSet[elem.sizset];
break;
}
if ( elem.nodeType === 1 ) {
if ( !isXML ) {
elem.sizcache = doneName;
elem.sizset = i;
}
if ( typeof cur !== "string" ) {
if ( elem === cur ) {
match = true;
break;
}
} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
match = elem;
break;
}
}
elem = elem[dir];
}
checkSet[i] = match;
}
}
}
if ( document.documentElement.contains ) {
Sizzle.contains = function( a, b ) {
return a !== b && (a.contains ? a.contains(b) : true);
};
} else if ( document.documentElement.compareDocumentPosition ) {
Sizzle.contains = function( a, b ) {
return !!(a.compareDocumentPosition(b) & 16);
};
} else {
Sizzle.contains = function() {
return false;
};
}
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;
return documentElement ? documentElement.nodeName !== "HTML" : false;
};
var posProcess = function( selector, context ) {
var match,
tmpSet = [],
later = "",
root = context.nodeType ? [context] : context;
// 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, "" );
}
selector = Expr.relative[selector] ? selector + "*" : selector;
for ( var i = 0, l = root.length; i < l; i++ ) {
Sizzle( selector, root[i], tmpSet );
}
return Sizzle.filter( later, tmpSet );
};
// EXPOSE
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;
jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;
})();
var runtil = /Until$/,
rparentsprev = /^(?:parents|prevUntil|prevAll)/,
// Note: This RegExp should be improved, or likely pulled from Sizzle
rmultiselector = /,/,
isSimple = /^.[^:#\[\.,]*$/,
slice = Array.prototype.slice,
POS = jQuery.expr.match.POS,
// methods guaranteed to produce a unique set when starting from a unique set
guaranteedUnique = {
children: true,
contents: true,
next: true,
prev: true
};
jQuery.fn.extend({
find: function( selector ) {
var ret = this.pushStack( "", "find", selector ),
length = 0;
for ( var i = 0, l = this.length; i < l; i++ ) {
length = ret.length;
jQuery.find( selector, this[i], ret );
if ( i > 0 ) {
// Make sure that the results are unique
for ( var n = length; n < ret.length; n++ ) {
for ( var r = 0; r < length; r++ ) {
if ( ret[r] === ret[n] ) {
ret.splice(n--, 1);
break;
}
}
}
}
}
return ret;
},
has: function( target ) {
var targets = jQuery( target );
return this.filter(function() {
for ( var i = 0, l = targets.length; i < l; i++ ) {
if ( jQuery.contains( this, targets[i] ) ) {
return true;
}
}
});
},
not: function( selector ) {
return this.pushStack( winnow(this, selector, false), "not", selector);
},
filter: function( selector ) {
return this.pushStack( winnow(this, selector, true), "filter", selector );
},
is: function( selector ) {
return !!selector && jQuery.filter( selector, this ).length > 0;
},
closest: function( selectors, context ) {
var ret = [], i, l, cur = this[0];
if ( jQuery.isArray( selectors ) ) {
var match, selector,
matches = {},
level = 1;
if ( cur && selectors.length ) {
for ( i = 0, l = selectors.length; i < l; i++ ) {
selector = selectors[i];
if ( !matches[selector] ) {
matches[selector] = jQuery.expr.match.POS.test( selector ) ?
jQuery( selector, context || this.context ) :
selector;
}
}
while ( cur && cur.ownerDocument && cur !== context ) {
for ( selector in matches ) {
match = matches[selector];
if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
ret.push({ selector: selector, elem: cur, level: level });
}
}
cur = cur.parentNode;
level++;
}
}
return ret;
}
var pos = POS.test( selectors ) ?
jQuery( selectors, context || this.context ) : null;
for ( i = 0, l = this.length; i < l; i++ ) {
cur = this[i];
while ( cur ) {
if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
ret.push( cur );
break;
} else {
cur = cur.parentNode;
if ( !cur || !cur.ownerDocument || cur === context ) {
break;
}
}
}
}
ret = ret.length > 1 ? jQuery.unique(ret) : ret;
return this.pushStack( ret, "closest", selectors );
},
// Determine the position of an element within
// the matched set of elements
index: function( elem ) {
if ( !elem || typeof elem === "string" ) {
return jQuery.inArray( this[0],
// If it receives a string, the selector is used
// If it receives nothing, the siblings are used
elem ? jQuery( elem ) : this.parent().children() );
}
// Locate the position of the desired element
return jQuery.inArray(
// If it receives a jQuery object, the first element is used
elem.jquery ? elem[0] : elem, this );
},
add: function( selector, context ) {
var set = typeof selector === "string" ?
jQuery( selector, context ) :
jQuery.makeArray( selector ),
all = jQuery.merge( this.get(), set );
return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
all :
jQuery.unique( all ) );
},
andSelf: function() {
return this.add( this.prevObject );
}
});
// A painfully simple check to see if an element is disconnected
// from a document (should be improved, where feasible).
function isDisconnected( node ) {
return !node || !node.parentNode || node.parentNode.nodeType === 11;
}
jQuery.each({
parent: function( elem ) {
var parent = elem.parentNode;
return parent && parent.nodeType !== 11 ? parent : null;
},
parents: function( elem ) {
return jQuery.dir( elem, "parentNode" );
},
parentsUntil: function( elem, i, until ) {
return jQuery.dir( elem, "parentNode", until );
},
next: function( elem ) {
return jQuery.nth( elem, 2, "nextSibling" );
},
prev: function( elem ) {
return jQuery.nth( elem, 2, "previousSibling" );
},
nextAll: function( elem ) {
return jQuery.dir( elem, "nextSibling" );
},
prevAll: function( elem ) {
return jQuery.dir( elem, "previousSibling" );
},
nextUntil: function( elem, i, until ) {
return jQuery.dir( elem, "nextSibling", until );
},
prevUntil: function( elem, i, until ) {
return jQuery.dir( elem, "previousSibling", until );
},
siblings: function( elem ) {
return jQuery.sibling( elem.parentNode.firstChild, elem );
},
children: function( elem ) {
return jQuery.sibling( elem.firstChild );
},
contents: function( elem ) {
return jQuery.nodeName( elem, "iframe" ) ?
elem.contentDocument || elem.contentWindow.document :
jQuery.makeArray( elem.childNodes );
}
}, function( name, fn ) {
jQuery.fn[ name ] = function( until, selector ) {
var ret = jQuery.map( this, fn, until ),
// The variable 'args' was introduced in
// https://github.com/jquery/jquery/commit/52a0238
// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
// http://code.google.com/p/v8/issues/detail?id=1050
args = slice.call(arguments);
if ( !runtil.test( name ) ) {
selector = until;
}
if ( selector && typeof selector === "string" ) {
ret = jQuery.filter( selector, ret );
}
ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
ret = ret.reverse();
}
return this.pushStack( ret, name, args.join(",") );
};
});
jQuery.extend({
filter: function( expr, elems, not ) {
if ( not ) {
expr = ":not(" + expr + ")";
}
return elems.length === 1 ?
jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
jQuery.find.matches(expr, elems);
},
dir: function( elem, dir, until ) {
var matched = [],
cur = elem[ dir ];
while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
if ( cur.nodeType === 1 ) {
matched.push( cur );
}
cur = cur[dir];
}
return matched;
},
nth: function( cur, result, dir, elem ) {
result = result || 1;
var num = 0;
for ( ; cur; cur = cur[dir] ) {
if ( cur.nodeType === 1 && ++num === result ) {
break;
}
}
return cur;
},
sibling: function( n, elem ) {
var r = [];
for ( ; n; n = n.nextSibling ) {
if ( n.nodeType === 1 && n !== elem ) {
r.push( n );
}
}
return r;
}
});
// Implement the identical functionality for filter and not
function winnow( elements, qualifier, keep ) {
if ( jQuery.isFunction( qualifier ) ) {
return jQuery.grep(elements, function( elem, i ) {
var retVal = !!qualifier.call( elem, i, elem );
return retVal === keep;
});
} else if ( qualifier.nodeType ) {
return jQuery.grep(elements, function( elem, i ) {
return (elem === qualifier) === keep;
});
} else if ( typeof qualifier === "string" ) {
var filtered = jQuery.grep(elements, function( elem ) {
return elem.nodeType === 1;
});
if ( isSimple.test( qualifier ) ) {
return jQuery.filter(qualifier, filtered, !keep);
} else {
qualifier = jQuery.filter( qualifier, filtered );
}
}
return jQuery.grep(elements, function( elem, i ) {
return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
});
}
var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
rleadingWhitespace = /^\s+/,
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
rtagName = /<([\w:]+)/,
rtbody = /<tbody/i,
rhtml = /<|&#?\w+;/,
rnocache = /<(?:script|object|embed|option|style)/i,
// checked="checked" or checked (html5)
rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
wrapMap = {
option: [ 1, "<select multiple='multiple'>", "</select>" ],
legend: [ 1, "<fieldset>", "</fieldset>" ],
thead: [ 1, "<table>", "</table>" ],
tr: [ 2, "<table><tbody>", "</tbody></table>" ],
td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
area: [ 1, "<map>", "</map>" ],
_default: [ 0, "", "" ]
};
wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;
// IE can't serialize <link> and <script> tags normally
if ( !jQuery.support.htmlSerialize ) {
wrapMap._default = [ 1, "div<div>", "</div>" ];
}
jQuery.fn.extend({
text: function( text ) {
if ( jQuery.isFunction(text) ) {
return this.each(function(i) {
var self = jQuery( this );
self.text( text.call(this, i, self.text()) );
});
}
if ( typeof text !== "object" && text !== undefined ) {
return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
}
return jQuery.text( this );
},
wrapAll: function( html ) {
if ( jQuery.isFunction( html ) ) {
return this.each(function(i) {
jQuery(this).wrapAll( html.call(this, i) );
});
}
if ( this[0] ) {
// The elements to wrap the target around
var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
if ( this[0].parentNode ) {
wrap.insertBefore( this[0] );
}
wrap.map(function() {
var elem = this;
while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
elem = elem.firstChild;
}
return elem;
}).append(this);
}
return this;
},
wrapInner: function( html ) {
if ( jQuery.isFunction( html ) ) {
return this.each(function(i) {
jQuery(this).wrapInner( html.call(this, i) );
});
}
return this.each(function() {
var self = jQuery( this ),
contents = self.contents();
if ( contents.length ) {
contents.wrapAll( html );
} else {
self.append( html );
}
});
},
wrap: function( html ) {
return this.each(function() {
jQuery( this ).wrapAll( html );
});
},
unwrap: function() {
return this.parent().each(function() {
if ( !jQuery.nodeName( this, "body" ) ) {
jQuery( this ).replaceWith( this.childNodes );
}
}).end();
},
append: function() {
return this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 ) {
this.appendChild( elem );
}
});
},
prepend: function() {
return this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 ) {
this.insertBefore( elem, this.firstChild );
}
});
},
before: function() {
if ( this[0] && this[0].parentNode ) {
return this.domManip(arguments, false, function( elem ) {
this.parentNode.insertBefore( elem, this );
});
} else if ( arguments.length ) {
var set = jQuery(arguments[0]);
set.push.apply( set, this.toArray() );
return this.pushStack( set, "before", arguments );
}
},
after: function() {
if ( this[0] && this[0].parentNode ) {
return this.domManip(arguments, false, function( elem ) {
this.parentNode.insertBefore( elem, this.nextSibling );
});
} else if ( arguments.length ) {
var set = this.pushStack( this, "after", arguments );
set.push.apply( set, jQuery(arguments[0]).toArray() );
return set;
}
},
// keepData is for internal use only--do not document
remove: function( selector, keepData ) {
for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
if ( !keepData && elem.nodeType === 1 ) {
jQuery.cleanData( elem.getElementsByTagName("*") );
jQuery.cleanData( [ elem ] );
}
if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
}
}
}
return this;
},
empty: function() {
for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
// Remove element nodes and prevent memory leaks
if ( elem.nodeType === 1 ) {
jQuery.cleanData( elem.getElementsByTagName("*") );
}
// Remove any remaining nodes
while ( elem.firstChild ) {
elem.removeChild( elem.firstChild );
}
}
return this;
},
clone: function( dataAndEvents, deepDataAndEvents ) {
dataAndEvents = dataAndEvents == null ? true : dataAndEvents;
deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
return this.map( function () {
return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
});
},
html: function( value ) {
if ( value === undefined ) {
return this[0] && this[0].nodeType === 1 ?
this[0].innerHTML.replace(rinlinejQuery, "") :
null;
// See if we can take a shortcut and just use innerHTML
} else if ( typeof value === "string" && !rnocache.test( value ) &&
(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
value = value.replace(rxhtmlTag, "<$1></$2>");
try {
for ( var i = 0, l = this.length; i < l; i++ ) {
// Remove element nodes and prevent memory leaks
if ( this[i].nodeType === 1 ) {
jQuery.cleanData( this[i].getElementsByTagName("*") );
this[i].innerHTML = value;
}
}
// If using innerHTML throws an exception, use the fallback method
} catch(e) {
this.empty().append( value );
}
} else if ( jQuery.isFunction( value ) ) {
this.each(function(i){
var self = jQuery( this );
self.html( value.call(this, i, self.html()) );
});
} else {
this.empty().append( value );
}
return this;
},
replaceWith: function( value ) {
if ( this[0] && this[0].parentNode ) {
// Make sure that the elements are removed from the DOM before they are inserted
// this can help fix replacing a parent with child elements
if ( jQuery.isFunction( value ) ) {
return this.each(function(i) {
var self = jQuery(this), old = self.html();
self.replaceWith( value.call( this, i, old ) );
});
}
if ( typeof value !== "string" ) {
value = jQuery( value ).detach();
}
return this.each(function() {
var next = this.nextSibling,
parent = this.parentNode;
jQuery( this ).remove();
if ( next ) {
jQuery(next).before( value );
} else {
jQuery(parent).append( value );
}
});
} else {
return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
}
},
detach: function( selector ) {
return this.remove( selector, true );
},
domManip: function( args, table, callback ) {
var results, first, fragment, parent,
value = args[0],
scripts = [];
// We can't cloneNode fragments that contain checked, in WebKit
if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
return this.each(function() {
jQuery(this).domManip( args, table, callback, true );
});
}
if ( jQuery.isFunction(value) ) {
return this.each(function(i) {
var self = jQuery(this);
args[0] = value.call(this, i, table ? self.html() : undefined);
self.domManip( args, table, callback );
});
}
if ( this[0] ) {
parent = value && value.parentNode;
// If we're in a fragment, just use that instead of building a new one
if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
results = { fragment: parent };
} else {
results = jQuery.buildFragment( args, this, scripts );
}
fragment = results.fragment;
if ( fragment.childNodes.length === 1 ) {
first = fragment = fragment.firstChild;
} else {
first = fragment.firstChild;
}
if ( first ) {
table = table && jQuery.nodeName( first, "tr" );
for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
callback.call(
table ?
root(this[i], first) :
this[i],
// Make sure that we do not leak memory by inadvertently discarding
// the original fragment (which might have attached data) instead of
// using it; in addition, use the original fragment object for the last
// item instead of first because it can end up being emptied incorrectly
// in certain situations (Bug #8070).
// Fragments from the fragment cache must always be cloned and never used
// in place.
results.cacheable || (l > 1 && i < lastIndex) ?
jQuery.clone( fragment, true, true ) :
fragment
);
}
}
if ( scripts.length ) {
jQuery.each( scripts, evalScript );
}
}
return this;
}
});
function root( elem, cur ) {
return jQuery.nodeName(elem, "table") ?
(elem.getElementsByTagName("tbody")[0] ||
elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
elem;
}
function cloneCopyEvent( src, dest ) {
if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
return;
}
var internalKey = jQuery.expando,
oldData = jQuery.data( src ),
curData = jQuery.data( dest, oldData );
// Switch to use the internal data object, if it exists, for the next
// stage of data copying
if ( (oldData = oldData[ internalKey ]) ) {
var events = oldData.events;
curData = curData[ internalKey ] = jQuery.extend({}, oldData);
if ( events ) {
delete curData.handle;
curData.events = {};
for ( var type in events ) {
for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
jQuery.event.add( dest, type, events[ type ][ i ], events[ type ][ i ].data );
}
}
}
}
}
function cloneFixAttributes(src, dest) {
// We do not need to do anything for non-Elements
if ( dest.nodeType !== 1 ) {
return;
}
var nodeName = dest.nodeName.toLowerCase();
// clearAttributes removes the attributes, which we don't want,
// but also removes the attachEvent events, which we *do* want
dest.clearAttributes();
// mergeAttributes, in contrast, only merges back on the
// original attributes, not the events
dest.mergeAttributes(src);
// IE6-8 fail to clone children inside object elements that use
// the proprietary classid attribute value (rather than the type
// attribute) to identify the type of content to display
if ( nodeName === "object" ) {
dest.outerHTML = src.outerHTML;
} else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
// IE6-8 fails to persist the checked state of a cloned checkbox
// or radio button. Worse, IE6-7 fail to give the cloned element
// a checked appearance if the defaultChecked value isn't also set
if ( src.checked ) {
dest.defaultChecked = dest.checked = src.checked;
}
// IE6-7 get confused and end up setting the value of a cloned
// checkbox/radio button to an empty string instead of "on"
if ( dest.value !== src.value ) {
dest.value = src.value;
}
// IE6-8 fails to return the selected option to the default selected
// state when cloning options
} else if ( nodeName === "option" ) {
dest.selected = src.defaultSelected;
// IE6-8 fails to set the defaultValue to the correct value when
// cloning other types of input fields
} else if ( nodeName === "input" || nodeName === "textarea" ) {
dest.defaultValue = src.defaultValue;
}
// Event data gets referenced instead of copied if the expando
// gets copied too
dest.removeAttribute( jQuery.expando );
}
jQuery.buildFragment = function( args, nodes, scripts ) {
var fragment, cacheable, cacheresults,
doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
// Only cache "small" (1/2 KB) HTML strings that are associated with the main document
// Cloning options loses the selected state, so don't cache them
// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
cacheable = true;
cacheresults = jQuery.fragments[ args[0] ];
if ( cacheresults ) {
if ( cacheresults !== 1 ) {
fragment = cacheresults;
}
}
}
if ( !fragment ) {
fragment = doc.createDocumentFragment();
jQuery.clean( args, doc, fragment, scripts );
}
if ( cacheable ) {
jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
}
return { fragment: fragment, cacheable: cacheable };
};
jQuery.fragments = {};
jQuery.each({
appendTo: "append",
prependTo: "prepend",
insertBefore: "before",
insertAfter: "after",
replaceAll: "replaceWith"
}, function( name, original ) {
jQuery.fn[ name ] = function( selector ) {
var ret = [],
insert = jQuery( selector ),
parent = this.length === 1 && this[0].parentNode;
if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
insert[ original ]( this[0] );
return this;
} else {
for ( var i = 0, l = insert.length; i < l; i++ ) {
var elems = (i > 0 ? this.clone(true) : this).get();
jQuery( insert[i] )[ original ]( elems );
ret = ret.concat( elems );
}
return this.pushStack( ret, name, insert.selector );
}
};
});
jQuery.extend({
clone: function( elem, dataAndEvents, deepDataAndEvents ) {
var clone = elem.cloneNode(true),
srcElements,
destElements,
i;
if ( !jQuery.support.noCloneEvent && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
// IE copies events bound via attachEvent when using cloneNode.
// Calling detachEvent on the clone will also remove the events
// from the original. In order to get around this, we use some
// proprietary methods to clear the events. Thanks to MooTools
// guys for this hotness.
// Using Sizzle here is crazy slow, so we use getElementsByTagName
// instead
srcElements = elem.getElementsByTagName("*");
destElements = clone.getElementsByTagName("*");
// Weird iteration because IE will replace the length property
// with an element if you are cloning the body and one of the
// elements on the page has a name or id of "length"
for ( i = 0; srcElements[i]; ++i ) {
cloneFixAttributes( srcElements[i], destElements[i] );
}
cloneFixAttributes( elem, clone );
}
// Copy the events from the original to the clone
if ( dataAndEvents ) {
cloneCopyEvent( elem, clone );
if ( deepDataAndEvents && "getElementsByTagName" in elem ) {
srcElements = elem.getElementsByTagName("*");
destElements = clone.getElementsByTagName("*");
if ( srcElements.length ) {
for ( i = 0; srcElements[i]; ++i ) {
cloneCopyEvent( srcElements[i], destElements[i] );
}
}
}
}
// Return the cloned set
return clone;
},
clean: function( elems, context, fragment, scripts ) {
context = context || document;
// !context.createElement fails in IE with an error but returns typeof 'object'
if ( typeof context.createElement === "undefined" ) {
context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
}
var ret = [];
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
if ( typeof elem === "number" ) {
elem += "";
}
if ( !elem ) {
continue;
}
// Convert html string into DOM nodes
if ( typeof elem === "string" && !rhtml.test( elem ) ) {
elem = context.createTextNode( elem );
} else if ( typeof elem === "string" ) {
// Fix "XHTML"-style tags in all browsers
elem = elem.replace(rxhtmlTag, "<$1></$2>");
// Trim whitespace, otherwise indexOf won't work as expected
var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
wrap = wrapMap[ tag ] || wrapMap._default,
depth = wrap[0],
div = context.createElement("div");
// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];
// Move to the right depth
while ( depth-- ) {
div = div.lastChild;
}
// Remove IE's autoinserted <tbody> from table fragments
if ( !jQuery.support.tbody ) {
// String was a <table>, *may* have spurious <tbody>
var hasBody = rtbody.test(elem),
tbody = tag === "table" && !hasBody ?
div.firstChild && div.firstChild.childNodes :
// String was a bare <thead> or <tfoot>
wrap[1] === "<table>" && !hasBody ?
div.childNodes :
[];
for ( var j = tbody.length - 1; j >= 0 ; --j ) {
if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
tbody[ j ].parentNode.removeChild( tbody[ j ] );
}
}
}
// IE completely kills leading whitespace when innerHTML is used
if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
}
elem = div.childNodes;
}
if ( elem.nodeType ) {
ret.push( elem );
} else {
ret = jQuery.merge( ret, elem );
}
}
if ( fragment ) {
for ( i = 0; ret[i]; i++ ) {
if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
} else {
if ( ret[i].nodeType === 1 ) {
ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
}
fragment.appendChild( ret[i] );
}
}
}
return ret;
},
cleanData: function( elems ) {
var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
deleteExpando = jQuery.support.deleteExpando;
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
continue;
}
id = elem[ jQuery.expando ];
if ( id ) {
data = cache[ id ] && cache[ id ][ internalKey ];
if ( data && data.events ) {
for ( var type in data.events ) {
if ( special[ type ] ) {
jQuery.event.remove( elem, type );
// This is a shortcut to avoid jQuery.event.remove's overhead
} else {
jQuery.removeEvent( elem, type, data.handle );
}
}
// Null the DOM reference to avoid IE6/7/8 leak (#7054)
if ( data.handle ) {
data.handle.elem = null;
}
}
if ( deleteExpando ) {
delete elem[ jQuery.expando ];
} else if ( elem.removeAttribute ) {
elem.removeAttribute( jQuery.expando );
}
delete cache[ id ];
}
}
}
});
function evalScript( i, elem ) {
if ( elem.src ) {
jQuery.ajax({
url: elem.src,
async: false,
dataType: "script"
});
} else {
jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
}
if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
}
}
var ralpha = /alpha\([^)]*\)/i,
ropacity = /opacity=([^)]*)/,
rdashAlpha = /-([a-z])/ig,
rupper = /([A-Z])/g,
rnumpx = /^-?\d+(?:px)?$/i,
rnum = /^-?\d/,
cssShow = { position: "absolute", visibility: "hidden", display: "block" },
cssWidth = [ "Left", "Right" ],
cssHeight = [ "Top", "Bottom" ],
curCSS,
getComputedStyle,
currentStyle,
fcamelCase = function( all, letter ) {
return letter.toUpperCase();
};
jQuery.fn.css = function( name, value ) {
// Setting 'undefined' is a no-op
if ( arguments.length === 2 && value === undefined ) {
return this;
}
return jQuery.access( this, name, value, true, function( elem, name, value ) {
return value !== undefined ?
jQuery.style( elem, name, value ) :
jQuery.css( elem, name );
});
};
jQuery.extend({
// Add in style property hooks for overriding the default
// behavior of getting and setting a style property
cssHooks: {
opacity: {
get: function( elem, computed ) {
if ( computed ) {
// We should always get a number back from opacity
var ret = curCSS( elem, "opacity", "opacity" );
return ret === "" ? "1" : ret;
} else {
return elem.style.opacity;
}
}
}
},
// Exclude the following css properties to add px
cssNumber: {
"zIndex": true,
"fontWeight": true,
"opacity": true,
"zoom": true,
"lineHeight": true
},
// Add in properties whose names you wish to fix before
// setting or getting the value
cssProps: {
// normalize float css property
"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
},
// Get and set the style property on a DOM Node
style: function( elem, name, value, extra ) {
// Don't set styles on text and comment nodes
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
return;
}
// Make sure that we're working with the right name
var ret, origName = jQuery.camelCase( name ),
style = elem.style, hooks = jQuery.cssHooks[ origName ];
name = jQuery.cssProps[ origName ] || origName;
// Check if we're setting a value
if ( value !== undefined ) {
// Make sure that NaN and null values aren't set. See: #7116
if ( typeof value === "number" && isNaN( value ) || value == null ) {
return;
}
// If a number was passed in, add 'px' to the (except for certain CSS properties)
if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) {
value += "px";
}
// If a hook was provided, use that value, otherwise just set the specified value
if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
// Fixes bug #5509
try {
style[ name ] = value;
} catch(e) {}
}
} else {
// If a hook was provided get the non-computed value from there
if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
return ret;
}
// Otherwise just get the value from the style object
return style[ name ];
}
},
css: function( elem, name, extra ) {
// Make sure that we're working with the right name
var ret, origName = jQuery.camelCase( name ),
hooks = jQuery.cssHooks[ origName ];
name = jQuery.cssProps[ origName ] || origName;
// If a hook was provided get the computed value from there
if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
return ret;
// Otherwise, if a way to get the computed value exists, use that
} else if ( curCSS ) {
return curCSS( elem, name, origName );
}
},
// A method for quickly swapping in/out CSS properties to get correct calculations
swap: function( elem, options, callback ) {
var old = {};
// Remember the old values, and insert the new ones
for ( var name in options ) {
old[ name ] = elem.style[ name ];
elem.style[ name ] = options[ name ];
}
callback.call( elem );
// Revert the old values
for ( name in options ) {
elem.style[ name ] = old[ name ];
}
},
camelCase: function( string ) {
return string.replace( rdashAlpha, fcamelCase );
}
});
// DEPRECATED, Use jQuery.css() instead
jQuery.curCSS = jQuery.css;
jQuery.each(["height", "width"], function( i, name ) {
jQuery.cssHooks[ name ] = {
get: function( elem, computed, extra ) {
var val;
if ( computed ) {
if ( elem.offsetWidth !== 0 ) {
val = getWH( elem, name, extra );
} else {
jQuery.swap( elem, cssShow, function() {
val = getWH( elem, name, extra );
});
}
if ( val <= 0 ) {
val = curCSS( elem, name, name );
if ( val === "0px" && currentStyle ) {
val = currentStyle( elem, name, name );
}
if ( val != null ) {
// Should return "auto" instead of 0, use 0 for
// temporary backwards-compat
return val === "" || val === "auto" ? "0px" : val;
}
}
if ( val < 0 || val == null ) {
val = elem.style[ name ];
// Should return "auto" instead of 0, use 0 for
// temporary backwards-compat
return val === "" || val === "auto" ? "0px" : val;
}
return typeof val === "string" ? val : val + "px";
}
},
set: function( elem, value ) {
if ( rnumpx.test( value ) ) {
// ignore negative width and height values #1599
value = parseFloat(value);
if ( value >= 0 ) {
return value + "px";
}
} else {
return value;
}
}
};
});
if ( !jQuery.support.opacity ) {
jQuery.cssHooks.opacity = {
get: function( elem, computed ) {
// IE uses filters for opacity
return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ?
(parseFloat(RegExp.$1) / 100) + "" :
computed ? "1" : "";
},
set: function( elem, value ) {
var style = elem.style;
// IE has trouble with opacity if it does not have layout
// Force it by setting the zoom level
style.zoom = 1;
// Set the alpha filter to set the opacity
var opacity = jQuery.isNaN(value) ?
"" :
"alpha(opacity=" + value * 100 + ")",
filter = style.filter || "";
style.filter = ralpha.test(filter) ?
filter.replace(ralpha, opacity) :
style.filter + ' ' + opacity;
}
};
}
if ( document.defaultView && document.defaultView.getComputedStyle ) {
getComputedStyle = function( elem, newName, name ) {
var ret, defaultView, computedStyle;
name = name.replace( rupper, "-$1" ).toLowerCase();
if ( !(defaultView = elem.ownerDocument.defaultView) ) {
return undefined;
}
if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
ret = computedStyle.getPropertyValue( name );
if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
ret = jQuery.style( elem, name );
}
}
return ret;
};
}
if ( document.documentElement.currentStyle ) {
currentStyle = function( elem, name ) {
var left,
ret = elem.currentStyle && elem.currentStyle[ name ],
rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
style = elem.style;
// From the awesome hack by Dean Edwards
// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
// If we're not dealing with a regular pixel number
// but a number that has a weird ending, we need to convert it to pixels
if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
// Remember the original values
left = style.left;
// Put in the new values to get a computed value out
if ( rsLeft ) {
elem.runtimeStyle.left = elem.currentStyle.left;
}
style.left = name === "fontSize" ? "1em" : (ret || 0);
ret = style.pixelLeft + "px";
// Revert the changed values
style.left = left;
if ( rsLeft ) {
elem.runtimeStyle.left = rsLeft;
}
}
return ret === "" ? "auto" : ret;
};
}
curCSS = getComputedStyle || currentStyle;
function getWH( elem, name, extra ) {
var which = name === "width" ? cssWidth : cssHeight,
val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
if ( extra === "border" ) {
return val;
}
jQuery.each( which, function() {
if ( !extra ) {
val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
}
if ( extra === "margin" ) {
val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;
} else {
val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;
}
});
return val;
}
if ( jQuery.expr && jQuery.expr.filters ) {
jQuery.expr.filters.hidden = function( elem ) {
var width = elem.offsetWidth,
height = elem.offsetHeight;
return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
};
jQuery.expr.filters.visible = function( elem ) {
return !jQuery.expr.filters.hidden( elem );
};
}
var r20 = /%20/g,
rbracket = /\[\]$/,
rCRLF = /\r?\n/g,
rhash = /#.*$/,
rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL
rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
rnoContent = /^(?:GET|HEAD)$/,
rprotocol = /^\/\//,
rquery = /\?/,
rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
rselectTextarea = /^(?:select|textarea)/i,
rspacesAjax = /\s+/,
rts = /([?&])_=[^&]*/,
rurl = /^(\w+:)\/\/([^\/?#:]+)(?::(\d+))?/,
// Keep a copy of the old load method
_load = jQuery.fn.load,
/* Prefilters
* 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
* 2) These are called:
* - BEFORE asking for a transport
* - AFTER param serialization (s.data is a string if s.processData is true)
* 3) key is the dataType
* 4) the catchall symbol "*" can be used
* 5) execution will start with transport dataType and THEN continue down to "*" if needed
*/
prefilters = {},
/* Transports bindings
* 1) key is the dataType
* 2) the catchall symbol "*" can be used
* 3) selection will start with transport dataType and THEN go to "*" if needed
*/
transports = {};
// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {
// dataTypeExpression is optional and defaults to "*"
return function( dataTypeExpression, func ) {
if ( typeof dataTypeExpression !== "string" ) {
func = dataTypeExpression;
dataTypeExpression = "*";
}
if ( jQuery.isFunction( func ) ) {
var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
i = 0,
length = dataTypes.length,
dataType,
list,
placeBefore;
// For each dataType in the dataTypeExpression
for(; i < length; i++ ) {
dataType = dataTypes[ i ];
// We control if we're asked to add before
// any existing element
placeBefore = /^\+/.test( dataType );
if ( placeBefore ) {
dataType = dataType.substr( 1 ) || "*";
}
list = structure[ dataType ] = structure[ dataType ] || [];
// then we add to the structure accordingly
list[ placeBefore ? "unshift" : "push" ]( func );
}
}
};
}
//Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, jXHR,
dataType /* internal */, inspected /* internal */ ) {
dataType = dataType || options.dataTypes[ 0 ];
inspected = inspected || {};
inspected[ dataType ] = true;
var list = structure[ dataType ],
i = 0,
length = list ? list.length : 0,
executeOnly = ( structure === prefilters ),
selection;
for(; i < length && ( executeOnly || !selection ); i++ ) {
selection = list[ i ]( options, originalOptions, jXHR );
// If we got redirected to another dataType
// we try there if not done already
if ( typeof selection === "string" ) {
if ( inspected[ selection ] ) {
selection = undefined;
} else {
options.dataTypes.unshift( selection );
selection = inspectPrefiltersOrTransports(
structure, options, originalOptions, jXHR, selection, inspected );
}
}
}
// If we're only executing or nothing was selected
// we try the catchall dataType if not done already
if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
selection = inspectPrefiltersOrTransports(
structure, options, originalOptions, jXHR, "*", inspected );
}
// unnecessary when only executing (prefilters)
// but it'll be ignored by the caller in that case
return selection;
}
jQuery.fn.extend({
load: function( url, params, callback ) {
if ( typeof url !== "string" && _load ) {
return _load.apply( this, arguments );
// Don't do a request if no elements are being requested
} else if ( !this.length ) {
return this;
}
var off = url.indexOf( " " );
if ( off >= 0 ) {
var selector = url.slice( off, url.length );
url = url.slice( 0, off );
}
// Default to a GET request
var type = "GET";
// If the second parameter was provided
if ( params ) {
// If it's a function
if ( jQuery.isFunction( params ) ) {
// We assume that it's the callback
callback = params;
params = null;
// Otherwise, build a param string
} else if ( typeof params === "object" ) {
params = jQuery.param( params, jQuery.ajaxSettings.traditional );
type = "POST";
}
}
var self = this;
// Request the remote document
jQuery.ajax({
url: url,
type: type,
dataType: "html",
data: params,
// Complete callback (responseText is used internally)
complete: function( jXHR, status, responseText ) {
// Store the response as specified by the jXHR object
responseText = jXHR.responseText;
// If successful, inject the HTML into all the matched elements
if ( jXHR.isResolved() ) {
// #4825: Get the actual response in case
// a dataFilter is present in ajaxSettings
jXHR.done(function( r ) {
responseText = r;
});
// See if a selector was specified
self.html( selector ?
// Create a dummy div to hold the results
jQuery("<div>")
// inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE
.append(responseText.replace(rscript, ""))
// Locate the specified elements
.find(selector) :
// If not, just inject the full result
responseText );
}
if ( callback ) {
self.each( callback, [ responseText, status, jXHR ] );
}
}
});
return this;
},
serialize: function() {
return jQuery.param( this.serializeArray() );
},
serializeArray: function() {
return this.map(function(){
return this.elements ? jQuery.makeArray( this.elements ) : this;
})
.filter(function(){
return this.name && !this.disabled &&
( this.checked || rselectTextarea.test( this.nodeName ) ||
rinput.test( this.type ) );
})
.map(function( i, elem ){
var val = jQuery( this ).val();
return val == null ?
null :
jQuery.isArray( val ) ?
jQuery.map( val, function( val, i ){
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}) :
{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}).get();
}
});
// Attach a bunch of functions for handling common AJAX events
jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
jQuery.fn[ o ] = function( f ){
return this.bind( o, f );
};
} );
jQuery.each( [ "get", "post" ], function( i, method ) {
jQuery[ method ] = function( url, data, callback, type ) {
// shift arguments if data argument was omitted
if ( jQuery.isFunction( data ) ) {
type = type || callback;
callback = data;
data = null;
}
return jQuery.ajax({
type: method,
url: url,
data: data,
success: callback,
dataType: type
});
};
} );
jQuery.extend({
getScript: function( url, callback ) {
return jQuery.get( url, null, callback, "script" );
},
getJSON: function( url, data, callback ) {
return jQuery.get( url, data, callback, "json" );
},
ajaxSetup: function( settings ) {
jQuery.extend( true, jQuery.ajaxSettings, settings );
if ( settings.context ) {
jQuery.ajaxSettings.context = settings.context;
}
},
ajaxSettings: {
url: location.href,
global: true,
type: "GET",
contentType: "application/x-www-form-urlencoded",
processData: true,
async: true,
/*
timeout: 0,
data: null,
dataType: null,
username: null,
password: null,
cache: null,
traditional: false,
headers: {},
crossDomain: null,
*/
accepts: {
xml: "application/xml, text/xml",
html: "text/html",
text: "text/plain",
json: "application/json, text/javascript",
"*": "*/*"
},
contents: {
xml: /xml/,
html: /html/,
json: /json/
},
responseFields: {
xml: "responseXML",
text: "responseText"
},
// List of data converters
// 1) key format is "source_type destination_type" (a single space in-between)
// 2) the catchall symbol "*" can be used for source_type
converters: {
// Convert anything to text
"* text": window.String,
// Text to html (true = no transformation)
"text html": true,
// Evaluate text as a json expression
"text json": jQuery.parseJSON,
// Parse text as xml
"text xml": jQuery.parseXML
}
},
ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
ajaxTransport: addToPrefiltersOrTransports( transports ),
// Main method
ajax: function( url, options ) {
// If options is not an object,
// we simulate pre-1.5 signature
if ( typeof options !== "object" ) {
options = url;
url = undefined;
}
// Force options to be an object
options = options || {};
var // Create the final options object
s = jQuery.extend( true, {}, jQuery.ajaxSettings, options ),
// Callbacks contexts
// We force the original context if it exists
// or take it from jQuery.ajaxSettings otherwise
// (plain objects used as context get extended)
callbackContext =
( s.context = ( "context" in options ? options : jQuery.ajaxSettings ).context ) || s,
globalEventContext = callbackContext === s ? jQuery.event : jQuery( callbackContext ),
// Deferreds
deferred = jQuery.Deferred(),
completeDeferred = jQuery._Deferred(),
// Status-dependent callbacks
statusCode = s.statusCode || {},
// Headers (they are sent all at once)
requestHeaders = {},
// Response headers
responseHeadersString,
responseHeaders,
// transport
transport,
// timeout handle
timeoutTimer,
// Cross-domain detection vars
loc = document.location,
protocol = loc.protocol || "http:",
parts,
// The jXHR state
state = 0,
// Loop variable
i,
// Fake xhr
jXHR = {
readyState: 0,
// Caches the header
setRequestHeader: function( name, value ) {
if ( state === 0 ) {
requestHeaders[ name.toLowerCase() ] = value;
}
return this;
},
// Raw string
getAllResponseHeaders: function() {
return state === 2 ? responseHeadersString : null;
},
// Builds headers hashtable if needed
getResponseHeader: function( key ) {
var match;
if ( state === 2 ) {
if ( !responseHeaders ) {
responseHeaders = {};
while( ( match = rheaders.exec( responseHeadersString ) ) ) {
responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
}
}
match = responseHeaders[ key.toLowerCase() ];
}
return match || null;
},
// Cancel the request
abort: function( statusText ) {
statusText = statusText || "abort";
if ( transport ) {
transport.abort( statusText );
}
done( 0, statusText );
return this;
}
};
// Callback for when everything is done
// It is defined here because jslint complains if it is declared
// at the end of the function (which would be more logical and readable)
function done( status, statusText, responses, headers) {
// Called once
if ( state === 2 ) {
return;
}
// State is "done" now
state = 2;
// Clear timeout if it exists
if ( timeoutTimer ) {
clearTimeout( timeoutTimer );
}
// Dereference transport for early garbage collection
// (no matter how long the jXHR object will be used)
transport = undefined;
// Cache response headers
responseHeadersString = headers || "";
// Set readyState
jXHR.readyState = status ? 4 : 0;
var isSuccess,
success,
error,
response = responses ? ajaxHandleResponses( s, jXHR, responses ) : undefined,
lastModified,
etag;
// If successful, handle type chaining
if ( status >= 200 && status < 300 || status === 304 ) {
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) {
if ( ( lastModified = jXHR.getResponseHeader( "Last-Modified" ) ) ) {
jQuery.lastModified[ s.url ] = lastModified;
}
if ( ( etag = jXHR.getResponseHeader( "Etag" ) ) ) {
jQuery.etag[ s.url ] = etag;
}
}
// If not modified
if ( status === 304 ) {
statusText = "notmodified";
isSuccess = true;
// If we have data
} else {
try {
success = ajaxConvert( s, response );
statusText = "success";
isSuccess = true;
} catch(e) {
// We have a parsererror
statusText = "parsererror";
error = e;
}
}
} else {
// We extract error from statusText
// then normalize statusText and status for non-aborts
error = statusText;
if( status ) {
statusText = "error";
if ( status < 0 ) {
status = 0;
}
}
}
// Set data for the fake xhr object
jXHR.status = status;
jXHR.statusText = statusText;
// Success/Error
if ( isSuccess ) {
deferred.resolveWith( callbackContext, [ success, statusText, jXHR ] );
} else {
deferred.rejectWith( callbackContext, [ jXHR, statusText, error ] );
}
// Status-dependent callbacks
jXHR.statusCode( statusCode );
statusCode = undefined;
if ( s.global ) {
globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
[ jXHR, s, isSuccess ? success : error ] );
}
// Complete
completeDeferred.resolveWith( callbackContext, [ jXHR, statusText ] );
if ( s.global ) {
globalEventContext.trigger( "ajaxComplete", [ jXHR, s] );
// Handle the global AJAX counter
if ( !( --jQuery.active ) ) {
jQuery.event.trigger( "ajaxStop" );
}
}
}
// Attach deferreds
deferred.promise( jXHR );
jXHR.success = jXHR.done;
jXHR.error = jXHR.fail;
jXHR.complete = completeDeferred.done;
// Status-dependent callbacks
jXHR.statusCode = function( map ) {
if ( map ) {
var tmp;
if ( state < 2 ) {
for( tmp in map ) {
statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
}
} else {
tmp = map[ jXHR.status ];
jXHR.then( tmp, tmp );
}
}
return this;
};
// Remove hash character (#7531: and string promotion)
// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
// We also use the url parameter if available
s.url = ( "" + ( url || s.url ) ).replace( rhash, "" ).replace( rprotocol, protocol + "//" );
// Extract dataTypes list
s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
// Determine if a cross-domain request is in order
if ( !s.crossDomain ) {
parts = rurl.exec( s.url.toLowerCase() );
s.crossDomain = !!( parts &&
( parts[ 1 ] != protocol || parts[ 2 ] != loc.hostname ||
( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
( loc.port || ( protocol === "http:" ? 80 : 443 ) ) )
);
}
// Convert data if not already a string
if ( s.data && s.processData && typeof s.data !== "string" ) {
s.data = jQuery.param( s.data, s.traditional );
}
// Apply prefilters
inspectPrefiltersOrTransports( prefilters, s, options, jXHR );
// Uppercase the type
s.type = s.type.toUpperCase();
// Determine if request has content
s.hasContent = !rnoContent.test( s.type );
// Watch for a new set of requests
if ( s.global && jQuery.active++ === 0 ) {
jQuery.event.trigger( "ajaxStart" );
}
// More options handling for requests with no content
if ( !s.hasContent ) {
// If data is available, append data to url
if ( s.data ) {
s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
}
// Add anti-cache in url if needed
if ( s.cache === false ) {
var ts = jQuery.now(),
// try replacing _= if it is there
ret = s.url.replace( rts, "$1_=" + ts );
// if nothing was replaced, add timestamp to the end
s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
}
}
// Set the correct header, if data is being sent
if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
requestHeaders[ "content-type" ] = s.contentType;
}
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) {
if ( jQuery.lastModified[ s.url ] ) {
requestHeaders[ "if-modified-since" ] = jQuery.lastModified[ s.url ];
}
if ( jQuery.etag[ s.url ] ) {
requestHeaders[ "if-none-match" ] = jQuery.etag[ s.url ];
}
}
// Set the Accepts header for the server, depending on the dataType
requestHeaders.accept = s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
s.accepts[ "*" ];
// Check for headers option
for ( i in s.headers ) {
requestHeaders[ i.toLowerCase() ] = s.headers[ i ];
}
// Allow custom headers/mimetypes and early abort
if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jXHR, s ) === false || state === 2 ) ) {
// Abort if not done already
done( 0, "abort" );
// Return false
jXHR = false;
} else {
// Install callbacks on deferreds
for ( i in { success: 1, error: 1, complete: 1 } ) {
jXHR[ i ]( s[ i ] );
}
// Get transport
transport = inspectPrefiltersOrTransports( transports, s, options, jXHR );
// If no transport, we auto-abort
if ( !transport ) {
done( -1, "No Transport" );
} else {
// Set state as sending
state = jXHR.readyState = 1;
// Send global event
if ( s.global ) {
globalEventContext.trigger( "ajaxSend", [ jXHR, s ] );
}
// Timeout
if ( s.async && s.timeout > 0 ) {
timeoutTimer = setTimeout( function(){
jXHR.abort( "timeout" );
}, s.timeout );
}
try {
transport.send( requestHeaders, done );
} catch (e) {
// Propagate exception as error if not done
if ( status < 2 ) {
done( -1, e );
// Simply rethrow otherwise
} else {
jQuery.error( e );
}
}
}
}
return jXHR;
},
// Serialize an array of form elements or a set of
// key/values into a query string
param: function( a, traditional ) {
var s = [],
add = function( key, value ) {
// If value is a function, invoke it and return its value
value = jQuery.isFunction( value ) ? value() : value;
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
};
// Set traditional to true for jQuery <= 1.3.2 behavior.
if ( traditional === undefined ) {
traditional = jQuery.ajaxSettings.traditional;
}
// If an array was passed in, assume that it is an array of form elements.
if ( jQuery.isArray( a ) || a.jquery ) {
// Serialize the form elements
jQuery.each( a, function() {
add( this.name, this.value );
} );
} else {
// If traditional, encode the "old" way (the way 1.3.2 or older
// did it), otherwise encode params recursively.
for ( var prefix in a ) {
buildParams( prefix, a[ prefix ], traditional, add );
}
}
// Return the resulting serialization
return s.join( "&" ).replace( r20, "+" );
}
});
function buildParams( prefix, obj, traditional, add ) {
if ( jQuery.isArray( obj ) && obj.length ) {
// Serialize array item.
jQuery.each( obj, function( i, v ) {
if ( traditional || rbracket.test( prefix ) ) {
// Treat each array item as a scalar.
add( prefix, v );
} else {
// If array item is non-scalar (array or object), encode its
// numeric index to resolve deserialization ambiguity issues.
// Note that rack (as of 1.0.0) can't currently deserialize
// nested arrays properly, and attempting to do so may cause
// a server error. Possible fixes are to modify rack's
// deserialization algorithm or to provide an option or flag
// to force array serialization to be shallow.
buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
}
});
} else if ( !traditional && obj != null && typeof obj === "object" ) {
// If we see an array here, it is empty and should be treated as an empty
// object
if ( jQuery.isArray( obj ) || jQuery.isEmptyObject( obj ) ) {
add( prefix, "" );
// Serialize object item.
} else {
jQuery.each( obj, function( k, v ) {
buildParams( prefix + "[" + k + "]", v, traditional, add );
});
}
} else {
// Serialize scalar item.
add( prefix, obj );
}
}
// This is still on the jQuery object... for now
// Want to move this to jQuery.ajax some day
jQuery.extend({
// Counter for holding the number of active queries
active: 0,
// Last-Modified header cache for next request
lastModified: {},
etag: {}
});
/* Handles responses to an ajax request:
* - sets all responseXXX fields accordingly
* - finds the right dataType (mediates between content-type and expected dataType)
* - returns the corresponding response
*/
function ajaxHandleResponses( s, jXHR, responses ) {
var contents = s.contents,
dataTypes = s.dataTypes,
responseFields = s.responseFields,
ct,
type,
finalDataType,
firstDataType;
// Fill responseXXX fields
for( type in responseFields ) {
if ( type in responses ) {
jXHR[ responseFields[type] ] = responses[ type ];
}
}
// Remove auto dataType and get content-type in the process
while( dataTypes[ 0 ] === "*" ) {
dataTypes.shift();
if ( ct === undefined ) {
ct = jXHR.getResponseHeader( "content-type" );
}
}
// Check if we're dealing with a known content-type
if ( ct ) {
for ( type in contents ) {
if ( contents[ type ] && contents[ type ].test( ct ) ) {
dataTypes.unshift( type );
break;
}
}
}
// Check to see if we have a response for the expected dataType
if ( dataTypes[ 0 ] in responses ) {
finalDataType = dataTypes[ 0 ];
} else {
// Try convertible dataTypes
for ( type in responses ) {
if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
finalDataType = type;
break;
}
if ( !firstDataType ) {
firstDataType = type;
}
}
// Or just use first one
finalDataType = finalDataType || firstDataType;
}
// If we found a dataType
// We add the dataType to the list if needed
// and return the corresponding response
if ( finalDataType ) {
if ( finalDataType !== dataTypes[ 0 ] ) {
dataTypes.unshift( finalDataType );
}
return responses[ finalDataType ];
}
}
// Chain conversions given the request and the original response
function ajaxConvert( s, response ) {
// Apply the dataFilter if provided
if ( s.dataFilter ) {
response = s.dataFilter( response, s.dataType );
}
var dataTypes = s.dataTypes,
converters = s.converters,
i,
length = dataTypes.length,
tmp,
// Current and previous dataTypes
current = dataTypes[ 0 ],
prev,
// Conversion expression
conversion,
// Conversion function
conv,
// Conversion functions (transitive conversion)
conv1,
conv2;
// For each dataType in the chain
for( i = 1; i < length; i++ ) {
// Get the dataTypes
prev = current;
current = dataTypes[ i ];
// If current is auto dataType, update it to prev
if( current === "*" ) {
current = prev;
// If no auto and dataTypes are actually different
} else if ( prev !== "*" && prev !== current ) {
// Get the converter
conversion = prev + " " + current;
conv = converters[ conversion ] || converters[ "* " + current ];
// If there is no direct converter, search transitively
if ( !conv ) {
conv2 = undefined;
for( conv1 in converters ) {
tmp = conv1.split( " " );
if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
conv2 = converters[ tmp[1] + " " + current ];
if ( conv2 ) {
conv1 = converters[ conv1 ];
if ( conv1 === true ) {
conv = conv2;
} else if ( conv2 === true ) {
conv = conv1;
}
break;
}
}
}
}
// If we found no converter, dispatch an error
if ( !( conv || conv2 ) ) {
jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
}
// If found converter is not an equivalence
if ( conv !== true ) {
// Convert with 1 or 2 converters accordingly
response = conv ? conv( response ) : conv2( conv1(response) );
}
}
}
return response;
}
var jsc = jQuery.now(),
jsre = /(\=)\?(&|$)|()\?\?()/i;
// Default jsonp settings
jQuery.ajaxSetup({
jsonp: "callback",
jsonpCallback: function() {
return jQuery.expando + "_" + ( jsc++ );
}
});
// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, dataIsString /* internal */ ) {
dataIsString = ( typeof s.data === "string" );
if ( s.dataTypes[ 0 ] === "jsonp" ||
originalSettings.jsonpCallback ||
originalSettings.jsonp != null ||
s.jsonp !== false && ( jsre.test( s.url ) ||
dataIsString && jsre.test( s.data ) ) ) {
var responseContainer,
jsonpCallback = s.jsonpCallback =
jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
previous = window[ jsonpCallback ],
url = s.url,
data = s.data,
replace = "$1" + jsonpCallback + "$2";
if ( s.jsonp !== false ) {
url = url.replace( jsre, replace );
if ( s.url === url ) {
if ( dataIsString ) {
data = data.replace( jsre, replace );
}
if ( s.data === data ) {
// Add callback manually
url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
}
}
}
s.url = url;
s.data = data;
window[ jsonpCallback ] = function( response ) {
responseContainer = [ response ];
};
s.complete = [ function() {
// Set callback back to previous value
window[ jsonpCallback ] = previous;
// Call if it was a function and we have a response
if ( previous) {
if ( responseContainer && jQuery.isFunction( previous ) ) {
window[ jsonpCallback ] ( responseContainer[ 0 ] );
}
} else {
// else, more memory leak avoidance
try{
delete window[ jsonpCallback ];
} catch( e ) {}
}
}, s.complete ];
// Use data converter to retrieve json after script execution
s.converters["script json"] = function() {
if ( ! responseContainer ) {
jQuery.error( jsonpCallback + " was not called" );
}
return responseContainer[ 0 ];
};
// force json dataType
s.dataTypes[ 0 ] = "json";
// Delegate to script
return "script";
}
} );
// Install script dataType
jQuery.ajaxSetup({
accepts: {
script: "text/javascript, application/javascript"
},
contents: {
script: /javascript/
},
converters: {
"text script": function( text ) {
jQuery.globalEval( text );
return text;
}
}
});
// Handle cache's special case and global
jQuery.ajaxPrefilter( "script", function( s ) {
if ( s.cache === undefined ) {
s.cache = false;
}
if ( s.crossDomain ) {
s.type = "GET";
s.global = false;
}
} );
// Bind script tag hack transport
jQuery.ajaxTransport( "script", function(s) {
// This transport only deals with cross domain requests
if ( s.crossDomain ) {
var script,
head = document.getElementsByTagName( "head" )[ 0 ] || document.documentElement;
return {
send: function( _, callback ) {
script = document.createElement( "script" );
script.async = "async";
if ( s.scriptCharset ) {
script.charset = s.scriptCharset;
}
script.src = s.url;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function( _, isAbort ) {
if ( !script.readyState || /loaded|complete/.test( script.readyState ) ) {
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
// Remove the script
if ( head && script.parentNode ) {
head.removeChild( script );
}
// Dereference the script
script = undefined;
// Callback if not abort
if ( !isAbort ) {
callback( 200, "success" );
}
}
};
// Use insertBefore instead of appendChild to circumvent an IE6 bug.
// This arises when a base node is used (#2709 and #4378).
head.insertBefore( script, head.firstChild );
},
abort: function() {
if ( script ) {
script.onload( 0, 1 );
}
}
};
}
} );
var // Next active xhr id
xhrId = jQuery.now(),
// active xhrs
xhrs = {},
// #5280: see below
xhrUnloadAbortInstalled,
// XHR used to determine supports properties
testXHR;
// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
/* Microsoft failed to properly
* implement the XMLHttpRequest in IE7 (can't request local files),
* so we use the ActiveXObject when it is available
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so
* we need a fallback.
*/
function() {
if ( window.location.protocol !== "file:" ) {
try {
return new window.XMLHttpRequest();
} catch( xhrError ) {}
}
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch( activeError ) {}
} :
// For all other browsers, use the standard XMLHttpRequest object
function() {
return new window.XMLHttpRequest();
};
// Test if we can create an xhr object
try {
testXHR = jQuery.ajaxSettings.xhr();
} catch( xhrCreationException ) {}
//Does this browser support XHR requests?
jQuery.support.ajax = !!testXHR;
// Does this browser support crossDomain XHR requests
jQuery.support.cors = testXHR && ( "withCredentials" in testXHR );
// No need for the temporary xhr anymore
testXHR = undefined;
// Create transport if the browser can provide an xhr
if ( jQuery.support.ajax ) {
jQuery.ajaxTransport(function( s ) {
// Cross domain only allowed if supported through XMLHttpRequest
if ( !s.crossDomain || jQuery.support.cors ) {
var callback;
return {
send: function( headers, complete ) {
// #5280: we need to abort on unload or IE will keep connections alive
if ( !xhrUnloadAbortInstalled ) {
xhrUnloadAbortInstalled = 1;
jQuery(window).bind( "unload", function() {
// Abort all pending requests
jQuery.each( xhrs, function( _, xhr ) {
if ( xhr.onreadystatechange ) {
xhr.onreadystatechange( 1 );
}
} );
} );
}
// Get a new xhr
var xhr = s.xhr(),
handle;
// Open the socket
// Passing null username, generates a login popup on Opera (#2865)
if ( s.username ) {
xhr.open( s.type, s.url, s.async, s.username, s.password );
} else {
xhr.open( s.type, s.url, s.async );
}
// Requested-With header
// Not set for crossDomain requests with no content
// (see why at http://trac.dojotoolkit.org/ticket/9486)
// Won't change header if already provided
if ( !( s.crossDomain && !s.hasContent ) && !headers["x-requested-with"] ) {
headers[ "x-requested-with" ] = "XMLHttpRequest";
}
// Need an extra try/catch for cross domain requests in Firefox 3
try {
jQuery.each( headers, function( key, value ) {
xhr.setRequestHeader( key, value );
} );
} catch( _ ) {}
// Do send the request
// This may raise an exception which is actually
// handled in jQuery.ajax (so no try/catch here)
xhr.send( ( s.hasContent && s.data ) || null );
// Listener
callback = function( _, isAbort ) {
// Was never called and is aborted or complete
if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
// Only called once
callback = 0;
// Do not keep as active anymore
if ( handle ) {
xhr.onreadystatechange = jQuery.noop;
delete xhrs[ handle ];
}
// If it's an abort
if ( isAbort ) {
// Abort it manually if needed
if ( xhr.readyState !== 4 ) {
xhr.abort();
}
} else {
// Get info
var status = xhr.status,
statusText,
responseHeaders = xhr.getAllResponseHeaders(),
responses = {},
xml = xhr.responseXML;
// Construct response list
if ( xml && xml.documentElement /* #4958 */ ) {
responses.xml = xml;
}
responses.text = xhr.responseText;
// Firefox throws an exception when accessing
// statusText for faulty cross-domain requests
try {
statusText = xhr.statusText;
} catch( e ) {
// We normalize with Webkit giving an empty statusText
statusText = "";
}
// Filter status for non standard behaviours
status =
// Opera returns 0 when it should be 304
// Webkit returns 0 for failing cross-domain no matter the real status
status === 0 ?
(
// Webkit, Firefox: filter out faulty cross-domain requests
!s.crossDomain || statusText ?
(
// Opera: filter out real aborts #6060
responseHeaders ?
304 :
0
) :
// We assume 302 but could be anything cross-domain related
302
) :
(
// IE sometimes returns 1223 when it should be 204 (see #1450)
status == 1223 ?
204 :
status
);
// Call complete
complete( status, statusText, responses, responseHeaders );
}
}
};
// if we're in sync mode or it's in cache
// and has been retrieved directly (IE6 & IE7)
// we need to manually fire the callback
if ( !s.async || xhr.readyState === 4 ) {
callback();
} else {
// Add to list of active xhrs
handle = xhrId++;
xhrs[ handle ] = xhr;
xhr.onreadystatechange = callback;
}
},
abort: function() {
if ( callback ) {
callback(0,1);
}
}
};
}
});
}
var elemdisplay = {},
rfxtypes = /^(?:toggle|show|hide)$/,
rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
timerId,
fxAttrs = [
// height animations
[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
// width animations
[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
// opacity animations
[ "opacity" ]
];
jQuery.fn.extend({
show: function( speed, easing, callback ) {
var elem, display;
if ( speed || speed === 0 ) {
return this.animate( genFx("show", 3), speed, easing, callback);
} else {
for ( var i = 0, j = this.length; i < j; i++ ) {
elem = this[i];
display = elem.style.display;
// Reset the inline display of this element to learn if it is
// being hidden by cascaded rules or not
if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
display = elem.style.display = "";
}
// Set elements which have been overridden with display: none
// in a stylesheet to whatever the default browser style is
// for such an element
if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
}
}
// Set the display of most of the elements in a second loop
// to avoid the constant reflow
for ( i = 0; i < j; i++ ) {
elem = this[i];
display = elem.style.display;
if ( display === "" || display === "none" ) {
elem.style.display = jQuery._data(elem, "olddisplay") || "";
}
}
return this;
}
},
hide: function( speed, easing, callback ) {
if ( speed || speed === 0 ) {
return this.animate( genFx("hide", 3), speed, easing, callback);
} else {
for ( var i = 0, j = this.length; i < j; i++ ) {
var display = jQuery.css( this[i], "display" );
if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
jQuery._data( this[i], "olddisplay", display );
}
}
// Set the display of the elements in a second loop
// to avoid the constant reflow
for ( i = 0; i < j; i++ ) {
this[i].style.display = "none";
}
return this;
}
},
// Save the old toggle function
_toggle: jQuery.fn.toggle,
toggle: function( fn, fn2, callback ) {
var bool = typeof fn === "boolean";
if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
this._toggle.apply( this, arguments );
} else if ( fn == null || bool ) {
this.each(function() {
var state = bool ? fn : jQuery(this).is(":hidden");
jQuery(this)[ state ? "show" : "hide" ]();
});
} else {
this.animate(genFx("toggle", 3), fn, fn2, callback);
}
return this;
},
fadeTo: function( speed, to, easing, callback ) {
return this.filter(":hidden").css("opacity", 0).show().end()
.animate({opacity: to}, speed, easing, callback);
},
animate: function( prop, speed, easing, callback ) {
var optall = jQuery.speed(speed, easing, callback);
if ( jQuery.isEmptyObject( prop ) ) {
return this.each( optall.complete );
}
return this[ optall.queue === false ? "each" : "queue" ](function() {
// XXX 'this' does not always have a nodeName when running the
// test suite
var opt = jQuery.extend({}, optall), p,
isElement = this.nodeType === 1,
hidden = isElement && jQuery(this).is(":hidden"),
self = this;
for ( p in prop ) {
var name = jQuery.camelCase( p );
if ( p !== name ) {
prop[ name ] = prop[ p ];
delete prop[ p ];
p = name;
}
if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
return opt.complete.call(this);
}
if ( isElement && ( p === "height" || p === "width" ) ) {
// Make sure that nothing sneaks out
// Record all 3 overflow attributes because IE does not
// change the overflow attribute when overflowX and
// overflowY are set to the same value
opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
// Set display property to inline-block for height/width
// animations on inline elements that are having width/height
// animated
if ( jQuery.css( this, "display" ) === "inline" &&
jQuery.css( this, "float" ) === "none" ) {
if ( !jQuery.support.inlineBlockNeedsLayout ) {
this.style.display = "inline-block";
} else {
var display = defaultDisplay(this.nodeName);
// inline-level elements accept inline-block;
// block-level elements need to be inline with layout
if ( display === "inline" ) {
this.style.display = "inline-block";
} else {
this.style.display = "inline";
this.style.zoom = 1;
}
}
}
}
if ( jQuery.isArray( prop[p] ) ) {
// Create (if needed) and add to specialEasing
(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
prop[p] = prop[p][0];
}
}
if ( opt.overflow != null ) {
this.style.overflow = "hidden";
}
opt.curAnim = jQuery.extend({}, prop);
jQuery.each( prop, function( name, val ) {
var e = new jQuery.fx( self, opt, name );
if ( rfxtypes.test(val) ) {
e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
} else {
var parts = rfxnum.exec(val),
start = e.cur() || 0;
if ( parts ) {
var end = parseFloat( parts[2] ),
unit = parts[3] || "px";
// We need to compute starting value
if ( unit !== "px" ) {
jQuery.style( self, name, (end || 1) + unit);
start = ((end || 1) / e.cur()) * start;
jQuery.style( self, name, start + unit);
}
// If a +=/-= token was provided, we're doing a relative animation
if ( parts[1] ) {
end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
}
e.custom( start, end, unit );
} else {
e.custom( start, val, "" );
}
}
});
// For JS strict compliance
return true;
});
},
stop: function( clearQueue, gotoEnd ) {
var timers = jQuery.timers;
if ( clearQueue ) {
this.queue([]);
}
this.each(function() {
// go in reverse order so anything added to the queue during the loop is ignored
for ( var i = timers.length - 1; i >= 0; i-- ) {
if ( timers[i].elem === this ) {
if (gotoEnd) {
// force the next step to be the last
timers[i](true);
}
timers.splice(i, 1);
}
}
});
// start the next in the queue if the last step wasn't forced
if ( !gotoEnd ) {
this.dequeue();
}
return this;
}
});
function genFx( type, num ) {
var obj = {};
jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
obj[ this ] = type;
});
return obj;
}
// Generate shortcuts for custom animations
jQuery.each({
slideDown: genFx("show", 1),
slideUp: genFx("hide", 1),
slideToggle: genFx("toggle", 1),
fadeIn: { opacity: "show" },
fadeOut: { opacity: "hide" },
fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
jQuery.fn[ name ] = function( speed, easing, callback ) {
return this.animate( props, speed, easing, callback );
};
});
jQuery.extend({
speed: function( speed, easing, fn ) {
var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
complete: fn || !fn && easing ||
jQuery.isFunction( speed ) && speed,
duration: speed,
easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
};
opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
// Queueing
opt.old = opt.complete;
opt.complete = function() {
if ( opt.queue !== false ) {
jQuery(this).dequeue();
}
if ( jQuery.isFunction( opt.old ) ) {
opt.old.call( this );
}
};
return opt;
},
easing: {
linear: function( p, n, firstNum, diff ) {
return firstNum + diff * p;
},
swing: function( p, n, firstNum, diff ) {
return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
}
},
timers: [],
fx: function( elem, options, prop ) {
this.options = options;
this.elem = elem;
this.prop = prop;
if ( !options.orig ) {
options.orig = {};
}
}
});
jQuery.fx.prototype = {
// Simple function for setting a style value
update: function() {
if ( this.options.step ) {
this.options.step.call( this.elem, this.now, this );
}
(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
},
// Get the current size
cur: function() {
if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
return this.elem[ this.prop ];
}
var r = parseFloat( jQuery.css( this.elem, this.prop ) );
return r || 0;
},
// Start an animation from one number to another
custom: function( from, to, unit ) {
var self = this,
fx = jQuery.fx;
this.startTime = jQuery.now();
this.start = from;
this.end = to;
this.unit = unit || this.unit || "px";
this.now = this.start;
this.pos = this.state = 0;
function t( gotoEnd ) {
return self.step(gotoEnd);
}
t.elem = this.elem;
if ( t() && jQuery.timers.push(t) && !timerId ) {
timerId = setInterval(fx.tick, fx.interval);
}
},
// Simple 'show' function
show: function() {
// Remember where we started, so that we can go back to it later
this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
this.options.show = true;
// Begin the animation
// Make sure that we start at a small width/height to avoid any
// flash of content
this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
// Start by showing the element
jQuery( this.elem ).show();
},
// Simple 'hide' function
hide: function() {
// Remember where we started, so that we can go back to it later
this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
this.options.hide = true;
// Begin the animation
this.custom(this.cur(), 0);
},
// Each step of an animation
step: function( gotoEnd ) {
var t = jQuery.now(), done = true;
if ( gotoEnd || t >= this.options.duration + this.startTime ) {
this.now = this.end;
this.pos = this.state = 1;
this.update();
this.options.curAnim[ this.prop ] = true;
for ( var i in this.options.curAnim ) {
if ( this.options.curAnim[i] !== true ) {
done = false;
}
}
if ( done ) {
// Reset the overflow
if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
var elem = this.elem,
options = this.options;
jQuery.each( [ "", "X", "Y" ], function (index, value) {
elem.style[ "overflow" + value ] = options.overflow[index];
} );
}
// Hide the element if the "hide" operation was done
if ( this.options.hide ) {
jQuery(this.elem).hide();
}
// Reset the properties, if the item has been hidden or shown
if ( this.options.hide || this.options.show ) {
for ( var p in this.options.curAnim ) {
jQuery.style( this.elem, p, this.options.orig[p] );
}
}
// Execute the complete function
this.options.complete.call( this.elem );
}
return false;
} else {
var n = t - this.startTime;
this.state = n / this.options.duration;
// Perform the easing function, defaults to swing
var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
this.now = this.start + ((this.end - this.start) * this.pos);
// Perform the next step of the animation
this.update();
}
return true;
}
};
jQuery.extend( jQuery.fx, {
tick: function() {
var timers = jQuery.timers;
for ( var i = 0; i < timers.length; i++ ) {
if ( !timers[i]() ) {
timers.splice(i--, 1);
}
}
if ( !timers.length ) {
jQuery.fx.stop();
}
},
interval: 13,
stop: function() {
clearInterval( timerId );
timerId = null;
},
speeds: {
slow: 600,
fast: 200,
// Default speed
_default: 400
},
step: {
opacity: function( fx ) {
jQuery.style( fx.elem, "opacity", fx.now );
},
_default: function( fx ) {
if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
} else {
fx.elem[ fx.prop ] = fx.now;
}
}
}
});
if ( jQuery.expr && jQuery.expr.filters ) {
jQuery.expr.filters.animated = function( elem ) {
return jQuery.grep(jQuery.timers, function( fn ) {
return elem === fn.elem;
}).length;
};
}
function defaultDisplay( nodeName ) {
if ( !elemdisplay[ nodeName ] ) {
var elem = jQuery("<" + nodeName + ">").appendTo("body"),
display = elem.css("display");
elem.remove();
if ( display === "none" || display === "" ) {
display = "block";
}
elemdisplay[ nodeName ] = display;
}
return elemdisplay[ nodeName ];
}
var rtable = /^t(?:able|d|h)$/i,
rroot = /^(?:body|html)$/i;
if ( "getBoundingClientRect" in document.documentElement ) {
jQuery.fn.offset = function( options ) {
var elem = this[0], box;
if ( options ) {
return this.each(function( i ) {
jQuery.offset.setOffset( this, options, i );
});
}
if ( !elem || !elem.ownerDocument ) {
return null;
}
if ( elem === elem.ownerDocument.body ) {
return jQuery.offset.bodyOffset( elem );
}
try {
box = elem.getBoundingClientRect();
} catch(e) {}
var doc = elem.ownerDocument,
docElem = doc.documentElement;
// Make sure we're not dealing with a disconnected DOM node
if ( !box || !jQuery.contains( docElem, elem ) ) {
return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
}
var body = doc.body,
win = getWindow(doc),
clientTop = docElem.clientTop || body.clientTop || 0,
clientLeft = docElem.clientLeft || body.clientLeft || 0,
scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ),
scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft),
top = box.top + scrollTop - clientTop,
left = box.left + scrollLeft - clientLeft;
return { top: top, left: left };
};
} else {
jQuery.fn.offset = function( options ) {
var elem = this[0];
if ( options ) {
return this.each(function( i ) {
jQuery.offset.setOffset( this, options, i );
});
}
if ( !elem || !elem.ownerDocument ) {
return null;
}
if ( elem === elem.ownerDocument.body ) {
return jQuery.offset.bodyOffset( elem );
}
jQuery.offset.initialize();
var computedStyle,
offsetParent = elem.offsetParent,
prevOffsetParent = elem,
doc = elem.ownerDocument,
docElem = doc.documentElement,
body = doc.body,
defaultView = doc.defaultView,
prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
top = elem.offsetTop,
left = elem.offsetLeft;
while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
break;
}
computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
top -= elem.scrollTop;
left -= elem.scrollLeft;
if ( elem === offsetParent ) {
top += elem.offsetTop;
left += elem.offsetLeft;
if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
top += parseFloat( computedStyle.borderTopWidth ) || 0;
left += parseFloat( computedStyle.borderLeftWidth ) || 0;
}
prevOffsetParent = offsetParent;
offsetParent = elem.offsetParent;
}
if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
top += parseFloat( computedStyle.borderTopWidth ) || 0;
left += parseFloat( computedStyle.borderLeftWidth ) || 0;
}
prevComputedStyle = computedStyle;
}
if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
top += body.offsetTop;
left += body.offsetLeft;
}
if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
top += Math.max( docElem.scrollTop, body.scrollTop );
left += Math.max( docElem.scrollLeft, body.scrollLeft );
}
return { top: top, left: left };
};
}
jQuery.offset = {
initialize: function() {
var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
container.innerHTML = html;
body.insertBefore( container, body.firstChild );
innerDiv = container.firstChild;
checkDiv = innerDiv.firstChild;
td = innerDiv.nextSibling.firstChild.firstChild;
this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
checkDiv.style.position = "fixed";
checkDiv.style.top = "20px";
// safari subtracts parent border width here which is 5px
this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
checkDiv.style.position = checkDiv.style.top = "";
innerDiv.style.overflow = "hidden";
innerDiv.style.position = "relative";
this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
body.removeChild( container );
body = container = innerDiv = checkDiv = table = td = null;
jQuery.offset.initialize = jQuery.noop;
},
bodyOffset: function( body ) {
var top = body.offsetTop,
left = body.offsetLeft;
jQuery.offset.initialize();
if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
}
return { top: top, left: left };
},
setOffset: function( elem, options, i ) {
var position = jQuery.css( elem, "position" );
// set position first, in-case top/left are set even on static elem
if ( position === "static" ) {
elem.style.position = "relative";
}
var curElem = jQuery( elem ),
curOffset = curElem.offset(),
curCSSTop = jQuery.css( elem, "top" ),
curCSSLeft = jQuery.css( elem, "left" ),
calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),
props = {}, curPosition = {}, curTop, curLeft;
// need to be able to calculate position if either top or left is auto and position is absolute
if ( calculatePosition ) {
curPosition = curElem.position();
}
curTop = calculatePosition ? curPosition.top : parseInt( curCSSTop, 10 ) || 0;
curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;
if ( jQuery.isFunction( options ) ) {
options = options.call( elem, i, curOffset );
}
if (options.top != null) {
props.top = (options.top - curOffset.top) + curTop;
}
if (options.left != null) {
props.left = (options.left - curOffset.left) + curLeft;
}
if ( "using" in options ) {
options.using.call( elem, props );
} else {
curElem.css( props );
}
}
};
jQuery.fn.extend({
position: function() {
if ( !this[0] ) {
return null;
}
var elem = this[0],
// Get *real* offsetParent
offsetParent = this.offsetParent(),
// Get correct offsets
offset = this.offset(),
parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
// Subtract element margins
// note: when an element has margin: auto the offsetLeft and marginLeft
// are the same in Safari causing offset.left to incorrectly be 0
offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
// Add offsetParent borders
parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
// Subtract the two offsets
return {
top: offset.top - parentOffset.top,
left: offset.left - parentOffset.left
};
},
offsetParent: function() {
return this.map(function() {
var offsetParent = this.offsetParent || document.body;
while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
offsetParent = offsetParent.offsetParent;
}
return offsetParent;
});
}
});
// Create scrollLeft and scrollTop methods
jQuery.each( ["Left", "Top"], function( i, name ) {
var method = "scroll" + name;
jQuery.fn[ method ] = function(val) {
var elem = this[0], win;
if ( !elem ) {
return null;
}
if ( val !== undefined ) {
// Set the scroll offset
return this.each(function() {
win = getWindow( this );
if ( win ) {
win.scrollTo(
!i ? val : jQuery(win).scrollLeft(),
i ? val : jQuery(win).scrollTop()
);
} else {
this[ method ] = val;
}
});
} else {
win = getWindow( elem );
// Return the scroll offset
return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
jQuery.support.boxModel && win.document.documentElement[ method ] ||
win.document.body[ method ] :
elem[ method ];
}
};
});
function getWindow( elem ) {
return jQuery.isWindow( elem ) ?
elem :
elem.nodeType === 9 ?
elem.defaultView || elem.parentWindow :
false;
}
// Create innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height", "Width" ], function( i, name ) {
var type = name.toLowerCase();
// innerHeight and innerWidth
jQuery.fn["inner" + name] = function() {
return this[0] ?
parseFloat( jQuery.css( this[0], type, "padding" ) ) :
null;
};
// outerHeight and outerWidth
jQuery.fn["outer" + name] = function( margin ) {
return this[0] ?
parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) :
null;
};
jQuery.fn[ type ] = function( size ) {
// Get window width or height
var elem = this[0];
if ( !elem ) {
return size == null ? null : this;
}
if ( jQuery.isFunction( size ) ) {
return this.each(function( i ) {
var self = jQuery( this );
self[ type ]( size.call( this, i, self[ type ]() ) );
});
}
if ( jQuery.isWindow( elem ) ) {
// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
var docElemProp = elem.document.documentElement[ "client" + name ];
return elem.document.compatMode === "CSS1Compat" && docElemProp ||
elem.document.body[ "client" + name ] || docElemProp;
// Get document width or height
} else if ( elem.nodeType === 9 ) {
// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
return Math.max(
elem.documentElement["client" + name],
elem.body["scroll" + name], elem.documentElement["scroll" + name],
elem.body["offset" + name], elem.documentElement["offset" + name]
);
// Get or set width or height on the element
} else if ( size === undefined ) {
var orig = jQuery.css( elem, type ),
ret = parseFloat( orig );
return jQuery.isNaN( ret ) ? orig : ret;
// Set the width or height on the element (default to pixels if value is unitless)
} else {
return this.css( type, typeof size === "string" ? size : size + "px" );
}
};
});
})(window);