/*!
* 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, "
// <thead> matched above(!tags.indexOf("<td") || !tags.indexOf("<th")) && [3, "
// IE can't serialize <link> and <script> tags normally! jQuery.support.htmlSerialize && [1, "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
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 = '
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"); };
});})();