*/\r
var jQuery = function(a,c) {\r
\r
- // Shortcut for document ready (because $(document).each() is silly)\r
+ // Shortcut for document ready\r
if ( a && typeof a == "function" && jQuery.fn.ready && !a.nodeType && a[0] == undefined ) // Safari reports typeof on DOM NodeLists as a function\r
return jQuery(document).ready(a);\r
\r
// Find the matching elements and save them for later\r
jQuery.find( a, c ) );\r
\r
+ // See if an extra function was provided\r
+ var fn = arguments[ arguments.length - 1 ];\r
+\r
+ // If so, execute it in context\r
+ if ( fn && typeof fn == "function" )\r
+ this.each(fn);\r
+\r
return this;\r
};\r
\r
* technically, chainable - there really isn't much use for chaining against it.\r
* You can have as many $(document).ready events on your page as you like.\r
*\r
+ * See ready(Function) for details about the ready event.\r
+ *\r
* @example $(function(){\r
* // Document is ready\r
* });\r
/**\r
* Set a single property to a value, on all matched elements.\r
*\r
+ * Note that you can't set the name property of input elements in IE.\r
+ * Use $(html) or $().append(html) or $().html(html) to create elements\r
+ * on the fly including the name property.\r
+ *\r
* @example $("img").attr("src","test.jpg");\r
* @before <img/>\r
* @result <img src="test.jpg"/>\r
*/\r
attr: function( key, value, type ) {\r
// Check to see if we're setting style values\r
- return key.constructor != String || value != undefined ?\r
+ return typeof key != "string" || value != undefined ?\r
this.each(function(){\r
// See if we're setting a hash of styles\r
if ( value == undefined )\r
find: function(t) {\r
return this.pushStack( jQuery.map( this, function(a){\r
return jQuery.find(t,a);\r
- }));\r
+ }), arguments );\r
},\r
\r
/**\r
clone: function(deep) {\r
return this.pushStack( jQuery.map( this, function(a){\r
return a.cloneNode( deep != undefined ? deep : true );\r
- }));\r
+ }), arguments );\r
},\r
\r
/**\r
typeof t == "function" &&\r
jQuery.grep( this, t ) ||\r
\r
- jQuery.filter(t,this).r );\r
+ jQuery.filter(t,this).r, arguments );\r
},\r
\r
/**\r
not: function(t) {\r
return this.pushStack( typeof t == "string" ?\r
jQuery.filter(t,this,false).r :\r
- jQuery.grep(this,function(a){ return a != t; }) );\r
+ jQuery.grep(this,function(a){ return a != t; }), arguments );\r
},\r
\r
/**\r
*/\r
add: function(t) {\r
return this.pushStack( jQuery.merge( this, typeof t == "string" ?\r
- jQuery.find(t) : t.constructor == Array ? t : [t] ) );\r
+ jQuery.find(t) : t.constructor == Array ? t : [t] ), arguments );\r
},\r
\r
/**\r
* @private\r
* @name domManip\r
* @param Array args\r
- * @param Boolean table\r
- * @param Number dir\r
+ * @param Boolean table Insert TBODY in TABLEs if one is not found.\r
+ * @param Number dir If dir<0, process args in reverse order.\r
* @param Function fn The function doing the DOM manipulation.\r
* @type jQuery\r
* @cat Core\r
*/\r
domManip: function(args, table, dir, fn){\r
- var clone = this.size() > 1;\r
+ var clone = this.length > 1; \r
var a = jQuery.clean(args);\r
+ if ( dir < 0 )\r
+ a.reverse();\r
\r
return this.each(function(){\r
var obj = this;\r
\r
- if ( table && this.nodeName.toUpperCase() == "TABLE" && a[0].nodeName.toUpperCase() != "THEAD" ) {\r
- var tbody = this.getElementsByTagName("tbody");\r
+ if ( table && this.nodeName.toUpperCase() == "TABLE" && a[0].nodeName.toUpperCase() == "TR" )\r
+ obj = this.getElementsByTagName("tbody")[0] || this.appendChild(document.createElement("tbody"));\r
\r
- if ( !tbody.length ) {\r
- obj = document.createElement("tbody");\r
- this.appendChild( obj );\r
- } else\r
- obj = tbody[0];\r
- }\r
+ for ( var i=0; i < a.length; i++ )\r
+ fn.apply( obj, [ clone ? a[i].cloneNode(true) : a[i] ] );\r
\r
- for ( var i = ( dir < 0 ? a.length - 1 : 0 );\r
- i != ( dir < 0 ? dir : a.length ); i += dir ) {\r
- fn.apply( obj, [ clone ? a[i].cloneNode(true) : a[i] ] );\r
- }\r
});\r
},\r
\r
* @type jQuery\r
* @cat Core\r
*/\r
- pushStack: function(a) {\r
- if ( !this.stack )\r
- this.stack = [];\r
- this.stack.push( this.get() );\r
- return this.set( a );\r
+ pushStack: function(a,args) {\r
+ var fn = args && args.length > 1 && args[args.length-1];\r
+ var fn2 = args && args.length > 2 && args[args.length-2];\r
+ \r
+ if ( fn && fn.constructor != Function ) fn = null;\r
+ if ( fn2 && fn2.constructor != Function ) fn2 = null;\r
+\r
+ if ( !fn ) {\r
+ if ( !this.stack ) this.stack = [];\r
+ this.stack.push( this.get() );\r
+ this.set( a );\r
+ } else {\r
+ var old = this.get();\r
+ this.set( a );\r
+\r
+ if ( fn2 && a.length || !fn2 )\r
+ this.each( fn2 || fn ).set( old );\r
+ else\r
+ this.set( old ).each( fn );\r
+ }\r
+\r
+ return this;\r
}\r
};\r
\r
\r
ret = elem.style[prop];\r
\r
- } else if (elem.currentStyle) {\r
-\r
- var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();});\r
- ret = elem.currentStyle[prop] || elem.currentStyle[newProp];\r
-\r
} else if (document.defaultView && document.defaultView.getComputedStyle) {\r
\r
if (prop == "cssFloat" || prop == "styleFloat")\r
ret = 'none';\r
else\r
jQuery.swap(elem, { display: 'block' }, function() {\r
- ret = document.defaultView.getComputedStyle(this,null).getPropertyValue(prop);\r
+ var c = document.defaultView.getComputedStyle(this, '');\r
+ ret = c && c.getPropertyValue(prop) || '';\r
});\r
\r
+ } else if (elem.currentStyle) {\r
+\r
+ var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();});\r
+ ret = elem.currentStyle[prop] || elem.currentStyle[newProp];\r
+ \r
}\r
\r
return ret;\r
},\r
\r
- clean: function(a) {\r
+ clean: function(a) {\r
var r = [];\r
for ( var i = 0; i < a.length; i++ ) {\r
var arg = a[i];\r
if ( typeof arg == "string" ) { // Convert html string into DOM nodes\r
// Trim whitespace, otherwise indexOf won't work as expected\r
- var s = jQuery.trim(arg), div = document.createElement("div"), wrap = [0,"",""];\r
+ var s = jQuery.trim(arg), s3 = s.substring(0,3), s6 = s.substring(0,6),\r
+ div = document.createElement("div"), wrap = [0,"",""];\r
\r
- if ( !s.indexOf("<opt") ) // option or optgroup\r
+ if ( s.substring(0,4) == "<opt" ) // option or optgroup\r
wrap = [1, "<select>", "</select>"];\r
- else if ( !s.indexOf("<thead") || !s.indexOf("<tbody") )\r
+ else if ( s6 == "<thead" || s6 == "<tbody" || s6 == "<tfoot" )\r
wrap = [1, "<table>", "</table>"];\r
- else if ( !s.indexOf("<tr") )\r
- wrap = [2, "<table>", "</table>"]; // tbody auto-inserted\r
- else if ( !s.indexOf("<td") || !s.indexOf("<th") )\r
+ else if ( s3 == "<tr" )\r
+ wrap = [2, "<table><tbody>", "</tbody></table>"];\r
+ else if ( s3 == "<td" || s3 == "<th" ) // <thead> matched above\r
wrap = [3, "<table><tbody><tr>", "</tr></tbody></table>"];\r
\r
// Go to html and back, then peel off extra wrappers\r
div.innerHTML = wrap[1] + s + wrap[2];\r
while ( wrap[0]-- ) div = div.firstChild;\r
+ \r
+ // Remove IE's autoinserted <tbody> from table fragments\r
+ if ( jQuery.browser.msie ) {\r
+ var tb = null;\r
+ // String was a <table>, *may* have spurious <tbody>\r
+ if ( s6 == "<table" && s.indexOf("<tbody") < 0 ) \r
+ tb = div.firstChild && div.firstChild.childNodes;\r
+ // String was a bare <thead> or <tfoot>\r
+ else if ( wrap[1] == "<table>" && s.indexOf("<tbody") < 0 )\r
+ tb = div.childNodes;\r
+ if ( tb ) {\r
+ for ( var n = tb.length-1; n >= 0 ; --n )\r
+ if ( tb[n].nodeName.toUpperCase() == "TBODY" && !tb[n].childNodes.length )\r
+ tb[n].parentNode.removeChild(tb[n]);\r
+ }\r
+ }\r
+ \r
arg = div.childNodes;\r
} \r
\r
\r
expr: {\r
"": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()",\r
- "#": "a.getAttribute('id')&&a.getAttribute('id')==m[2]",\r
+ "#": "a.getAttribute('id')==m[2]",\r
":": {\r
// Position Checks\r
lt: "i<m[3]-0",\r
enabled: "!a.disabled",\r
disabled: "a.disabled",\r
checked: "a.checked",\r
- selected: "a.selected || jQuery.attr(a, 'selected')",\r
+ selected: "a.selected",\r
\r
// Form elements\r
text: "a.type=='text'",\r
// Set the correct context (if none is provided)\r
context = context || document;\r
\r
- if ( t.constructor != String ) return [t];\r
+ if ( typeof t != "string" ) return [t];\r
\r
if ( !t.indexOf("//") ) {\r
context = context.documentElement;\r
var re2 = /^([#.]?)([a-z0-9\\*_-]*)/i;\r
var m = re2.exec(t);\r
\r
- if ( m[1] == "#" ) {\r
- // Ummm, should make this work in all XML docs\r
- var oid = document.getElementById(m[2]);\r
+ if ( m[1] == "#" && ret[ret.length-1].getElementById ) {\r
+ // Optimization for HTML document case\r
+ var oid = ret[ret.length-1].getElementById(m[2]);\r
r = ret = oid ? [oid] : [];\r
t = t.replace( re2, "" );\r
} else {\r
- if ( !m[2] || m[1] == "." ) m[2] = "*";\r
+ if ( !m[2] || m[1] == "." || m[1] == "#" ) m[2] = "*";\r
\r
for ( var i = 0; i < ret.length; i++ )\r
r = jQuery.merge( r,\r
value: "value",\r
disabled: "disabled",\r
checked: "checked",\r
- readonly: "readOnly"\r
+ readonly: "readOnly",\r
+ selected: "selected"\r
};\r
\r
// IE actually uses filters for opacity ... elem is actually elem.style\r
// Otherwise, find the expression to execute\r
else {\r
var f = jQuery.expr[m[1]];\r
- if ( f.constructor != String )\r
+ if ( typeof f != "string" )\r
f = jQuery.expr[m[1]][m[2]];\r
\r
// Build a custom macro to enclose it\r
for ( var k = 0; k < first.length; k++ )\r
result[k] = first[k];\r
\r
- // Now check for duplicates between a and b and only\r
- // add the unique items\r
+ // Now check for duplicates between a and b\r
+ // and only add the unique items\r
+ DupCheck:\r
for ( var i = 0; i < second.length; i++ ) {\r
- var noCollision = true;\r
-\r
- // The collision-checking process\r
for ( var j = 0; j < first.length; j++ )\r
if ( second[i] == first[j] )\r
- noCollision = false;\r
-\r
- // If the item is unique, add it\r
- if ( noCollision )\r
- result.push( second[i] );\r
+ continue DupCheck;\r
+ // The item is unique, add it\r
+ result.push( second[i] );\r
}\r
\r
return result;\r
\r
event = jQuery.event.fix( event || window.event || {} ); // Empty object is for triggered events with no data\r
\r
- // If no correct event was found, fail\r
- if ( !event ) return false;\r
-\r
var returnValue = true;\r
\r
var c = this.events[event.type];\r
},\r
\r
fix: function(event) {\r
- // check IE\r
- if(jQuery.browser.msie) {\r
- // fix target property, if available\r
- // check prevents overwriting of fake target coming from trigger\r
- if(event.srcElement)\r
- event.target = event.srcElement;\r
- \r
- // calculate pageX/Y\r
+ // fix target property, if available\r
+ if(event.srcElement)\r
+ event.target = event.srcElement;\r
+ \r
+ // calculate pageX/Y if missing\r
+ if(typeof event.pageX == "undefined") {\r
var e = document.documentElement, b = document.body;\r
event.pageX = event.clientX + (e.scrollLeft || b.scrollLeft);\r
event.pageY = event.clientY + (e.scrollTop || b.scrollTop);\r
+ }\r
\r
- // check safari and if target is a textnode\r
- } else if(jQuery.browser.safari && event.target.nodeType == 3) {\r
+ // check if target is a textnode (only for safari)\r
+ if(jQuery.browser.safari && event.target.nodeType == 3) {\r
// target is readonly, clone the event object\r
event = jQuery.extend({}, event);\r
// get parentnode from textnode\r
}\r
\r
// fix preventDefault and stopPropagation\r
- if (!event.preventDefault)\r
+ if (!event.preventDefault) {\r
event.preventDefault = function() {\r
this.returnValue = false;\r
};\r
+ }\r
\r
- if (!event.stopPropagation)\r
+ if (!event.stopPropagation) {\r
event.stopPropagation = function() {\r
this.cancelBubble = true;\r
};\r
+ }\r
\r
return event;\r
}\r
* This property is available before the DOM is ready, therefore you can\r
* use it to add ready events only for certain browsers.\r
*\r
+ * There are situations where object detections is not reliable enough, in that\r
+ * cases it makes sense to use browser detection. Simply try to avoid both!\r
+ *\r
+ * A combination of browser and object detection yields quite reliable results.\r
+ *\r
* @example $.browser.msie\r
* @desc Returns true if the current useragent is some version of microsoft's internet explorer\r
*\r
/**\r
* Get the html contents of the first matched element.\r
*\r
+ * A wrapper for the innerHTML property of DOM elements, therefore\r
+ * not available for XML documents.\r
+ *\r
* @example $("div").html();\r
* @before <div><input/></div>\r
* @result <input/>\r
/**\r
* Set the html contents of every matched element.\r
*\r
+ * A wrapper for the innerHTML property of DOM elements, therefore\r
+ * not available for XML documents.\r
+ *\r
* @example $("div").html("<b>new stuff</b>");\r
* @before <div><input/></div>\r
* @result <div><b>new stuff</b></div>\r