/*!
- * Ext JS Library 3.1.0
- * Copyright(c) 2006-2009 Ext JS, LLC
+ * Ext JS Library 3.1.1
+ * Copyright(c) 2006-2010 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
*/
<li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>\r
<li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>\r
<li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>\r
+ <li> <b>E:any(S1|S2|S2)</b> an E element which matches any of the simple selectors S1, S2 or S3//\\</li>\r
</ul>\r
<h4>CSS Value Selectors:</h4>\r
<ul class="list">\r
nthRe = /(\d*)n\+?(\d*)/, \r
nthRe2 = /\D/,\r
// This is for IE MSXML which does not support expandos.\r
- // IE runs the same speed using setAttribute, however FF slows way down\r
- // and Safari completely fails so they need to continue to use expandos.\r
- isIE = window.ActiveXObject ? true : false,\r
- key = 30803;\r
- \r
+ // IE runs the same speed using setAttribute, however FF slows way down\r
+ // and Safari completely fails so they need to continue to use expandos.\r
+ isIE = window.ActiveXObject ? true : false,\r
+ key = 30803;\r
+ \r
// this eval is stop the compressor from\r
- // renaming the variable to something shorter\r
- eval("var batch = 30803;"); \r
+ // renaming the variable to something shorter\r
+ eval("var batch = 30803;"); \r
\r
- function child(p, index){\r
+ // Retrieve the child node from a particular\r
+ // parent at the specified index.\r
+ function child(parent, index){\r
var i = 0,\r
- n = p.firstChild;\r
+ n = parent.firstChild;\r
while(n){\r
if(n.nodeType == 1){\r
if(++i == index){\r
n = n.nextSibling;\r
}\r
return null;\r
- };\r
+ }\r
\r
- function next(n){\r
+ // retrieve the next element node\r
+ function next(n){ \r
while((n = n.nextSibling) && n.nodeType != 1);\r
return n;\r
- };\r
+ }\r
\r
+ // retrieve the previous element node \r
function prev(n){\r
while((n = n.previousSibling) && n.nodeType != 1);\r
return n;\r
- };\r
+ }\r
+\r
+ // Mark each child node with a nodeIndex skipping and\r
+ // removing empty text nodes.\r
+ function children(parent){\r
+ var n = parent.firstChild,\r
+ nodeIndex = -1,\r
+ nextNode;\r
+ while(n){\r
+ nextNode = n.nextSibling;\r
+ // clean worthless empty nodes.\r
+ if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){\r
+ parent.removeChild(n);\r
+ }else{\r
+ // add an expando nodeIndex\r
+ n.nodeIndex = ++nodeIndex;\r
+ }\r
+ n = nextNode;\r
+ }\r
+ return this;\r
+ }\r
+\r
\r
- function children(d){\r
- var n = d.firstChild, ni = -1,\r
- nx;\r
- while(n){\r
- nx = n.nextSibling;\r
- if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){\r
- d.removeChild(n);\r
- }else{\r
- n.nodeIndex = ++ni;\r
- }\r
- n = nx;\r
- }\r
- return this;\r
- };\r
-\r
- function byClassName(c, a, v){\r
- if(!v){\r
- return c;\r
+ // nodeSet - array of nodes\r
+ // cls - CSS Class\r
+ function byClassName(nodeSet, cls){\r
+ if(!cls){\r
+ return nodeSet;\r
}\r
- var r = [], ri = -1, cn;\r
- for(var i = 0, ci; ci = c[i]; i++){\r
- if((' '+ci.className+' ').indexOf(v) != -1){\r
- r[++ri] = ci;\r
+ var result = [], ri = -1;\r
+ for(var i = 0, ci; ci = nodeSet[i]; i++){\r
+ if((' '+ci.className+' ').indexOf(cls) != -1){\r
+ result[++ri] = ci;\r
}\r
}\r
- return r;\r
+ return result;\r
};\r
\r
function attrValue(n, attr){\r
+ // if its an array, use the first node.\r
if(!n.tagName && typeof n.length != "undefined"){\r
n = n[0];\r
}\r
if(!n){\r
return null;\r
}\r
+\r
if(attr == "for"){\r
return n.htmlFor;\r
}\r
\r
};\r
\r
+\r
+ // ns - nodes\r
+ // mode - false, /, >, +, ~\r
+ // tagName - defaults to "*"\r
function getNodes(ns, mode, tagName){\r
var result = [], ri = -1, cs;\r
if(!ns){\r
return result;\r
}\r
tagName = tagName || "*";\r
+ // convert to array\r
if(typeof ns.getElementsByTagName != "undefined"){\r
ns = [ns];\r
}\r
+ \r
+ // no mode specified, grab all elements by tagName\r
+ // at any depth\r
if(!mode){\r
for(var i = 0, ni; ni = ns[i]; i++){\r
cs = ni.getElementsByTagName(tagName);\r
result[++ri] = ci;\r
}\r
}\r
- }else if(mode == "/" || mode == ">"){\r
+ // Direct Child mode (/ or >)\r
+ // E > F or E/F all direct children elements of E that have the tag \r
+ } else if(mode == "/" || mode == ">"){\r
var utag = tagName.toUpperCase();\r
for(var i = 0, ni, cn; ni = ns[i]; i++){\r
cn = ni.childNodes;\r
}\r
}\r
}\r
+ // Immediately Preceding mode (+)\r
+ // E + F all elements with the tag F that are immediately preceded by an element with the tag E\r
}else if(mode == "+"){\r
var utag = tagName.toUpperCase();\r
for(var i = 0, n; n = ns[i]; i++){\r
result[++ri] = n;\r
}\r
}\r
+ // Sibling mode (~)\r
+ // E ~ F all elements with the tag F that are preceded by a sibling element with the tag E\r
}else if(mode == "~"){\r
var utag = tagName.toUpperCase();\r
for(var i = 0, n; n = ns[i]; i++){\r
}\r
}\r
return result;\r
- };\r
+ }\r
\r
function concat(a, b){\r
if(b.slice){\r
if(!tagName){\r
return cs;\r
}\r
- var r = [], ri = -1;\r
+ var result = [], ri = -1;\r
tagName = tagName.toLowerCase();\r
for(var i = 0, ci; ci = cs[i]; i++){\r
- if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){\r
- r[++ri] = ci;\r
+ if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){\r
+ result[++ri] = ci;\r
}\r
}\r
- return r;\r
- };\r
+ return result;\r
+ }\r
\r
- function byId(cs, attr, id){\r
+ function byId(cs, id){\r
if(cs.tagName || cs == document){\r
cs = [cs];\r
}\r
if(!id){\r
return cs;\r
}\r
- var r = [], ri = -1;\r
- for(var i = 0,ci; ci = cs[i]; i++){\r
+ var result = [], ri = -1;\r
+ for(var i = 0, ci; ci = cs[i]; i++){\r
if(ci && ci.id == id){\r
- r[++ri] = ci;\r
- return r;\r
+ result[++ri] = ci;\r
+ return result;\r
}\r
}\r
- return r;\r
- };\r
+ return result;\r
+ }\r
\r
+ // operators are =, !=, ^=, $=, *=, %=, |= and ~=\r
+ // custom can be "{"\r
function byAttribute(cs, attr, value, op, custom){\r
- var r = [], \r
- ri = -1, \r
- st = custom=="{",\r
- f = Ext.DomQuery.operators[op];\r
+ var result = [], \r
+ ri = -1, \r
+ useGetStyle = custom == "{", \r
+ fn = Ext.DomQuery.operators[op], \r
+ a, \r
+ innerHTML;\r
for(var i = 0, ci; ci = cs[i]; i++){\r
+ // skip non-element nodes.\r
if(ci.nodeType != 1){\r
continue;\r
}\r
- var a;\r
- if(st){\r
- a = Ext.DomQuery.getStyle(ci, attr);\r
- }\r
- else if(attr == "class" || attr == "className"){\r
- a = ci.className;\r
- }else if(attr == "for"){\r
- a = ci.htmlFor;\r
- }else if(attr == "href"){\r
- a = ci.getAttribute("href", 2);\r
+ \r
+ innerHTML = ci.innerHTML;\r
+ // we only need to change the property names if we're dealing with html nodes, not XML\r
+ if(innerHTML !== null && innerHTML !== undefined){\r
+ if(useGetStyle){\r
+ a = Ext.DomQuery.getStyle(ci, attr);\r
+ } else if (attr == "class" || attr == "className"){\r
+ a = ci.className;\r
+ } else if (attr == "for"){\r
+ a = ci.htmlFor;\r
+ } else if (attr == "href"){\r
+ // getAttribute href bug\r
+ // http://www.glennjones.net/Post/809/getAttributehrefbug.htm\r
+ a = ci.getAttribute("href", 2);\r
+ } else{\r
+ a = ci.getAttribute(attr);\r
+ }\r
}else{\r
a = ci.getAttribute(attr);\r
}\r
- if((f && f(a, value)) || (!f && a)){\r
- r[++ri] = ci;\r
+ if((fn && fn(a, value)) || (!fn && a)){\r
+ result[++ri] = ci;\r
}\r
}\r
- return r;\r
- };\r
+ return result;\r
+ }\r
\r
function byPseudo(cs, name, value){\r
return Ext.DomQuery.pseudos[name](cs, value);\r
- };\r
+ }\r
\r
function nodupIEXml(cs){\r
var d = ++key, \r
- r;\r
+ r;\r
cs[0].setAttribute("_nodup", d);\r
r = [cs[0]];\r
for(var i = 1, len = cs.length; i < len; i++){\r
\r
function quickDiffIEXml(c1, c2){\r
var d = ++key,\r
- r = [];\r
+ r = [];\r
for(var i = 0, len = c1.length; i < len; i++){\r
c1[i].setAttribute("_qdiff", d);\r
} \r
return d.getElementById(id);\r
}\r
ns = getNodes(ns, mode, "*");\r
- return byId(ns, null, id);\r
+ return byId(ns, id);\r
}\r
\r
return {\r
compile : function(path, type){\r
type = type || "select";\r
\r
+ // setup fn preamble\r
var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],\r
- q = path, mode, lq,\r
- tk = Ext.DomQuery.matchers,\r
- tklen = tk.length,\r
- mm,\r
+ mode, \r
+ lastPath,\r
+ matchers = Ext.DomQuery.matchers,\r
+ matchersLn = matchers.length,\r
+ modeMatch,\r
// accept leading mode switch\r
- lmode = q.match(modeRe);\r
+ lmode = path.match(modeRe);\r
\r
if(lmode && lmode[1]){\r
fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';\r
- q = q.replace(lmode[1], "");\r
+ path = path.replace(lmode[1], "");\r
}\r
+ \r
// strip leading slashes\r
while(path.substr(0, 1)=="/"){\r
path = path.substr(1);\r
}\r
\r
- while(q && lq != q){\r
- lq = q;\r
- var tm = q.match(tagTokenRe);\r
+ while(path && lastPath != path){\r
+ lastPath = path;\r
+ var tokenMatch = path.match(tagTokenRe);\r
if(type == "select"){\r
- if(tm){\r
- if(tm[1] == "#"){\r
- fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';\r
+ if(tokenMatch){\r
+ // ID Selector\r
+ if(tokenMatch[1] == "#"){\r
+ fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");'; \r
}else{\r
- fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';\r
+ fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';\r
}\r
- q = q.replace(tm[0], "");\r
- }else if(q.substr(0, 1) != '@'){\r
+ path = path.replace(tokenMatch[0], "");\r
+ }else if(path.substr(0, 1) != '@'){\r
fn[fn.length] = 'n = getNodes(n, mode, "*");';\r
}\r
+ // type of "simple"\r
}else{\r
- if(tm){\r
- if(tm[1] == "#"){\r
- fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';\r
+ if(tokenMatch){\r
+ if(tokenMatch[1] == "#"){\r
+ fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';\r
}else{\r
- fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';\r
+ fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';\r
}\r
- q = q.replace(tm[0], "");\r
+ path = path.replace(tokenMatch[0], "");\r
}\r
}\r
- while(!(mm = q.match(modeRe))){\r
+ while(!(modeMatch = path.match(modeRe))){\r
var matched = false;\r
- for(var j = 0; j < tklen; j++){\r
- var t = tk[j];\r
- var m = q.match(t.re);\r
+ for(var j = 0; j < matchersLn; j++){\r
+ var t = matchers[j];\r
+ var m = path.match(t.re);\r
if(m){\r
fn[fn.length] = t.select.replace(tplRe, function(x, i){\r
- return m[i];\r
- });\r
- q = q.replace(m[0], "");\r
+ return m[i];\r
+ });\r
+ path = path.replace(m[0], "");\r
matched = true;\r
break;\r
}\r
}\r
// prevent infinite loop on bad selector\r
if(!matched){\r
- throw 'Error parsing selector, parsing failed at "' + q + '"';\r
+ throw 'Error parsing selector, parsing failed at "' + path + '"';\r
}\r
}\r
- if(mm[1]){\r
- fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';\r
- q = q.replace(mm[1], "");\r
+ if(modeMatch[1]){\r
+ fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';\r
+ path = path.replace(modeMatch[1], "");\r
}\r
}\r
+ // close fn out\r
fn[fn.length] = "return nodup(n);\n}";\r
+ \r
+ // eval fn and return it\r
eval(fn.join(""));\r
return f;\r
},\r
/**\r
* Selects a group of elements.\r
* @param {String} selector The selector/xpath query (can be a comma separated list of selectors)\r
- * @param {Node} root (optional) The start of the query (defaults to document).\r
+ * @param {Node/String} root (optional) The start of the query (defaults to document).\r
* @return {Array} An Array of DOM elements which match the selector. If there are\r
* no matches, and empty Array is returned.\r
*/\r
- select : function(path, root, type){\r
- if(!root || root == document){\r
- root = document;\r
- }\r
+ jsSelect: function(path, root, type){\r
+ // set root to doc if not specified.\r
+ root = root || document;\r
+ \r
if(typeof root == "string"){\r
root = document.getElementById(root);\r
}\r
var paths = path.split(","),\r
results = [];\r
- for(var i = 0, len = paths.length; i < len; i++){\r
- var p = paths[i].replace(trimRe, "");\r
- if(!cache[p]){\r
- cache[p] = Ext.DomQuery.compile(p);\r
- if(!cache[p]){\r
- throw p + " is not a valid selector";\r
+ \r
+ // loop over each selector\r
+ for(var i = 0, len = paths.length; i < len; i++){ \r
+ var subPath = paths[i].replace(trimRe, "");\r
+ // compile and place in cache\r
+ if(!cache[subPath]){\r
+ cache[subPath] = Ext.DomQuery.compile(subPath);\r
+ if(!cache[subPath]){\r
+ throw subPath + " is not a valid selector";\r
}\r
}\r
- var result = cache[p](root);\r
+ var result = cache[subPath](root);\r
if(result && result != document){\r
results = results.concat(result);\r
}\r
}\r
+ \r
+ // if there were multiple selectors, make sure dups\r
+ // are eliminated\r
if(paths.length > 1){\r
return nodup(results);\r
}\r
return results;\r
},\r
+ isXml: function(el) {\r
+ var docEl = (el ? el.ownerDocument || el : 0).documentElement;\r
+ return docEl ? docEl.nodeName !== "HTML" : false;\r
+ },\r
+ select : document.querySelectorAll ? function(path, root, type) {\r
+ root = root || document;\r
+ if (!Ext.DomQuery.isXml(root)) {\r
+ try {\r
+ var cs = root.querySelectorAll(path);\r
+ return Ext.toArray(cs);\r
+ }\r
+ catch (ex) {} \r
+ } \r
+ return Ext.DomQuery.jsSelect.call(this, path, root, type);\r
+ } : function(path, root, type) {\r
+ return Ext.DomQuery.jsSelect.call(this, path, root, type);\r
+ },\r
\r
/**\r
* Selects a single element.\r
}\r
var n = valueCache[path](root), v;\r
n = n[0] ? n[0] : n;\r
- \r
+ \r
+ // overcome a limitation of maximum textnode size\r
+ // Rumored to potentially crash IE6 but has not been confirmed.\r
+ // http://reference.sitepoint.com/javascript/Node/normalize\r
+ // https://developer.mozilla.org/En/DOM/Node.normalize \r
if (typeof n.normalize == 'function') n.normalize();\r
\r
v = (n && n.firstChild ? n.firstChild.nodeValue : null);\r
\r
/**\r
* Collection of matching regular expressions and code snippets.\r
+ * Each capture group within () will be replace the {} in the select\r
+ * statement as specified by their index.\r
*/\r
matchers : [{\r
re: /^\.([\w-]+)/,\r
- select: 'n = byClassName(n, null, " {1} ");'\r
+ select: 'n = byClassName(n, " {1} ");'\r
}, {\r
re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,\r
select: 'n = byPseudo(n, "{1}", "{2}");'\r
select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'\r
}, {\r
re: /^#([\w-]+)/,\r
- select: 'n = byId(n, null, "{1}");'\r
+ select: 'n = byId(n, "{1}");'\r
},{\r
re: /^@([\w-]+)/,\r
select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'\r
};
};
-function createBuffered(h, o, fn, scope){
- fn.task = new EXTUTIL.DelayedTask();
+function createBuffered(h, o, l, scope){
+ l.task = new EXTUTIL.DelayedTask();
return function(){
- fn.task.delay(o.buffer, h, scope, TOARRAY(arguments));
+ l.task.delay(o.buffer, h, scope, TOARRAY(arguments));
};
-}
+};
function createSingle(h, e, fn, scope){
return function(){
e.removeListener(fn, scope);
return h.apply(scope, arguments);
};
-}
+};
-function createDelayed(h, o, fn, scope){
+function createDelayed(h, o, l, scope){
return function(){
var task = new EXTUTIL.DelayedTask();
- if(!fn.tasks) {
- fn.tasks = [];
+ if(!l.tasks) {
+ l.tasks = [];
}
- fn.tasks.push(task);
+ l.tasks.push(task);
task.delay(o.delay || 10, h, scope, TOARRAY(arguments));
};
};
h = createTargeted(h, o, scope);
}
if(o.delay){
- h = createDelayed(h, o, fn, scope);
+ h = createDelayed(h, o, l, scope);
}
if(o.single){
h = createSingle(h, this, fn, scope);
}
if(o.buffer){
- h = createBuffered(h, o, fn, scope);
+ h = createBuffered(h, o, l, scope);
}
l.fireFn = h;
return l;
if (me.firing) {
me.listeners = me.listeners.slice(0);
}
- l = me.listeners[index].fn;
- // Cancel buffered tasks
+ l = me.listeners[index];
if(l.task) {
l.task.cancel();
delete l.task;
}
- // Cancel delayed tasks
k = l.tasks && l.tasks.length;
if(k) {
while(k--) {
};\r
\r
/// There is some jquery work around stuff here that isn't needed in Ext Core.\r
- function addListener(el, ename, fn, wrap, scope){\r
+ function addListener(el, ename, fn, task, wrap, scope){\r
el = Ext.getDom(el);\r
var id = getId(el),\r
es = Ext.elCache[id].events,\r
\r
wfn = E.on(el, ename, wrap);\r
es[ename] = es[ename] || [];\r
- es[ename].push([fn, wrap, scope, wfn]);\r
+\r
+ /* 0 = Original Function,\r
+ 1 = Event Manager Wrapped Function,\r
+ 2 = Scope,\r
+ 3 = Adapter Wrapped Function,\r
+ 4 = Buffered Task\r
+ */\r
+ es[ename].push([fn, wrap, scope, wfn, task]);\r
\r
// this is a workaround for jQuery and should somehow be removed from Ext Core in the future\r
// without breaking ExtJS.\r
- if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery\r
+\r
+ // workaround for jQuery\r
+ if(el.addEventListener && ename == "mousewheel"){\r
var args = ["DOMMouseScroll", wrap, false];\r
el.addEventListener.apply(el, args);\r
Ext.EventManager.addListener(WINDOW, 'unload', function(){\r
el.removeEventListener.apply(el, args);\r
});\r
}\r
- if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document\r
+\r
+ // fix stopped mousedowns on the document\r
+ if(el == DOC && ename == "mousedown"){\r
Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);\r
}\r
};\r
};\r
};\r
\r
- function createBuffered(h, o, fn){\r
- fn.task = new Ext.util.DelayedTask(h);\r
- var w = function(e){\r
+ function createBuffered(h, o, task){\r
+ return function(e){\r
// create new event object impl so new events don't wipe out properties\r
- fn.task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);\r
+ task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);\r
};\r
- return w;\r
};\r
\r
function createSingle(h, el, ename, fn, scope){\r
\r
function listen(element, ename, opt, fn, scope){\r
var o = !Ext.isObject(opt) ? {} : opt,\r
- el = Ext.getDom(element);\r
+ el = Ext.getDom(element), task;\r
\r
fn = fn || o.fn;\r
scope = scope || o.scope;\r
h = createSingle(h, el, ename, fn, scope);\r
}\r
if(o.buffer){\r
- h = createBuffered(h, o, fn);\r
+ task = new Ext.util.DelayedTask(h);\r
+ h = createBuffered(h, o, task);\r
}\r
\r
- addListener(el, ename, fn, h, scope);\r
+ addListener(el, ename, fn, task, h, scope);\r
return h;\r
};\r
\r
el = Ext.getDom(el);\r
var id = getId(el),\r
f = el && (Ext.elCache[id].events)[eventName] || [],\r
- wrap, i, l, k, wf;\r
+ wrap, i, l, k, len, fnc;\r
\r
for (i = 0, len = f.length; i < len; i++) {\r
- if (Ext.isArray(f[i]) && f[i][0] == fn && (!scope || f[i][2] == scope)) {\r
- if(fn.task) {\r
- fn.task.cancel();\r
- delete fn.task;\r
+\r
+ /* 0 = Original Function,\r
+ 1 = Event Manager Wrapped Function,\r
+ 2 = Scope,\r
+ 3 = Adapter Wrapped Function,\r
+ 4 = Buffered Task\r
+ */\r
+ if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {\r
+ if(fnc[4]) {\r
+ fnc[4].cancel();\r
}\r
k = fn.tasks && fn.tasks.length;\r
if(k) {\r
}\r
delete fn.tasks;\r
}\r
- wf = wrap = f[i][1];\r
- if (E.extAdapter) {\r
- wf = f[i][3];\r
+ wrap = fnc[1];\r
+ E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);\r
+\r
+ // jQuery workaround that should be removed from Ext Core\r
+ if(wrap && el.addEventListener && eventName == "mousewheel"){\r
+ el.removeEventListener("DOMMouseScroll", wrap, false);\r
+ }\r
+\r
+ // fix stopped mousedowns on the document\r
+ if(wrap && el == DOC && eventName == "mousedown"){\r
+ Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);\r
}\r
- E.un(el, eventName, wf);\r
- f.splice(i,1);\r
+\r
+ f.splice(i, 1);\r
if (f.length === 0) {\r
delete Ext.elCache[id].events[eventName];\r
}\r
return false;\r
}\r
}\r
-\r
- // jQuery workaround that should be removed from Ext Core\r
- if(eventName == "mousewheel" && el.addEventListener && wrap){\r
- el.removeEventListener("DOMMouseScroll", wrap, false);\r
- }\r
-\r
- if(eventName == "mousedown" && el == DOC && wrap){ // fix stopped mousedowns on the document\r
- Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);\r
- }\r
},\r
\r
/**\r
var id = getId(el),\r
ec = Ext.elCache[id] || {},\r
es = ec.events || {},\r
- f, i, len, ename, fn, k;\r
+ f, i, len, ename, fn, k, wrap;\r
\r
for(ename in es){\r
if(es.hasOwnProperty(ename)){\r
f = es[ename];\r
+ /* 0 = Original Function,\r
+ 1 = Event Manager Wrapped Function,\r
+ 2 = Scope,\r
+ 3 = Adapter Wrapped Function,\r
+ 4 = Buffered Task\r
+ */\r
for (i = 0, len = f.length; i < len; i++) {\r
- fn = f[i][0];\r
- if(fn.task) {\r
- fn.task.cancel();\r
- delete fn.task;\r
+ fn = f[i];\r
+ if(fn[4]) {\r
+ fn[4].cancel();\r
}\r
- if(fn.tasks && (k = fn.tasks.length)) {\r
+ if(fn[0].tasks && (k = fn[0].tasks.length)) {\r
while(k--) {\r
- fn.tasks[k].cancel();\r
+ fn[0].tasks[k].cancel();\r
}\r
delete fn.tasks;\r
}\r
- E.un(el, ename, E.extAdapter ? f[i][3] : f[i][1]);\r
+ wrap = fn[1];\r
+ E.un(el, ename, E.extAdapter ? fn[3] : wrap);\r
+\r
+ // jQuery workaround that should be removed from Ext Core\r
+ if(el.addEventListener && wrap && ename == "mousewheel"){\r
+ el.removeEventListener("DOMMouseScroll", wrap, false);\r
+ }\r
+\r
+ // fix stopped mousedowns on the document\r
+ if(wrap && el == DOC && ename == "mousedown"){\r
+ Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);\r
+ }\r
}\r
}\r
}\r
for (el in Ext.elCache) {\r
Ext.EventManager.removeAll(el);\r
}\r
+ delete Ext.elCache;\r
+ delete Ext.Element._flyweights;\r
},\r
/**\r
* Adds a listener to be notified when the document is ready (before onload and before images are loaded). Can be\r
\r
return new Ext.EventObjectImpl();\r
}();\r
-\r
/**
* @class Ext.EventManager
*/
var h = D.getViewHeight(),
w = D.getViewWidth();
- //whacky problem in IE where the resize event will fire even though the w/h are the same.
- if(curHeight != h || curWidth != w){
+ //whacky problem in IE where the resize event will fire even though the w/h are the same.
+ if(curHeight != h || curWidth != w){
resizeEvent.fire(curWidth = w, curHeight = h);
- }
+ }
},
/**
- * Adds a listener to be notified when the browser window is resized and provides resize event buffering (50 milliseconds),
+ * Adds a listener to be notified when the browser window is resized and provides resize event buffering (100 milliseconds),
* passes new viewport width and height to handlers.
* @param {Function} fn The handler function the window resize event invokes.
* @param {Object} scope The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
// exposed only to allow manual firing
fireWindowResize : function(){
if(resizeEvent){
- if((Ext.isIE||Ext.isAir) && resizeTask){
- resizeTask.delay(50);
- }else{
- resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
- }
+ resizeTask.delay(100);
}
},
};
El.addToCache = function(el, id){
- id = id || el.id;
+ id = id || el.id;
EC[id] = {
el: el,
data: {},
noBoxAdjust['button'] = 1;
}
-
-Ext.EventManager.on(window, 'unload', function(){
- delete EC;
- delete El._flyweights;
-});
})();
/**
* @class Ext.Element
\r
Ext.Element.addMethods(function(){\r
var INTERNAL = "_internal",\r
- pxMatch = /(\d+)px/;\r
+ pxMatch = /(\d+\.?\d+)px/;\r
return {\r
/**\r
* More flexible version of {@link #setStyle} for setting style properties.\r
return ret;\r
},\r
\r
- // deprecated\r
- getStyleSize : function(){\r
- var me = this,\r
- w,\r
- h,\r
- d = this.dom,\r
- s = d.style;\r
- if(s.width && s.width != 'auto'){\r
- w = parseInt(s.width, 10);\r
- if(me.isBorderBox()){\r
- w -= me.getFrameWidth('lr');\r
- }\r
- }\r
- if(s.height && s.height != 'auto'){\r
- h = parseInt(s.height, 10);\r
- if(me.isBorderBox()){\r
- h -= me.getFrameWidth('tb');\r
- }\r
- }\r
- return {width: w || me.getWidth(true), height: h || me.getHeight(true)};\r
- },\r
-\r
// private ==> used by ext full\r
setOverflow : function(v){\r
var dom = this.dom;\r
var me = this,\r
h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);\r
if(!h){\r
- h = parseInt(me.getStyle('height'), 10) || 0;\r
+ h = parseFloat(me.getStyle('height')) || 0;\r
if(!me.isBorderBox()){\r
h += me.getFrameWidth('tb');\r
}\r
getComputedWidth : function(){\r
var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);\r
if(!w){\r
- w = parseInt(this.getStyle('width'), 10) || 0;\r
+ w = parseFloat(this.getStyle('width')) || 0;\r
if(!this.isBorderBox()){\r
w += this.getFrameWidth('lr');\r
}\r
height: vpSize.height * 0.95\r
});\r
// To handle window resizing you would have to hook onto onWindowResize.\r
- </code></pre>\r
- * @param {Boolean} contentBox True to return the W3 content box <i>within</i> the padding area of the element. False\r
- * or omitted to return the full area of the element within the border. See <a href="http://www.w3.org/TR/CSS2/box.html">http://www.w3.org/TR/CSS2/box.html</a>\r
- * @return {Object} An object containing the elements's area: <code>{width: <element width>, height: <element height>}</code>\r
- */\r
- getViewSize : function(contentBox){\r
+ * </code></pre>\r
+ *\r
+ * getViewSize utilizes clientHeight/clientWidth which excludes sizing of scrollbars.\r
+ * To obtain the size including scrollbars, use getStyleSize\r
+ *\r
+ * Sizing of the document body is handled at the adapter level which handles special cases for IE and strict modes, etc.\r
+ */\r
+\r
+ getViewSize : function(){\r
var doc = document,\r
- me = this,\r
- d = me.dom,\r
- extdom = Ext.lib.Dom,\r
- isDoc = (d == doc || d == doc.body),\r
- isBB, w, h, tbBorder = 0, lrBorder = 0,\r
- tbPadding = 0, lrPadding = 0;\r
+ d = this.dom,\r
+ isDoc = (d == doc || d == doc.body);\r
+\r
+ // If the body, use Ext.lib.Dom\r
if (isDoc) {\r
- return { width: extdom.getViewWidth(), height: extdom.getViewHeight() };\r
- }\r
- isBB = me.isBorderBox();\r
- tbBorder = me.getBorderWidth('tb');\r
- lrBorder = me.getBorderWidth('lr');\r
- tbPadding = me.getPadding('tb');\r
- lrPadding = me.getPadding('lr');\r
-\r
- // Width calcs\r
- // Try the style first, then clientWidth, then offsetWidth\r
- if (w = me.getStyle('width').match(pxMatch)){\r
- if ((w = parseInt(w[1], 10)) && isBB){\r
- // Style includes the padding and border if isBB\r
- w -= (lrBorder + lrPadding);\r
- }\r
- if (!contentBox){\r
- w += lrPadding;\r
+ var extdom = Ext.lib.Dom;\r
+ return {\r
+ width : extdom.getViewWidth(),\r
+ height : extdom.getViewHeight()\r
}\r
+\r
+ // Else use clientHeight/clientWidth\r
} else {\r
- if (!(w = d.clientWidth) && (w = d.offsetWidth)){\r
- w -= lrBorder;\r
- }\r
- if (w && contentBox){\r
- w -= lrPadding;\r
+ return {\r
+ width : d.clientWidth,\r
+ height : d.clientHeight\r
}\r
}\r
+ },\r
\r
- // Height calcs\r
- // Try the style first, then clientHeight, then offsetHeight\r
- if (h = me.getStyle('height').match(pxMatch)){\r
- if ((h = parseInt(h[1], 10)) && isBB){\r
- // Style includes the padding and border if isBB\r
- h -= (tbBorder + tbPadding);\r
- }\r
- if (!contentBox){\r
- h += tbPadding;\r
+ /**\r
+ * <p>Returns the dimensions of the element available to lay content out in.<p>\r
+ *\r
+ * getStyleSize utilizes prefers style sizing if present, otherwise it chooses the larger of offsetHeight/clientHeight and offsetWidth/clientWidth.\r
+ * To obtain the size excluding scrollbars, use getViewSize\r
+ *\r
+ * Sizing of the document body is handled at the adapter level which handles special cases for IE and strict modes, etc.\r
+ */\r
+\r
+ getStyleSize : function(){\r
+ var me = this,\r
+ w, h,\r
+ doc = document,\r
+ d = this.dom,\r
+ isDoc = (d == doc || d == doc.body),\r
+ s = d.style;\r
+\r
+ // If the body, use Ext.lib.Dom\r
+ if (isDoc) {\r
+ var extdom = Ext.lib.Dom;\r
+ return {\r
+ width : extdom.getViewWidth(),\r
+ height : extdom.getViewHeight()\r
}\r
- } else {\r
- if (!(h = d.clientHeight) && (h = d.offsetHeight)){\r
- h -= tbBorder;\r
+ }\r
+ // Use Styles if they are set\r
+ if(s.width && s.width != 'auto'){\r
+ w = parseFloat(s.width);\r
+ if(me.isBorderBox()){\r
+ w -= me.getFrameWidth('lr');\r
}\r
- if (h && contentBox){\r
- h -= tbPadding;\r
+ }\r
+ // Use Styles if they are set\r
+ if(s.height && s.height != 'auto'){\r
+ h = parseFloat(s.height);\r
+ if(me.isBorderBox()){\r
+ h -= me.getFrameWidth('tb');\r
}\r
}\r
-\r
- return {\r
- width : w,\r
- height : h\r
- };\r
+ // Use getWidth/getHeight if style not set.\r
+ return {width: w || me.getWidth(true), height: h || me.getHeight(true)};\r
},\r
\r
/**\r
\r
if (!side) {\r
for (key in me.margins){\r
- o[hash[key]] = parseInt(me.getStyle(me.margins[key]), 10) || 0;\r
+ o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;\r
}\r
return o;\r
} else {\r
XMASKED = "x-masked",\r
XMASKEDRELATIVE = "x-masked-relative",\r
data = Ext.Element.data;\r
- \r
+\r
return {\r
/**\r
* Checks whether the element is currently visible using both visibility and display properties.\r
p = this.dom.parentNode;\r
if(deep !== true || !vis){\r
return vis;\r
- } \r
- while(p && !/body/i.test(p.tagName)){\r
+ }\r
+ while(p && !/^body/i.test(p.tagName)){\r
if(!Ext.fly(p, '_isVisible').isVisible()){\r
return false;\r
}\r
}\r
return true;\r
},\r
- \r
+\r
/**\r
* Returns true if display is not "none"\r
* @return {Boolean}\r
isDisplayed : function() {\r
return !this.isStyle(DISPLAY, NONE);\r
},\r
- \r
+\r
/**\r
* Convenience method for setVisibilityMode(Element.DISPLAY)\r
* @param {String} display (optional) What to set display to when visible\r
* @return {Ext.Element} this\r
*/\r
- enableDisplayMode : function(display){ \r
+ enableDisplayMode : function(display){\r
this.setVisibilityMode(Ext.Element.DISPLAY);\r
if(!Ext.isEmpty(display)){\r
data(this.dom, 'originalDisplay', display);\r
}\r
return this;\r
},\r
- \r
+\r
/**\r
* Puts a mask over this element to disable user interaction. Requires core.css.\r
* This method can only be applied to elements which accept child nodes.\r
dom = me.dom,\r
dh = Ext.DomHelper,\r
EXTELMASKMSG = "ext-el-mask-msg",\r
- el, \r
+ el,\r
mask;\r
- \r
+\r
if(me.getStyle("position") == "static"){\r
me.addClass(XMASKEDRELATIVE);\r
}\r
if((el = data(dom, 'mask'))){\r
el.remove();\r
}\r
- \r
+\r
mask = dh.append(dom, {cls : "ext-el-mask"}, true);\r
data(dom, 'mask', mask);\r
- \r
+\r
me.addClass(XMASKED);\r
mask.setDisplayed(true);\r
if(typeof msg == 'string'){\r
}\r
return mask;\r
},\r
- \r
+\r
/**\r
* Removes a previously applied mask.\r
*/\r
}\r
me.removeClass([XMASKED, XMASKEDRELATIVE]);\r
},\r
- \r
+\r
/**\r
* Returns true if this element is masked\r
* @return {Boolean}\r
var m = data(this.dom, 'mask');\r
return m && m.isVisible();\r
},\r
- \r
+\r
/**\r
* Creates an iframe shim for this element to keep selects and other windowed objects from\r
* showing through.\r
* @return {Ext.Element} The new shim element\r
*/\r
createShim : function(){\r
- var el = document.createElement('iframe'), \r
+ var el = document.createElement('iframe'),\r
shim;\r
el.frameBorder = '0';\r
el.className = 'ext-shim';\r
var me = this,\r
els = me.elements,\r
len = els.length, \r
- e;\r
+ e, \r
+ i;\r
\r
- for(i = 0; i<len; i++) {\r
+ for(i = 0; i < len; i++) {\r
e = els[i];\r
if(e){\r
Ext.Element.prototype[fn].apply(me.getElement(e), args);\r
e = els[i];\r
if(e){\r
e = this.getElement(e);\r
- if(fn.call(scope || e, e, me, i)){\r
+ if(fn.call(scope || e, e, me, i) === false){\r
break;\r
}\r
}\r
POST = 'POST',\r
GET = 'GET',\r
WINDOW = window;\r
- \r
+\r
/**\r
* @class Ext.data.Connection\r
* @extends Ext.util.Observable\r
* @constructor\r
* @param {Object} config a configuration object.\r
*/\r
- Ext.data.Connection = function(config){ \r
+ Ext.data.Connection = function(config){\r
Ext.apply(this, config);\r
this.addEvents(\r
/**\r
* @type Boolean\r
*/\r
autoAbort:false,\r
- \r
+\r
/**\r
* @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)\r
* @type Boolean\r
*/\r
disableCaching: true,\r
- \r
+\r
/**\r
* @cfg {String} disableCachingParam (Optional) Change the parameter which is sent went disabling caching\r
* through a cache buster. Defaults to '_dc'\r
* @type String\r
*/\r
disableCachingParam: '_dc',\r
- \r
+\r
/**\r
* <p>Sends an HTTP request to a remote server.</p>\r
* <p><b>Important:</b> Ajax server requests are asynchronous, and this call will\r
* parameters:<ul>\r
* <li><b>options</b> : Object<div class="sub-desc">The parameter to the request call.</div></li>\r
* <li><b>success</b> : Boolean<div class="sub-desc">True if the request succeeded.</div></li>\r
- * <li><b>response</b> : Object<div class="sub-desc">The XMLHttpRequest object containing the response data. \r
- * See <a href="http://www.w3.org/TR/XMLHttpRequest/">http://www.w3.org/TR/XMLHttpRequest/</a> for details about \r
+ * <li><b>response</b> : Object<div class="sub-desc">The XMLHttpRequest object containing the response data.\r
+ * See <a href="http://www.w3.org/TR/XMLHttpRequest/">http://www.w3.org/TR/XMLHttpRequest/</a> for details about\r
* accessing elements of the response.</div></li>\r
* </ul></div></li>\r
* <li><a id="request-option-success"></a><b>success</b> : Function (Optional)<div class="sub-desc">The function\r
* <li><b>timeout</b> : Number (Optional)<div class="sub-desc">The timeout in milliseconds to be used for this request. Defaults to 30 seconds.</div></li>\r
* <li><b>form</b> : Element/HTMLElement/String (Optional)<div class="sub-desc">The <tt><form></tt>\r
* Element or the id of the <tt><form></tt> to pull parameters from.</div></li>\r
- * <li><a id="request-option-isUpload"></a><b>isUpload</b> : Boolean (Optional)<div class="sub-desc"><b>Only meaningful when used \r
+ * <li><a id="request-option-isUpload"></a><b>isUpload</b> : Boolean (Optional)<div class="sub-desc"><b>Only meaningful when used\r
* with the <tt>form</tt> option</b>.\r
* <p>True if the form object is a file upload (will be set automatically if the form was\r
* configured with <b><tt>enctype</tt></b> "multipart/form-data").</p>\r
me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";\r
}\r
if(me.indicatorText) {\r
- Ext.getDom(o.el).innerHTML = me.indicatorText; \r
+ Ext.getDom(o.el).innerHTML = me.indicatorText;\r
}\r
o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {\r
Ext.getDom(o.el).innerHTML = response.responseText;\r
});\r
}\r
- \r
+\r
var p = o.params,\r
- url = o.url || me.url, \r
+ url = o.url || me.url,\r
method,\r
cb = {success: me.handleResponse,\r
failure: me.handleFailure,\r
argument: {options: o},\r
timeout : o.timeout || me.timeout\r
},\r
- form, \r
- serForm; \r
- \r
- \r
+ form,\r
+ serForm;\r
+\r
+\r
if (Ext.isFunction(p)) {\r
p = p.call(o.scope||WINDOW, o);\r
}\r
- \r
- p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p); \r
- \r
+\r
+ p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);\r
+\r
if (Ext.isFunction(url)) {\r
url = url.call(o.scope || WINDOW, o);\r
}\r
- \r
+\r
if((form = Ext.getDom(o.form))){\r
url = url || form.action;\r
- if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype"))) { \r
+ if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype"))) {\r
return me.doFormUpload.call(me, o, p, url);\r
}\r
- serForm = Ext.lib.Ajax.serializeForm(form); \r
+ serForm = Ext.lib.Ajax.serializeForm(form);\r
p = p ? (p + '&' + serForm) : serForm;\r
}\r
- \r
+\r
method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);\r
- \r
+\r
if(method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){\r
var dcp = o.disableCachingParam || me.disableCachingParam;\r
url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));\r
}\r
- \r
+\r
o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});\r
- \r
+\r
if(o.autoAbort === true || me.autoAbort) {\r
me.abort();\r
}\r
- \r
+\r
if((method == GET || o.xmlData || o.jsonData) && p){\r
- url = Ext.urlAppend(url, p); \r
+ url = Ext.urlAppend(url, p);\r
p = '';\r
}\r
return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));\r
- }else{ \r
+ }else{\r
return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;\r
}\r
},\r
- \r
+\r
/**\r
* Determine whether this object has a request outstanding.\r
* @param {Number} transactionId (Optional) defaults to the last transaction\r
* @return {Boolean} True if there is an outstanding request.\r
*/\r
isLoading : function(transId){\r
- return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId; \r
+ return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;\r
},\r
- \r
+\r
/**\r
* Aborts any outstanding request.\r
* @param {Number} transactionId (Optional) defaults to the last transaction\r
Ext.fly(frame).set({\r
id: id,\r
name: id,\r
- cls: 'x-hidden',\r
- src: Ext.SSL_SECURE_URL // for IE\r
+ cls: 'x-hidden'\r
+\r
});\r
+\r
doc.body.appendChild(frame);\r
\r
+ //Reset the Frame to neutral domain\r
+ Ext.fly(frame).set({\r
+ src : Ext.SSL_SECURE_URL\r
+ });\r
+\r
// This is required so that IE doesn't pop the response up in a new window.\r
if(Ext.isIE){\r
document.frames[id].name = id;\r
}\r
\r
+\r
Ext.fly(form).set({\r
target: id,\r
method: POST,\r
Ext.Ajax.defaultHeaders = {\r
'Powered-By': 'Ext'\r
};\r
- * </code></pre> \r
+ * </code></pre>\r
* </p>\r
* <p>Common <b>Events</b> you may want to set are:<div class="mdetail-params"><ul>\r
* <li><b><tt>{@link Ext.data.Connection#beforerequest beforerequest}</tt></b><p class="sub-desc"></p></li>\r
Ext.Ajax.on('beforerequest', this.showSpinner, this);\r
Ext.Ajax.on('requestcomplete', this.hideSpinner, this);\r
Ext.Ajax.on('requestexception', this.hideSpinner, this);\r
- * </code></pre> \r
+ * </code></pre>\r
* </p>\r
* <p>An example request:</p>\r
* <pre><code>\r
form: 'some-form',\r
params: 'foo=bar'\r
});\r
- * </code></pre> \r
+ * </code></pre>\r
* </p>\r
* @singleton\r
*/\r
"dt = (new Date()).clearTime();",
// date calculations (note: these calculations create a dependency on Ext.num())
- "y = y >= 0? y : Ext.num(def.y, dt.getFullYear());",
- "m = m >= 0? m : Ext.num(def.m - 1, dt.getMonth());",
- "d = d >= 0? d : Ext.num(def.d, dt.getDate());",
+ "y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));",
+ "m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));",
+ "d = Ext.num(d, Ext.num(def.d, dt.getDate()));",
// time calculations (note: these calculations create a dependency on Ext.num())
- "h = h || Ext.num(def.h, dt.getHours());",
- "i = i || Ext.num(def.i, dt.getMinutes());",
- "s = s || Ext.num(def.s, dt.getSeconds());",
- "ms = ms || Ext.num(def.ms, dt.getMilliseconds());",
+ "h = Ext.num(h, Ext.num(def.h, dt.getHours()));",
+ "i = Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
+ "s = Ext.num(s, Ext.num(def.s, dt.getSeconds()));",
+ "ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));",
"if(z >= 0 && y >= 0){",
// both the year and zero-based day of year are defined and >= 0.
return a.join("");
};
+ /**
+ * <p>Encodes a Date. This returns the actual string which is inserted into the JSON string as the literal expression.
+ * <b>The returned value includes enclosing double quotation marks.</b></p>
+ * <p>The default return format is "yyyy-mm-ddThh:mm:ss".</p>
+ * <p>To override this:</p><pre><code>
+Ext.util.JSON.encodeDate = function(d) {
+ return d.format('"Y-m-d"');
+};
+</code></pre>
+ * @param {Date} d The Date to encode
+ * @return {String} The string literal to use in a JSON string.
+ */
this.encodeDate = function(o){
return '"' + o.getFullYear() + "-" +
pad(o.getMonth() + 1) + "-" +