|
/* |
|
Oliver Caldwell's JavaScript toolbox |
|
An example use of Mappa (github.com/Wolfy87/Mappa) |
|
|
|
Copyright 2011, Oliver Caldwell (flowdev.co.uk) |
|
*/ |
|
|
|
// All the mapping is done at the bottom, after the functions have initialised |
|
|
|
// Cookie Toolbox Javascript |
|
// copyright 4th September 2002, by Stephen Chapman, Felgall Pty Ltd |
|
|
|
// You have permission to copy and use this javascript provided that |
|
// the content of the script is not changed in any way. |
|
// For instructions on how to use these functions see "A Cookie Toolbox" |
|
// in the Javascript section of our site at http://www.felgall.com/ |
|
|
|
var dbug = 0; function d_a(ary) {var beg = next_entry(ary) - 1; for (var i = beg ; i > -1; i--) {ary[i] = null;}} function init_array() {if (dbug) alert('init_cookie'); var ary = new Array(null); return ary;} function set_cookie(name,value,expires) {if (dbug) alert('set_cookie'); if (!expires) expires = new Date(); |
|
document.cookie = name + '=' + escape(value) + '; expires=' + expires.toGMTString() + '; path=/';} function get_cookie(name) {if (dbug) alert('get_cookie'); var dcookie = document.cookie; var cname = name + "="; var clen = dcookie.length; var cbegin = 0; while (cbegin < clen) {var vbegin = cbegin + cname.length; |
|
if (dcookie.substring(cbegin, vbegin) == cname) {var vend = dcookie.indexOf (";", vbegin); if (vend == -1) vend = clen; return unescape(dcookie.substring(vbegin, vend));} cbegin = dcookie.indexOf(" ", cbegin) + 1; if (cbegin == 0) break;} return null;} function del_cookie(name) {if (dbug) alert('del_cookie'); |
|
document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/';} function get_array(name, ary) {if (dbug) alert('get_array'); d_a(ary); var ent = get_cookie(name); if (ent) {i = 1; while (ent.indexOf('^') != '-1') {ary[i] = ent.substring(0,ent.indexOf('^')); i++; |
|
ent = ent.substring(ent.indexOf('^')+1, ent.length);}}} function set_array(name, ary, expires) {if (dbug) alert('set_array'); var value = ''; for (var i = 1; ary[i]; i++) {value += ary[i] + '^';} set_cookie(name, value, expires);} function del_entry(name, ary, pos, expires) {if (dbug) alert('del_entry'); |
|
var value = ''; get_array(name, ary); for (var i = 1; i < pos; i++) {value += ary[i] + '^';} for (var j = pos + 1; ary[j]; j++) {value += ary[j] + '^';} set_cookie(name, value, expires);} function next_entry(ary) {if (dbug) alert('next_entry'); var j = 0; for (var i = 1; ary[i]; i++) {j = i} return j + 1;} |
|
function debug_on() {dbug = 1;} function debug_off() {dbug = 0;} function dump_cookies() {if (document.cookie == '') document.write('No Cookies Found'); else {thisCookie = document.cookie.split('; '); for (i=0; i<thisCookie.length; i++) {document.write(thisCookie[i] + '<br \/>');}}} |
|
|
|
// =================================================================== |
|
// Author: Matt Kruse <matt@ajaxtoolbox.com> |
|
// WWW: http://www.AjaxToolbox.com/ |
|
// |
|
// NOTICE: You may use this code for any purpose, commercial or |
|
// private, without any further permission from the author. You may |
|
// remove this notice from your final code if you wish, however it is |
|
// appreciated by the author if at least my web site address is kept. |
|
// |
|
// You may *NOT* re-distribute this code in any way except through its |
|
// use. That means, you can include it in your product, or your web |
|
// site, or any other form where the code is actually being used. You |
|
// may not put the plain javascript up on your site for download or |
|
// include it in your javascript libraries for download. |
|
// If you wish to share this code with others, please just point them |
|
// to the URL instead. |
|
// Please DO NOT link directly to my .js files from your site. Copy |
|
// the files to your server and use them there. Thank you. |
|
// =================================================================== |
|
|
|
/** |
|
* The AjaxRequest class is a wrapper for the XMLHttpRequest objects which |
|
* are available in most modern browsers. It simplifies the interfaces for |
|
* making Ajax requests, adds commonly-used convenience methods, and makes |
|
* the process of handling state changes more intuitive. |
|
* An object may be instantiated and used, or the Class methods may be used |
|
* which internally create an AjaxRequest object. |
|
*/ |
|
function AjaxRequest() { |
|
var req = new Object(); |
|
|
|
// ------------------- |
|
// Instance properties |
|
// ------------------- |
|
|
|
/** |
|
* Timeout period (in ms) until an async request will be aborted, and |
|
* the onTimeout function will be called |
|
*/ |
|
req.timeout = null; |
|
|
|
/** |
|
* Since some browsers cache GET requests via XMLHttpRequest, an |
|
* additional parameter called AjaxRequestUniqueId will be added to |
|
* the request URI with a unique numeric value appended so that the requested |
|
* URL will not be cached. |
|
*/ |
|
req.generateUniqueUrl = true; |
|
|
|
/** |
|
* The url that the request will be made to, which defaults to the current |
|
* url of the window |
|
*/ |
|
req.url = window.location.href; |
|
|
|
/** |
|
* The method of the request, either GET (default), POST, or HEAD |
|
*/ |
|
req.method = "GET"; |
|
|
|
/** |
|
* Whether or not the request will be asynchronous. In general, synchronous |
|
* requests should not be used so this should rarely be changed from true |
|
*/ |
|
req.async = true; |
|
|
|
/** |
|
* The username used to access the URL |
|
*/ |
|
req.username = null; |
|
|
|
/** |
|
* The password used to access the URL |
|
*/ |
|
req.password = null; |
|
|
|
/** |
|
* The parameters is an object holding name/value pairs which will be |
|
* added to the url for a GET request or the request content for a POST request |
|
*/ |
|
req.parameters = new Object(); |
|
|
|
/** |
|
* The sequential index number of this request, updated internally |
|
*/ |
|
req.requestIndex = AjaxRequest.numAjaxRequests++; |
|
|
|
/** |
|
* Indicates whether a response has been received yet from the server |
|
*/ |
|
req.responseReceived = false; |
|
|
|
/** |
|
* The name of the group that this request belongs to, for activity |
|
* monitoring purposes |
|
*/ |
|
req.groupName = null; |
|
|
|
/** |
|
* The query string to be added to the end of a GET request, in proper |
|
* URIEncoded format |
|
*/ |
|
req.queryString = ""; |
|
|
|
/** |
|
* After a response has been received, this will hold the text contents of |
|
* the response - even in case of error |
|
*/ |
|
req.responseText = null; |
|
|
|
/** |
|
* After a response has been received, this will hold the XML content |
|
*/ |
|
req.responseXML = null; |
|
|
|
/** |
|
* After a response has been received, this will hold the status code of |
|
* the response as returned by the server. |
|
*/ |
|
req.status = null; |
|
|
|
/** |
|
* After a response has been received, this will hold the text description |
|
* of the response code |
|
*/ |
|
req.statusText = null; |
|
|
|
/** |
|
* An internal flag to indicate whether the request has been aborted |
|
*/ |
|
req.aborted = false; |
|
|
|
/** |
|
* The XMLHttpRequest object used internally |
|
*/ |
|
req.xmlHttpRequest = null; |
|
|
|
// -------------- |
|
// Event handlers |
|
// -------------- |
|
|
|
/** |
|
* If a timeout period is set, and it is reached before a response is |
|
* received, a function reference assigned to onTimeout will be called |
|
*/ |
|
req.onTimeout = null; |
|
|
|
/** |
|
* A function reference assigned will be called when readyState=1 |
|
*/ |
|
req.onLoading = null; |
|
|
|
/** |
|
* A function reference assigned will be called when readyState=2 |
|
*/ |
|
req.onLoaded = null; |
|
|
|
/** |
|
* A function reference assigned will be called when readyState=3 |
|
*/ |
|
req.onInteractive = null; |
|
|
|
/** |
|
* A function reference assigned will be called when readyState=4 |
|
*/ |
|
req.onComplete = null; |
|
|
|
/** |
|
* A function reference assigned will be called after onComplete, if |
|
* the statusCode=200 |
|
*/ |
|
req.onSuccess = null; |
|
|
|
/** |
|
* A function reference assigned will be called after onComplete, if |
|
* the statusCode != 200 |
|
*/ |
|
req.onError = null; |
|
|
|
/** |
|
* If this request has a group name, this function reference will be called |
|
* and passed the group name if this is the first request in the group to |
|
* become active |
|
*/ |
|
req.onGroupBegin = null; |
|
|
|
/** |
|
* If this request has a group name, and this request is the last request |
|
* in the group to complete, this function reference will be called |
|
*/ |
|
req.onGroupEnd = null; |
|
|
|
// Get the XMLHttpRequest object itself |
|
req.xmlHttpRequest = AjaxRequest.getXmlHttpRequest(); |
|
if (req.xmlHttpRequest==null) { return null; } |
|
|
|
// ------------------------------------------------------- |
|
// Attach the event handlers for the XMLHttpRequest object |
|
// ------------------------------------------------------- |
|
req.xmlHttpRequest.onreadystatechange = |
|
function() { |
|
if (req==null || req.xmlHttpRequest==null) { return; } |
|
if (req.xmlHttpRequest.readyState==1) { req.onLoadingInternal(req); } |
|
if (req.xmlHttpRequest.readyState==2) { req.onLoadedInternal(req); } |
|
if (req.xmlHttpRequest.readyState==3) { req.onInteractiveInternal(req); } |
|
if (req.xmlHttpRequest.readyState==4) { req.onCompleteInternal(req); } |
|
}; |
|
|
|
// --------------------------------------------------------------------------- |
|
// Internal event handlers that fire, and in turn fire the user event handlers |
|
// --------------------------------------------------------------------------- |
|
// Flags to keep track if each event has been handled, in case of |
|
// multiple calls (some browsers may call the onreadystatechange |
|
// multiple times for the same state) |
|
req.onLoadingInternalHandled = false; |
|
req.onLoadedInternalHandled = false; |
|
req.onInteractiveInternalHandled = false; |
|
req.onCompleteInternalHandled = false; |
|
req.onLoadingInternal = |
|
function() { |
|
if (req.onLoadingInternalHandled) { return; } |
|
AjaxRequest.numActiveAjaxRequests++; |
|
if (AjaxRequest.numActiveAjaxRequests==1 && typeof(window['AjaxRequestBegin'])=="function") { |
|
AjaxRequestBegin(); |
|
} |
|
if (req.groupName!=null) { |
|
if (typeof(AjaxRequest.numActiveAjaxGroupRequests[req.groupName])=="undefined") { |
|
AjaxRequest.numActiveAjaxGroupRequests[req.groupName] = 0; |
|
} |
|
AjaxRequest.numActiveAjaxGroupRequests[req.groupName]++; |
|
if (AjaxRequest.numActiveAjaxGroupRequests[req.groupName]==1 && typeof(req.onGroupBegin)=="function") { |
|
req.onGroupBegin(req.groupName); |
|
} |
|
} |
|
if (typeof(req.onLoading)=="function") { |
|
req.onLoading(req); |
|
} |
|
req.onLoadingInternalHandled = true; |
|
}; |
|
req.onLoadedInternal = |
|
function() { |
|
if (req.onLoadedInternalHandled) { return; } |
|
if (typeof(req.onLoaded)=="function") { |
|
req.onLoaded(req); |
|
} |
|
req.onLoadedInternalHandled = true; |
|
}; |
|
req.onInteractiveInternal = |
|
function() { |
|
if (req.onInteractiveInternalHandled) { return; } |
|
if (typeof(req.onInteractive)=="function") { |
|
req.onInteractive(req); |
|
} |
|
req.onInteractiveInternalHandled = true; |
|
}; |
|
req.onCompleteInternal = |
|
function() { |
|
if (req.onCompleteInternalHandled || req.aborted) { return; } |
|
req.onCompleteInternalHandled = true; |
|
AjaxRequest.numActiveAjaxRequests--; |
|
if (AjaxRequest.numActiveAjaxRequests==0 && typeof(window['AjaxRequestEnd'])=="function") { |
|
AjaxRequestEnd(req.groupName); |
|
} |
|
if (req.groupName!=null) { |
|
AjaxRequest.numActiveAjaxGroupRequests[req.groupName]--; |
|
if (AjaxRequest.numActiveAjaxGroupRequests[req.groupName]==0 && typeof(req.onGroupEnd)=="function") { |
|
req.onGroupEnd(req.groupName); |
|
} |
|
} |
|
req.responseReceived = true; |
|
req.status = req.xmlHttpRequest.status; |
|
req.statusText = req.xmlHttpRequest.statusText; |
|
req.responseText = req.xmlHttpRequest.responseText; |
|
req.responseXML = req.xmlHttpRequest.responseXML; |
|
if (typeof(req.onComplete)=="function") { |
|
req.onComplete(req); |
|
} |
|
if (req.xmlHttpRequest.status==200 && typeof(req.onSuccess)=="function") { |
|
req.onSuccess(req); |
|
} |
|
else if (typeof(req.onError)=="function") { |
|
req.onError(req); |
|
} |
|
|
|
// Clean up so IE doesn't leak memory |
|
delete req.xmlHttpRequest['onreadystatechange']; |
|
req.xmlHttpRequest = null; |
|
}; |
|
req.onTimeoutInternal = |
|
function() { |
|
if (req!=null && req.xmlHttpRequest!=null && !req.onCompleteInternalHandled) { |
|
req.aborted = true; |
|
req.xmlHttpRequest.abort(); |
|
AjaxRequest.numActiveAjaxRequests--; |
|
if (AjaxRequest.numActiveAjaxRequests==0 && typeof(window['AjaxRequestEnd'])=="function") { |
|
AjaxRequestEnd(req.groupName); |
|
} |
|
if (req.groupName!=null) { |
|
AjaxRequest.numActiveAjaxGroupRequests[req.groupName]--; |
|
if (AjaxRequest.numActiveAjaxGroupRequests[req.groupName]==0 && typeof(req.onGroupEnd)=="function") { |
|
req.onGroupEnd(req.groupName); |
|
} |
|
} |
|
if (typeof(req.onTimeout)=="function") { |
|
req.onTimeout(req); |
|
} |
|
// Opera won't fire onreadystatechange after abort, but other browsers do. |
|
// So we can't rely on the onreadystate function getting called. Clean up here! |
|
delete req.xmlHttpRequest['onreadystatechange']; |
|
req.xmlHttpRequest = null; |
|
} |
|
}; |
|
|
|
// ---------------- |
|
// Instance methods |
|
// ---------------- |
|
/** |
|
* The process method is called to actually make the request. It builds the |
|
* querystring for GET requests (the content for POST requests), sets the |
|
* appropriate headers if necessary, and calls the |
|
* XMLHttpRequest.send() method |
|
*/ |
|
req.process = |
|
function() { |
|
if (req.xmlHttpRequest!=null) { |
|
// Some logic to get the real request URL |
|
if (req.generateUniqueUrl && req.method=="GET") { |
|
req.parameters["AjaxRequestUniqueId"] = new Date().getTime() + "" + req.requestIndex; |
|
} |
|
var content = null; // For POST requests, to hold query string |
|
for (var i in req.parameters) { |
|
if (req.queryString.length>0) { req.queryString += "&"; } |
|
req.queryString += encodeURIComponent(i) + "=" + encodeURIComponent(req.parameters[i]); |
|
} |
|
if (req.method=="GET") { |
|
if (req.queryString.length>0) { |
|
req.url += ((req.url.indexOf("?")>-1)?"&":"?") + req.queryString; |
|
} |
|
} |
|
req.xmlHttpRequest.open(req.method,req.url,req.async,req.username,req.password); |
|
if (req.method=="POST") { |
|
if (typeof(req.xmlHttpRequest.setRequestHeader)!="undefined") { |
|
req.xmlHttpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); |
|
} |
|
content = req.queryString; |
|
} |
|
if (req.timeout>0) { |
|
setTimeout(req.onTimeoutInternal,req.timeout); |
|
} |
|
req.xmlHttpRequest.send(content); |
|
} |
|
}; |
|
|
|
/** |
|
* An internal function to handle an Object argument, which may contain |
|
* either AjaxRequest field values or parameter name/values |
|
*/ |
|
req.handleArguments = |
|
function(args) { |
|
for (var i in args) { |
|
// If the AjaxRequest object doesn't have a property which was passed, treat it as a url parameter |
|
if (typeof(req[i])=="undefined") { |
|
req.parameters[i] = args[i]; |
|
} |
|
else { |
|
req[i] = args[i]; |
|
} |
|
} |
|
}; |
|
|
|
/** |
|
* Returns the results of XMLHttpRequest.getAllResponseHeaders(). |
|
* Only available after a response has been returned |
|
*/ |
|
req.getAllResponseHeaders = |
|
function() { |
|
if (req.xmlHttpRequest!=null) { |
|
if (req.responseReceived) { |
|
return req.xmlHttpRequest.getAllResponseHeaders(); |
|
} |
|
alert("Cannot getAllResponseHeaders because a response has not yet been received"); |
|
} |
|
}; |
|
|
|
/** |
|
* Returns the the value of a response header as returned by |
|
* XMLHttpRequest,getResponseHeader(). |
|
* Only available after a response has been returned |
|
*/ |
|
req.getResponseHeader = |
|
function(headerName) { |
|
if (req.xmlHttpRequest!=null) { |
|
if (req.responseReceived) { |
|
return req.xmlHttpRequest.getResponseHeader(headerName); |
|
} |
|
alert("Cannot getResponseHeader because a response has not yet been received"); |
|
} |
|
}; |
|
|
|
return req; |
|
} |
|
|
|
// --------------------------------------- |
|
// Static methods of the AjaxRequest class |
|
// --------------------------------------- |
|
|
|
/** |
|
* Returns an XMLHttpRequest object, either as a core object or an ActiveX |
|
* implementation. If an object cannot be instantiated, it will return null; |
|
*/ |
|
AjaxRequest.getXmlHttpRequest = function() { |
|
if (window.XMLHttpRequest) { |
|
return new XMLHttpRequest(); |
|
} |
|
else if (window.ActiveXObject) { |
|
// Based on http://jibbering.com/2002/4/httprequest.html |
|
/*@cc_on @*/ |
|
/*@if (@_jscript_version >= 5) |
|
try { |
|
return new ActiveXObject("Msxml2.XMLHTTP"); |
|
} catch (e) { |
|
try { |
|
return new ActiveXObject("Microsoft.XMLHTTP"); |
|
} catch (E) { |
|
return null; |
|
} |
|
} |
|
@end @*/ |
|
} |
|
else { |
|
return null; |
|
} |
|
}; |
|
|
|
/** |
|
* See if any request is active in the background |
|
*/ |
|
AjaxRequest.isActive = function() { |
|
return (AjaxRequest.numActiveAjaxRequests>0); |
|
}; |
|
|
|
/** |
|
* Make a GET request. Pass an object containing parameters and arguments as |
|
* the second argument. |
|
* These areguments may be either AjaxRequest properties to set on the request |
|
* object or name/values to set in the request querystring. |
|
*/ |
|
AjaxRequest.get = function(args) { |
|
AjaxRequest.doRequest("GET",args); |
|
}; |
|
|
|
/** |
|
* Make a POST request. Pass an object containing parameters and arguments as |
|
* the second argument. |
|
* These areguments may be either AjaxRequest properties to set on the request |
|
* object or name/values to set in the request querystring. |
|
*/ |
|
AjaxRequest.post = function(args) { |
|
AjaxRequest.doRequest("POST",args); |
|
}; |
|
|
|
/** |
|
* The internal method used by the .get() and .post() methods |
|
*/ |
|
AjaxRequest.doRequest = function(method,args) { |
|
if (typeof(args)!="undefined" && args!=null) { |
|
var myRequest = new AjaxRequest(); |
|
myRequest.method = method; |
|
myRequest.handleArguments(args); |
|
myRequest.process(); |
|
} |
|
} ; |
|
|
|
/** |
|
* Submit a form. The requested URL will be the form's ACTION, and the request |
|
* method will be the form's METHOD. |
|
* Returns true if the submittal was handled successfully, else false so it |
|
* can easily be used with an onSubmit event for a form, and fallback to |
|
* submitting the form normally. |
|
*/ |
|
AjaxRequest.submit = function(theform, args) { |
|
var myRequest = new AjaxRequest(); |
|
if (myRequest==null) { return false; } |
|
var serializedForm = AjaxRequest.serializeForm(theform); |
|
myRequest.method = theform.method.toUpperCase(); |
|
myRequest.url = theform.action; |
|
myRequest.handleArguments(args); |
|
myRequest.queryString = serializedForm; |
|
myRequest.process(); |
|
return true; |
|
}; |
|
|
|
/** |
|
* Serialize a form into a format which can be sent as a GET string or a POST |
|
* content.It correctly ignores disabled fields, maintains order of the fields |
|
* as in the elements[] array. The 'file' input type is not supported, as |
|
* its content is not available to javascript. This method is used internally |
|
* by the submit class method. |
|
*/ |
|
AjaxRequest.serializeForm = function(theform) { |
|
var els = theform.elements; |
|
var len = els.length; |
|
var queryString = ""; |
|
this.addField = |
|
function(name,value) { |
|
if (queryString.length>0) { |
|
queryString += "&"; |
|
} |
|
queryString += encodeURIComponent(name) + "=" + encodeURIComponent(value); |
|
}; |
|
for (var i=0; i<len; i++) { |
|
var el = els[i]; |
|
if (!el.disabled) { |
|
switch(el.type) { |
|
case 'text': case 'password': case 'hidden': case 'textarea': |
|
this.addField(el.name,el.value); |
|
break; |
|
case 'select-one': |
|
if (el.selectedIndex>=0) { |
|
this.addField(el.name,el.options[el.selectedIndex].value); |
|
} |
|
break; |
|
case 'select-multiple': |
|
for (var j=0; j<el.options.length; j++) { |
|
if (el.options[j].selected) { |
|
this.addField(el.name,el.options[j].value); |
|
} |
|
} |
|
break; |
|
case 'checkbox': case 'radio': |
|
if (el.checked) { |
|
this.addField(el.name,el.value); |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
return queryString; |
|
}; |
|
|
|
// ----------------------- |
|
// Static Class variables |
|
// ----------------------- |
|
|
|
/** |
|
* The number of total AjaxRequest objects currently active and running |
|
*/ |
|
AjaxRequest.numActiveAjaxRequests = 0; |
|
|
|
/** |
|
* An object holding the number of active requests for each group |
|
*/ |
|
AjaxRequest.numActiveAjaxGroupRequests = new Object(); |
|
|
|
/** |
|
* The total number of AjaxRequest objects instantiated |
|
*/ |
|
AjaxRequest.numAjaxRequests = 0; |
|
|
|
var BrowserDetect = { |
|
init: function () { |
|
this.browser = this.searchString(this.dataBrowser) || "An unknown browser"; |
|
this.version = this.searchVersion(navigator.userAgent) |
|
|| this.searchVersion(navigator.appVersion) |
|
|| "an unknown version"; |
|
this.OS = this.searchString(this.dataOS) || "an unknown OS"; |
|
}, |
|
searchString: function (data) { |
|
for (var i=0;i<data.length;i++) { |
|
var dataString = data[i].string; |
|
var dataProp = data[i].prop; |
|
this.versionSearchString = data[i].versionSearch || data[i].identity; |
|
if (dataString) { |
|
if (dataString.indexOf(data[i].subString) != -1) |
|
return data[i].identity; |
|
} |
|
else if (dataProp) |
|
return data[i].identity; |
|
} |
|
}, |
|
searchVersion: function (dataString) { |
|
var index = dataString.indexOf(this.versionSearchString); |
|
if (index == -1) return; |
|
return parseFloat(dataString.substring(index+this.versionSearchString.length+1)); |
|
}, |
|
dataBrowser: [ |
|
{ |
|
string: navigator.userAgent, |
|
subString: "Chrome", |
|
identity: "Chrome" |
|
}, |
|
{ string: navigator.userAgent, |
|
subString: "OmniWeb", |
|
versionSearch: "OmniWeb/", |
|
identity: "OmniWeb" |
|
}, |
|
{ |
|
string: navigator.vendor, |
|
subString: "Apple", |
|
identity: "Safari", |
|
versionSearch: "Version" |
|
}, |
|
{ |
|
prop: window.opera, |
|
identity: "Opera" |
|
}, |
|
{ |
|
string: navigator.vendor, |
|
subString: "iCab", |
|
identity: "iCab" |
|
}, |
|
{ |
|
string: navigator.vendor, |
|
subString: "KDE", |
|
identity: "Konqueror" |
|
}, |
|
{ |
|
string: navigator.userAgent, |
|
subString: "Firefox", |
|
identity: "Firefox" |
|
}, |
|
{ |
|
string: navigator.vendor, |
|
subString: "Camino", |
|
identity: "Camino" |
|
}, |
|
{ // for newer Netscapes (6+) |
|
string: navigator.userAgent, |
|
subString: "Netscape", |
|
identity: "Netscape" |
|
}, |
|
{ |
|
string: navigator.userAgent, |
|
subString: "MSIE", |
|
identity: "Explorer", |
|
versionSearch: "MSIE" |
|
}, |
|
{ |
|
string: navigator.userAgent, |
|
subString: "Gecko", |
|
identity: "Mozilla", |
|
versionSearch: "rv" |
|
}, |
|
{ // for older Netscapes (4-) |
|
string: navigator.userAgent, |
|
subString: "Mozilla", |
|
identity: "Netscape", |
|
versionSearch: "Mozilla" |
|
} |
|
], |
|
dataOS : [ |
|
{ |
|
string: navigator.platform, |
|
subString: "Win", |
|
identity: "Windows" |
|
}, |
|
{ |
|
string: navigator.platform, |
|
subString: "Mac", |
|
identity: "Mac" |
|
}, |
|
{ |
|
string: navigator.userAgent, |
|
subString: "iPhone", |
|
identity: "iPhone/iPod" |
|
}, |
|
{ |
|
string: navigator.platform, |
|
subString: "Linux", |
|
identity: "Linux" |
|
} |
|
] |
|
|
|
}; |
|
BrowserDetect.init(); |
|
// Cookie Toolbox Javascript |
|
// // copyright 4th September 2002, by Stephen Chapman, Felgall Pty Ltd |
|
// |
|
// // You have permission to copy and use this javascript provided that |
|
// // the content of the script is not changed in any way. |
|
// // For instructions on how to use these functions see "A Cookie Toolbox" |
|
// // in the Javascript section of our site at http://www.felgall.com/ |
|
// |
|
// var dbug = 0; function d_a(ary) {var beg = next_entry(ary) - 1; for (var i = beg ; i > -1; i--) {ary[i] = null;}} function init_array() {if (dbug) alert('init_cookie'); var ary = new Array(null); return ary;} function set_cookie(name,value,expires) {if (dbug) alert('set_cookie'); if (!expires) expires = new Date(); |
|
// document.cookie = name + '=' + escape(value) + '; expires=' + expires.toGMTString() + '; path=/';} function get_cookie(name) {if (dbug) alert('get_cookie'); var dcookie = document.cookie; var cname = name + "="; var clen = dcookie.length; var cbegin = 0; while (cbegin < clen) {var vbegin = cbegin + cname.length; |
|
// if (dcookie.substring(cbegin, vbegin) == cname) {var vend = dcookie.indexOf (";", vbegin); if (vend == -1) vend = clen; return unescape(dcookie.substring(vbegin, vend));} cbegin = dcookie.indexOf(" ", cbegin) + 1; if (cbegin == 0) break;} return null;} function del_cookie(name) {if (dbug) alert('del_cookie'); |
|
// document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/';} function get_array(name, ary) {if (dbug) alert('get_array'); d_a(ary); var ent = get_cookie(name); if (ent) {i = 1; while (ent.indexOf('^') != '-1') {ary[i] = ent.substring(0,ent.indexOf('^')); i++; |
|
// ent = ent.substring(ent.indexOf('^')+1, ent.length);}}} function set_array(name, ary, expires) {if (dbug) alert('set_array'); var value = ''; for (var i = 1; ary[i]; i++) {value += ary[i] + '^';} set_cookie(name, value, expires);} function del_entry(name, ary, pos, expires) {if (dbug) alert('del_entry'); |
|
// var value = ''; get_array(name, ary); for (var i = 1; i < pos; i++) {value += ary[i] + '^';} for (var j = pos + 1; ary[j]; j++) {value += ary[j] + '^';} set_cookie(name, value, expires);} function next_entry(ary) {if (dbug) alert('next_entry'); var j = 0; for (var i = 1; ary[i]; i++) {j = i} return j + 1;} |
|
// function debug_on() {dbug = 1;} function debug_off() {dbug = 0;} function dump_cookies() {if (document.cookie == '') document.write('No Cookies Found'); else {thisCookie = document.cookie.split('; '); for (i=0; i<thisCookie.length; i++) {document.write(thisCookie[i] + '<br \/>');}}} |
|
/** |
|
Written by Peter Wilkinson of http://dynamic-tools.net |
|
Feel free to use or modify this script for any purpose. I'd appreciate you leaving |
|
this header in though. |
|
*/ |
|
function addEvent(elem, eventType, handler) |
|
{ |
|
if (!elem.eventHandlers) elem.eventHandlers = []; |
|
if (!elem.eventHandlers[eventType]) |
|
{ |
|
elem.eventHandlers[eventType] = []; |
|
if (elem['on' + eventType]) elem.eventHandlers[eventType].push(elem['on' + eventType]); |
|
elem['on' + eventType] = handleEvent; |
|
} |
|
elem.eventHandlers[eventType].push(handler); |
|
} |
|
|
|
function removeEvent(elem, eventType, handler) |
|
{ |
|
var handlers = elem.eventHandlers[eventType]; |
|
for (var i in handlers) if (handlers[i] == handler) delete handlers[i]; |
|
} |
|
|
|
function handleEvent(e) |
|
{ |
|
var returnValue = true; |
|
if (!e) e = fixEvent(event); |
|
var handlers = this.eventHandlers[e.type] |
|
for (var i in handlers) |
|
{ |
|
this.$$handleEvent = handlers[i]; |
|
returnValue = !((returnValue && this.$$handleEvent(e)) === false); |
|
} |
|
return returnValue; |
|
} |
|
|
|
function fixEvent(e) |
|
{ |
|
// add W3C standard event methods |
|
e.preventDefault = fixEvent.preventDefault; |
|
e.stopPropagation = fixEvent.stopPropagation; |
|
return event; |
|
}; |
|
|
|
fixEvent.preventDefault = function() { |
|
this.returnValue = false; |
|
}; |
|
|
|
fixEvent.stopPropagation = function() { |
|
this.cancelBubble = true; |
|
}; /*! |
|
jsAnim: Powerful javascript animation |
|
-------------------------------------------- |
|
Copyright 2009 Kevin Dolan |
|
-http://www.thekevindolan.com |
|
|
|
Code licensed under the MIT license |
|
-See license.txt |
|
|
|
v0.2 |
|
*/ |
|
|
|
//These vars are used to hold all jsAnimManagers |
|
var jsAnimManagers = new Array(); |
|
var jsAnimManagerId = 0; |
|
|
|
/*! public, accessible |
|
jsAnimManager object constructor |
|
Used by end-user to manage jsAnim objects |
|
Params: |
|
-[timestep] : time between frames, defaults to 40 |
|
*/ |
|
function jsAnimManager(timestep) { |
|
|
|
jsAnimManagers[jsAnimManagerId] = this; |
|
this.myId = jsAnimManagerId; |
|
jsAnimManagerId++; |
|
|
|
if(timestep) |
|
this.timestep = timestep; |
|
else |
|
this.timestep = 40; |
|
|
|
this.paused = false; |
|
|
|
this.animObjects = new Array(); |
|
this.index = 0; |
|
|
|
//Used internally to process a single frame of all active animations |
|
this.step = function() { |
|
if(!this.paused) { |
|
for(x in this.animObjects) { |
|
this.animObjects[x].step(); |
|
} |
|
setTimeout("jsAnimManagers["+this.myId+"].step()",this.timestep); |
|
} |
|
}; |
|
|
|
//Used internally to kill a jsAnimObject |
|
this.kill = function(id) { |
|
delete this.animObjects[id]; |
|
}; |
|
|
|
/*! public |
|
Called to create a new animation object |
|
Params: |
|
-objId : id of object being controlled |
|
*/ |
|
this.createAnimObject = function(objId) { |
|
var el = document.getElementById(objId); |
|
var id = this.index; |
|
this.animObjects[id] = new jsAnimObject(el, id, this); |
|
this.index++; |
|
return this.animObjects[id]; |
|
}; |
|
|
|
/*! public |
|
Called to pause the animation manager |
|
*/ |
|
this.pause = function() { |
|
this.paused = true; |
|
}; |
|
|
|
/*! public |
|
Called to unpause the animation manager |
|
*/ |
|
this.resume = function() { |
|
this.paused = false; |
|
this.step(); |
|
}; |
|
|
|
/*! public |
|
Called to set the appropriate style values to allow position to be controlled by jsAnim |
|
Params: |
|
-objId : id of object to be registered |
|
-[fixed] : fixed positioning, false to absolute fixed, defaults to false |
|
*/ |
|
this.registerPosition = function(objId, fixed) { |
|
var el = document.getElementById(objId); |
|
var width = el.offsetWidth; |
|
var height = el.offsetHeight; |
|
|
|
if(fixed) |
|
el.style.position = "fixed"; |
|
else |
|
el.style.position = "absolute"; |
|
|
|
el.style.top = "0px"; |
|
el.style.left = "50%"; |
|
el.halfWidth = Math.floor(width/2); |
|
el.halfHeight = Math.floor(height/2); |
|
el.style.marginLeft = (-el.halfWidth)+"px"; |
|
el.style.marginTop = (-el.halfHeight)+"px"; |
|
|
|
el.positionRegistered = true; |
|
|
|
/*! public |
|
Called to manually set the position of this object |
|
*/ |
|
el.setPosition = function(x, y) { |
|
this.style.marginLeft = (x - this.halfWidth)+"px"; |
|
this.style.marginTop = (y - this.halfHeight)+"px"; |
|
}; |
|
|
|
}; |
|
|
|
this.step(); |
|
return true; |
|
} |
|
|
|
/*! accesible |
|
jsAnimObject object constructor |
|
Used internally to hold the state of a single animation manager |
|
Params: |
|
-obj : object being animated |
|
|
|
*/ |
|
function jsAnimObject(obj, id, manager) { |
|
|
|
this.id = id; |
|
this.obj = obj; |
|
this.paused = false; |
|
this.animEntries = new Array(); |
|
this.animLoops = new Array(); |
|
this.current = 0; |
|
this.manager = manager; |
|
|
|
this.step = function() { |
|
if(!this.paused) { |
|
//Ugly code to get only the first element in the array |
|
for(x in this.animEntries) { |
|
var finished = this.animEntries[x].step(); |
|
if(finished) { |
|
this.animLoops[x]--; |
|
this.animEntries[x].current = 0; |
|
this.animEntries[x].onLoop(); |
|
} |
|
if(this.animLoops[x] == 0) { |
|
this.animEntries[x].onComplete(); |
|
delete this.animEntries[x]; |
|
} |
|
break; |
|
} |
|
} |
|
}; |
|
|
|
/*! public |
|
Called to add an animation to the chain |
|
Params: |
|
-params : a collection in the containing the following elements |
|
- property : the Prop object to animate |
|
- [from] : optional from value, if unspecified current value is used |
|
- to : the value to animate to |
|
- duration : the length of time this animation should take |
|
- [ease] : the jsAnimEase object to use, if unspecified linear will be used |
|
- [loop] : the number of times to loop the animation, negative values are infinite, if unspecified 1 will be used |
|
- [onLoop] : the callback function for loop completion |
|
- [onComplete] : the callback function for animation completion |
|
*/ |
|
this.add = function(params) { |
|
|
|
var property = params.property; |
|
var from = params.from |
|
var to = params.to; |
|
var duration = params.duration; |
|
if(params.ease) |
|
var ease = params.ease; |
|
else |
|
var ease = jsAnimEase.linear; |
|
if(params.loop) |
|
var loop = params.loop; |
|
else |
|
var loop = 1; |
|
if(params.onLoop) |
|
var onLoop = params.onLoop; |
|
else |
|
var onLoop = function() {}; |
|
if(params.onComplete) |
|
var onComplete = params.onComplete; |
|
else |
|
var onComplete = function() {}; |
|
|
|
this.animEntries[this.current] = new jsAnimEntry(this.obj, property, from, to, duration, this.manager.timestep, ease, onLoop, onComplete); |
|
this.animLoops[this.current] = loop; |
|
|
|
this.current++; |
|
|
|
}; |
|
|
|
/*! public |
|
Called to skip the current animation, can be used to exit an infinite loop |
|
*/ |
|
this.skip = function() { |
|
//Ugly code to get only the first element in the array |
|
for(x in this.animEntries) { |
|
delete this.animEntries[x]; |
|
break; |
|
} |
|
}; |
|
|
|
/*! public |
|
Called to pause this animator |
|
*/ |
|
this.pause = function() { |
|
this.paused = true; |
|
}; |
|
|
|
/*! public |
|
Called to resum this animator |
|
*/ |
|
this.resume = function() { |
|
this.paused = false; |
|
}; |
|
|
|
/*! public |
|
Called to kill this animator |
|
*/ |
|
this.kill = function() { |
|
this.manager.kill(this.id); |
|
}; |
|
|
|
return true; |
|
} |
|
|
|
/*! public, accesible |
|
Pos object constructor |
|
Called to store an x and y coordinate representing an object's center |
|
according to the jsAnim coordinate system |
|
Params: |
|
-x : x coordinate, 0 is center, negative is left, positive is right |
|
-y : y coordinate, 0 is top, positive id below |
|
*/ |
|
function Pos(x, y) { |
|
|
|
//public |
|
this.x = x; |
|
|
|
//public |
|
this.y = y; |
|
|
|
return true; |
|
} |
|
|
|
/*! public, accesible |
|
Dim object constructor |
|
Called to store a width/height dimension |
|
Params: |
|
-w : width |
|
-h : height |
|
*/ |
|
function Dim(w, h) { |
|
|
|
//public |
|
this.w = w; |
|
|
|
//public |
|
this.h = h; |
|
|
|
return true; |
|
} |
|
|
|
/*! public, accesible |
|
Col object constructor |
|
Called to store an RGB color |
|
Params: |
|
-r : red value (0,255) |
|
-g : green value (0,255) |
|
-b : blue value (0,255) |
|
*/ |
|
function Col(r, g, b) { |
|
|
|
//public |
|
this.r = r; |
|
|
|
//public |
|
this.g = g; |
|
|
|
//public |
|
this.b = b; |
|
|
|
return true; |
|
} |
|
|
|
/*! |
|
jsAnimEntry object constructor |
|
Used internally to hold the state of single animation entry |
|
Params: |
|
-property : jsAnimProp object |
|
-from : initial value |
|
-to : end value |
|
-duration : total time of animation (ms) |
|
-ease : jsAnimEase object |
|
-timestep : the timestep value of the animation manager |
|
-onLoop : called after each loop |
|
-onComplete : called after completion |
|
*/ |
|
function jsAnimEntry(obj, property, from, to, duration, timestep, ease, onLoop, onComplete) { |
|
|
|
this.obj = obj; |
|
this.property = property; |
|
this.from = from; |
|
this.to = to; |
|
this.duration = duration; |
|
this.timestep = timestep; |
|
this.ease = ease; |
|
this.current = 0; |
|
this.onLoop = onLoop; |
|
this.onComplete = onComplete; |
|
|
|
/*! |
|
Used internally to move the object one step |
|
Returns : true if this anim entry has completed, false otherwise |
|
*/ |
|
this.step = function() { |
|
if(!this.from) |
|
this.from = this.property.current(this.obj); |
|
|
|
if(this.current >= this.duration) { |
|
var p = this.ease.transform(1); |
|
this.property.update(this.obj, this.from, this.to, p); |
|
return true; |
|
} |
|
else { |
|
var t = this.current / this.duration; |
|
var p = this.ease.transform(t); |
|
this.property.update(this.obj, this.from, this.to, p); |
|
this.current += this.timestep; |
|
return false; |
|
} |
|
}; |
|
|
|
return true; |
|
} |
|
|
|
/*! public |
|
jsAnimEase objects |
|
Used to control easing |
|
Methods: |
|
transform : Transform a number 0-1 representing a time proportion |
|
to a new number 0-1 representing a progress proportion |
|
*/ |
|
var jsAnimEase = { |
|
|
|
/*!public |
|
Constant Rate |
|
*/ |
|
linear : { |
|
transform : function(t) { |
|
return t; |
|
} |
|
}, |
|
|
|
/*!public |
|
Starts slow, then speeds up |
|
*/ |
|
parabolicPos : { |
|
transform : function(t) { |
|
return t * t; |
|
} |
|
}, |
|
|
|
/*!public |
|
Starts fast, then slows down |
|
*/ |
|
parabolicNeg : { |
|
transform : function(t) { |
|
return 1 - (t-1) * (t-1); |
|
} |
|
}, |
|
|
|
/*!public |
|
Overshoots target then returns to target |
|
Params: |
|
-g : overshoot amount [0-1] |
|
*/ |
|
backout : function(g) { |
|
return { |
|
transform : function(t) { |
|
return (-1 * t * (t + g - 2)) / (1 - g); |
|
} |
|
}; |
|
}, |
|
|
|
/*!public |
|
Backs up a bit then moves to target |
|
Params: |
|
-g : backup amount [0-1] |
|
*/ |
|
backin : function(g) { |
|
return { |
|
transform : function(t) { |
|
return 1 + ((t+1-g) * ((t+1-g) + g - 2)) / (1 - g); |
|
} |
|
}; |
|
}, |
|
|
|
/*!public |
|
Goes to target and then back at constant rate |
|
*/ |
|
bounceLinear : { |
|
transform : function(t) { |
|
if(t < 0.5) |
|
return 2 * t; |
|
else |
|
return 1 - 2 * (t - 0.5) |
|
} |
|
}, |
|
|
|
/*!public |
|
Goes to target and then back at variable rate |
|
*/ |
|
bounceParabolic : { |
|
transform : function(t) { |
|
return -4 * t * (t-1); |
|
} |
|
}, |
|
|
|
/*!public |
|
Goes to target and then back smoothly |
|
*/ |
|
bounceSmooth : { |
|
transform : function(t) { |
|
return 0.5 - 0.5 * Math.cos(2 * Math.PI * t); |
|
} |
|
} |
|
} |
|
|
|
/*! |
|
Utility objects for internal use |
|
*/ |
|
var jsAnimUtil = { |
|
|
|
interp : function (v1, v2, percent) { |
|
if(isNaN(v1)) |
|
v1 = 0; |
|
if(isNaN(v2)) |
|
v2 = 0; |
|
var v = v1 + percent * (v2-v1); |
|
return Math.floor(v); |
|
}, |
|
|
|
getCSS : function (elem, field) { |
|
var css = document.defaultView && document.defaultView.getComputedStyle ? |
|
document.defaultView.getComputedStyle(elem, null) |
|
: elem.currentStyle || elem.style; |
|
return css[field]; |
|
}, |
|
|
|
explode : function ( delimiter, string, limit ) { |
|
// http://kevin.vanzonneveld.net |
|
// + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) |
|
// + improved by: kenneth |
|
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) |
|
// + improved by: d3x |
|
// + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) |
|
// * example 1: explode(' ', 'Kevin van Zonneveld'); |
|
// * returns 1: {0: 'Kevin', 1: 'van', 2: 'Zonneveld'} |
|
// * example 2: explode('=', 'a=bc=d', 2); |
|
// * returns 2: ['a', 'bc=d'] |
|
|
|
var emptyArray = { 0: '' }; |
|
|
|
// third argument is not required |
|
if ( arguments.length < 2 || |
|
typeof arguments[0] == 'undefined' || |
|
typeof arguments[1] == 'undefined' ) |
|
{ |
|
return null; |
|
} |
|
|
|
if ( delimiter === '' || |
|
delimiter === false || |
|
delimiter === null ) |
|
{ |
|
return false; |
|
} |
|
|
|
if ( typeof delimiter == 'function' || |
|
typeof delimiter == 'object' || |
|
typeof string == 'function' || |
|
typeof string == 'object' ) |
|
{ |
|
return emptyArray; |
|
} |
|
|
|
if ( delimiter === true ) { |
|
delimiter = '1'; |
|
} |
|
|
|
if (!limit) { |
|
return string.toString().split(delimiter.toString()); |
|
} else { |
|
// support for limit argument |
|
var splitted = string.toString().split(delimiter.toString()); |
|
var partA = splitted.splice(0, limit - 1); |
|
var partB = splitted.join(delimiter.toString()); |
|
partA.push(partB); |
|
return partA; |
|
} |
|
} |
|
} |
|
|
|
/*! public |
|
Prop objects |
|
Used to keep track of which property is being controlled |
|
Methods: |
|
update : update the property to where it should be at the given time |
|
current : return a natural representation of the current property |
|
*/ |
|
var Prop = { |
|
/*! public |
|
Wait, while doing no animating |
|
*/ |
|
wait : { |
|
update : function(obj, from, to, percent) {}, |
|
current : function(obj) {return 0;} |
|
}, |
|
|
|
/*! public |
|
Follows a linear path |
|
*/ |
|
position : { |
|
update : function(obj, from, to, percent) { |
|
var x = jsAnimUtil.interp(from.x, to.x, percent); |
|
var y = jsAnimUtil.interp(from.y, to.y, percent); |
|
|
|
obj.setPosition(x, y); |
|
}, |
|
|
|
current : function(obj) { |
|
var left = parseInt(obj.style.marginLeft); |
|
var top = parseInt(obj.style.marginTop); |
|
var x = left + obj.halfWidth; |
|
var y = top + obj.halfHeight; |
|
return new Pos(x,y); |
|
} |
|
}, |
|
|
|
/*! public |
|
Follows a semicircular path |
|
Params: |
|
-clockwise : True for clockwise, false otherwise |
|
*/ |
|
positionSemicircle : function(clockwise) { |
|
return { |
|
update : function(obj, from, to, percent) { |
|
var centerX = (from.x + to.x) / 2; |
|
var centerY = (from.y + to.y) / 2; |
|
|
|
var h = centerY - from.y; |
|
var w = from.x - centerX; |
|
|
|
var dist = Math.sqrt(h * h + w * w); |
|
|
|
if(w == 0) { |
|
if(h > 0) |
|
var initAngle = - Math.PI / 2; |
|
else |
|
var initAngle = Math.PI / 2; |
|
} |
|
else { |
|
var atan = Math.atan(h / Math.abs(w)); |
|
if(w > 0) |
|
var initAngle = atan; |
|
else { |
|
var initAngle = Math.PI - atan; |
|
} |
|
} |
|
|
|
if(clockwise) |
|
var addAngle = - percent * Math.PI; |
|
else |
|
var addAngle = percent * Math.PI; |
|
|
|
var angle = initAngle + addAngle; |
|
|
|
var x = Math.floor(centerX + dist * Math.cos(angle)); |
|
var y = Math.floor(centerY - dist * Math.sin(angle)); |
|
|
|
obj.setPosition(x, y); |
|
}, |
|
|
|
current : function(obj) { |
|
var left = parseInt(obj.style.marginLeft); |
|
var top = parseInt(obj.style.marginTop); |
|
var x = left + obj.halfWidth; |
|
var y = top + obj.halfHeight; |
|
return new Pos(x,y); |
|
} |
|
} |
|
}, |
|
|
|
/*! public |
|
Follows a circular path through target then back to start |
|
Params: |
|
-clockwise : True for clockwise, false otherwise |
|
*/ |
|
positionCircle : function(clockwise) { |
|
return { |
|
update : function(obj, from, to, percent) { |
|
var centerX = (from.x + to.x) / 2; |
|
var centerY = (from.y + to.y) / 2; |
|
|
|
var h = centerY - from.y; |
|
var w = from.x - centerX; |
|
|
|
var dist = Math.sqrt(h * h + w * w); |
|
|
|
if(w == 0) { |
|
if(h > 0) |
|
var initAngle = - Math.PI / 2; |
|
else |
|
var initAngle = Math.PI / 2; |
|
} |
|
else { |
|
var atan = Math.atan(h / Math.abs(w)); |
|
if(w > 0) |
|
var initAngle = atan; |
|
else { |
|
var initAngle = Math.PI - atan; |
|
} |
|
} |
|
|
|
if(clockwise) |
|
var addAngle = 2 * percent * Math.PI; |
|
else |
|
var addAngle = -2 * percent * Math.PI; |
|
|
|
var angle = initAngle + addAngle; |
|
|
|
var x = Math.floor(centerX + dist * Math.cos(angle)); |
|
var y = Math.floor(centerY + dist * Math.sin(angle)); |
|
|
|
obj.setPosition(x, y); |
|
}, |
|
|
|
current : function(obj) { |
|
var left = parseInt(obj.style.marginLeft); |
|
var top = parseInt(obj.style.marginTop); |
|
var x = left + obj.halfWidth; |
|
var y = top + obj.halfHeight; |
|
return new Pos(x,y); |
|
} |
|
} |
|
}, |
|
|
|
//public |
|
top : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.top = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'top')); |
|
} |
|
|
|
}, |
|
|
|
//public |
|
right : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.right = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'right')); |
|
} |
|
}, |
|
|
|
//public |
|
bottom : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.bottom = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'bottom')); |
|
} |
|
}, |
|
|
|
//public |
|
left : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.left = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'left')); |
|
} |
|
}, |
|
|
|
//public |
|
margin : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.margin = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'margin')); |
|
} |
|
}, |
|
|
|
//public |
|
marginTop : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.marginTop = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'marginTop')); |
|
} |
|
}, |
|
|
|
//public |
|
marginRight : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.marginRight = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'marginRight')); |
|
} |
|
}, |
|
|
|
//public |
|
marginBottom : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.marginBottom = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'marginBottom')); |
|
} |
|
}, |
|
|
|
//public |
|
marginLeft : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.marginLeft = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'marginLeft')); |
|
} |
|
}, |
|
|
|
//public |
|
padding : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.padding = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'padding')); |
|
} |
|
}, |
|
|
|
//public |
|
paddingTop : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.paddingTop = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'paddingTop')); |
|
} |
|
}, |
|
|
|
//public |
|
paddingRight : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.paddingRight = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'paddingRight')); |
|
} |
|
}, |
|
|
|
//public |
|
paddingBottom : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.paddingBottom = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'paddingBottom')); |
|
} |
|
}, |
|
|
|
//public |
|
paddingLeft : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.paddingLeft = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'paddingLeft')); |
|
} |
|
}, |
|
|
|
//public |
|
borderWidth : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.borderWidth = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'borderWidth')); |
|
} |
|
}, |
|
|
|
//public |
|
borderTopWidth : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.borderTopWidth = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'borderTopWidth')); |
|
} |
|
}, |
|
|
|
//public |
|
borderRightWidth : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.borderRightWidth = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'borderRightWidth')); |
|
} |
|
}, |
|
|
|
//public |
|
borderBottomWidth : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.borderBottomWidth = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'borderBottomWidth')); |
|
} |
|
}, |
|
|
|
//public |
|
borderLeftWidth : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.borderLeftWidth = jsAnimUtil.interp(from, to, percent) + "px"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'borderLeftWidth')); |
|
} |
|
}, |
|
|
|
//public |
|
fontSize : { |
|
update : function(obj, from, to, percent) { |
|
obj.style.fontSize = jsAnimUtil.interp(from, to, percent) + "pt"; |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'fontSize')); |
|
} |
|
}, |
|
|
|
//public |
|
height : { |
|
update : function(obj, from, to, percent) { |
|
var v = jsAnimUtil.interp(from, to, percent); |
|
|
|
obj.style.height = v + "px"; |
|
|
|
//Update the position if registered |
|
if(obj.positionRegistered) { |
|
var y = parseInt(obj.style.marginTop) + obj.halfHeight; |
|
obj.halfHeight = Math.floor(obj.offsetHeight/2); |
|
obj.style.marginTop = y - obj.halfHeight + "px"; |
|
} |
|
}, |
|
|
|
current : function(obj) { |
|
var ht = jsAnimUtil.getCSS(obj, 'height'); |
|
if(ht == "auto") |
|
return obj.offsetHeight; |
|
else |
|
return parseInt(ht); |
|
} |
|
}, |
|
|
|
//public |
|
width : { |
|
update : function(obj, from, to, percent) { |
|
var v = jsAnimUtil.interp(from, to, percent); |
|
|
|
obj.style.width = v + "px"; |
|
|
|
//Update the position if registered |
|
if(obj.positionRegistered) { |
|
var x = parseInt(obj.style.marginLeft) + obj.halfWidth; |
|
obj.halfWidth = Math.floor(obj.offsetWidth/2); |
|
obj.style.marginLeft = x - obj.halfWidth + "px"; |
|
} |
|
}, |
|
|
|
current : function(obj) { |
|
return parseInt(jsAnimUtil.getCSS(obj, 'width')); |
|
} |
|
}, |
|
|
|
//public |
|
dimension : { |
|
update : function(obj, from, to, percent) { |
|
var h = jsAnimUtil.interp(from.h, to.h, percent); |
|
var w = jsAnimUtil.interp(from.w, to.w, percent); |
|
|
|
obj.style.height = h + "px"; |
|
obj.style.width = w + "px"; |
|
|
|
//Update the position if registered |
|
if(obj.positionRegistered) { |
|
var y = parseInt(obj.style.marginTop) + obj.halfHeight; |
|
obj.halfHeight = Math.floor(obj.offsetHeight/2); |
|
obj.style.marginTop = (y - obj.halfHeight) + "px"; |
|
|
|
var x = parseInt(obj.style.marginLeft) + obj.halfWidth; |
|
obj.halfWidth = Math.floor(obj.offsetWidth/2); |
|
obj.style.marginLeft = (x - obj.halfWidth) + "px"; |
|
} |
|
}, |
|
|
|
current : function(obj) { |
|
var ht = jsAnimUtil.getCSS(obj, 'height'); |
|
if(ht == "auto") |
|
var h = obj.offsetHeight; |
|
else |
|
var h = parseInt(ht); |
|
var w = parseInt(jsAnimUtil.getCSS(obj, 'width')); |
|
return new Dim(w, h); |
|
} |
|
}, |
|
|
|
//public |
|
color : { |
|
update : function(obj, from, to, percent) { |
|
r = jsAnimUtil.interp(from.r, to.r, percent); |
|
g = jsAnimUtil.interp(from.g, to.g, percent); |
|
b = jsAnimUtil.interp(from.b, to.b, percent); |
|
|
|
obj.style.color = "rgb("+r+","+g+","+b+")"; |
|
}, |
|
|
|
current : function(obj) { |
|
var color = jsAnimUtil.getCSS(obj, 'color'); |
|
color = color.substring(4,color.length-1); |
|
var rgb = jsAnimUtil.explode(",",color); |
|
return new Col(parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])); |
|
} |
|
}, |
|
|
|
//public |
|
backgroundColor : { |
|
update : function(obj, from, to, percent) { |
|
r = jsAnimUtil.interp(from.r, to.r, percent); |
|
g = jsAnimUtil.interp(from.g, to.g, percent); |
|
b = jsAnimUtil.interp(from.b, to.b, percent); |
|
|
|
obj.style.backgroundColor = "rgb("+r+","+g+","+b+")"; |
|
}, |
|
|
|
current : function(obj) { |
|
var color = jsAnimUtil.getCSS(obj, 'backgroundColor'); |
|
color = color.substring(4,color.length-1); |
|
var rgb = jsAnimUtil.explode(",",color); |
|
|
|
return new Col(parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])); |
|
} |
|
}, |
|
|
|
//public |
|
borderColor : { |
|
update : function(obj, from, to, percent) { |
|
r = jsAnimUtil.interp(from.r, to.r, percent); |
|
g = jsAnimUtil.interp(from.g, to.g, percent); |
|
b = jsAnimUtil.interp(from.b, to.b, percent); |
|
|
|
obj.style.borderColor = "rgb("+r+","+g+","+b+")"; |
|
}, |
|
|
|
current : function(obj) { |
|
var color = jsAnimUtil.getCSS(obj, 'borderColor'); |
|
color = color.substring(4,color.length-1); |
|
var rgb = jsAnimUtil.explode(",",color); |
|
return new Col(parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])); |
|
} |
|
}, |
|
|
|
//public |
|
opacity : { |
|
update : function(obj, from, to, percent) { |
|
v = jsAnimUtil.interp(100*from, 100*to, percent); |
|
obj.style.opacity = v / 100; |
|
}, |
|
|
|
current : function(obj) { |
|
return jsAnimUtil.getCSS(obj, 'opacity'); |
|
} |
|
} |
|
}/* |
|
http://www.JSON.org/json2.js |
|
2011-02-23 |
|
|
|
Public Domain. |
|
|
|
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. |
|
|
|
See http://www.JSON.org/js.html |
|
|
|
|
|
This code should be minified before deployment. |
|
See http://javascript.crockford.com/jsmin.html |
|
|
|
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO |
|
NOT CONTROL. |
|
|
|
|
|
This file creates a global JSON object containing two methods: stringify |
|
and parse. |
|
|
|
JSON.stringify(value, replacer, space) |
|
value any JavaScript value, usually an object or array. |
|
|
|
replacer an optional parameter that determines how object |
|
values are stringified for objects. It can be a |
|
function or an array of strings. |
|
|
|
space an optional parameter that specifies the indentation |
|
of nested structures. If it is omitted, the text will |
|
be packed without extra whitespace. If it is a number, |
|
it will specify the number of spaces to indent at each |
|
level. If it is a string (such as '\t' or ' '), |
|
it contains the characters used to indent at each level. |
|
|
|
This method produces a JSON text from a JavaScript value. |
|
|
|
When an object value is found, if the object contains a toJSON |
|
method, its toJSON method will be called and the result will be |
|
stringified. A toJSON method does not serialize: it returns the |
|
value represented by the name/value pair that should be serialized, |
|
or undefined if nothing should be serialized. The toJSON method |
|
will be passed the key associated with the value, and this will be |
|
bound to the value |
|
|
|
For example, this would serialize Dates as ISO strings. |
|
|
|
Date.prototype.toJSON = function (key) { |
|
function f(n) { |
|
// Format integers to have at least two digits. |
|
return n < 10 ? '0' + n : n; |
|
} |
|
|
|
return this.getUTCFullYear() + '-' + |
|
f(this.getUTCMonth() + 1) + '-' + |
|
f(this.getUTCDate()) + 'T' + |
|
f(this.getUTCHours()) + ':' + |
|
f(this.getUTCMinutes()) + ':' + |
|
f(this.getUTCSeconds()) + 'Z'; |
|
}; |
|
|
|
You can provide an optional replacer method. It will be passed the |
|
key and value of each member, with this bound to the containing |
|
object. The value that is returned from your method will be |
|
serialized. If your method returns undefined, then the member will |
|
be excluded from the serialization. |
|
|
|
If the replacer parameter is an array of strings, then it will be |
|
used to select the members to be serialized. It filters the results |
|
such that only members with keys listed in the replacer array are |
|
stringified. |
|
|
|
Values that do not have JSON representations, such as undefined or |
|
functions, will not be serialized. Such values in objects will be |
|
dropped; in arrays they will be replaced with null. You can use |
|
a replacer function to replace those with JSON values. |
|
JSON.stringify(undefined) returns undefined. |
|
|
|
The optional space parameter produces a stringification of the |
|
value that is filled with line breaks and indentation to make it |
|
easier to read. |
|
|
|
If the space parameter is a non-empty string, then that string will |
|
be used for indentation. If the space parameter is a number, then |
|
the indentation will be that many spaces. |
|
|
|
Example: |
|
|
|
text = JSON.stringify(['e', {pluribus: 'unum'}]); |
|
// text is '["e",{"pluribus":"unum"}]' |
|
|
|
|
|
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); |
|
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' |
|
|
|
text = JSON.stringify([new Date()], function (key, value) { |
|
return this[key] instanceof Date ? |
|
'Date(' + this[key] + ')' : value; |
|
}); |
|
// text is '["Date(---current time---)"]' |
|
|
|
|
|
JSON.parse(text, reviver) |
|
This method parses a JSON text to produce an object or array. |
|
It can throw a SyntaxError exception. |
|
|
|
The optional reviver parameter is a function that can filter and |
|
transform the results. It receives each of the keys and values, |
|
and its return value is used instead of the original value. |
|
If it returns what it received, then the structure is not modified. |
|
If it returns undefined then the member is deleted. |
|
|
|
Example: |
|
|
|
// Parse the text. Values that look like ISO date strings will |
|
// be converted to Date objects. |
|
|
|
myData = JSON.parse(text, function (key, value) { |
|
var a; |
|
if (typeof value === 'string') { |
|
a = |
|
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); |
|
if (a) { |
|
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], |
|
+a[5], +a[6])); |
|
} |
|
} |
|
return value; |
|
}); |
|
|
|
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { |
|
var d; |
|
if (typeof value === 'string' && |
|
value.slice(0, 5) === 'Date(' && |
|
value.slice(-1) === ')') { |
|
d = new Date(value.slice(5, -1)); |
|
if (d) { |
|
return d; |
|
} |
|
} |
|
return value; |
|
}); |
|
|
|
|
|
This is a reference implementation. You are free to copy, modify, or |
|
redistribute. |
|
*/ |
|
|
|
/*jslint evil: true, strict: false, regexp: false */ |
|
|
|
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, |
|
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, |
|
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, |
|
lastIndex, length, parse, prototype, push, replace, slice, stringify, |
|
test, toJSON, toString, valueOf |
|
*/ |
|
|
|
|
|
// Create a JSON object only if one does not already exist. We create the |
|
// methods in a closure to avoid creating global variables. |
|
|
|
var JSON; |
|
if (!JSON) { |
|
JSON = {}; |
|
} |
|
|
|
(function () { |
|
"use strict"; |
|
|
|
function f(n) { |
|
// Format integers to have at least two digits. |
|
return n < 10 ? '0' + n : n; |
|
} |
|
|
|
if (typeof Date.prototype.toJSON !== 'function') { |
|
|
|
Date.prototype.toJSON = function (key) { |
|
|
|
return isFinite(this.valueOf()) ? |
|
this.getUTCFullYear() + '-' + |
|
f(this.getUTCMonth() + 1) + '-' + |
|
f(this.getUTCDate()) + 'T' + |
|
f(this.getUTCHours()) + ':' + |
|
f(this.getUTCMinutes()) + ':' + |
|
f(this.getUTCSeconds()) + 'Z' : null; |
|
}; |
|
|
|
String.prototype.toJSON = |
|
Number.prototype.toJSON = |
|
Boolean.prototype.toJSON = function (key) { |
|
return this.valueOf(); |
|
}; |
|
} |
|
|
|
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, |
|
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, |
|
gap, |
|
indent, |
|
meta = { // table of character substitutions |
|
'\b': '\\b', |
|
'\t': '\\t', |
|
'\n': '\\n', |
|
'\f': '\\f', |
|
'\r': '\\r', |
|
'"' : '\\"', |
|
'\\': '\\\\' |
|
}, |
|
rep; |
|
|
|
|
|
function quote(string) { |
|
|
|
// If the string contains no control characters, no quote characters, and no |
|
// backslash characters, then we can safely slap some quotes around it. |
|
// Otherwise we must also replace the offending characters with safe escape |
|
// sequences. |
|
|
|
escapable.lastIndex = 0; |
|
return escapable.test(string) ? '"' + string.replace(escapable, function (a) { |
|
var c = meta[a]; |
|
return typeof c === 'string' ? c : |
|
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
|
}) + '"' : '"' + string + '"'; |
|
} |
|
|
|
|
|
function str(key, holder) { |
|
|
|
// Produce a string from holder[key]. |
|
|
|
var i, // The loop counter. |
|
k, // The member key. |
|
v, // The member value. |
|
length, |
|
mind = gap, |
|
partial, |
|
value = holder[key]; |
|
|
|
// If the value has a toJSON method, call it to obtain a replacement value. |
|
|
|
if (value && typeof value === 'object' && |
|
typeof value.toJSON === 'function') { |
|
value = value.toJSON(key); |
|
} |
|
|
|
// If we were called with a replacer function, then call the replacer to |
|
// obtain a replacement value. |
|
|
|
if (typeof rep === 'function') { |
|
value = rep.call(holder, key, value); |
|
} |
|
|
|
// What happens next depends on the value's type. |
|
|
|
switch (typeof value) { |
|
case 'string': |
|
return quote(value); |
|
|
|
case 'number': |
|
|
|
// JSON numbers must be finite. Encode non-finite numbers as null. |
|
|
|
return isFinite(value) ? String(value) : 'null'; |
|
|
|
case 'boolean': |
|
case 'null': |
|
|
|
// If the value is a boolean or null, convert it to a string. Note: |
|
// typeof null does not produce 'null'. The case is included here in |
|
// the remote chance that this gets fixed someday. |
|
|
|
return String(value); |
|
|
|
// If the type is 'object', we might be dealing with an object or an array or |
|
// null. |
|
|
|
case 'object': |
|
|
|
// Due to a specification blunder in ECMAScript, typeof null is 'object', |
|
// so watch out for that case. |
|
|
|
if (!value) { |
|
return 'null'; |
|
} |
|
|
|
// Make an array to hold the partial results of stringifying this object value. |
|
|
|
gap += indent; |
|
partial = []; |
|
|
|
// Is the value an array? |
|
|
|
if (Object.prototype.toString.apply(value) === '[object Array]') { |
|
|
|
// The value is an array. Stringify every element. Use null as a placeholder |
|
// for non-JSON values. |
|
|
|
length = value.length; |
|
for (i = 0; i < length; i += 1) { |
|
partial[i] = str(i, value) || 'null'; |
|
} |
|
|
|
// Join all of the elements together, separated with commas, and wrap them in |
|
// brackets. |
|
|
|
v = partial.length === 0 ? '[]' : gap ? |
|
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : |
|
'[' + partial.join(',') + ']'; |
|
gap = mind; |
|
return v; |
|
} |
|
|
|
// If the replacer is an array, use it to select the members to be stringified. |
|
|
|
if (rep && typeof rep === 'object') { |
|
length = rep.length; |
|
for (i = 0; i < length; i += 1) { |
|
if (typeof rep[i] === 'string') { |
|
k = rep[i]; |
|
v = str(k, value); |
|
if (v) { |
|
partial.push(quote(k) + (gap ? ': ' : ':') + v); |
|
} |
|
} |
|
} |
|
} else { |
|
|
|
// Otherwise, iterate through all of the keys in the object. |
|
|
|
for (k in value) { |
|
if (Object.prototype.hasOwnProperty.call(value, k)) { |
|
v = str(k, value); |
|
if (v) { |
|
partial.push(quote(k) + (gap ? ': ' : ':') + v); |
|
} |
|
} |
|
} |
|
} |
|
|
|
// Join all of the member texts together, separated with commas, |
|
// and wrap them in braces. |
|
|
|
v = partial.length === 0 ? '{}' : gap ? |
|
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : |
|
'{' + partial.join(',') + '}'; |
|
gap = mind; |
|
return v; |
|
} |
|
} |
|
|
|
// If the JSON object does not yet have a stringify method, give it one. |
|
|
|
if (typeof JSON.stringify !== 'function') { |
|
JSON.stringify = function (value, replacer, space) { |
|
|
|
// The stringify method takes a value and an optional replacer, and an optional |
|
// space parameter, and returns a JSON text. The replacer can be a function |
|
// that can replace values, or an array of strings that will select the keys. |
|
// A default replacer method can be provided. Use of the space parameter can |
|
// produce text that is more easily readable. |
|
|
|
var i; |
|
gap = ''; |
|
indent = ''; |
|
|
|
// If the space parameter is a number, make an indent string containing that |
|
// many spaces. |
|
|
|
if (typeof space === 'number') { |
|
for (i = 0; i < space; i += 1) { |
|
indent += ' '; |
|
} |
|
|
|
// If the space parameter is a string, it will be used as the indent string. |
|
|
|
} else if (typeof space === 'string') { |
|
indent = space; |
|
} |
|
|
|
// If there is a replacer, it must be a function or an array. |
|
// Otherwise, throw an error. |
|
|
|
rep = replacer; |
|
if (replacer && typeof replacer !== 'function' && |
|
(typeof replacer !== 'object' || |
|
typeof replacer.length !== 'number')) { |
|
throw new Error('JSON.stringify'); |
|
} |
|
|
|
// Make a fake root object containing our value under the key of ''. |
|
// Return the result of stringifying the value. |
|
|
|
return str('', {'': value}); |
|
}; |
|
} |
|
|
|
|
|
// If the JSON object does not yet have a parse method, give it one. |
|
|
|
if (typeof JSON.parse !== 'function') { |
|
JSON.parse = function (text, reviver) { |
|
|
|
// The parse method takes a text and an optional reviver function, and returns |
|
// a JavaScript value if the text is a valid JSON text. |
|
|
|
var j; |
|
|
|
function walk(holder, key) { |
|
|
|
// The walk method is used to recursively walk the resulting structure so |
|
// that modifications can be made. |
|
|
|
var k, v, value = holder[key]; |
|
if (value && typeof value === 'object') { |
|
for (k in value) { |
|
if (Object.prototype.hasOwnProperty.call(value, k)) { |
|
v = walk(value, k); |
|
if (v !== undefined) { |
|
value[k] = v; |
|
} else { |
|
delete value[k]; |
|
} |
|
} |
|
} |
|
} |
|
return reviver.call(holder, key, value); |
|
} |
|
|
|
|
|
// Parsing happens in four stages. In the first stage, we replace certain |
|
// Unicode characters with escape sequences. JavaScript handles many characters |
|
// incorrectly, either silently deleting them, or treating them as line endings. |
|
|
|
text = String(text); |
|
cx.lastIndex = 0; |
|
if (cx.test(text)) { |
|
text = text.replace(cx, function (a) { |
|
return '\\u' + |
|
('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
|
}); |
|
} |
|
|
|
// In the second stage, we run the text against regular expressions that look |
|
// for non-JSON patterns. We are especially concerned with '()' and 'new' |
|
// because they can cause invocation, and '=' because it can cause mutation. |
|
// But just to be safe, we want to reject all unexpected forms. |
|
|
|
// We split the second stage into 4 regexp operations in order to work around |
|
// crippling inefficiencies in IE's and Safari's regexp engines. First we |
|
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we |
|
// replace all simple value tokens with ']' characters. Third, we delete all |
|
// open brackets that follow a colon or comma or that begin the text. Finally, |
|
// we look to see that the remaining characters are only whitespace or ']' or |
|
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. |
|
|
|
if (/^[\],:{}\s]*$/ |
|
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') |
|
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') |
|
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { |
|
|
|
// In the third stage we use the eval function to compile the text into a |
|
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity |
|
// in JavaScript: it can begin a block or an object literal. We wrap the text |
|
// in parens to eliminate the ambiguity. |
|
|
|
j = eval('(' + text + ')'); |
|
|
|
// In the optional fourth stage, we recursively walk the new structure, passing |
|
// each name/value pair to a reviver function for possible transformation. |
|
|
|
return typeof reviver === 'function' ? |
|
walk({'': j}, '') : j; |
|
} |
|
|
|
// If the text is not JSON parseable, then a SyntaxError is thrown. |
|
|
|
throw new SyntaxError('JSON.parse'); |
|
}; |
|
} |
|
}()); |
|
/*! |
|
* 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, |
|
rBackslash = /\\/g, |
|
rNonWord = /\W/; |
|
|
|
// 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( rBackslash, "" ); |
|
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" ); |
|
}, |
|
type: function( elem ) { |
|
return elem.getAttribute( "type" ); |
|
} |
|
}, |
|
|
|
relative: { |
|
"+": function(checkSet, part){ |
|
var isPartStr = typeof part === "string", |
|
isTag = isPartStr && !rNonWord.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 && !rNonWord.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" && !rNonWord.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" && !rNonWord.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( rBackslash, "" ) + " "; |
|
|
|
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( rBackslash, "" ); |
|
}, |
|
|
|
TAG: function( match, curLoop ) { |
|
return match[1].replace( rBackslash, "" ).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( rBackslash, "" ); |
|
|
|
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( rBackslash, "" ); |
|
|
|
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 |
|
if ( elem.parentNode ) { |
|
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 ) { |
|
var attr = elem.getAttribute( "type" ), type = elem.type; |
|
// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) |
|
// use getAttribute instead to test this case |
|
return "text" === type && ( attr === type || attr === null ); |
|
}, |
|
|
|
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 oldContext = context, |
|
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 ) { |
|
oldContext.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 |
|
|
|
window.Sizzle = Sizzle; |
|
|
|
})(); |
|
// This fixes the syntax highlighting in TextMate " |
|
|
|
// First set up the alias |
|
Mappa.addAlias('Toolbox'); |
|
|
|
// Then map all of the functions |
|
|
|
// Sizzle |
|
Toolbox.addMap('find', Sizzle); |
|
|
|
// JSON |
|
Toolbox.addMap('json', { |
|
encode: JSON.stringify, |
|
decode: JSON.parse |
|
}); |
|
|
|
// Browser detect |
|
Toolbox.addMap('client', { |
|
browser: BrowserDetect.browser, |
|
version: BrowserDetect.version, |
|
os: BrowserDetect.OS |
|
}); |
|
|
|
// Cookie |
|
Toolbox.addMap('cookie', { |
|
set: set_cookie, |
|
get: get_cookie, |
|
del: del_cookie, |
|
array: { |
|
init: init_array, |
|
set: set_array, |
|
get: get_array, |
|
entry: { |
|
del: del_entry, |
|
next: next_entry |
|
} |
|
}, |
|
debug: { |
|
on: debug_on, |
|
off: debug_off |
|
}, |
|
dump: dump_cookies |
|
}); |
|
|
|
// Events |
|
Toolbox.addMap('event', { |
|
add: addEvent, |
|
remove: removeEvent, |
|
handle: handleEvent, |
|
fix: fixEvent |
|
}); |
|
|
|
// AJAX |
|
Toolbox.addMap('ajax', AjaxRequest); |
|
|
|
// Animate |
|
Toolbox.addMap('animator', jsAnimManager); |