diff --git a/1.6.1/SpryDOMUtils.js b/1.6.1/SpryDOMUtils.js
new file mode 100755
index 0000000..5ff4616
--- /dev/null
+++ b/1.6.1/SpryDOMUtils.js
@@ -0,0 +1,1069 @@
+// SpryDOMUtils.js - version 0.6 - Spry Pre-Release 1.6.1
+//
+// Copyright (c) 2007. Adobe Systems Incorporated.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Adobe Systems Incorporated nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+var Spry; if (!Spry) Spry = {}; if (!Spry.Utils) Spry.Utils = {};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Define Prototype's $() convenience function, but make sure it is
+// namespaced under Spry so that we avoid collisions with other
+// toolkits.
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.$ = function(element)
+{
+ if (arguments.length > 1)
+ {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push(Spry.$(arguments[i]));
+ return elements;
+ }
+ if (typeof element == 'string')
+ element = document.getElementById(element);
+ return element;
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// DOM Utils
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Utils.setAttribute = function(ele, name, value)
+{
+ ele = Spry.$(ele);
+ if (!ele || !name)
+ return;
+
+ // IE doesn't allow you to set the "class" attribute. You
+ // have to set the className property instead.
+
+ if (name == "class")
+ ele.className = value;
+ else
+ ele.setAttribute(name, value);
+};
+
+Spry.Utils.removeAttribute = function(ele, name)
+{
+ ele = Spry.$(ele);
+ if (!ele || !name)
+ return;
+
+ try
+ {
+ ele.removeAttribute(name);
+
+ // IE doesn't allow you to remove the "class" attribute.
+ // It requires you to remove "className" instead, so go
+ // ahead and try to remove that too.
+ //
+ // XXX: We should add a check for IE here instead of doing
+ // it for every browser.
+
+ if (name == "class")
+ ele.removeAttribute("className");
+ } catch(e) {}
+};
+
+Spry.Utils.addClassName = function(ele, className)
+{
+ ele = Spry.$(ele);
+ if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))
+ return;
+ ele.className += (ele.className ? " " : "") + className;
+};
+
+Spry.Utils.removeClassName = function(ele, className)
+{
+ ele = Spry.$(ele);
+ if (Spry.Utils.hasClassName(ele, className))
+ ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
+};
+
+Spry.Utils.toggleClassName = function(ele, className)
+{
+ if (Spry.Utils.hasClassName(ele, className))
+ Spry.Utils.removeClassName(ele, className);
+ else
+ Spry.Utils.addClassName(ele, className);
+};
+
+Spry.Utils.hasClassName = function(ele, className)
+{
+ ele = Spry.$(ele);
+ if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)
+ return false;
+ return true;
+};
+
+Spry.Utils.camelizeString = function(str)
+{
+ var cStr = "";
+ var a = str.split("-");
+ for (var i = 0; i < a.length; i++)
+ {
+ var s = a[i];
+ if (s)
+ cStr = cStr ? (cStr + s.charAt(0).toUpperCase() + s.substring(1)) : s;
+ }
+ return cStr;
+};
+
+Spry.Utils.styleStringToObject = function(styleStr)
+{
+ var o = {};
+ if (styleStr)
+ {
+ pvA = styleStr.split(";");
+ for (var i = 0; i < pvA.length; i++)
+ {
+ var pv = pvA[i];
+ if (pv && pv.indexOf(":") != -1)
+ {
+ var nvA = pv.split(":");
+ var n = nvA[0].replace(/^\s*|\s*$/g, "");
+ var v = nvA[1].replace(/^\s*|\s*$/g, "");
+ if (n && v)
+ o[Spry.Utils.camelizeString(n)] = v;
+ }
+ }
+ }
+ return o;
+};
+
+Spry.Utils.addEventListener = function(element, eventType, handler, capture)
+{
+ try
+ {
+ if (!Spry.Utils.eventListenerIsBoundToElement(element, eventType, handler, capture))
+ {
+ element = Spry.$(element);
+ handler = Spry.Utils.bindEventListenerToElement(element, eventType, handler, capture);
+ if (element.addEventListener)
+ element.addEventListener(eventType, handler, capture);
+ else if (element.attachEvent)
+ element.attachEvent("on" + eventType, handler);
+ }
+ }
+ catch (e) {}
+};
+
+Spry.Utils.removeEventListener = function(element, eventType, handler, capture)
+{
+ try
+ {
+ element = Spry.$(element);
+ handler = Spry.Utils.unbindEventListenerFromElement(element, eventType, handler, capture);
+ if (element.removeEventListener)
+ element.removeEventListener(eventType, handler, capture);
+ else if (element.detachEvent)
+ element.detachEvent("on" + eventType, handler);
+ }
+ catch (e) {}
+};
+
+Spry.Utils.eventListenerHash = {};
+Spry.Utils.nextEventListenerID = 1;
+
+Spry.Utils.getHashForElementAndHandler = function(element, eventType, handler, capture)
+{
+ var hash = null;
+ element = Spry.$(element);
+ if (element)
+ {
+ if (typeof element.spryEventListenerID == "undefined")
+ element.spryEventListenerID = "e" + (Spry.Utils.nextEventListenerID++);
+ if (typeof handler.spryEventHandlerID == "undefined")
+ handler.spryEventHandlerID = "h" + (Spry.Utils.nextEventListenerID++);
+ hash = element.spryEventListenerID + "-" + handler.spryEventHandlerID + "-" + eventType + (capture?"-capture":"");
+ }
+ return hash;
+};
+
+Spry.Utils.eventListenerIsBoundToElement = function(element, eventType, handler, capture)
+{
+ element = Spry.$(element);
+ var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture);
+ return Spry.Utils.eventListenerHash[hash] != undefined;
+};
+
+Spry.Utils.bindEventListenerToElement = function(element, eventType, handler, capture)
+{
+ element = Spry.$(element);
+ var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture);
+ if (Spry.Utils.eventListenerHash[hash])
+ return Spry.Utils.eventListenerHash[hash];
+ return Spry.Utils.eventListenerHash[hash] = function(e)
+ {
+ e = e || window.event;
+
+ if (!e.preventDefault) e.preventDefault = function() { this.returnValue = false; };
+ if (!e.stopPropagation) e.stopPropagation = function() { this.cancelBubble = true; };
+
+ var result = handler.call(element, e);
+ if (result == false)
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ return result;
+ };
+};
+
+Spry.Utils.unbindEventListenerFromElement = function(element, eventType, handler, capture)
+{
+ element = Spry.$(element);
+ var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture);
+ if (Spry.Utils.eventListenerHash[hash])
+ {
+ handler = Spry.Utils.eventListenerHash[hash];
+ Spry.Utils.eventListenerHash[hash] = undefined;
+ }
+ return handler;
+};
+
+Spry.Utils.addLoadListener = function(handler)
+{
+ if (typeof window.addEventListener != 'undefined')
+ window.addEventListener('load', handler, false);
+ else if (typeof document.addEventListener != 'undefined')
+ document.addEventListener('load', handler, false);
+ else if (typeof window.attachEvent != 'undefined')
+ window.attachEvent('onload', handler);
+};
+
+Spry.Utils.getAncestor = function(ele, selector)
+{
+ ele = Spry.$(ele);
+ if (ele)
+ {
+ var s = Spry.$$.tokenizeSequence(selector ? selector : "*")[0];
+ var t = s ? s[0] : null;
+ if (t)
+ {
+ var p = ele.parentNode;
+ while (p)
+ {
+ if (t.match(p))
+ return p;
+ p = p.parentNode;
+ }
+ }
+ }
+ return null;
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// CSS Selector Matching
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.$$ = function(selectorSequence, rootNode)
+{
+ if (!rootNode)
+ rootNode = document;
+ else
+ rootNode = Spry.$(rootNode);
+
+ var sequences = Spry.$$.tokenizeSequence(selectorSequence);
+
+ var matches = [];
+ Spry.$$.addExtensions(matches);
+ ++Spry.$$.queryID;
+
+ var nid = 0;
+ var ns = sequences.length;
+ for (var i = 0; i < ns; i++)
+ {
+ var m = Spry.$$.processTokens(sequences[i], rootNode);
+ var nm = m.length;
+ for (var j = 0; j < nm; j++)
+ {
+ var n = m[j];
+ if (!n.spry$$ID)
+ {
+ n.spry$$ID = ++nid;
+ matches.push(n);
+ }
+ }
+ }
+
+ var nm = matches.length;
+ for (i = 0; i < nm; i++)
+ matches[i].spry$$ID = undefined;
+
+ return matches;
+};
+
+Spry.$$.cache = {};
+Spry.$$.queryID = 0;
+
+Spry.$$.Token = function()
+{
+ this.type = Spry.$$.Token.SELECTOR;
+ this.name = "*";
+ this.id = "";
+ this.classes = [];
+ this.attrs = [];
+ this.pseudos = [];
+};
+
+Spry.$$.Token.Attr = function(n, v)
+{
+ this.name = n;
+ this.value = v ? new RegExp(v) : undefined;
+};
+
+Spry.$$.Token.PseudoClass = function(pstr)
+{
+ this.name = pstr.replace(/\(.*/, "");
+ this.arg = pstr.replace(/^[^\(\)]*\(?\s*|\)\s*$/g, "");
+ this.func = Spry.$$.pseudoFuncs[this.name];
+};
+
+Spry.$$.Token.SELECTOR = 0;
+Spry.$$.Token.COMBINATOR = 1;
+
+Spry.$$.Token.prototype.match = function(ele, nameAlreadyMatches)
+{
+ if (this.type == Spry.$$.Token.COMBINATOR)
+ return false;
+ if (!nameAlreadyMatches && this.name != '*' && this.name != ele.nodeName.toLowerCase())
+ return false;
+ if (this.id && this.id != ele.id)
+ return false;
+ var classes = this.classes;
+ var len = classes.length;
+ for (var i = 0; i < len; i++)
+ {
+ if (!ele.className || !classes[i].value.test(ele.className))
+ return false;
+ }
+
+ var attrs = this.attrs;
+ len = attrs.length;
+ for (var i = 0; i < len; i++)
+ {
+ var a = attrs[i];
+ var an = ele.attributes.getNamedItem(a.name);
+ if (!an || (!a.value && an.nodeValue == undefined) || (a.value && !a.value.test(an.nodeValue)))
+ return false;
+ }
+
+ var ps = this.pseudos;
+ var len = ps.length;
+ for (var i = 0; i < len; i++)
+ {
+ var p = ps[i];
+ if (p && p.func && !p.func(p.arg, ele, this))
+ return false;
+ }
+
+ return true;
+};
+
+Spry.$$.Token.prototype.getNodeNameIfTypeMatches = function(ele)
+{
+ var nodeName = ele.nodeName.toLowerCase();
+ if (this.name != '*')
+ {
+ if (this.name != nodeName)
+ return null;
+ return this.name;
+ }
+ return nodeName;
+};
+
+Spry.$$.escapeRegExpCharsRE = /\/|\.|\*|\+|\(|\)|\[|\]|\{|\}|\\|\|/g;
+
+Spry.$$.tokenizeSequence = function(s)
+{
+ var cc = Spry.$$.cache[s];
+ if (cc) return cc;
+
+ // Attribute Selector: /(\[[^\"'~\^\$\*\|\]=]+([~\^\$\*\|]?=\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\])/g
+ // Simple Selector: /((:[^\.#:\s,>~\+\[\]]+\(([^\(\)]+|\([^\(\)]*\))*\))|[\.#:]?[^\.#:\s,>~\+\[\]]+)/g
+ // Combinator: /(\s*[\s,>~\+]\s*)/g
+
+ var tokenExpr = /(\[[^\"'~\^\$\*\|\]=]+([~\^\$\*\|]?=\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\])|((:[^\.#:\s,>~\+\[\]]+\(([^\(\)]+|\([^\(\)]*\))*\))|[\.#:]?[^\.#:\s,>~\+\[\]]+)|(\s*[\s,>~\+]\s*)/g;
+
+ var tkn = new Spry.$$.Token;
+ var sequence = [];
+ sequence.push(tkn);
+ var tokenSequences = [];
+ tokenSequences.push(sequence);
+
+ s = s.replace(/^\s*|\s*$/, "");
+
+ var expMatch = tokenExpr.exec(s);
+ while (expMatch)
+ {
+ var tstr = expMatch[0];
+ var c = tstr.charAt(0);
+ switch (c)
+ {
+ case '.':
+ tkn.classes.push(new Spry.$$.Token.Attr("class", "\\b" + tstr.substr(1) + "\\b"));
+ break;
+ case '#':
+ tkn.id = tstr.substr(1);
+ break;
+ case ':':
+ tkn.pseudos.push(new Spry.$$.Token.PseudoClass(tstr));
+ break;
+ case '[':
+ var attrComps = tstr.match(/\[([^\"'~\^\$\*\|\]=]+)(([~\^\$\*\|]?=)\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\]/);
+ var name = attrComps[1];
+ var matchType = attrComps[3];
+ var val = attrComps[4];
+ if (val)
+ {
+ val = val.replace(/^['"]|['"]$/g, "");
+ val = val.replace(Spry.$$.escapeRegExpCharsRE, '\\$&');
+ }
+
+ var matchStr = undefined;
+
+ switch(matchType)
+ {
+ case "=":
+ matchStr = "^" + val + "$";
+ break;
+ case "^=":
+ matchStr = "^" + val;
+ break;
+ case "$=":
+ matchStr = val + "$";
+ break;
+ case "~=":
+ case "|=":
+ matchStr = "\\b" + val + "\\b";
+ break;
+ case "*=":
+ matchStr = val;
+ break;
+ }
+
+ tkn.attrs.push(new Spry.$$.Token.Attr(name, matchStr));
+ break;
+ default:
+ var combiMatch = tstr.match(/^\s*([\s,~>\+])\s*$/);
+ if (combiMatch)
+ {
+ if (combiMatch[1] == ',')
+ {
+ sequence = new Array;
+ tokenSequences.push(sequence);
+ tkn = new Spry.$$.Token;
+ sequence.push(tkn);
+ }
+ else
+ {
+ tkn = new Spry.$$.Token;
+ tkn.type = Spry.$$.Token.COMBINATOR;
+ tkn.name = combiMatch[1];
+ sequence.push(tkn);
+ tkn = new Spry.$$.Token();
+ sequence.push(tkn);
+ }
+ }
+ else
+ tkn.name = tstr.toLowerCase();
+ break;
+ }
+ expMatch = tokenExpr.exec(s);
+ }
+
+ Spry.$$.cache[s] = tokenSequences;
+
+ return tokenSequences;
+};
+
+Spry.$$.combinatorFuncs = {
+ // Element Descendant
+
+ " ": function(nodes, token)
+ {
+ var uid = ++Spry.$$.uniqueID;
+ var results = [];
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i];
+ if (uid != n.spry$$uid)
+ {
+ // n.spry$$uid = uid;
+ var ea = nodes[i].getElementsByTagName(token.name);
+ var ne = ea.length;
+ for (var j = 0; j < ne; j++)
+ {
+ var e = ea[j];
+ if (token.match(e, true))
+ results.push(e);
+ e.spry$$uid = uid;
+ }
+ }
+ }
+ return results;
+ },
+
+ // Element Child
+
+ ">": function(nodes, token)
+ {
+ var results = [];
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i].firstChild;
+ while (n)
+ {
+ if (n.nodeType == 1 /* Node.ELEMENT_NODE */ && token.match(n))
+ results.push(n);
+ n = n.nextSibling;
+ }
+ }
+ return results;
+ },
+
+ // Element Immediately Preceded By
+
+ "+": function(nodes, token)
+ {
+ var results = [];
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i].nextSibling;
+ while (n && n.nodeType != 1 /* Node.ELEMENT_NODE */)
+ n = n.nextSibling;
+ if (n && token.match(n))
+ results.push(n);
+ }
+ return results;
+ },
+
+ // Element Preceded By
+
+ "~": function(nodes, token)
+ {
+ var uid = ++Spry.$$.uniqueID;
+ var results = [];
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i].nextSibling;
+ while (n)
+ {
+ if (n.nodeType == 1 /* Node.ELEMENT_NODE */)
+ {
+ if (uid == n.spry$$uid)
+ break;
+
+ if (token.match(n))
+ {
+ results.push(n);
+ n.spry$$uid = uid;
+ }
+ }
+ n = n.nextSibling;
+ }
+ }
+ return results;
+ }
+};
+
+Spry.$$.uniqueID = 0;
+
+Spry.$$.pseudoFuncs = {
+ ":first-child": function(arg, node, token)
+ {
+ var n = node.previousSibling;
+ while (n)
+ {
+ if (n.nodeType == 1) return false; // Node.ELEMENT_NODE
+ n = n.previousSibling;
+ }
+
+ return true;
+ },
+
+ ":last-child": function(arg, node, token)
+ {
+ var n = node.nextSibling;
+ while (n)
+ {
+ if (n.nodeType == 1) // Node.ELEMENT_NODE
+ return false;
+ n = n.nextSibling;
+ }
+ return true;
+ },
+
+ ":empty": function(arg, node, token)
+ {
+ var n = node.firstChild;
+ while (n)
+ {
+ switch(n.nodeType)
+ {
+ case 1: // Node.ELEMENT_NODE
+ case 3: // Node.TEXT_NODE
+ case 4: // Node.CDATA_NODE
+ case 5: // Node.ENTITY_REFERENCE_NODE
+ return false;
+ }
+ n = n.nextSibling;
+ }
+ return true;
+ },
+
+ ":nth-child": function(arg, node, token)
+ {
+ return Spry.$$.nthChild(arg, node, token);
+ },
+
+ ":nth-last-child": function(arg, node, token)
+ {
+ return Spry.$$.nthChild(arg, node, token, true);
+ },
+
+ ":nth-of-type": function(arg, node, token)
+ {
+ return Spry.$$.nthChild(arg, node, token, false, true);
+ },
+
+ ":nth-last-of-type": function(arg, node, token)
+ {
+ return Spry.$$.nthChild(arg, node, token, true, true);
+ },
+
+ ":first-of-type": function(arg, node, token)
+ {
+ var nodeName = token.getNodeNameIfTypeMatches(node);
+ if (!nodeName) return false;
+
+ var n = node.previousSibling;
+ while (n)
+ {
+ if (n.nodeType == 1 && nodeName == n.nodeName.toLowerCase()) return false; // Node.ELEMENT_NODE
+ n = n.previousSibling;
+ }
+
+ return true;
+ },
+
+ ":last-of-type": function(arg, node, token)
+ {
+ var nodeName = token.getNodeNameIfTypeMatches(node);
+ if (!nodeName) return false;
+
+ var n = node.nextSibling;
+ while (n)
+ {
+ if (n.nodeType == 1 && nodeName == n.nodeName.toLowerCase()) // Node.ELEMENT_NODE
+ return false;
+ n = n.nextSibling;
+ }
+ return true;
+ },
+
+ ":only-child": function(arg, node, token)
+ {
+ var f = Spry.$$.pseudoFuncs;
+ return f[":first-child"](arg, node, token) && f[":last-child"](arg, node, token);
+ },
+
+ ":only-of-type": function(arg, node, token)
+ {
+ var f = Spry.$$.pseudoFuncs;
+ return f[":first-of-type"](arg, node, token) && f[":last-of-type"](arg, node, token);
+ },
+
+ ":not": function(arg, node, token)
+ {
+ var s = Spry.$$.tokenizeSequence(arg)[0];
+ var t = s ? s[0] : null;
+ return !t || !t.match(node);
+ },
+
+ ":enabled": function(arg, node, token)
+ {
+ return !node.disabled;
+ },
+
+ ":disabled": function(arg, node, token)
+ {
+ return node.disabled;
+ },
+
+ ":checked": function(arg, node, token)
+ {
+ return node.checked;
+ },
+
+ ":root": function(arg, node, token)
+ {
+ return node.parentNode && node.ownerDocument && node.parentNode == node.ownerDocument;
+ }
+};
+
+Spry.$$.nthRegExp = /((-|[0-9]+)?n)?([+-]?[0-9]*)/;
+
+Spry.$$.nthCache = {
+ "even": { a: 2, b: 0, mode: 1, invalid: false }
+ , "odd": { a: 2, b: 1, mode: 1, invalid: false }
+ , "2n": { a: 2, b: 0, mode: 1, invalid: false }
+ , "2n+1": { a: 2, b: 1, mode: 1, invalid: false }
+};
+
+Spry.$$.parseNthChildString = function(str)
+{
+ var o = Spry.$$.nthCache[str];
+ if (!o)
+ {
+ var m = str.match(Spry.$$.nthRegExp);
+ var n = m[1];
+ var a = m[2];
+ var b = m[3];
+
+ if (!a)
+ {
+ // An 'a' value was not specified. Was there an 'n' present?
+ // If so, we treat it as an increment of 1, otherwise we're
+ // in no-repeat mode.
+
+ a = n ? 1 : 0;
+ }
+ else if (a == "-")
+ {
+ // The string is using the "-n" short-hand which is
+ // short for -1.
+
+ a = -1;
+ }
+ else
+ {
+ // An integer repeat value for 'a' was specified. Convert
+ // it into number.
+
+ a = parseInt(a, 10);
+ }
+
+ // If a 'b' value was specified, turn it into a number.
+ // If no 'b' value was specified, default to zero.
+
+ b = b ? parseInt(b, 10) : 0;
+
+ // Figure out the mode:
+ //
+ // -1 - repeat backwards
+ // 0 - no repeat
+ // 1 - repeat forwards
+
+ var mode = (a == 0) ? 0 : ((a > 0) ? 1 : -1);
+ var invalid = false;
+
+ // Fix up 'a' and 'b' for proper repeating.
+
+ if (a > 0 && b < 0)
+ {
+ b = b % a;
+ b = ((b=(b%a)) < 0) ? a + b : b;
+ }
+ else if (a < 0)
+ {
+ if (b < 0)
+ invalid = true;
+ else
+ a = Math.abs(a);
+ }
+
+ o = new Object;
+ o.a = a;
+ o.b = b;
+ o.mode = mode;
+ o.invalid = invalid;
+
+ Spry.$$.nthCache[str] = o;
+ }
+
+ return o;
+};
+
+Spry.$$.nthChild = function(arg, node, token, fromLastSib, matchNodeName)
+{
+ if (matchNodeName)
+ {
+ var nodeName = token.getNodeNameIfTypeMatches(node);
+ if (!nodeName) return false;
+ }
+
+ var o = Spry.$$.parseNthChildString(arg);
+
+ if (o.invalid)
+ return false;
+
+ var qidProp = "spry$$ncQueryID";
+ var posProp = "spry$$ncPos";
+ var countProp = "spry$$ncCount";
+ if (matchNodeName)
+ {
+ qidProp += nodeName;
+ posProp += nodeName;
+ countProp += nodeName;
+ }
+
+ var parent = node.parentNode;
+ if (parent[qidProp] != Spry.$$.queryID)
+ {
+ var pos = 0;
+ parent[qidProp] = Spry.$$.queryID;
+ var c = parent.firstChild;
+ while (c)
+ {
+ if (c.nodeType == 1 && (!matchNodeName || nodeName == c.nodeName.toLowerCase()))
+ c[posProp] = ++pos;
+ c = c.nextSibling;
+ }
+ parent[countProp] = pos;
+ }
+
+ pos = node[posProp];
+ if (fromLastSib)
+ pos = parent[countProp] - pos + 1;
+
+/*
+ var sib = fromLastSib ? "nextSibling" : "previousSibling";
+
+ var pos = 1;
+ var n = node[sib];
+ while (n)
+ {
+ if (n.nodeType == 1 && (!matchNodeName || nodeName == n.nodeName.toLowerCase()))
+ {
+ if (n == node) break;
+ ++pos;
+ }
+ n = n[sib];
+ }
+*/
+
+ if (o.mode == 0) // Exact match
+ return pos == o.b;
+ if (o.mode > 0) // Forward Repeat
+ return (pos < o.b) ? false : (!((pos - o.b) % o.a));
+ return (pos > o.b) ? false : (!((o.b - pos) % o.a)); // Backward Repeat
+};
+
+Spry.$$.processTokens = function(tokens, root)
+{
+ var numTokens = tokens.length;
+ var nodeSet = [ root ];
+ var combiFunc = null;
+
+ for (var i = 0; i < numTokens && nodeSet.length > 0; i++)
+ {
+ var t = tokens[i];
+ if (t.type == Spry.$$.Token.SELECTOR)
+ {
+ if (combiFunc)
+ {
+ nodeSet = combiFunc(nodeSet, t);
+ combiFunc = null;
+ }
+ else
+ nodeSet = Spry.$$.getMatchingElements(nodeSet, t);
+ }
+ else // Spry.$$.Token.COMBINATOR
+ combiFunc = Spry.$$.combinatorFuncs[t.name];
+ }
+ return nodeSet;
+};
+
+Spry.$$.getMatchingElements = function(nodes, token)
+{
+ var results = [];
+ if (token.id)
+ {
+ n = nodes[0];
+ if (n && n.ownerDocument)
+ {
+ var e = n.ownerDocument.getElementById(token.id);
+ if (e)
+ {
+ // XXX: We need to make sure that the element
+ // we found is actually underneath the root
+ // we were given!
+
+ if (token.match(e))
+ results.push(e);
+ }
+ return results;
+ }
+ }
+
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i];
+ // if (token.match(n)) results.push(n);
+
+ var ea = n.getElementsByTagName(token.name);
+ var ne = ea.length;
+ for (var j = 0; j < ne; j++)
+ {
+ var e = ea[j];
+ if (token.match(e, true))
+ results.push(e);
+ }
+ }
+ return results;
+};
+
+/*
+Spry.$$.dumpSequences = function(sequences)
+{
+ Spry.Debug.trace("
Number of Sequences: " + sequences.length);
+ for (var i = 0; i < sequences.length; i++)
+ {
+ var str = "";
+ var s = sequences[i];
+ Spry.Debug.trace("
Sequence " + i + " -- Tokens: " + s.length);
+ for (var j = 0; j < s.length; j++)
+ {
+ var t = s[j];
+ if (t.type == Spry.$$.Token.SELECTOR)
+ {
+ str += " SELECTOR:\n Name: " + t.name + "\n ID: " + t.id + "\n Attrs:\n";
+ for (var k = 0; k < t.classes.length; k++)
+ str += " " + t.classes[k].name + ": " + t.classes[k].value + "\n";
+ for (var k = 0; k < t.attrs.length; k++)
+ str += " " + t.attrs[k].name + ": " + t.attrs[k].value + "\n";
+ str += " Pseudos:\n";
+ for (var k = 0; k < t.pseudos.length; k++)
+ str += " " + t.pseudos[k].name + (t.pseudos[k].arg ? "(" + t.pseudos[k].arg + ")" : "") + "\n";
+ }
+ else
+ {
+ str += " COMBINATOR:\n Name: '" + t.name + "'\n";
+ }
+ }
+ Spry.Debug.trace("" + Spry.Utils.encodeEntities(str) + "
");
+ }
+};
+*/
+
+Spry.$$.addExtensions = function(a)
+{
+ for (var f in Spry.$$.Results)
+ a[f] = Spry.$$.Results[f];
+};
+
+Spry.$$.Results = {};
+
+Spry.$$.Results.forEach = function(func)
+{
+ var n = this.length;
+ for (var i = 0; i < n; i++)
+ func(this[i]);
+ return this;
+};
+
+Spry.$$.Results.setAttribute = function(name, value)
+{
+ return this.forEach(function(n) { Spry.Utils.setAttribute(n, name, value); });
+};
+
+Spry.$$.Results.removeAttribute = function(name)
+{
+ return this.forEach(function(n) { Spry.Utils.removeAttribute(n, name); });
+};
+
+Spry.$$.Results.addClassName = function(className)
+{
+ return this.forEach(function(n) { Spry.Utils.addClassName(n, className); });
+};
+
+Spry.$$.Results.removeClassName = function(className)
+{
+ return this.forEach(function(n) { Spry.Utils.removeClassName(n, className); });
+};
+
+Spry.$$.Results.toggleClassName = function(className)
+{
+ return this.forEach(function(n) { Spry.Utils.toggleClassName(n, className); });
+};
+
+Spry.$$.Results.addEventListener = function(eventType, handler, capture, bindHandler)
+{
+ return this.forEach(function(n) { Spry.Utils.addEventListener(n, eventType, handler, capture, bindHandler); });
+};
+
+Spry.$$.Results.removeEventListener = function(eventType, handler, capture)
+{
+ return this.forEach(function(n) { Spry.Utils.removeEventListener(n, eventType, handler, capture); });
+};
+
+Spry.$$.Results.setStyle = function(style)
+{
+ if (style)
+ {
+ style = Spry.Utils.styleStringToObject(style);
+ this.forEach(function(n)
+ {
+ for (var p in style)
+ try { n.style[p] = style[p]; } catch (e) {}
+ });
+ }
+ return this;
+};
+
+Spry.$$.Results.setProperty = function(prop, value)
+{
+ if (prop)
+ {
+ if (typeof prop == "string")
+ {
+ var p = {};
+ p[prop] = value;
+ prop = p;
+ }
+
+ this.forEach(function(n)
+ {
+ for (var p in prop)
+ try { n[p] = prop[p]; } catch (e) {}
+ });
+ }
+ return this;
+};
\ No newline at end of file
diff --git a/1.6.1/SpryEffects.js b/1.6.1/SpryEffects.js
new file mode 100755
index 0000000..955b4fb
--- /dev/null
+++ b/1.6.1/SpryEffects.js
@@ -0,0 +1,2468 @@
+// Spry.Effect.js - version 0.38 - Spry Pre-Release 1.6.1
+//
+// Copyright (c) 2006. Adobe Systems Incorporated.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Adobe Systems Incorporated nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+var Spry;
+
+if (!Spry) Spry = {};
+
+Spry.forwards = 1; // const
+Spry.backwards = 2; // const
+
+if (!Spry.Effect) Spry.Effect = {};
+
+Spry.Effect.Transitions = {
+ linearTransition: function(time, begin, change, duration)
+ {
+ if (time > duration) return change+begin;
+ return begin + (time / duration) * change;
+ },
+ sinusoidalTransition: function(time, begin, change, duration)
+ {
+ if (time > duration) return change+begin;
+ return begin + ((-Math.cos((time/duration)*Math.PI)/2) + 0.5) * change;
+ },
+ squareTransition: function(time, begin, change, duration)
+ {
+ if (time > duration) return change+begin;
+ return begin + Math.pow(time/duration, 2) * change;
+ },
+ squarerootTransition: function(time, begin, change, duration)
+ {
+ if (time > duration) return change+begin;
+ return begin + Math.sqrt(time/duration) * change;
+ },
+ fifthTransition: function(time, begin, change, duration)
+ {
+ if (time > duration) return change+begin;
+ return begin + Math.sqrt((-Math.cos((time/duration)*Math.PI)/2) + 0.5) * change;
+ },
+ circleTransition: function(time, begin, change, duration)
+ {
+ if (time > duration) return change+begin;
+ var pos = time/duration;
+ return begin + Math.sqrt(1 - Math.pow((pos-1), 2))* change;
+ },
+ pulsateTransition: function(time, begin, change, duration)
+ {
+ if (time > duration) return change+begin;
+ return begin + (0.5 + Math.sin(17*time/duration)/2) * change;
+ },
+ growSpecificTransition: function(time, begin, change, duration)
+ {
+ if (time > duration) return change+begin;
+ var pos = time/duration;
+ return begin + (5 * Math.pow(pos, 3) - 6.4 * Math.pow(pos, 2) + 2 * pos) * change;
+ }
+};
+for (var trans in Spry.Effect.Transitions)
+{
+ Spry[trans] = Spry.Effect.Transitions[trans];
+}
+//////////////////////////////////////////////////////////////////////
+//
+// Spry.Effect.Registry
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Effect.Registry = function()
+{
+ this.effects = [];
+};
+
+Spry.Effect.Registry.prototype.getRegisteredEffect = function(element, options)
+{
+ var a = {};
+ a.element = Spry.Effect.getElement(element);
+ a.options = options;
+
+ for (var i=0; i0)
+ {
+ if(isFirstEntry)
+ {
+ camelizedString = oStringList[i];
+ isFirstEntry = false;
+ }
+ else
+ {
+ var s = oStringList[i];
+ camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
+ }
+ }
+ }
+
+ return camelizedString;
+};
+
+Spry.Effect.Utils.isPercentValue = function(value)
+{
+ var result = false;
+ if (typeof value == 'string' && value.length > 0 && value.lastIndexOf("%") > 0)
+ result = true;
+
+ return result;
+};
+
+Spry.Effect.Utils.getPercentValue = function(value)
+{
+ var result = 0;
+ try
+ {
+ result = Number(value.substring(0, value.lastIndexOf("%")));
+ }
+ catch (e) {Spry.Effect.Utils.showError('Spry.Effect.Utils.getPercentValue: ' + e);}
+ return result;
+};
+
+Spry.Effect.Utils.getPixelValue = function(value)
+{
+ var result = 0;
+ if (typeof value == 'number') return value;
+ var unitIndex = value.lastIndexOf("px");
+ if ( unitIndex == -1)
+ unitIndex = value.length;
+ try
+ {
+ result = parseInt(value.substring(0, unitIndex), 10);
+ }
+ catch (e){}
+ return result;
+};
+
+Spry.Effect.Utils.getFirstChildElement = function(node)
+{
+ if (node)
+ {
+ var childCurr = node.firstChild;
+ while (childCurr)
+ {
+ if (childCurr.nodeType == 1) // Node.ELEMENT_NODE
+ return childCurr;
+
+ childCurr = childCurr.nextSibling;
+ }
+ }
+
+ return null;
+};
+
+Spry.Effect.Utils.fetchChildImages = function(startEltIn, targetImagesOut)
+{
+ if(!startEltIn || startEltIn.nodeType != 1 || !targetImagesOut)
+ return;
+
+ if(startEltIn.hasChildNodes())
+ {
+ var childImages = startEltIn.getElementsByTagName('img');
+ var imageCnt = childImages.length;
+ for(var i=0; i therefore we save the height before changing the overflow property and set the old size back
+ var heightCache = 0;
+ var needsCache = /MSIE 7.0/.test(navigator.userAgent) && /Windows NT/.test(navigator.userAgent);
+ if(needsCache)
+ heightCache = Spry.Effect.getDimensionsRegardlessOfDisplayState(element).height;
+
+ Spry.Effect.setStyleProp(element, 'overflow', 'hidden');
+
+ if(needsCache)
+ Spry.Effect.setStyleProp(element, 'height', heightCache+'px');
+ }
+};
+
+Spry.Effect.cleanWhitespace = function(element)
+{
+ var childCountInit = element.childNodes.length;
+ for (var i = childCountInit - 1; i >= 0; i--) {
+ var node = element.childNodes[i];
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ try
+ {
+ element.removeChild(node);
+ }
+ catch (e) {Spry.Effect.Utils.showError('Spry.Effect.cleanWhitespace: ' + e);}
+ }
+};
+
+Spry.Effect.getComputedStyle = function(element)
+{
+ return /MSIE/.test(navigator.userAgent) ? element.currentStyle : document.defaultView.getComputedStyle(element, null);
+};
+
+Spry.Effect.getDimensions = function(element)
+{
+ var dimensions = new Spry.Effect.Utils.Rectangle;
+ var computedStyle = null;
+
+ if (element.style.width && /px/i.test(element.style.width))
+ dimensions.width = parseInt(element.style.width, 10); // without padding
+ else
+ {
+ computedStyle = Spry.Effect.getComputedStyle(element);
+ var tryComputedStyle = computedStyle && computedStyle.width && /px/i.test(computedStyle.width);
+
+ if (tryComputedStyle)
+ dimensions.width = parseInt(computedStyle.width, 10); // without padding, includes css
+
+ if (!tryComputedStyle || dimensions.width == 0) // otherwise we might run into problems on safari and opera (mac only)
+ dimensions.width = element.offsetWidth; // includes padding
+ }
+
+ if (element.style.height && /px/i.test(element.style.height))
+ dimensions.height = parseInt(element.style.height, 10); // without padding
+ else
+ {
+ if (!computedStyle)
+ computedStyle = Spry.Effect.getComputedStyle(element);
+
+ var tryComputedStyle = computedStyle && computedStyle.height && /px/i.test(computedStyle.height);
+
+ if (tryComputedStyle)
+ dimensions.height = parseInt(computedStyle.height, 10); // without padding, includes css
+
+ if(!tryComputedStyle || dimensions.height == 0) // otherwise we might run into problems on safari and opera (mac only)
+ dimensions.height = element.offsetHeight; // includes padding
+ }
+ return dimensions;
+};
+
+Spry.Effect.getDimensionsRegardlessOfDisplayState = function(element, displayElement)
+{
+ // If the displayElement display property is set to 'none', we temporarily set its
+ // visibility state to 'hidden' to be able to calculate the dimension.
+
+ var refElement = displayElement ? displayElement : element;
+ var displayOrig = Spry.Effect.getStyleProp(refElement, 'display');
+ var visibilityOrig = Spry.Effect.getStyleProp(refElement, 'visibility');
+
+ if(displayOrig == 'none')
+ {
+ Spry.Effect.setStyleProp(refElement, 'visibility', 'hidden');
+ Spry.Effect.setStyleProp(refElement, 'display', 'block');
+
+ if(window.opera) // opera needs focus to calculate the size for hidden elements
+ refElement.focus();
+ }
+
+ var dimensions = Spry.Effect.getDimensions(element);
+
+ if(displayOrig == 'none') // reset the original values
+ {
+ Spry.Effect.setStyleProp(refElement, 'display', 'none');
+ Spry.Effect.setStyleProp(refElement, 'visibility', visibilityOrig);
+ }
+ return dimensions;
+};
+
+Spry.Effect.getOpacity = function(element)
+{
+ var o = Spry.Effect.getStyleProp(element, "opacity");
+ if (typeof o == 'undefined' || o == null)
+ o = 1.0;
+ return o;
+};
+
+Spry.Effect.getBgColor = function(ele)
+{
+ return Spry.Effect.getStyleProp(ele, "background-color");
+};
+
+Spry.Effect.intPropStyle = function(e, prop){
+ var i = parseInt(Spry.Effect.getStyleProp(e, prop), 10);
+ if (isNaN(i))
+ return 0;
+ return i;
+};
+
+Spry.Effect.getPosition = function(element)
+{
+ var position = new Spry.Effect.Utils.Position;
+ var computedStyle = null;
+
+ if (element.style.left && /px/i.test(element.style.left))
+ position.x = parseInt(element.style.left, 10); // without padding
+ else
+ {
+ computedStyle = Spry.Effect.getComputedStyle(element);
+ var tryComputedStyle = computedStyle && computedStyle.left && /px/i.test(computedStyle.left);
+
+ if (tryComputedStyle)
+ position.x = parseInt(computedStyle.left, 10); // without padding, includes css
+
+ if(!tryComputedStyle || position.x == 0) // otherwise we might run into problems on safari and opera (mac only)
+ position.x = element.offsetLeft; // includes padding
+ }
+
+ if (element.style.top && /px/i.test(element.style.top))
+ position.y = parseInt(element.style.top, 10); // without padding
+ else
+ {
+ if (!computedStyle)
+ computedStyle = Spry.Effect.getComputedStyle(element);
+
+ var tryComputedStyle = computedStyle && computedStyle.top && /px/i.test(computedStyle.top);
+
+ if (tryComputedStyle)
+ position.y = parseInt(computedStyle.top, 10); // without padding, includes css
+
+ if(!tryComputedStyle || position.y == 0) // otherwise we might run into problems on safari and opera (mac only)
+ position.y = element.offsetTop; // includes padding
+ }
+ return position;
+};
+
+Spry.Effect.getOffsetPosition = Spry.Effect.getPosition; // deprecated
+
+//////////////////////////////////////////////////////////////////////
+//
+// Spry.Effect.Animator
+// (base class)
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Effect.Animator = function(options)
+{
+ Spry.Utils.Notifier.call(this);
+
+ this.name = 'Animator';
+ this.element = null;
+ this.startMilliseconds = 0;
+ this.repeat = 'none';
+ this.isRunning = false;
+ this.timer = null;
+ this.cancelRemaining = 0;
+
+ if (!options)
+ var options = {};
+
+ if (options.toggle)
+ this.direction = false;
+ else
+ this.direction = Spry.forwards;
+
+ var self = this;
+ if (options.setup != null)
+ this.addObserver({onPreEffect: function(){try{self.options.setup(self.element, self);}catch(e){Spry.Effect.Utils.showError('Spry.Effect.Animator.prototype.start: setup callback: ' + e);}}});
+
+ if (options.finish != null)
+ this.addObserver({onPostEffect: function(){try{self.options.finish(self.element, self);}catch(e){Spry.Effect.Utils.showError('Spry.Effect.Animator.prototype.stop: finish callback: ' + e);}}});
+
+ this.options = {
+ duration: 1000,
+ toggle: false,
+ transition: Spry.linearTransition,
+ interval: 16 // ca. 62 fps
+ };
+
+ this.setOptions(options);
+ if (options.transition)
+ this.setTransition(options.transition);
+
+ if (options.fps)
+ this.setFps(options.fps);
+};
+Spry.Effect.Animator.prototype = new Spry.Utils.Notifier();
+Spry.Effect.Animator.prototype.constructor = Spry.Utils.Animator;
+
+Spry.Effect.Animator.prototype.notStaticAnimator = true;
+
+Spry.Effect.Animator.prototype.setOptions = function(options)
+{
+ if (!options)
+ return;
+ for (var prop in options)
+ this.options[prop] = options[prop];
+};
+Spry.Effect.Animator.prototype.setTransition = function(transition){
+ if (typeof transition == 'number' || transition == "1" || transition == "2")
+ switch (parseInt(transition,10))
+ {
+ case 1: transition = Spry.linearTransition; break;
+ case 2: transition = Spry.sinusoidalTransition; break;
+ default: Spry.Effect.Utils.showError('unknown transition');
+ }
+
+ else if (typeof transition == 'string')
+ {
+ if (typeof window[transition] == 'function')
+ transition = window[transition];
+ else if (typeof Spry[transition] == 'function')
+ transition = Spry[transition];
+ else
+ Spry.Effect.Utils.showError('unknown transition');
+ }
+
+ this.options.transition = transition;
+ if (typeof this.effectsArray != 'undefined'){
+ var l = this.effectsArray.length;
+ for (var i = 0; i < l; i++)
+ this.effectsArray[i].effect.setTransition(transition);
+ }
+};
+
+Spry.Effect.Animator.prototype.setDuration = function(duration){
+ this.options.duration = duration;
+ if (typeof this.effectsArray != 'undefined')
+ {
+ var l = this.effectsArray.length;
+ for (var i = 0; i < l; i++)
+ {
+ this.effectsArray[i].effect.setDuration(duration);
+ }
+ }
+};
+
+Spry.Effect.Animator.prototype.setFps = function(fps){
+ this.options.interval = parseInt(1000 / fps, 10);
+ this.options.fps = fps;
+ if (typeof this.effectsArray != 'undefined')
+ {
+ var l = this.effectsArray.length;
+ for (var i = 0; i < l; i++)
+ {
+ this.effectsArray[i].effect.setFps(fps);
+ }
+ }
+};
+
+Spry.Effect.Animator.prototype.start = function(withoutTimer)
+{
+ if (!this.element)
+ return;
+
+ if (arguments.length == 0)
+ withoutTimer = false;
+
+ if (this.isRunning)
+ this.cancel();
+
+ this.prepareStart();
+ var currDate = new Date();
+ this.startMilliseconds = currDate.getTime();
+
+ if (this.element.id)
+ this.element = document.getElementById(this.element.id);
+
+ if (this.cancelRemaining != 0 && this.options.toggle)
+ {
+ if (this.cancelRemaining < 1 && typeof this.options.transition == 'function')
+ {
+ var startTime = 0;
+ var stopTime = this.options.duration;
+ var start = 0;
+ var stop = 1;
+ var emergency = 0;
+ this.cancelRemaining = Math.round(this.cancelRemaining * 1000) / 1000;
+ var found = false;
+ var middle = 0;
+ while (!found)
+ {
+ if (emergency++ > this.options.duration) break;
+ var half = startTime + ((stopTime - startTime) / 2);
+ middle = Math.round(this.options.transition(half, 1, -1, this.options.duration) * 1000) / 1000;
+ if (middle == this.cancelRemaining)
+ {
+ this.startMilliseconds -= half;
+ found = true;
+ }
+ if (middle < this.cancelRemaining)
+ {
+ stopTime = half;
+ stop = middle;
+ }
+ else
+ {
+ startTime = half;
+ start = middle;
+ }
+ }
+ }
+ this.cancelRemaining = 0;
+ }
+ this.notifyObservers('onPreEffect', this);
+
+ if (withoutTimer == false)
+ {
+ var self = this;
+ this.timer = setInterval(function() { self.drawEffect(); }, this.options.interval);
+ }
+ this.isRunning = true;
+};
+Spry.Effect.Animator.prototype.stopFlagReset = function()
+{
+ if (this.timer)
+ {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+ this.startMilliseconds = 0;
+};
+Spry.Effect.Animator.prototype.stop = function()
+{
+ this.stopFlagReset();
+ this.notifyObservers('onPostEffect', this);
+ this.isRunning = false;
+};
+
+Spry.Effect.Animator.prototype.cancel = function()
+{
+ var elapsed = this.getElapsedMilliseconds();
+ if (this.startMilliseconds > 0 && elapsed < this.options.duration)
+ this.cancelRemaining = this.options.transition(elapsed, 0, 1, this.options.duration);
+
+ this.stopFlagReset();
+ this.notifyObservers('onCancel', this);
+ this.isRunning = false;
+};
+
+Spry.Effect.Animator.prototype.drawEffect = function()
+{
+ var isRunning = true;
+
+ this.notifyObservers('onStep', this);
+ var timeElapsed = this.getElapsedMilliseconds();
+
+ if (typeof this.options.transition != 'function'){
+ Spry.Effect.Utils.showError('unknown transition');
+ return;
+ }
+ this.animate();
+
+ if (timeElapsed > this.options.duration)
+ {
+ isRunning = false;
+ this.stop();
+ }
+ return isRunning;
+};
+
+Spry.Effect.Animator.prototype.getElapsedMilliseconds = function()
+{
+ if (this.startMilliseconds > 0)
+ {
+ var currDate = new Date();
+ return (currDate.getTime() - this.startMilliseconds);
+ }
+ return 0;
+};
+
+Spry.Effect.Animator.prototype.doToggle = function()
+{
+ if (!this.direction)
+ {
+ this.direction = Spry.forwards;
+ return;
+ }
+ if (this.options.toggle == true)
+ {
+ if (this.direction == Spry.forwards)
+ {
+ this.direction = Spry.backwards;
+ this.notifyObservers('onToggle', this);
+ }
+ else if (this.direction == Spry.backwards)
+ {
+ this.direction = Spry.forwards;
+ }
+ }
+};
+
+Spry.Effect.Animator.prototype.prepareStart = function()
+{
+ if (this.options && this.options.toggle)
+ this.doToggle();
+};
+
+Spry.Effect.Animator.prototype.animate = function(){};
+Spry.Effect.Animator.prototype.onStep = function(el)
+{
+ if (el != this)
+ this.notifyObservers('onStep', this);
+};
+//////////////////////////////////////////////////////////////////////
+//
+// Spry.Effect.Move
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Effect.Move = function(element, fromPos, toPos, options)
+{
+ this.dynamicFromPos = false;
+ if (arguments.length == 3)
+ {
+ options = toPos;
+ toPos = fromPos;
+ fromPos = Spry.Effect.getPosition(element);
+ this.dynamicFromPos = true;
+ }
+
+ Spry.Effect.Animator.call(this, options);
+
+ this.name = 'Move';
+ this.element = Spry.Effect.getElement(element);
+ if (!this.element)
+ return;
+
+ if (fromPos.units != toPos.units)
+ Spry.Effect.Utils.showError('Spry.Effect.Move: Conflicting units (' + fromPos.units + ', ' + toPos.units + ')');
+
+ this.units = fromPos.units;
+ this.startX = Number(fromPos.x);
+ this.stopX = Number(toPos.x);
+ this.startY = Number(fromPos.y);
+ this.stopY = Number(toPos.y);
+};
+
+Spry.Effect.Move.prototype = new Spry.Effect.Animator();
+Spry.Effect.Move.prototype.constructor = Spry.Effect.Move;
+
+Spry.Effect.Move.prototype.animate = function()
+{
+ var left = 0;
+ var top = 0;
+ var floor = Math.floor;
+ var elapsed = this.getElapsedMilliseconds();
+ if (this.direction == Spry.forwards)
+ {
+ left = floor(this.options.transition(elapsed, this.startX, this.stopX - this.startX, this.options.duration));
+ top = floor(this.options.transition(elapsed, this.startY, this.stopY - this.startY, this.options.duration));
+ }
+ else if (this.direction == Spry.backwards)
+ {
+ left = floor(this.options.transition(elapsed, this.stopX, this.startX - this.stopX, this.options.duration));
+ top = floor(this.options.transition(elapsed, this.stopY, this.startY - this.stopY, this.options.duration));
+ }
+
+ this.element.style.left = left + this.units;
+ this.element.style.top = top + this.units;
+};
+
+Spry.Effect.Move.prototype.prepareStart = function()
+{
+ if (this.options && this.options.toggle)
+ this.doToggle();
+
+ if (this.dynamicFromPos == true)
+ {
+ var fromPos = Spry.Effect.getPosition(this.element);
+ this.startX = fromPos.x;
+ this.startY = fromPos.y;
+
+ this.rangeMoveX = this.startX - this.stopX;
+ this.rangeMoveY= this.startY - this.stopY;
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Spry.Effect.Size
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Effect.Size = function(element, fromRect, toRect, options)
+{
+ this.dynamicFromRect = false;
+
+ if (arguments.length == 3)
+ {
+ options = toRect;
+ toRect = fromRect;
+ fromRect = Spry.Effect.getDimensionsRegardlessOfDisplayState(element);
+ this.dynamicFromRect = true;
+ }
+
+ Spry.Effect.Animator.call(this, options);
+
+ this.name = 'Size';
+ this.element = Spry.Effect.getElement(element);
+ if (!this.element)
+ return;
+
+ element = this.element;
+
+ if (fromRect.units != toRect.units)
+ {
+ Spry.Effect.Utils.showError('Spry.Effect.Size: Conflicting units (' + fromRect.units + ', ' + toRect.units + ')');
+ return false;
+ }
+
+ this.units = fromRect.units;
+
+ var originalRect = Spry.Effect.getDimensionsRegardlessOfDisplayState(element);
+ this.originalWidth = originalRect.width;
+ this.originalHeight = originalRect.height;
+
+ this.startWidth = fromRect.width;
+ this.startHeight = fromRect.height;
+ this.stopWidth = toRect.width;
+ this.stopHeight = toRect.height;
+ this.childImages = new Array();
+
+ if (this.options.useCSSBox){
+ Spry.Effect.makePositioned(this.element);
+ var intProp = Spry.Effect.intPropStyle;
+ this.startFromBorder_top = intProp(element, 'border-top-width');
+ this.startFromBorder_bottom = intProp(element, 'border-bottom-width');
+ this.startFromBorder_left = intProp(element, 'border-left-width');
+ this.startFromBorder_right = intProp(element, 'border-right-width');
+ this.startFromPadding_top = intProp(element, 'padding-top');
+ this.startFromPadding_bottom = intProp(element, 'padding-bottom');
+ this.startFromPadding_left = intProp(element, 'padding-left');
+ this.startFromPadding_right = intProp(element, 'padding-right');
+ this.startFromMargin_top = intProp(element, 'margin-top');
+ this.startFromMargin_bottom = intProp(element, 'margin-bottom');
+ this.startFromMargin_right = intProp(element, 'margin-right');
+ this.startFromMargin_left = intProp(element, 'margin-left');
+ this.startLeft = intProp(element, 'left');
+ this.startTop = intProp(element, 'top');
+ }
+
+ if(this.options.scaleContent)
+ Spry.Effect.Utils.fetchChildImages(element, this.childImages);
+
+ this.fontFactor = 1.0;
+ var fontSize = Spry.Effect.getStyleProp(this.element, 'font-size');
+ if(fontSize && /em\s*$/.test(fontSize))
+ this.fontFactor = parseFloat(fontSize);
+
+ var isPercent = Spry.Effect.Utils.isPercentValue;
+
+ if (isPercent(this.startWidth))
+ {
+ var startWidthPercent = Spry.Effect.Utils.getPercentValue(this.startWidth);
+ this.startWidth = originalRect.width * (startWidthPercent / 100);
+ }
+
+ if (isPercent(this.startHeight))
+ {
+ var startHeightPercent = Spry.Effect.Utils.getPercentValue(this.startHeight);
+ this.startHeight = originalRect.height * (startHeightPercent / 100);
+ }
+
+ if (isPercent(this.stopWidth))
+ {
+ var stopWidthPercent = Spry.Effect.Utils.getPercentValue(this.stopWidth);
+ this.stopWidth = originalRect.width * (stopWidthPercent / 100);
+ }
+
+ if (isPercent(this.stopHeight))
+ {
+ var stopHeightPercent = Spry.Effect.Utils.getPercentValue(this.stopHeight);
+ this.stopHeight = originalRect.height * (stopHeightPercent / 100);
+ }
+
+ this.enforceVisible = Spry.Effect.isInvisible(this.element);
+};
+
+Spry.Effect.Size.prototype = new Spry.Effect.Animator();
+Spry.Effect.Size.prototype.constructor = Spry.Effect.Size;
+
+Spry.Effect.Size.prototype.animate = function()
+{
+ var width = 0;
+ var height = 0;
+ var fontSize = 0;
+ var direction = 0;
+ var floor = Math.floor;
+ var elapsed = this.getElapsedMilliseconds();
+
+ if (this.direction == Spry.forwards) {
+ width = floor(this.options.transition(elapsed, this.startWidth, this.stopWidth - this.startWidth, this.options.duration));
+ height = floor(this.options.transition(elapsed, this.startHeight, this.stopHeight - this.startHeight, this.options.duration));
+ direction = 1;
+ } else if (this.direction == Spry.backwards) {
+ width = floor(this.options.transition(elapsed, this.stopWidth, this.startWidth - this.stopWidth, this.options.duration));
+ height = floor(this.options.transition(elapsed, this.stopHeight, this.startHeight - this.stopHeight, this.options.duration));
+ direction = -1;
+ }
+
+ var propFactor = width/this.originalWidth;
+ fontSize = this.fontFactor * propFactor;
+
+ var elStyle = this.element.style;
+ if (width < 0)
+ width = 0;
+
+ if (height < 0)
+ height = 0;
+
+ elStyle.width = width + this.units;
+ elStyle.height = height + this.units;
+
+ if (typeof this.options.useCSSBox != 'undefined' && this.options.useCSSBox == true)
+ {
+ var intProp = Spry.Effect.intPropStyle;
+ var origTop = intProp(this.element, 'top');
+ var origLeft = intProp(this.element, 'left');
+ var origMarginTop = intProp(this.element, 'margin-top');
+ var origMarginLeft = intProp(this.element, 'margin-left');
+
+ var widthFactor = propFactor;
+ var heightFactor = height / this.originalHeight;
+ var border_top = floor(this.startFromBorder_top * heightFactor);
+ var border_bottom = floor(this.startFromBorder_bottom * heightFactor);
+ var border_left = floor(this.startFromBorder_left * widthFactor);
+ var border_right = floor(this.startFromBorder_right * widthFactor);
+ var padding_top = floor(this.startFromPadding_top * heightFactor);
+ var padding_bottom = floor(this.startFromPadding_bottom * heightFactor);
+ var padding_left = floor(this.startFromPadding_left * widthFactor);
+ var padding_right = floor(this.startFromPadding_right * widthFactor);
+ var margin_top = floor(this.startFromMargin_top * heightFactor);
+ var margin_bottom = floor(this.startFromMargin_bottom * heightFactor);
+ var margin_right = floor(this.startFromMargin_right * widthFactor);
+ var margin_left = floor(this.startFromMargin_left * widthFactor);
+
+ elStyle.borderTopWidth = border_top + this.units;
+ elStyle.borderBottomWidth = border_bottom + this.units;
+ elStyle.borderLeftWidth = border_left + this.units;
+ elStyle.borderRightWidth = border_right + this.units;
+ elStyle.paddingTop = padding_top + this.units;
+ elStyle.paddingBottom = padding_bottom + this.units;
+ elStyle.paddingLeft = padding_left + this.units;
+ elStyle.paddingRight = padding_right + this.units;
+ elStyle.marginTop = margin_top + this.units;
+ elStyle.marginBottom = margin_bottom + this.units;
+ elStyle.marginLeft = margin_left + this.units;
+ elStyle.marginRight = margin_right + this.units;
+
+ // compensate the margin shrinking
+ elStyle.left = floor(origLeft + origMarginLeft - margin_left) + this.units;
+ elStyle.top = floor(origTop + origMarginTop - margin_top) + this.units;
+ }
+
+ if (this.options.scaleContent)
+ {
+
+ for(var i=0; i < this.childImages.length; i++)
+ {
+ this.childImages[i][0].style.width = propFactor * this.childImages[i][1] + this.units;
+ this.childImages[i][0].style.height = propFactor * this.childImages[i][2] + this.units;
+ }
+ this.element.style.fontSize = fontSize + 'em';
+ }
+
+ if(this.enforceVisible)
+ {
+ Spry.Effect.enforceVisible(this.element);
+ this.enforceVisible = false;
+ }
+};
+
+Spry.Effect.Size.prototype.prepareStart = function()
+{
+ if (this.options && this.options.toggle)
+ this.doToggle();
+
+ if (this.dynamicFromRect == true)
+ {
+ var fromRect = Spry.Effect.getDimensions(this.element);
+ this.startWidth = fromRect.width;
+ this.startHeight = fromRect.height;
+
+ this.widthRange = this.startWidth - this.stopWidth;
+ this.heightRange = this.startHeight - this.stopHeight;
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Spry.Effect.Opacity
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Effect.Opacity = function(element, startOpacity, stopOpacity, options)
+{
+ this.dynamicStartOpacity = false;
+ if (arguments.length == 3)
+ {
+ options = stopOpacity;
+ stopOpacity = startOpacity;
+ startOpacity = Spry.Effect.getOpacity(element);
+ this.dynamicStartOpacity = true;
+ }
+
+ Spry.Effect.Animator.call(this, options);
+
+ this.name = 'Opacity';
+ this.element = Spry.Effect.getElement(element);
+ if (!this.element)
+ return;
+
+ // make this work on IE on elements without 'layout'
+ if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
+ Spry.Effect.setStyleProp(this.element, 'zoom', '1');
+
+ this.startOpacity = startOpacity;
+ this.stopOpacity = stopOpacity;
+ this.enforceVisible = Spry.Effect.isInvisible(this.element);
+};
+
+Spry.Effect.Opacity.prototype = new Spry.Effect.Animator();
+Spry.Effect.Opacity.prototype.constructor = Spry.Effect.Opacity;
+
+Spry.Effect.Opacity.prototype.animate = function()
+{
+ var opacity = 0;
+ var elapsed = this.getElapsedMilliseconds();
+ if (this.direction == Spry.forwards)
+ opacity = this.options.transition(elapsed, this.startOpacity, this.stopOpacity - this.startOpacity, this.options.duration);
+ else if (this.direction == Spry.backwards)
+ opacity = this.options.transition(elapsed, this.stopOpacity, this.startOpacity - this.stopOpacity, this.options.duration);
+
+ if (opacity < 0)
+ opacity = 0;
+
+ if(/MSIE/.test(navigator.userAgent))
+ {
+ var tmpval = Spry.Effect.getStyleProp(this.element,'filter');
+ if (tmpval){
+ tmpval = tmpval.replace(/alpha\(opacity=[0-9]{1,3}\)/g, '');
+ }
+ this.element.style.filter = tmpval + "alpha(opacity=" + Math.floor(opacity * 100) + ")";
+ }
+ else
+ this.element.style.opacity = opacity;
+
+ if(this.enforceVisible)
+ {
+ Spry.Effect.enforceVisible(this.element);
+ this.enforceVisible = false;
+ }
+};
+
+Spry.Effect.Opacity.prototype.prepareStart = function()
+{
+ if (this.options && this.options.toggle)
+ this.doToggle();
+
+ if (this.dynamicStartOpacity == true)
+ {
+ this.startOpacity = Spry.Effect.getOpacity(this.element);
+ this.opacityRange = this.startOpacity - this.stopOpacity;
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Spry.Effect.Color
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Effect.Color = function(element, startColor, stopColor, options)
+{
+ this.dynamicStartColor = false;
+ if (arguments.length == 3)
+ {
+ options = stopColor;
+ stopColor = startColor;
+ startColor = Spry.Effect.getBgColor(element);
+ this.dynamicStartColor = true;
+ }
+
+ Spry.Effect.Animator.call(this, options);
+
+ this.name = 'Color';
+ this.element = Spry.Effect.getElement(element);
+ if (!this.element)
+ return;
+
+ this.startColor = startColor;
+ this.stopColor = stopColor;
+ this.startRedColor = Spry.Effect.Utils.hexToInt(startColor.substr(1,2));
+ this.startGreenColor = Spry.Effect.Utils.hexToInt(startColor.substr(3,2));
+ this.startBlueColor = Spry.Effect.Utils.hexToInt(startColor.substr(5,2));
+ this.stopRedColor = Spry.Effect.Utils.hexToInt(stopColor.substr(1,2));
+ this.stopGreenColor = Spry.Effect.Utils.hexToInt(stopColor.substr(3,2));
+ this.stopBlueColor = Spry.Effect.Utils.hexToInt(stopColor.substr(5,2));
+};
+
+Spry.Effect.Color.prototype = new Spry.Effect.Animator();
+Spry.Effect.Color.prototype.constructor = Spry.Effect.Color;
+
+Spry.Effect.Color.prototype.animate = function()
+{
+ var redColor = 0;
+ var greenColor = 0;
+ var blueColor = 0;
+ var floor = Math.floor;
+ var elapsed = this.getElapsedMilliseconds();
+
+ if (this.direction == Spry.forwards)
+ {
+ redColor = floor(this.options.transition(elapsed, this.startRedColor, this.stopRedColor - this.startRedColor, this.options.duration));
+ greenColor = floor(this.options.transition(elapsed, this.startGreenColor, this.stopGreenColor - this.startGreenColor, this.options.duration));
+ blueColor = floor(this.options.transition(elapsed, this.startBlueColor, this.stopBlueColor - this.startBlueColor, this.options.duration));
+ }
+ else if (this.direction == Spry.backwards)
+ {
+ redColor = floor(this.options.transition(elapsed, this.stopRedColor, this.startRedColor - this.stopRedColor, this.options.duration));
+ greenColor = floor(this.options.transition(elapsed, this.stopGreenColor, this.startGreenColor - this.stopGreenColor, this.options.duration));
+ blueColor = floor(this.options.transition(elapsed, this.stopBlueColor, this.startBlueColor - this.stopBlueColor, this.options.duration));
+ }
+
+ this.element.style.backgroundColor = Spry.Effect.Utils.rgb(redColor, greenColor, blueColor);
+};
+
+Spry.Effect.Color.prototype.prepareStart = function()
+{
+ if (this.options && this.options.toggle)
+ this.doToggle();
+
+ if (this.dynamicStartColor == true)
+ {
+ this.startColor = Spry.Effect.getBgColor(element);
+ this.startRedColor = Spry.Effect.Utils.hexToInt(startColor.substr(1,2));
+ this.startGreenColor = Spry.Effect.Utils.hexToInt(startColor.substr(3,2));
+ this.startBlueColor = Spry.Effect.Utils.hexToInt(startColor.substr(5,2));
+ this.redColorRange = this.startRedColor - this.stopRedColor;
+ this.greenColorRange = this.startGreenColor - this.stopGreenColor;
+ this.blueColorRange = this.startBlueColor - this.stopBlueColor;
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Spry.Effect.Cluster
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Effect.Cluster = function(options)
+{
+ Spry.Effect.Animator.call(this, options);
+
+ this.name = 'Cluster';
+ this.effectsArray = new Array();
+ this.currIdx = -1;
+ var _ClusteredEffect = function(effect, kind)
+ {
+ this.effect = effect;
+ this.kind = kind; // "parallel" or "queue"
+ this.isRunning = false;
+ };
+
+ this.ClusteredEffect = _ClusteredEffect;
+};
+
+Spry.Effect.Cluster.prototype = new Spry.Effect.Animator();
+Spry.Effect.Cluster.prototype.constructor = Spry.Effect.Cluster;
+
+Spry.Effect.Cluster.prototype.setInterval = function(interval){
+ var l = this.effectsArray.length;
+ this.options.interval = interval;
+ for (var i = 0; i < l; i++)
+ {
+ this.effectsArray[i].effect.setInterval(interval);
+ }
+};
+Spry.Effect.Cluster.prototype.drawEffect = function()
+{
+ var isRunning = true;
+ var allEffectsDidRun = false;
+ var baseEffectIsStillRunning = false;
+ var evalNextEffectsRunning = false;
+
+ if ((this.currIdx == -1 && this.direction == Spry.forwards) || (this.currIdx == this.effectsArray.length && this.direction == Spry.backwards))
+ this.initNextEffectsRunning();
+
+ var start = this.direction == Spry.forwards ? 0 : this.effectsArray.length-1;
+ var stop = this.direction == Spry.forwards ? this.effectsArray.length : -1;
+ var step = this.direction == Spry.forwards ? 1 : -1;
+ for (var i = start; i != stop; i+=step)
+ {
+ if (this.effectsArray[i].isRunning == true)
+ {
+ baseEffectIsStillRunning = this.effectsArray[i].effect.drawEffect();
+ if (baseEffectIsStillRunning == false && i == this.currIdx)
+ {
+ this.effectsArray[i].isRunning = false;
+ evalNextEffectsRunning = true;
+ }
+ }
+ }
+
+ if (evalNextEffectsRunning == true)
+ allEffectsDidRun = this.initNextEffectsRunning();
+
+ if (allEffectsDidRun == true) {
+ this.stop();
+ isRunning = false;
+ for (var i = 0; i < this.effectsArray.length; i++)
+ this.effectsArray[i].isRunning = false;
+
+ this.currIdx = this.direction == Spry.forwards ? this.effectsArray.length: -1;
+ }
+ return isRunning;
+};
+
+Spry.Effect.Cluster.prototype.initNextEffectsRunning = function()
+{
+ var allEffectsDidRun = false;
+ var step = this.direction == Spry.forwards ? 1 : -1;
+ var stop = this.direction == Spry.forwards ? this.effectsArray.length : -1;
+ this.currIdx+=step;
+ if ( (this.currIdx > (this.effectsArray.length - 1) && this.direction == Spry.forwards) || (this.currIdx < 0 && this.direction == Spry.backwards))
+ allEffectsDidRun = true;
+ else
+ for (var i = this.currIdx; i != stop; i+=step)
+ {
+ if ((i > this.currIdx && this.direction == Spry.forwards || i < this.currIdx && this.direction == Spry.backwards) && this.effectsArray[i].kind == "queue")
+ break;
+ this.effectsArray[i].effect.start(true);
+ this.effectsArray[i].isRunning = true;
+ this.currIdx = i;
+ }
+
+ return allEffectsDidRun;
+};
+
+Spry.Effect.Cluster.prototype.toggleCluster = function()
+{
+ if (!this.direction)
+ {
+ this.direction = Spry.forwards;
+ return;
+ }
+
+ if (this.options.toggle == true)
+ {
+ if (this.direction == Spry.forwards)
+ {
+ this.direction = Spry.backwards;
+ this.notifyObservers('onToggle', this);
+ this.currIdx = this.effectsArray.length;
+ }
+ else if (this.direction == Spry.backwards)
+ {
+ this.direction = Spry.forwards;
+ this.currIdx = -1;
+ }
+ }
+ else
+ {
+ if (this.direction == Spry.forwards)
+ this.currIdx = -1;
+ else if (this.direction == Spry.backwards)
+ this.currIdx = this.effectsArray.length;
+ }
+};
+
+Spry.Effect.Cluster.prototype.doToggle = function()
+{
+ this.toggleCluster();
+
+ // toggle all effects of the cluster, too
+ for (var i = 0; i < this.effectsArray.length; i++)
+ {
+ if (this.effectsArray[i].effect.options && (this.effectsArray[i].effect.options.toggle != null))
+ if (this.effectsArray[i].effect.options.toggle == true)
+ this.effectsArray[i].effect.doToggle();
+ }
+};
+
+Spry.Effect.Cluster.prototype.cancel = function()
+{
+ for (var i = 0; i < this.effectsArray.length; i++)
+ if (this.effectsArray[i].effect.isRunning)
+ this.effectsArray[i].effect.cancel();
+
+ var elapsed = this.getElapsedMilliseconds();
+ if (this.startMilliseconds > 0 && elapsed < this.options.duration)
+ this.cancelRemaining = this.options.transition(elapsed, 0, 1, this.options.duration);
+ this.stopFlagReset();
+ this.notifyObservers('onCancel', this);
+ this.isRunning = false;
+};
+
+Spry.Effect.Cluster.prototype.addNextEffect = function(effect)
+{
+ effect.addObserver(this);
+ this.effectsArray[this.effectsArray.length] = new this.ClusteredEffect(effect, "queue");
+ if (this.effectsArray.length == 1)
+ {
+ // with the first added effect we know the element
+ // that the cluster is working on
+ this.element = effect.element;
+ }
+};
+
+Spry.Effect.Cluster.prototype.addParallelEffect = function(effect)
+{
+ if (this.effectsArray.length == 0 || this.effectsArray[this.effectsArray.length-1].kind != 'parallel')
+ effect.addObserver(this);
+
+ this.effectsArray[this.effectsArray.length] = new this.ClusteredEffect(effect, "parallel");
+ if (this.effectsArray.length == 1)
+ {
+ // with the first added effect we know the element
+ // that the cluster is working on
+ this.element = effect.element;
+ }
+};
+
+Spry.Effect.Cluster.prototype.prepareStart = function()
+{
+ this.toggleCluster();
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Combination effects
+// Custom effects can be build by combining basic effect bahaviour
+// like Move, Size, Color, Opacity
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Effect.Fade = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Fade');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ this.name = 'Fade';
+ var element = Spry.Effect.getElement(element);
+ this.element = element;
+ if (!this.element)
+ return;
+ var durationInMilliseconds = 1000;
+ var fromOpacity = 0.0;
+ var toOpacity = 100.0;
+ var doToggle = false;
+ var transition = Spry.fifthTransition;
+ var fps = 60;
+ var originalOpacity = 0;
+ if(/MSIE/.test(navigator.userAgent))
+ originalOpacity = parseInt(Spry.Effect.getStylePropRegardlessOfDisplayState(this.element, 'filter').replace(/alpha\(opacity=([0-9]{1,3})\)/g, '$1'), 10);
+ else
+ originalOpacity = parseInt(Spry.Effect.getStylePropRegardlessOfDisplayState(this.element, 'opacity') * 100, 10);
+
+ if (isNaN(originalOpacity))
+ originalOpacity = 100;
+
+ if (options)
+ {
+ if (options.duration != null) durationInMilliseconds = options.duration;
+ if (options.from != null){
+ if (Spry.Effect.Utils.isPercentValue(options.from))
+ fromOpacity = Spry.Effect.Utils.getPercentValue(options.from) * originalOpacity / 100;
+ else
+ fromOpacity = options.from;
+ }
+ if (options.to != null)
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.to))
+ toOpacity = Spry.Effect.Utils.getPercentValue(options.to) * originalOpacity / 100;
+ else
+ toOpacity = options.to;
+ }
+ if (options.toggle != null) doToggle = options.toggle;
+ if (options.transition != null) transition = options.transition;
+ if (options.fps != null) fps = options.fps;
+ else this.options.transition = transition;
+ }
+
+ fromOpacity = fromOpacity/ 100.0;
+ toOpacity = toOpacity / 100.0;
+
+ options = {duration: durationInMilliseconds, toggle: doToggle, transition: transition, from: fromOpacity, to: toOpacity, fps: fps};
+ var fadeEffect = new Spry.Effect.Opacity(element, fromOpacity, toOpacity, options);
+ this.addNextEffect(fadeEffect);
+};
+
+Spry.Effect.Fade.prototype = new Spry.Effect.Cluster();
+Spry.Effect.Fade.prototype.constructor = Spry.Effect.Fade;
+
+Spry.Effect.Blind = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Blind');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ this.name = 'Blind';
+ var element = Spry.Effect.getElement(element);
+ this.element = element;
+ if (!this.element)
+ return;
+ var durationInMilliseconds = 1000;
+ var doToggle = false;
+ var kindOfTransition = Spry.circleTransition;
+ var fps = 60;
+ var doScaleContent = false;
+
+ Spry.Effect.makeClipping(element);
+
+ var originalRect = Spry.Effect.getDimensionsRegardlessOfDisplayState(element);
+ var fromHeightPx = originalRect.height;
+ var toHeightPx = 0;
+ var optionFrom = options ? options.from : originalRect.height;
+ var optionTo = options ? options.to : 0;
+ var fullCSSBox = false;
+
+
+ if (options)
+ {
+ if (options.duration != null) durationInMilliseconds = options.duration;
+ if (options.from != null)
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.from))
+ fromHeightPx = Spry.Effect.Utils.getPercentValue(options.from) * originalRect.height / 100;
+ else
+ fromHeightPx = Spry.Effect.Utils.getPixelValue(options.from);
+ }
+ if (options.to != null)
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.to))
+ toHeightPx = Spry.Effect.Utils.getPercentValue(options.to) * originalRect.height / 100;
+ else
+ toHeightPx = Spry.Effect.Utils.getPixelValue(options.to);
+ }
+ if (options.toggle != null) doToggle = options.toggle;
+ if (options.transition != null) kindOfTransition = options.transition;
+ if (options.fps != null) fps = options.fps;
+ if (options.useCSSBox != null) fullCSSBox = options.useCSSBox;
+ }
+
+ var fromRect = new Spry.Effect.Utils.Rectangle;
+ fromRect.width = originalRect.width;
+ fromRect.height = fromHeightPx;
+
+ var toRect = new Spry.Effect.Utils.Rectangle;
+ toRect.width = originalRect.width;
+ toRect.height = toHeightPx;
+
+ options = {duration:durationInMilliseconds, toggle:doToggle, transition:kindOfTransition, scaleContent:doScaleContent, useCSSBox: fullCSSBox, from: optionFrom, to: optionTo, fps: fps};
+ var blindEffect = new Spry.Effect.Size(element, fromRect, toRect, options);
+ this.addNextEffect(blindEffect);
+};
+
+Spry.Effect.Blind.prototype = new Spry.Effect.Cluster();
+Spry.Effect.Blind.prototype.constructor = Spry.Effect.Blind;
+
+Spry.Effect.Highlight = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Highlight');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ this.name = 'Highlight';
+ var durationInMilliseconds = 1000;
+ var toColor = "#ffffff";
+ var doToggle = false;
+ var kindOfTransition = Spry.sinusoidalTransition;
+ var fps = 60;
+ var element = Spry.Effect.getElement(element);
+ this.element = element;
+ if (!this.element)
+ return;
+ var fromColor = Spry.Effect.getBgColor(element);
+ if (fromColor == "transparent") fromColor = "#ffff99";
+
+ if (options)
+ {
+ if (options.duration != null) durationInMilliseconds = options.duration;
+ if (options.from != null) fromColor = options.from;
+ if (options.to != null) toColor = options.to;
+ if (options.toggle != null) doToggle = options.toggle;
+ if (options.transition != null) kindOfTransition = options.transition;
+ if (options.fps != null) fps = options.fps;
+ }
+
+ if ( fromColor.indexOf('rgb') != -1 )
+ var fromColor = Spry.Effect.Utils.rgb(parseInt(fromColor.substring(fromColor.indexOf('(')+1, fromColor.indexOf(',')),10), parseInt(fromColor.substring(fromColor.indexOf(',')+1, fromColor.lastIndexOf(',')),10), parseInt(fromColor.substring(fromColor.lastIndexOf(',')+1, fromColor.indexOf(')')),10));
+
+ if ( toColor.indexOf('rgb') != -1 )
+ var toColor = Spry.Effect.Utils.rgb(parseInt(toColor.substring(toColor.indexOf('(')+1, toColor.indexOf(',')),10), parseInt(toColor.substring(toColor.indexOf(',')+1, toColor.lastIndexOf(',')),10), parseInt(toColor.substring(toColor.lastIndexOf(',')+1, toColor.indexOf(')')),10));
+
+ var fromColor = Spry.Effect.Utils.longColorVersion(fromColor);
+ var toColor = Spry.Effect.Utils.longColorVersion(toColor);
+
+ this.restoreBackgroundImage = Spry.Effect.getStyleProp(element, 'background-image');
+
+ options = {duration: durationInMilliseconds, toggle: doToggle, transition: kindOfTransition, fps: fps};
+ var highlightEffect = new Spry.Effect.Color(element, fromColor, toColor, options);
+ this.addNextEffect(highlightEffect);
+
+ this.addObserver({
+ onPreEffect:
+ function(effect){
+ Spry.Effect.setStyleProp(effect.element, 'background-image', 'none');
+ },
+ onPostEffect:
+ function(effect){
+ Spry.Effect.setStyleProp(effect.element, 'background-image', effect.restoreBackgroundImage);
+
+ if (effect.direction == Spry.forwards && effect.options.restoreColor)
+ Spry.Effect.setStyleProp(element, 'background-color', effect.options.restoreColor);
+ }
+ });
+};
+
+Spry.Effect.Highlight.prototype = new Spry.Effect.Cluster();
+Spry.Effect.Highlight.prototype.constructor = Spry.Effect.Highlight;
+
+Spry.Effect.Slide = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Slide');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ this.name = 'Slide';
+ var element = Spry.Effect.getElement(element);
+ this.element = element;
+ if (!this.element)
+ return;
+ var durationInMilliseconds = 1000;
+ var doToggle = false;
+ var kindOfTransition = Spry.sinusoidalTransition;
+ var fps = 60;
+ var slideHorizontally = false;
+ var firstChildElt = Spry.Effect.Utils.getFirstChildElement(element);
+ var direction = -1;
+
+ // IE 7 does not clip static positioned elements -> make element position relative
+ if(/MSIE 7.0/.test(navigator.userAgent) && /Windows NT/.test(navigator.userAgent))
+ Spry.Effect.makePositioned(element);
+
+ Spry.Effect.makeClipping(element);
+
+ // for IE 6 on win: check if position is static or fixed -> not supported and would cause trouble
+ if(/MSIE 6.0/.test(navigator.userAgent) && /Windows NT/.test(navigator.userAgent))
+ {
+ var pos = Spry.Effect.getStyleProp(element, 'position');
+ if(pos && (pos == 'static' || pos == 'fixed'))
+ {
+ Spry.Effect.setStyleProp(element, 'position', 'relative');
+ Spry.Effect.setStyleProp(element, 'top', '');
+ Spry.Effect.setStyleProp(element, 'left', '');
+ }
+ }
+
+ if(firstChildElt)
+ {
+ Spry.Effect.makePositioned(firstChildElt);
+ Spry.Effect.makeClipping(firstChildElt);
+
+ var childRect = Spry.Effect.getDimensionsRegardlessOfDisplayState(firstChildElt, element);
+ Spry.Effect.setStyleProp(firstChildElt, 'width', childRect.width + 'px');
+ }
+
+ var fromDim = Spry.Effect.getDimensionsRegardlessOfDisplayState(element);
+
+ var initDim = new Spry.Effect.Utils.Rectangle();
+ var toDim = new Spry.Effect.Utils.Rectangle();
+ initDim.width = toDim.width = fromDim.width;
+ initDim.height = toDim.height = fromDim.height;
+
+ if (!this.options.to){
+ if (!options)
+ options = {};
+
+ options.to = '0%';
+ }
+
+ if (options && options.horizontal !== null && options.horizontal === true)
+ slideHorizontally = true;
+
+ if (options.duration != null) durationInMilliseconds = options.duration;
+
+ if (options.from != null)
+ {
+ if(slideHorizontally)
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.from))
+ fromDim.width = initDim.width * Spry.Effect.Utils.getPercentValue(options.from) / 100;
+ else
+ fromDim.width = Spry.Effect.Utils.getPixelValue(options.from);
+ }
+ else
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.from))
+ fromDim.height = initDim.height * Spry.Effect.Utils.getPercentValue(options.from) / 100;
+ else
+ fromDim.height = Spry.Effect.Utils.getPixelValue(options.from);
+ }
+ }
+
+ if (options.to != null)
+ {
+ if(slideHorizontally)
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.to))
+ toDim.width = initDim.width * Spry.Effect.Utils.getPercentValue(options.to) / 100;
+ else
+ toDim.width = Spry.Effect.Utils.getPixelValue(options.to);
+ }
+ else
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.to))
+ toDim.height = initDim.height * Spry.Effect.Utils.getPercentValue(options.to) / 100;
+ else
+ toDim.height = Spry.Effect.Utils.getPixelValue(options.to);
+ }
+ }
+ if (options.toggle != null) doToggle = options.toggle;
+ if (options.transition != null) kindOfTransition = options.transition;
+ if (options.fps != null) fps = options.fps;
+
+ options = {duration: durationInMilliseconds, transition: kindOfTransition, scaleContent: false, toggle:doToggle, fps: fps};
+ var size = new Spry.Effect.Size(element, fromDim, toDim, options);
+ this.addParallelEffect(size);
+
+ if ( (fromDim.width < toDim.width && slideHorizontally) || (fromDim.height < toDim.height && !slideHorizontally))
+ direction = 1;
+
+ var fromPos = new Spry.Effect.Utils.Position();
+ var toPos = new Spry.Effect.Utils.Position();
+ toPos.x = fromPos.x = Spry.Effect.intPropStyle(firstChildElt, 'left');
+ toPos.y = fromPos.y = Spry.Effect.intPropStyle(firstChildElt, 'top');
+ toPos.units = fromPos.units;
+
+ if (slideHorizontally)
+ toPos.x = parseInt(fromPos.x + direction * (fromDim.width - toDim.width), 10);
+ else
+ toPos.y = parseInt(fromPos.y + direction * (fromDim.height - toDim.height), 10);
+
+ if (direction == 1){
+ var tmp = fromPos;
+ var fromPos = toPos;
+ var toPos = tmp;
+ }
+
+ options = {duration: durationInMilliseconds, transition: kindOfTransition, toggle:doToggle, from: fromPos, to: toPos, fps: fps};
+ var move = new Spry.Effect.Move(firstChildElt, fromPos, toPos, options);
+ this.addParallelEffect(move);
+};
+
+Spry.Effect.Slide.prototype = new Spry.Effect.Cluster();
+Spry.Effect.Slide.prototype.constructor = Spry.Effect.Slide;
+
+Spry.Effect.Grow = function (element, options)
+{
+ if (!element)
+ return;
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Grow');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ this.name = 'Grow';
+ var durationInMilliseconds = 1000;
+ var doToggle = false;
+ var doScaleContent = true;
+ var calcHeight = false;
+ var growFromCenter = true;
+ var fullCSSBox = false;
+ var kindOfTransition = Spry.squareTransition;
+ var fps = 60;
+ var element = Spry.Effect.getElement(element);
+ this.element = element;
+ if (!this.element)
+ return;
+
+ Spry.Effect.makeClipping(element);
+
+ var dimRect = Spry.Effect.getDimensionsRegardlessOfDisplayState(element);
+ var originalWidth = dimRect.width;
+ var originalHeight = dimRect.height;
+ var propFactor = (originalWidth == 0) ? 1 :originalHeight/originalWidth;
+
+ var fromRect = new Spry.Effect.Utils.Rectangle;
+ fromRect.width = 0;
+ fromRect.height = 0;
+
+ var toRect = new Spry.Effect.Utils.Rectangle;
+ toRect.width = originalWidth;
+ toRect.height = originalHeight;
+
+ var optionFrom = options ? options.from : dimRect.width;
+ var optionTo = options ? options.to : 0;
+ var pixelValue = Spry.Effect.Utils.getPixelValue;
+
+ if (options)
+ {
+ if (options.growCenter != null) growFromCenter = options.growCenter;
+ if (options.duration != null) durationInMilliseconds = options.duration;
+ if (options.useCSSBox != null) fullCSSBox = options.useCSSBox;
+ if (options.scaleContent != null) doScaleContent = options.scaleContent;
+ if (options.from != null)
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.from))
+ {
+ fromRect.width = originalWidth * (Spry.Effect.Utils.getPercentValue(options.from) / 100);
+ fromRect.height = originalHeight * (Spry.Effect.Utils.getPercentValue(options.from) / 100);
+ }
+ else
+ {
+ if(calcHeight)
+ {
+ fromRect.height = pixelValue(options.from);
+ fromRect.width = pixelValue(options.from) / propFactor;
+ }
+ else
+ {
+ fromRect.width = pixelValue(options.from);
+ fromRect.height = propFactor * pixelValue(options.from);
+ }
+ }
+ }
+ if (options.to != null)
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.to))
+ {
+ toRect.width = originalWidth * (Spry.Effect.Utils.getPercentValue(options.to) / 100);
+ toRect.height = originalHeight * (Spry.Effect.Utils.getPercentValue(options.to) / 100);
+ }
+ else
+ {
+ if(calcHeight)
+ {
+ toRect.height = pixelValue(options.to);
+ toRect.width = pixelValue(options.to) / propFactor;
+ }
+ else
+ {
+ toRect.width = pixelValue(options.to);
+ toRect.height = propFactor * pixelValue(options.to);
+ }
+ }
+ }
+ if (options.toggle != null) doToggle = options.toggle;
+ if (options.transition != null) kindOfTransition = options.transition;
+ if (options.fps != null) fps = options.fps;
+ }
+
+ options = {duration:durationInMilliseconds, toggle:doToggle, transition:kindOfTransition, scaleContent:doScaleContent, useCSSBox: fullCSSBox, fps: fps};
+ var sizeEffect = new Spry.Effect.Size(element, fromRect, toRect, options);
+ this.addParallelEffect(sizeEffect);
+
+ if(growFromCenter)
+ {
+ Spry.Effect.makePositioned(element);
+
+ var startOffsetPosition = new Spry.Effect.Utils.Position();
+ startOffsetPosition.x = parseInt(Spry.Effect.getStylePropRegardlessOfDisplayState(element, "left"), 10);
+ startOffsetPosition.y = parseInt(Spry.Effect.getStylePropRegardlessOfDisplayState(element, "top"), 10);
+ if (!startOffsetPosition.x) startOffsetPosition.x = 0;
+ if (!startOffsetPosition.y) startOffsetPosition.y = 0;
+
+ options = {duration:durationInMilliseconds, toggle:doToggle, transition:kindOfTransition, from: optionFrom, to: optionTo, fps: fps};
+ var fromPos = new Spry.Effect.Utils.Position;
+ fromPos.x = startOffsetPosition.x + (originalWidth - fromRect.width) / 2.0;
+ fromPos.y = startOffsetPosition.y + (originalHeight - fromRect.height) / 2.0;
+
+ var toPos = new Spry.Effect.Utils.Position;
+ toPos.x = startOffsetPosition.x + (originalWidth - toRect.width) / 2.0;
+ toPos.y = startOffsetPosition.y + (originalHeight - toRect.height) / 2.0;
+
+ var moveEffect = new Spry.Effect.Move(element, fromPos, toPos, options);
+ this.addParallelEffect(moveEffect);
+ }
+};
+
+Spry.Effect.Grow.prototype = new Spry.Effect.Cluster();
+Spry.Effect.Grow.prototype.constructor = Spry.Effect.Grow;
+
+Spry.Effect.Shake = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Shake');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ // toggle is not supported
+ this.options.direction = false;
+ if (this.options.toggle)
+ this.options.toggle = false;
+
+ this.name = 'Shake';
+
+ var element = Spry.Effect.getElement(element);
+ this.element = element;
+ if (!this.element)
+ return;
+ var durationInMilliseconds = 100;
+ var kindOfTransition = Spry.linearTransition;
+ var fps = 60;
+ var steps = 4;
+
+ if (options)
+ {
+ if (options.duration != null) steps = Math.ceil(this.options.duration / durationInMilliseconds) - 1;
+ if (options.fps != null) fps = options.fps;
+ if (options.transition != null) kindOfTransition = options.transition;
+ }
+
+ Spry.Effect.makePositioned(element);
+
+ var startOffsetPosition = new Spry.Effect.Utils.Position();
+ startOffsetPosition.x = parseInt(Spry.Effect.getStyleProp(element, "left"), 10);
+ startOffsetPosition.y = parseInt(Spry.Effect.getStyleProp(element, "top"), 10);
+ if (!startOffsetPosition.x) startOffsetPosition.x = 0;
+ if (!startOffsetPosition.y) startOffsetPosition.y = 0;
+
+ var centerPos = new Spry.Effect.Utils.Position;
+ centerPos.x = startOffsetPosition.x;
+ centerPos.y = startOffsetPosition.y;
+
+ var rightPos = new Spry.Effect.Utils.Position;
+ rightPos.x = startOffsetPosition.x + 20;
+ rightPos.y = startOffsetPosition.y + 0;
+
+ var leftPos = new Spry.Effect.Utils.Position;
+ leftPos.x = startOffsetPosition.x + -20;
+ leftPos.y = startOffsetPosition.y + 0;
+
+ options = {duration:Math.ceil(durationInMilliseconds / 2), toggle:false, fps: fps, transition: kindOfTransition};
+ var effect = new Spry.Effect.Move(element, centerPos, rightPos, options);
+ this.addNextEffect(effect);
+
+ options = {duration:durationInMilliseconds, toggle:false, fps:fps, transition: kindOfTransition};
+ var effectToRight = new Spry.Effect.Move(element, rightPos, leftPos, options);
+ var effectToLeft = new Spry.Effect.Move(element, leftPos, rightPos, options);
+
+ for (var i=0; i < steps; i++)
+ {
+ if (i % 2 == 0)
+ this.addNextEffect(effectToRight);
+ else
+ this.addNextEffect(effectToLeft);
+ }
+ var pos = (steps % 2 == 0) ? rightPos: leftPos;
+
+ options = {duration:Math.ceil(durationInMilliseconds / 2), toggle:false, fps: fps, transition: kindOfTransition};
+ var effect = new Spry.Effect.Move(element, pos, centerPos, options);
+ this.addNextEffect(effect);
+};
+Spry.Effect.Shake.prototype = new Spry.Effect.Cluster();
+Spry.Effect.Shake.prototype.constructor = Spry.Effect.Shake;
+Spry.Effect.Shake.prototype.doToggle = function(){};
+
+Spry.Effect.Squish = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Squish');
+
+ if (!options)
+ options = {};
+ if (!options.to)
+ options.to = '0%';
+ if (!options.from)
+ options.from = '100%';
+
+ options.growCenter = false;
+ Spry.Effect.Grow.call(this, element, options);
+ this.name = 'Squish';
+};
+Spry.Effect.Squish.prototype = new Spry.Effect.Grow();
+Spry.Effect.Squish.prototype.constructor = Spry.Effect.Squish;
+
+Spry.Effect.Pulsate = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Pulsate');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ // toggle is not supported
+ this.options.direction = false;
+ if (this.options.toggle)
+ this.options.toggle = false;
+
+ var element = Spry.Effect.getElement(element);
+ var originalOpacity = 0;
+ this.element = element;
+ if (!this.element)
+ return;
+
+ this.name = 'Pulsate';
+ var durationInMilliseconds = 100;
+ var fromOpacity = 100.0;
+ var toOpacity = 0.0;
+ var doToggle = false;
+ var kindOfTransition = Spry.linearTransition;
+ var fps = 60;
+ if(/MSIE/.test(navigator.userAgent))
+ originalOpacity = parseInt(Spry.Effect.getStylePropRegardlessOfDisplayState(this.element, 'filter').replace(/alpha\(opacity=([0-9]{1,3})\)/g, '$1'), 10);
+ else
+ originalOpacity = parseInt(Spry.Effect.getStylePropRegardlessOfDisplayState(this.element, 'opacity') * 100, 10);
+
+ if (isNaN(originalOpacity)){
+ originalOpacity = 100;
+ }
+
+ if (options)
+ {
+ if (options.from != null){
+ if (Spry.Effect.Utils.isPercentValue(options.from))
+ fromOpacity = Spry.Effect.Utils.getPercentValue(options.from) * originalOpacity / 100;
+ else
+ fromOpacity = options.from;
+ }
+ if (options.to != null)
+ {
+ if (Spry.Effect.Utils.isPercentValue(options.to))
+ toOpacity = Spry.Effect.Utils.getPercentValue(options.to) * originalOpacity / 100;
+ else
+ toOpacity = options.to;
+ }
+ if (options.transition != null) kindOfTransition = options.transition;
+ if (options.fps != null) fps = options.fps;
+ }
+
+ options = {duration:durationInMilliseconds, toggle:doToggle, transition:kindOfTransition, fps:fps};
+ fromOpacity = fromOpacity / 100.0;
+ toOpacity = toOpacity / 100.0;
+
+ var fadeEffect = new Spry.Effect.Opacity(element, fromOpacity, toOpacity, options);
+ var appearEffect = new Spry.Effect.Opacity(element, toOpacity, fromOpacity, options);
+ var steps = parseInt(this.options.duration / 200, 10);
+ for (var i=0; i < steps; i++){
+ this.addNextEffect(fadeEffect);
+ this.addNextEffect(appearEffect);
+ }
+};
+Spry.Effect.Pulsate.prototype = new Spry.Effect.Cluster();
+Spry.Effect.Pulsate.prototype.constructor = Spry.Effect.Pulsate;
+Spry.Effect.Pulsate.prototype.doToggle = function(){};
+
+Spry.Effect.Puff = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Puff');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ var element = Spry.Effect.getElement(element);
+ this.element = element;
+ if (!this.element)
+ return;
+ this.name = 'Puff';
+ var doToggle = false;
+ var doScaleContent = false;
+ var durationInMilliseconds = 1000;
+ var kindOfTransition = Spry.fifthTransition;
+ var fps = 60;
+
+ Spry.Effect.makePositioned(element); // for move
+
+ if (options){
+ if (options.toggle != null) doToggle = options.toggle;
+ if (options.duration != null) durationInMilliseconds = options.duration;
+ if (options.transition != null) kindOfTransition = options.transition;
+ if (options.fps != null) fps = options.fps;
+ }
+ var originalRect = Spry.Effect.getDimensions(element);
+ var startWidth = originalRect.width;
+ var startHeight = originalRect.height;
+
+ options = {duration:durationInMilliseconds, toggle:doToggle, transition: kindOfTransition, fps: fps};
+
+ var fromOpacity = 1.0;
+ var toOpacity = 0.0;
+ var opacityEffect = new Spry.Effect.Opacity(element, fromOpacity, toOpacity, options);
+ this.addParallelEffect(opacityEffect);
+
+ var fromPos = Spry.Effect.getPosition(element);
+
+ var toPos = new Spry.Effect.Utils.Position;
+ toPos.x = startWidth / 2.0 * -1.0;
+ toPos.y = startHeight / 2.0 * -1.0;
+
+ options = {duration:durationInMilliseconds, toggle:doToggle, transition:kindOfTransition, from: fromPos, to: toPos, fps: fps};
+ var moveEffect = new Spry.Effect.Move(element, fromPos, toPos, options);
+ this.addParallelEffect(moveEffect);
+
+ var self = this;
+ this.addObserver({
+ onPreEffect:function(){if (self.direction == Spry.backwards){self.element.style.display = 'block';}},
+ onPostEffect: function(){if (self.direction == Spry.forwards){self.element.style.display = 'none';}}
+ });
+};
+Spry.Effect.Puff.prototype = new Spry.Effect.Cluster;
+Spry.Effect.Puff.prototype.constructor = Spry.Effect.Puff;
+
+Spry.Effect.DropOut = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('DropOut');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ var element = Spry.Effect.getElement(element);
+ this.element = element;
+ if (!this.element)
+ return;
+ var durationInMilliseconds = 1000;
+ var fps = 60;
+ var kindOfTransition = Spry.fifthTransition;
+ var direction = Spry.forwards;
+ var doToggle = false;
+ this.name = 'DropOut';
+
+ Spry.Effect.makePositioned(element);
+
+ if (options)
+ {
+ if (options.duration != null) durationInMilliseconds = options.duration;
+ if (options.toggle != null) doToggle = options.toggle;
+ if (options.fps != null) fps = options.fps;
+ if (options.transition != null) kindOfTransition = options.transition;
+ if (options.dropIn != null) direction = -1;
+ }
+
+ var startOffsetPosition = new Spry.Effect.Utils.Position();
+ startOffsetPosition.x = parseInt(Spry.Effect.getStyleProp(element, "left"), 10);
+ startOffsetPosition.y = parseInt(Spry.Effect.getStyleProp(element, "top"), 10);
+ if (!startOffsetPosition.x) startOffsetPosition.x = 0;
+ if (!startOffsetPosition.y) startOffsetPosition.y = 0;
+
+ var fromPos = new Spry.Effect.Utils.Position;
+ fromPos.x = startOffsetPosition.x + 0;
+ fromPos.y = startOffsetPosition.y + 0;
+
+ var toPos = new Spry.Effect.Utils.Position;
+ toPos.x = startOffsetPosition.x + 0;
+ toPos.y = startOffsetPosition.y + (direction * 160);
+
+ options = {from:fromPos, to:toPos, duration:durationInMilliseconds, toggle:doToggle, transition: kindOfTransition, fps: fps};
+ var moveEffect = new Spry.Effect.Move(element, options.from, options.to, options);
+ this.addParallelEffect(moveEffect);
+
+ var fromOpacity = 1.0;
+ var toOpacity = 0.0;
+ options = {duration:durationInMilliseconds, toggle:doToggle, transition: kindOfTransition, fps: fps};
+ var opacityEffect = new Spry.Effect.Opacity(element, fromOpacity, toOpacity, options);
+ this.addParallelEffect(opacityEffect);
+
+ var self = this;
+ this.addObserver({
+ onPreEffect:function(){self.element.style.display = 'block';},
+ onPostEffect: function(){if (self.direction == Spry.forwards){self.element.style.display = 'none';}}
+ });
+
+};
+Spry.Effect.DropOut.prototype = new Spry.Effect.Cluster();
+Spry.Effect.DropOut.prototype.constructor = Spry.Effect.DropOut;
+
+Spry.Effect.Fold = function (element, options)
+{
+ if (!this.notStaticAnimator)
+ return Spry.Effect.Utils.showInitError('Fold');
+
+ Spry.Effect.Cluster.call(this, options);
+
+ var element = Spry.Effect.getElement(element);
+ this.element = element;
+ if (!this.element)
+ return;
+ this.name = 'Fold';
+ var durationInMilliseconds = 1000;
+ var doToggle = false;
+ var doScaleContent = true;
+ var fullCSSBox = false;
+ var kindOfTransition = Spry.fifthTransition;
+ var fps = fps;
+
+ Spry.Effect.makeClipping(element);
+
+ var originalRect = Spry.Effect.getDimensionsRegardlessOfDisplayState(element);
+ var startWidth = originalRect.width;
+ var startHeight = originalRect.height;
+
+ var stopWidth = startWidth;
+ var stopHeight = startHeight / 5;
+
+ var fromRect = new Spry.Effect.Utils.Rectangle;
+ fromRect.width = startWidth;
+ fromRect.height = startHeight;
+
+ var toRect = new Spry.Effect.Utils.Rectangle;
+ toRect.width = stopWidth;
+ toRect.height = stopHeight;
+
+ if (options)
+ {
+ if (options.duration != null) durationInMilliseconds = Math.ceil(options.duration/2);
+ if (options.toggle != null) doToggle = options.toggle;
+ if (options.useCSSBox != null) fullCSSBox = options.useCSSBox;
+ if (options.fps != null) fps = options.fps;
+ if (options.transition != null) kindOfTransition = options.transition;
+ }
+
+ options = {duration:durationInMilliseconds, toggle:doToggle, scaleContent:doScaleContent, useCSSBox: fullCSSBox, transition: kindOfTransition, fps: fps};
+ var sizeEffect = new Spry.Effect.Size(element, fromRect, toRect, options);
+ this.addNextEffect(sizeEffect);
+
+ fromRect.width = toRect.width;
+ fromRect.height = toRect.height;
+ toRect.width = '0%';
+ var sizeEffect = new Spry.Effect.Size(element, fromRect, toRect, options);
+ this.addNextEffect(sizeEffect);
+};
+
+Spry.Effect.Fold.prototype = new Spry.Effect.Cluster();
+Spry.Effect.Fold.prototype.constructor = Spry.Effect.Fold;
+
+//////////////////////////////////////////////////////////////
+// //
+// The names of some of the static effect functions //
+// changed in Spry 1.5. These wrappers will insure that we //
+// remain compatible with previous versions of Spry. //
+// //
+//////////////////////////////////////////////////////////////
+
+Spry.Effect.DoFade = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Fade', element, options);
+};
+
+Spry.Effect.DoBlind = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Blind', element, options);
+};
+
+Spry.Effect.DoHighlight = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Highlight', element, options);
+};
+
+Spry.Effect.DoSlide = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Slide', element, options);
+};
+
+Spry.Effect.DoGrow = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Grow', element, options);
+};
+
+Spry.Effect.DoShake = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Shake', element, options);
+};
+
+Spry.Effect.DoSquish = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Squish', element, options);
+};
+
+Spry.Effect.DoPulsate = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Pulsate', element, options);
+};
+
+Spry.Effect.DoPuff = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Puff', element, options);
+};
+
+Spry.Effect.DoDropOut = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('DropOut', element, options);
+};
+
+Spry.Effect.DoFold = function (element, options)
+{
+ return Spry.Effect.Utils.DoEffect('Fold', element, options);
+};
diff --git a/1.6.1/SpryProgressBar.js b/1.6.1/SpryProgressBar.js
new file mode 100644
index 0000000..bcf24a6
--- /dev/null
+++ b/1.6.1/SpryProgressBar.js
@@ -0,0 +1,193 @@
+Spry.Widget.ProgressBar = function( element, opts ){
+ var that = this;
+
+ Spry.Utils.Notifier.call(this);
+
+ Spry.Utils.setOptions(this, Spry.Widget.ProgressBar.config);
+
+ Spry.Utils.setOptions(this, opts);
+
+ this.version = "0.1.0"; // version number pattern: major, minor, bugfix
+ this.element = Spry.$$( element )[0];
+ this.bar = Spry.$$( "." + this.barClass, this.element );
+ this.initialWidth = Spry.Effect.getDimensionsRegardlessOfDisplayState( this.bar[0], this.displayElement || this.bar[0] ).width;
+ this.currentWidth = this.initialWidth;
+ this.counter = 0;
+
+ // forces the bar to its default size
+ this.bar[0].style.width = (this.currentWidth = this.initialWidth / 100 * this.percentage);
+
+ if( this.autoStart ){
+ this.setPercentage( 100, this.duration );
+ }
+
+ this.addObserver({
+ onComplete: function(){
+ if( that.hideOnComplete ){
+ that.hide();
+ }
+ }
+ });
+};
+
+// a linear transition
+Spry.Widget.ProgressBar.defaultEaseFunc = function(time, begin, change, duration){
+ if (time > duration) return change + begin;
+ return begin + (time / duration) * change;
+};
+
+Spry.Widget.ProgressBar.config = {
+
+ // initial percentage of the bar
+ percentage: 0,
+
+ // default transition for the effect
+ transition: Spry.Widget.ProgressBar.defaultEaseFunc,
+
+ // the default length of the animation
+ duration: 2E3,
+
+ // is the widget enabled or disabled
+ autoStart: false,
+
+ // if the progress bar should be hidden once it's completed
+ hideOnComplete: true,
+
+ // what className is used for the bar
+ barClass: "bar"
+};
+
+Spry.Widget.ProgressBar.prototype = new Spry.Utils.Notifier();
+Spry.Widget.ProgressBar.prototype.constructor = Spry.Widget.ProgressBar;
+
+Spry.Widget.ProgressBar.prototype.setPercentage = function( percentage, duration, callback ){
+ // makesure its a valid value
+ percentage = this.cleanPercentage ( percentage );
+ duration = duration || this.duration;
+
+ var that = this,
+ // are we increasing or decreasing
+ increase = percentage >= this.percentage,
+
+ // target width
+ to = this.initialWidth / 100 * percentage,
+
+ // diffence between the current and new percentage
+ difference = increase ? percentage - this.percentage : this.percentage - percentage;
+
+ // create sliding effect
+ this.effect = new Spry.Effect.Slide( this.bar[0], {
+ duration: duration,
+ from: Spry.Effect.getDimensionsRegardlessOfDisplayState( this.bar[0] ).width + "px",
+ to: to + "px",
+ horizontal: true,
+ transition: this.transition,
+ finish: callback || null
+ });
+
+ this.currentWidth = to;
+ this.percentage = percentage;
+
+ // add events to the effect so we can fire off our custom notifications as well
+ this.effect.addObserver({
+ onPostEffect: function(){
+ if( that.percentage === 100 ){
+ that.notifyObservers( "onComplete" ); // the progressbar has been completed
+ }
+
+ // we set the percentage
+ that.notifyObservers( "onPercentageChanged", ( that.counter = percentage ) );
+ that.notifyObservers( "onPercentageSet", that.percentage );
+ },
+
+ onStep: function( effect, info ){
+ if( info.getElapsedMilliseconds() >= effect.increase && !( that.counter >= 100 ) ){
+ effect.increase = effect.avg + effect.increase;
+
+ var _percent = Math.floor( info.getElapsedMilliseconds() / effect.avg ),
+ _difference;
+
+ if( !effect.percent || effect.percent < _percent ){
+ _difference = _percent - effect.percent || 1;
+ effect.percent = _percent;
+
+ that.notifyObservers(
+ "onPercentageChanged",
+ (
+ that.counter = that.cleanPercentage(
+ increase ? ( that.counter + _difference ) : ( that.counter - _difference)
+ )
+ )
+ );
+ }
+ }
+ }
+ });
+
+ // calculate the elapsed when the percentage needs to increased
+ this.effect.avg = this.effect.increase= Math.round( duration / difference );
+
+ // run the animation
+ this.effect.start();
+};
+
+// prevent race conditions, so you can stop them at will...
+Spry.Widget.ProgressBar.prototype.stop = function(){
+ this.effect.stop();
+};
+
+// when you stop, you might want to start it again.. go figure :0
+Spry.Widget.ProgressBar.prototype.start = function(){
+ this.effect.start();
+};
+
+// increase the value of the progress
+Spry.Widget.ProgressBar.prototype.add = function( percentage, duration ){
+ percentage = percentage ? this.cleanPercentage( percentage ) : 5;
+ this.setPercentage( this.counter + percentage, duration );
+};
+
+// decrease the value of the progress
+Spry.Widget.ProgressBar.prototype.remove = function( percentage, duration ){
+ percentage = percentage ? this.cleanPercentage( percentage ) : 5;
+ this.setPercentage( this.counter - percentage, duration );
+};
+
+// reset the progress bar back to 0;
+Spry.Widget.ProgressBar.prototype.reset = function( ){
+ var that = this;
+
+ if( this.hidden ){
+ this.show();
+ }
+
+ this.counter = 0;
+ this.setPercentage( 0, 1, function(){ that.notifyObservers( "onReset" ); });
+};
+
+// complete the progress bar, fast
+Spry.Widget.ProgressBar.prototype.complete = function( duration ){
+ this.setPercentage( 100, duration || 200 );
+};
+
+// cleans out the percentage, parses down 100% to 100 and makes sure its between 0 and 100;
+Spry.Widget.ProgressBar.prototype.cleanPercentage = function( value ){
+ value = typeof value === "number" ? value : parseFloat( value.replace(/\%/g, '' ) );
+ return value > 100 ? 100 : (value < 0 ? 0 : value); // percentage can't be higher than 100%
+};
+
+// returns the current percentage or the expected percentage
+Spry.Widget.ProgressBar.prototype.getPercentage = function( total ){
+ return total ? this.percentage : this.counter;
+};
+
+// shows the widget
+Spry.Widget.ProgressBar.prototype.show = function(){
+ this.element.style.display = "";
+ this.hidden = false;
+};
+
+Spry.Widget.ProgressBar.prototype.hide = function(){
+ this.element.style.display = "none";
+ this.hidden = true;
+};
\ No newline at end of file
diff --git a/1.7/SpryDOMEffects.js b/1.7/SpryDOMEffects.js
new file mode 100644
index 0000000..cd7d336
--- /dev/null
+++ b/1.7/SpryDOMEffects.js
@@ -0,0 +1,469 @@
+// SpryDOMEffects.js - version 0.6 - Spry Pre-Release 1.7
+//
+// Copyright (c) 2007. Adobe Systems Incorporated.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Adobe Systems Incorporated nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+(function() { // BeginSpryComponent
+
+if (typeof Spry == "undefined" || !Spry.Utils || !Spry.$$)
+{
+ alert("SpryDOMEffects.js requires SpryDOMUtils.js");
+ return;
+}
+
+if (!Spry.Effect) Spry.Effect = {};
+
+Spry.Effect.Animator = function(opts)
+{
+ Spry.Effect.Animator.Notifier.call(this);
+
+ this.animatorID = Spry.Effect.Animator.nextID++;
+ this.dropFrames = true;
+ this.fps = 60; // frames per-second
+ this.duration = 500; // msecs
+ this.timer = 0;
+ this.startTime = 0; // Used only when dropFrames is true.
+ this.currentFrame = 0;
+ this.easeFunc = Spry.Effect.Animator.defaultEaseFunc;
+ this.stopped = false;
+
+ Spry.Effect.Animator.copyProps(this, opts);
+
+ this.interval = 1000 / this.fps;
+ this.numFrames = (this.duration / 1000) * this.fps;
+
+ if (this.onComplete)
+ {
+ var self = this;
+ this.addObserver({ onAnimationComplete: function(){ self.onComplete(); } });
+ }
+};
+
+Spry.Effect.Animator.nextID = 1;
+
+Spry.Effect.Animator.copyProps = function(dst, src)
+{
+ if (src)
+ {
+ for (prop in src)
+ dst[prop] = src[prop];
+ }
+ return dst;
+};
+
+Spry.Effect.Animator.getElement = function(element)
+{
+ if (arguments.length > 1)
+ {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push(Spry.Effect.Animator.getElement(arguments[i]));
+ return elements;
+ }
+ if (typeof element == 'string')
+ element = document.getElementById(element);
+ return element;
+};
+
+Spry.Effect.Animator.defaultEaseFunc = function(time, begin, finish, duration) { time /= duration; return begin + ((2 - time) * time * finish); };
+
+Spry.Effect.Animator.Notifier = function()
+{
+ this.observers = [];
+ this.suppressNotifications = 0;
+};
+
+Spry.Effect.Animator.Notifier.prototype.addObserver = function(observer)
+{
+ if (!observer)
+ return;
+
+ // Make sure the observer isn't already on the list.
+
+ var len = this.observers.length;
+ for (var i = 0; i < len; i++)
+ {
+ if (this.observers[i] == observer)
+ return;
+ }
+ this.observers[len] = observer;
+};
+
+Spry.Effect.Animator.Notifier.prototype.removeObserver = function(observer)
+{
+ if (!observer)
+ return;
+
+ for (var i = 0; i < this.observers.length; i++)
+ {
+ if (this.observers[i] == observer)
+ {
+ this.observers.splice(i, 1);
+ break;
+ }
+ }
+};
+
+Spry.Effect.Animator.Notifier.prototype.notifyObservers = function(methodName, data)
+{
+ if (!methodName)
+ return;
+
+ if (!this.suppressNotifications)
+ {
+ var len = this.observers.length;
+ for (var i = 0; i < len; i++)
+ {
+ var obs = this.observers[i];
+ if (obs)
+ {
+ if (typeof obs == "function")
+ obs(methodName, this, data);
+ else if (obs[methodName])
+ obs[methodName](this, data);
+ }
+ }
+ }
+};
+
+Spry.Effect.Animator.Notifier.prototype.enableNotifications = function()
+{
+ if (--this.suppressNotifications < 0)
+ {
+ this.suppressNotifications = 0;
+ Spry.Debug.reportError("Unbalanced enableNotifications() call!\n");
+ }
+};
+
+Spry.Effect.Animator.Notifier.prototype.disableNotifications = function()
+{
+ ++this.suppressNotifications;
+};
+
+Spry.Effect.Animator.prototype = new Spry.Effect.Animator.Notifier;
+Spry.Effect.Animator.prototype.constructor = Spry.Effect.Animator;
+
+Spry.Effect.Animator.prototype.start = function()
+{
+ this.stopped = false;
+ this.currentFrame = 0;
+ this.startTime = (new Date()).getTime();
+
+ this.notifyObservers("onAnimationStart");
+
+ var self = this;
+ this.timer = setTimeout(function(){ self.onStepAnimation(); }, this.interval);
+};
+
+Spry.Effect.Animator.prototype.stop = function()
+{
+ if (this.timer)
+ clearTimeout(this.timer);
+ this.timer = 0;
+ this.stopped = true;
+
+ this.notifyObservers("onAnimationStopped");
+};
+
+Spry.Effect.Animator.prototype.onStepAnimation = function()
+{
+ var obj = {};
+
+ if (this.dropFrames)
+ {
+ obj.duration = this.duration;
+ obj.elapsed = ((new Date).getTime()) - this.startTime;
+ if (obj.elapsed > obj.duration)
+ obj.elapsed = obj.duration;
+ }
+ else
+ {
+ obj.duration = this.numFrames;
+ obj.elapsed = ++this.currentFrame;
+ }
+
+ obj.easingConst = this.easeFunc(obj.elapsed, 0, 1, obj.duration)
+
+ this.notifyObservers("onPreDraw", obj);
+ this.draw(obj.elapsed, obj.duration, obj.easingConst);
+ this.notifyObservers("onPostDraw", obj);
+
+ if (!this.stopped)
+ {
+ if (obj.elapsed < obj.duration)
+ {
+ var self = this;
+ this.timer = setTimeout(function(){ self.onStepAnimation(); }, this.interval);
+ }
+ else
+ {
+ this.stop();
+ this.notifyObservers("onAnimationComplete");
+ }
+ }
+};
+
+Spry.Effect.Animator.prototype.draw = function(elapsed, duration, easingConst)
+{
+ // The default draw method does nothing. It is assumed that
+ // derived classes will provide their own implementation of this
+ // method.
+
+ debug.log("elapsed: " + elapsed + " -- duration: " + duration + " -- easingConst: " + easingConst);
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+Spry.Effect.CSSAnimator = function(elements, styleStr, opts)
+{
+ this.animationSets = [];
+
+ Spry.Effect.Animator.call(this, opts);
+
+ this.add(elements, styleStr);
+};
+
+Spry.Effect.CSSAnimator.prototype = new Spry.Effect.Animator();
+Spry.Effect.CSSAnimator.prototype.constructor = Spry.Effect.CSSAnimator;
+
+Spry.Effect.CSSAnimator.prototype.add = function(elements, styleStr)
+{
+ // The first argument for the CSSAnimator can be
+ // the id of an element, an element node, or an array of
+ // elements and/or ids.
+
+ elements = Spry.$$(elements);
+
+ if (elements.length < 1)
+ return;
+
+ var animSet = { elements: elements, cssProps: []};
+
+ this.animationSets.push(animSet);
+
+ // Convert the styleStr into an object.
+
+ var toObj = Spry.Utils.styleStringToObject(styleStr);
+ for (var p in toObj)
+ {
+ var obj = new Object;
+ var v = toObj[p];
+ obj.value = new Number(v.replace(/[^-\d\.]+/g, ""));
+ obj.units = v.replace(/[-\d+\.]/g, "");
+ toObj[p] = obj;
+ }
+
+ for (var i = 0; i < elements.length; i++)
+ {
+ var obj = animSet.cssProps[i] = new Object;
+ for (var p in toObj)
+ {
+ var pFuncs = Spry.Effect.CSSAnimator.stylePropFuncs[p];
+ if (!pFuncs)
+ pFuncs = Spry.Effect.CSSAnimator.stylePropFuncs["default"];
+
+ obj[p] = new Object;
+ obj[p].from = new Number(pFuncs.get(elements[i], p).replace(/[^-\d\.]+/g, ""));
+ obj[p].to = toObj[p].value;
+ obj[p].distance = obj[p].to - obj[p].from;
+ obj[p].units = toObj[p].units;
+ }
+ }
+};
+
+Spry.Effect.CSSAnimator.prototype.start = function()
+{
+ for (var s = 0; s < this.animationSets.length; s++)
+ {
+ var animSet = this.animationSets[s];
+ var elements = animSet.elements;
+ var cssProps = animSet.cssProps;
+
+ for (var i = 0; i < elements.length; i++)
+ {
+ var ele = elements[i];
+
+ var eleProps = ele.spryCSSAnimatorProps;
+ if (!eleProps)
+ eleProps = ele.spryCSSAnimatorProps = new Object;
+
+ var obj = cssProps[i];
+ for (var p in obj)
+ eleProps[p] = this.animatorID;
+ }
+ }
+
+ return Spry.Effect.Animator.prototype.start.call(this);
+};
+
+Spry.Effect.CSSAnimator.prototype.stop = function()
+{
+ for (var s = 0; s < this.animationSets.length; s++)
+ {
+ var animSet = this.animationSets[s];
+ var elements = animSet.elements;
+ var cssProps = animSet.cssProps;
+
+ for (var i = 0; i < elements.length; i++)
+ {
+ var ele = elements[i];
+ var obj = cssProps[i];
+
+ var eleProps = ele.spryCSSAnimatorProps;
+ for (var p in obj)
+ {
+ if (eleProps[p] == this.animatorID)
+ delete eleProps[p];
+ }
+ }
+ }
+
+ return Spry.Effect.Animator.prototype.stop.call(this);
+};
+
+Spry.Effect.CSSAnimator.prototype.draw = function(elapsed, duration, easingConst)
+{
+ for (var s = 0; s < this.animationSets.length; s++)
+ {
+ var animSet = this.animationSets[s];
+ var elements = animSet.elements;
+ var cssProps = animSet.cssProps;
+
+ for (var i = 0; i < elements.length; i++)
+ {
+ var ele = elements[i];
+ var eleProps = ele.spryCSSAnimatorProps;
+ var obj = cssProps[i];
+ for (var p in obj)
+ {
+ if (eleProps[p] == this.animatorID)
+ {
+ var pFuncs = Spry.Effect.CSSAnimator.stylePropFuncs[p];
+ if (!pFuncs)
+ pFuncs = Spry.Effect.CSSAnimator.stylePropFuncs["default"];
+
+ if (elapsed > duration)
+ pFuncs.set(ele, p, obj[p].to + obj[p].units);
+ else
+ pFuncs.set(ele, p, obj[p].from + (obj[p].distance * easingConst) + obj[p].units);
+ }
+ }
+ }
+ }
+};
+
+Spry.Effect.CSSAnimator.stylePropFuncs = {};
+
+Spry.Effect.CSSAnimator.stylePropFuncs["default"] = {
+ get: function(ele, prop)
+ {
+ return ele.style[prop];
+ },
+
+ set: function(ele, prop, val)
+ {
+ ele.style[prop] = val;
+ }
+};
+
+Spry.Effect.CSSAnimator.stylePropFuncs["opacity"] = {
+ get: function(ele, prop)
+ {
+ var val = 1;
+
+ if (ele.style.opacity)
+ val = ele.style.opacity;
+ else if (ele.style.filter)
+ {
+ var strVal = ele.style.filter.replace(/.*alpha\(opacity=(\d+)\).*/, "$1");
+ if (strVal)
+ val = parseInt(strVal) / 100;
+ }
+ return val + "";
+ },
+
+ set: function(ele, prop, val)
+ {
+ ele.style.opacity = "" + val;
+ ele.style.filter = "alpha(opacity=" + (val * 100) + ")";
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+Spry.$$.Results.defaultEaseFunc = function(time, begin, finish, duration) { time /= duration; return begin + ((2 - time) * time * finish); };
+
+Spry.$$.Results.animatePropertyTo = function(propName, to, options)
+{
+ var opts = { interval: 10, duration: 1000, onComplete: null, transition: Spry.$$.Results.defaultEaseFunc };
+ Spry.Effect.Animator.copyProps(opts, options);
+
+ var objs = [];
+ for (var i = 0; i < this.length; i++)
+ {
+ var obj = objs[i] = new Object;
+ obj.ele = this[i];
+ obj.from = obj.ele[propName];
+ obj.distance = to - obj.from;
+ }
+
+ var startTime = (new Date).getTime();
+
+ var animateFunc = function()
+ {
+ var elapsedTime = ((new Date).getTime()) - startTime;
+
+ if (elapsedTime > opts.duration)
+ {
+ for (var i = 0; i < objs.length; i++)
+ objs[i].ele[propName] = to;
+ if (opts.onComplete)
+ opts.onComplete();
+ }
+ else
+ {
+ for (var i = 0; i < objs.length; i++)
+ {
+ var obj = objs[i];
+ obj.ele[propName] = opts.transition(elapsedTime, obj.from, obj.distance, opts.duration);
+ }
+ setTimeout(animateFunc, opts.interval);
+ }
+ };
+
+ setTimeout(animateFunc, opts.interval);
+ return this;
+};
+
+Spry.$$.Results.animateStyleTo = function(styleStr, options)
+{
+ var a = new Spry.Effect.CSSAnimator(this, styleStr, options);
+ a.start();
+ return this;
+};
+
+})(); // EndSpryComponent
\ No newline at end of file
diff --git a/1.7/SpryDOMUtils.js b/1.7/SpryDOMUtils.js
new file mode 100644
index 0000000..f5103de
--- /dev/null
+++ b/1.7/SpryDOMUtils.js
@@ -0,0 +1,1158 @@
+// SpryDOMUtils.js - version 0.12 - Spry Pre-Release 1.7
+//
+// Copyright (c) 2007. Adobe Systems Incorporated.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Adobe Systems Incorporated nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+(function() { // BeginSpryComponent
+
+if (typeof Spry == "undefined") window.Spry = {}; if (!Spry.Utils) Spry.Utils = {};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Define Prototype's $() convenience function, but make sure it is
+// namespaced under Spry so that we avoid collisions with other
+// toolkits.
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.$ = function(element)
+{
+ if (arguments.length > 1)
+ {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push(Spry.$(arguments[i]));
+ return elements;
+ }
+ if (typeof element == 'string')
+ element = document.getElementById(element);
+ return element;
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// DOM Utils
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.Utils.getAttribute = function(ele, name)
+{
+ ele = Spry.$(ele);
+ if (!ele || !name)
+ return null;
+
+ // We need to wrap getAttribute with a try/catch because IE will throw
+ // an exception if you call it with a namespace prefixed attribute name
+ // that doesn't exist.
+
+ try { var value = ele.getAttribute(name); }
+ catch (e) { value == undefined; }
+
+ // XXX: Workaround for Safari 2.x and earlier:
+ //
+ // If value is undefined, the attribute didn't exist. Check to see if this is
+ // a namespace prefixed attribute name. If it is, remove the ':' from the name
+ // and try again. This allows us to support spry attributes of the form
+ // "spry:region" and "spryregion".
+
+ if (value == undefined && name.search(/:/) != -1)
+ {
+ try { var value = ele.getAttribute(name.replace(/:/, "")); }
+ catch (e) { value == undefined; }
+ }
+
+ return value;
+};
+
+Spry.Utils.setAttribute = function(ele, name, value)
+{
+ ele = Spry.$(ele);
+ if (!ele || !name)
+ return;
+
+ // IE doesn't allow you to set the "class" attribute. You
+ // have to set the className property instead.
+
+ if (name == "class")
+ ele.className = value;
+ else
+ {
+ // I'm probably being a bit paranoid, but given the fact that
+ // getAttribute() throws exceptions when dealing with namespace
+ // prefixed attributes, I'm going to wrap this setAttribute()
+ // call with try/catch just in case ...
+
+ try { ele.setAttribute(name, value); } catch(e) {}
+
+ // XXX: Workaround for Safari 2.x and earlier:
+ //
+ // If this is a namespace prefixed attribute, check to make
+ // sure an attribute was created. This is necessary because some
+ // older versions of Safari (2.x and earlier) drop the namespace
+ // prefixes. If the attribute was munged, try removing the ':'
+ // character from the attribute name and setting the attribute
+ // using the resulting name. The idea here is that even if we
+ // remove the ':' character, Spry.Utils.getAttribute() will still
+ // find the attribute.
+
+ if (name.search(/:/) != -1 && ele.getAttribute(name) == undefined)
+ ele.setAttribute(name.replace(/:/, ""), value);
+ }
+};
+
+Spry.Utils.removeAttribute = function(ele, name)
+{
+ ele = Spry.$(ele);
+ if (!ele || !name)
+ return;
+
+ try { ele.removeAttribute(name); } catch(e) {}
+
+ // XXX: Workaround for Safari 2.x and earlier:
+ //
+ // If this is a namespace prefixed attribute, make sure we
+ // also remove any attributes with the same name, but without
+ // the ':' character.
+
+ if (name.search(/:/) != -1)
+ ele.removeAttribute(name.replace(/:/, ""));
+
+ // XXX: Workaround for IE
+ //
+ // IE doesn't allow you to remove the "class" attribute.
+ // It requires you to remove "className" instead, so go
+ // ahead and try to remove that too.
+
+ if (name == "class")
+ ele.removeAttribute("className");
+};
+
+Spry.Utils.addClassName = function(ele, className)
+{
+ ele = Spry.$(ele);
+ if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))
+ return;
+ ele.className += (ele.className ? " " : "") + className;
+};
+
+Spry.Utils.removeClassName = function(ele, className)
+{
+ ele = Spry.$(ele);
+ if (Spry.Utils.hasClassName(ele, className))
+ ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
+};
+
+Spry.Utils.toggleClassName = function(ele, className)
+{
+ if (Spry.Utils.hasClassName(ele, className))
+ Spry.Utils.removeClassName(ele, className);
+ else
+ Spry.Utils.addClassName(ele, className);
+};
+
+Spry.Utils.hasClassName = function(ele, className)
+{
+ ele = Spry.$(ele);
+ if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)
+ return false;
+ return true;
+};
+
+Spry.Utils.camelizeString = function(str)
+{
+ var cStr = "";
+ var a = str.split("-");
+ for (var i = 0; i < a.length; i++)
+ {
+ var s = a[i];
+ if (s)
+ cStr = cStr ? (cStr + s.charAt(0).toUpperCase() + s.substring(1)) : s;
+ }
+ return cStr;
+};
+
+Spry.Utils.styleStringToObject = function(styleStr)
+{
+ var o = {};
+ if (styleStr)
+ {
+ var pvA = styleStr.split(";");
+ for (var i = 0; i < pvA.length; i++)
+ {
+ var pv = pvA[i];
+ if (pv && pv.indexOf(":") != -1)
+ {
+ var nvA = pv.split(":");
+ var n = nvA[0].replace(/^\s*|\s*$/g, "");
+ var v = nvA[1].replace(/^\s*|\s*$/g, "");
+ if (n && v)
+ o[Spry.Utils.camelizeString(n)] = v;
+ }
+ }
+ }
+ return o;
+};
+
+Spry.Utils.addEventListener = function(element, eventType, handler, capture)
+{
+ try
+ {
+ if (!Spry.Utils.eventListenerIsBoundToElement(element, eventType, handler, capture))
+ {
+ element = Spry.$(element);
+ handler = Spry.Utils.bindEventListenerToElement(element, eventType, handler, capture);
+ if (element.addEventListener)
+ element.addEventListener(eventType, handler, capture);
+ else if (element.attachEvent)
+ element.attachEvent("on" + eventType, handler);
+ }
+ }
+ catch (e) {}
+};
+
+Spry.Utils.removeEventListener = function(element, eventType, handler, capture)
+{
+ try
+ {
+ element = Spry.$(element);
+ handler = Spry.Utils.unbindEventListenerFromElement(element, eventType, handler, capture);
+ if (element.removeEventListener)
+ element.removeEventListener(eventType, handler, capture);
+ else if (element.detachEvent)
+ element.detachEvent("on" + eventType, handler);
+ }
+ catch (e) {}
+};
+
+Spry.Utils.eventListenerHash = {};
+Spry.Utils.nextEventListenerID = 1;
+
+Spry.Utils.getHashForElementAndHandler = function(element, eventType, handler, capture)
+{
+ var hash = null;
+ element = Spry.$(element);
+ if (element)
+ {
+ if (typeof element.spryEventListenerID == "undefined")
+ element.spryEventListenerID = "e" + (Spry.Utils.nextEventListenerID++);
+ if (typeof handler.spryEventHandlerID == "undefined")
+ handler.spryEventHandlerID = "h" + (Spry.Utils.nextEventListenerID++);
+ hash = element.spryEventListenerID + "-" + handler.spryEventHandlerID + "-" + eventType + (capture?"-capture":"");
+ }
+ return hash;
+};
+
+Spry.Utils.eventListenerIsBoundToElement = function(element, eventType, handler, capture)
+{
+ element = Spry.$(element);
+ var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture);
+ return Spry.Utils.eventListenerHash[hash] != undefined;
+};
+
+Spry.Utils.bindEventListenerToElement = function(element, eventType, handler, capture)
+{
+ element = Spry.$(element);
+ var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture);
+ if (Spry.Utils.eventListenerHash[hash])
+ return Spry.Utils.eventListenerHash[hash];
+ return Spry.Utils.eventListenerHash[hash] = function(e)
+ {
+ e = e || window.event;
+
+ if (!e.preventDefault) e.preventDefault = function() { this.returnValue = false; };
+ if (!e.stopPropagation) e.stopPropagation = function() { this.cancelBubble = true; };
+
+ var result = handler.call(element, e);
+ if (result == false)
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ return result;
+ };
+};
+
+Spry.Utils.unbindEventListenerFromElement = function(element, eventType, handler, capture)
+{
+ element = Spry.$(element);
+ var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture);
+ if (Spry.Utils.eventListenerHash[hash])
+ {
+ handler = Spry.Utils.eventListenerHash[hash];
+ Spry.Utils.eventListenerHash[hash] = undefined;
+ }
+ return handler;
+};
+
+Spry.Utils.addLoadListener = function(handler)
+{
+ if (typeof window.addEventListener != 'undefined')
+ window.addEventListener('load', handler, false);
+ else if (typeof document.addEventListener != 'undefined')
+ document.addEventListener('load', handler, false);
+ else if (typeof window.attachEvent != 'undefined')
+ window.attachEvent('onload', handler);
+};
+
+Spry.Utils.getAncestor = function(ele, selector)
+{
+ ele = Spry.$(ele);
+ if (ele)
+ {
+ var s = Spry.$$.tokenizeSequence(selector ? selector : "*")[0];
+ var t = s ? s[0] : null;
+ if (t)
+ {
+ var p = ele.parentNode;
+ while (p)
+ {
+ if (t.match(p))
+ return p;
+ p = p.parentNode;
+ }
+ }
+ }
+ return null;
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// CSS Selector Matching
+//
+//////////////////////////////////////////////////////////////////////
+
+Spry.$$ = function(selectorSequence, rootNode)
+{
+ var matches = [];
+ Spry.$$.addExtensions(matches);
+
+ // If the first argument to $$() is an object, it
+ // is assumed that all args are either a DOM element
+ // or an array of DOM elements, in which case we
+ // simply append all DOM elements to our special
+ // matches array and return immediately.
+
+ if (typeof arguments[0] == "object")
+ {
+ for (var i = 0; i < arguments.length; i++)
+ {
+ if (arguments[i].constructor == Array)
+ matches.push.apply(matches, arguments[i]);
+ else
+ matches.push(arguments[i]);
+ }
+ return matches;
+ }
+
+ if (!rootNode)
+ rootNode = document;
+ else
+ rootNode = Spry.$(rootNode);
+
+ var sequences = Spry.$$.tokenizeSequence(selectorSequence);
+
+ ++Spry.$$.queryID;
+
+ var nid = 0;
+ var ns = sequences.length;
+ for (var i = 0; i < ns; i++)
+ {
+ var m = Spry.$$.processTokens(sequences[i], rootNode);
+ var nm = m.length;
+ for (var j = 0; j < nm; j++)
+ {
+ var n = m[j];
+ if (!n.spry$$ID)
+ {
+ n.spry$$ID = ++nid;
+ matches.push(n);
+ }
+ }
+ }
+
+ var nm = matches.length;
+ for (i = 0; i < nm; i++)
+ matches[i].spry$$ID = undefined;
+
+ return matches;
+};
+
+Spry.$$.cache = {};
+Spry.$$.queryID = 0;
+
+Spry.$$.Token = function()
+{
+ this.type = Spry.$$.Token.SELECTOR;
+ this.name = "*";
+ this.id = "";
+ this.classes = [];
+ this.attrs = [];
+
+ this.pseudos = [];
+};
+
+Spry.$$.Token.Attr = function(n, v)
+{
+ this.name = n;
+ this.value = v ? new RegExp(v) : undefined;
+};
+
+Spry.$$.Token.PseudoClass = function(pstr)
+{
+ this.name = pstr.replace(/\(.*/, "");
+ this.arg = pstr.replace(/^[^\(\)]*\(?\s*|\)\s*$/g, "");
+ this.func = Spry.$$.pseudoFuncs[this.name];
+};
+
+Spry.$$.Token.SELECTOR = 0;
+Spry.$$.Token.COMBINATOR = 1;
+
+Spry.$$.Token.prototype.match = function(ele, nameAlreadyMatches)
+{
+ if (this.type == Spry.$$.Token.COMBINATOR)
+ return false;
+ if (!nameAlreadyMatches && this.name != '*' && this.name != ele.nodeName.toLowerCase())
+ return false;
+ if (this.id && this.id != ele.id)
+ return false;
+ var classes = this.classes;
+ var len = classes.length;
+ for (var i = 0; i < len; i++)
+ {
+ if (!ele.className || !classes[i].value.test(ele.className))
+ return false;
+ }
+
+ var attrs = this.attrs;
+ len = attrs.length;
+ for (var i = 0; i < len; i++)
+ {
+ var a = attrs[i];
+ var an = ele.attributes.getNamedItem(a.name);
+ if (!an || (!a.value && an.nodeValue == undefined) || (a.value && !a.value.test(an.nodeValue)))
+ return false;
+ }
+
+ var ps = this.pseudos;
+ var len = ps.length;
+ for (var i = 0; i < len; i++)
+ {
+ var p = ps[i];
+ if (p && p.func && !p.func(p.arg, ele, this))
+ return false;
+ }
+
+ return true;
+};
+
+Spry.$$.Token.prototype.getNodeNameIfTypeMatches = function(ele)
+{
+ var nodeName = ele.nodeName.toLowerCase();
+ if (this.name != '*')
+ {
+ if (this.name != nodeName)
+ return null;
+ return this.name;
+ }
+ return nodeName;
+};
+
+Spry.$$.escapeRegExpCharsRE = /\/|\.|\*|\+|\(|\)|\[|\]|\{|\}|\\|\|/g;
+
+Spry.$$.tokenizeSequence = function(s)
+{
+ var cc = Spry.$$.cache[s];
+ if (cc) return cc;
+
+ // Attribute Selector: /(\[[^\"'~\^\$\*\|\]=]+([~\^\$\*\|]?=\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\])/g
+ // Simple Selector: /((:[^\.#:\s,>~\+\[\]]+\(([^\(\)]+|\([^\(\)]*\))*\))|[\.#:]?[^\.#:\s,>~\+\[\]]+)/g
+ // Combinator: /(\s*[\s,>~\+]\s*)/g
+
+ var tokenExpr = /(\[[^\"'~\^\$\*\|\]=]+([~\^\$\*\|]?=\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\])|((:[^\.#:\s,>~\+\[\]]+\(([^\(\)]+|\([^\(\)]*\))*\))|[\.#:]?[^\.#:\s,>~\+\[\]]+)|(\s*[\s,>~\+]\s*)/g;
+
+ var tkn = new Spry.$$.Token;
+ var sequence = [];
+ sequence.push(tkn);
+ var tokenSequences = [];
+ tokenSequences.push(sequence);
+
+ s = s.replace(/^\s*|\s*$/, "");
+
+ var expMatch = tokenExpr.exec(s);
+ while (expMatch)
+ {
+ var tstr = expMatch[0];
+ var c = tstr.charAt(0);
+ switch (c)
+ {
+ case '.':
+ tkn.classes.push(new Spry.$$.Token.Attr("class", "\\b" + tstr.substr(1) + "\\b"));
+ break;
+ case '#':
+ tkn.id = tstr.substr(1);
+ break;
+ case ':':
+ tkn.pseudos.push(new Spry.$$.Token.PseudoClass(tstr));
+ break;
+ case '[':
+ var attrComps = tstr.match(/\[([^\"'~\^\$\*\|\]=]+)(([~\^\$\*\|]?=)\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\]/);
+ var name = attrComps[1];
+ var matchType = attrComps[3];
+ var val = attrComps[4];
+ if (val)
+ {
+ val = val.replace(/^['"]|['"]$/g, "");
+ val = val.replace(Spry.$$.escapeRegExpCharsRE, '\\$&');
+ }
+
+ var matchStr = undefined;
+
+ switch(matchType)
+ {
+ case "=":
+ matchStr = "^" + val + "$";
+ break;
+ case "^=":
+ matchStr = "^" + val;
+ break;
+ case "$=":
+ matchStr = val + "$";
+ break;
+ case "~=":
+ case "|=":
+ matchStr = "\\b" + val + "\\b";
+ break;
+ case "*=":
+ matchStr = val;
+ break;
+ }
+
+ tkn.attrs.push(new Spry.$$.Token.Attr(name, matchStr));
+ break;
+ default:
+ var combiMatch = tstr.match(/^\s*([\s,~>\+])\s*$/);
+ if (combiMatch)
+ {
+ if (combiMatch[1] == ',')
+ {
+ sequence = new Array;
+ tokenSequences.push(sequence);
+ tkn = new Spry.$$.Token;
+ sequence.push(tkn);
+ }
+ else
+ {
+ tkn = new Spry.$$.Token;
+ tkn.type = Spry.$$.Token.COMBINATOR;
+ tkn.name = combiMatch[1];
+ sequence.push(tkn);
+ tkn = new Spry.$$.Token();
+ sequence.push(tkn);
+ }
+ }
+ else
+ tkn.name = tstr.toLowerCase();
+ break;
+ }
+ expMatch = tokenExpr.exec(s);
+ }
+
+ Spry.$$.cache[s] = tokenSequences;
+
+ return tokenSequences;
+};
+
+Spry.$$.combinatorFuncs = {
+ // Element Descendant
+
+ " ": function(nodes, token)
+ {
+ var uid = ++Spry.$$.uniqueID;
+ var results = [];
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i];
+ if (uid != n.spry$$uid)
+ {
+ // n.spry$$uid = uid;
+ var ea = nodes[i].getElementsByTagName(token.name);
+ var ne = ea.length;
+ for (var j = 0; j < ne; j++)
+ {
+ var e = ea[j];
+
+ // If the token matches, add it to our results. We have
+ // to make sure e is an element because IE6 returns the DOCTYPE
+ // tag as a comment when '*' is used in the call to getElementsByTagName().
+
+ if (e.nodeType == 1 /* Node.ELEMENT_NODE */ && token.match(e, true))
+ results.push(e);
+ e.spry$$uid = uid;
+ }
+ }
+ }
+ return results;
+ },
+
+ // Element Child
+
+ ">": function(nodes, token)
+ {
+ var results = [];
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i].firstChild;
+ while (n)
+ {
+ if (n.nodeType == 1 /* Node.ELEMENT_NODE */ && token.match(n))
+ results.push(n);
+ n = n.nextSibling;
+ }
+ }
+ return results;
+ },
+
+ // Element Immediately Preceded By
+
+ "+": function(nodes, token)
+ {
+ var results = [];
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i].nextSibling;
+ while (n && n.nodeType != 1 /* Node.ELEMENT_NODE */)
+ n = n.nextSibling;
+ if (n && token.match(n))
+ results.push(n);
+ }
+ return results;
+ },
+
+ // Element Preceded By
+
+ "~": function(nodes, token)
+ {
+ var uid = ++Spry.$$.uniqueID;
+ var results = [];
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i].nextSibling;
+ while (n)
+ {
+ if (n.nodeType == 1 /* Node.ELEMENT_NODE */)
+ {
+ if (uid == n.spry$$uid)
+ break;
+
+ if (token.match(n))
+ {
+ results.push(n);
+ n.spry$$uid = uid;
+ }
+ }
+ n = n.nextSibling;
+ }
+ }
+ return results;
+ }
+};
+
+Spry.$$.uniqueID = 0;
+
+Spry.$$.pseudoFuncs = {
+ ":first-child": function(arg, node, token)
+ {
+ var n = node.previousSibling;
+ while (n)
+ {
+ if (n.nodeType == 1) return false; // Node.ELEMENT_NODE
+ n = n.previousSibling;
+ }
+
+ return true;
+ },
+
+ ":last-child": function(arg, node, token)
+ {
+ var n = node.nextSibling;
+ while (n)
+ {
+ if (n.nodeType == 1) // Node.ELEMENT_NODE
+ return false;
+ n = n.nextSibling;
+ }
+ return true;
+ },
+
+ ":empty": function(arg, node, token)
+ {
+ var n = node.firstChild;
+ while (n)
+ {
+ switch(n.nodeType)
+ {
+ case 1: // Node.ELEMENT_NODE
+ case 3: // Node.TEXT_NODE
+ case 4: // Node.CDATA_NODE
+ case 5: // Node.ENTITY_REFERENCE_NODE
+ return false;
+ }
+ n = n.nextSibling;
+ }
+ return true;
+ },
+
+ ":nth-child": function(arg, node, token)
+ {
+ return Spry.$$.nthChild(arg, node, token);
+ },
+
+ ":nth-last-child": function(arg, node, token)
+ {
+ return Spry.$$.nthChild(arg, node, token, true);
+ },
+
+ ":nth-of-type": function(arg, node, token)
+ {
+ return Spry.$$.nthChild(arg, node, token, false, true);
+ },
+
+ ":nth-last-of-type": function(arg, node, token)
+ {
+ return Spry.$$.nthChild(arg, node, token, true, true);
+ },
+
+ ":first-of-type": function(arg, node, token)
+ {
+ var nodeName = token.getNodeNameIfTypeMatches(node);
+ if (!nodeName) return false;
+
+ var n = node.previousSibling;
+ while (n)
+ {
+ if (n.nodeType == 1 && nodeName == n.nodeName.toLowerCase()) return false; // Node.ELEMENT_NODE
+ n = n.previousSibling;
+ }
+
+ return true;
+ },
+
+ ":last-of-type": function(arg, node, token)
+ {
+ var nodeName = token.getNodeNameIfTypeMatches(node);
+ if (!nodeName) return false;
+
+ var n = node.nextSibling;
+ while (n)
+ {
+ if (n.nodeType == 1 && nodeName == n.nodeName.toLowerCase()) // Node.ELEMENT_NODE
+ return false;
+ n = n.nextSibling;
+ }
+ return true;
+ },
+
+ ":only-child": function(arg, node, token)
+ {
+ var f = Spry.$$.pseudoFuncs;
+ return f[":first-child"](arg, node, token) && f[":last-child"](arg, node, token);
+ },
+
+ ":only-of-type": function(arg, node, token)
+ {
+ var f = Spry.$$.pseudoFuncs;
+ return f[":first-of-type"](arg, node, token) && f[":last-of-type"](arg, node, token);
+ },
+
+ ":not": function(arg, node, token)
+ {
+ var s = Spry.$$.tokenizeSequence(arg)[0];
+ var t = s ? s[0] : null;
+ return !t || !t.match(node);
+ },
+
+ ":enabled": function(arg, node, token)
+ {
+ return !node.disabled;
+ },
+
+ ":disabled": function(arg, node, token)
+ {
+ return node.disabled;
+ },
+
+ ":checked": function(arg, node, token)
+ {
+ return node.checked;
+ },
+
+ ":root": function(arg, node, token)
+ {
+ return node.parentNode && node.ownerDocument && node.parentNode == node.ownerDocument;
+ }
+};
+
+Spry.$$.nthRegExp = /((-|[0-9]+)?n)?([+-]?[0-9]*)/;
+
+Spry.$$.nthCache = {
+ "even": { a: 2, b: 0, mode: 1, invalid: false }
+ , "odd": { a: 2, b: 1, mode: 1, invalid: false }
+ , "2n": { a: 2, b: 0, mode: 1, invalid: false }
+ , "2n+1": { a: 2, b: 1, mode: 1, invalid: false }
+};
+
+Spry.$$.parseNthChildString = function(str)
+{
+ var o = Spry.$$.nthCache[str];
+ if (!o)
+ {
+ var m = str.match(Spry.$$.nthRegExp);
+ var n = m[1];
+ var a = m[2];
+ var b = m[3];
+
+ if (!a)
+ {
+ // An 'a' value was not specified. Was there an 'n' present?
+ // If so, we treat it as an increment of 1, otherwise we're
+ // in no-repeat mode.
+
+ a = n ? 1 : 0;
+ }
+ else if (a == "-")
+ {
+ // The string is using the "-n" short-hand which is
+ // short for -1.
+
+ a = -1;
+ }
+ else
+ {
+ // An integer repeat value for 'a' was specified. Convert
+ // it into number.
+
+ a = parseInt(a, 10);
+ }
+
+ // If a 'b' value was specified, turn it into a number.
+ // If no 'b' value was specified, default to zero.
+
+ b = b ? parseInt(b, 10) : 0;
+
+ // Figure out the mode:
+ //
+ // -1 - repeat backwards
+ // 0 - no repeat
+ // 1 - repeat forwards
+
+ var mode = (a == 0) ? 0 : ((a > 0) ? 1 : -1);
+ var invalid = false;
+
+ // Fix up 'a' and 'b' for proper repeating.
+
+ if (a > 0 && b < 0)
+ {
+ b = b % a;
+ b = ((b=(b%a)) < 0) ? a + b : b;
+ }
+ else if (a < 0)
+ {
+ if (b < 0)
+ invalid = true;
+ else
+ a = Math.abs(a);
+ }
+
+ o = new Object;
+ o.a = a;
+ o.b = b;
+ o.mode = mode;
+ o.invalid = invalid;
+
+ Spry.$$.nthCache[str] = o;
+ }
+
+ return o;
+};
+
+Spry.$$.nthChild = function(arg, node, token, fromLastSib, matchNodeName)
+{
+ if (matchNodeName)
+ {
+ var nodeName = token.getNodeNameIfTypeMatches(node);
+ if (!nodeName) return false;
+ }
+
+ var o = Spry.$$.parseNthChildString(arg);
+
+ if (o.invalid)
+ return false;
+
+ var qidProp = "spry$$ncQueryID";
+ var posProp = "spry$$ncPos";
+ var countProp = "spry$$ncCount";
+ if (matchNodeName)
+ {
+ qidProp += nodeName;
+ posProp += nodeName;
+ countProp += nodeName;
+ }
+
+ var parent = node.parentNode;
+ if (parent[qidProp] != Spry.$$.queryID)
+ {
+ var pos = 0;
+ parent[qidProp] = Spry.$$.queryID;
+ var c = parent.firstChild;
+ while (c)
+ {
+ if (c.nodeType == 1 && (!matchNodeName || nodeName == c.nodeName.toLowerCase()))
+ c[posProp] = ++pos;
+ c = c.nextSibling;
+ }
+ parent[countProp] = pos;
+ }
+
+ pos = node[posProp];
+ if (fromLastSib)
+ pos = parent[countProp] - pos + 1;
+
+/*
+ var sib = fromLastSib ? "nextSibling" : "previousSibling";
+
+ var pos = 1;
+ var n = node[sib];
+ while (n)
+ {
+ if (n.nodeType == 1 && (!matchNodeName || nodeName == n.nodeName.toLowerCase()))
+ {
+ if (n == node) break;
+ ++pos;
+ }
+ n = n[sib];
+ }
+*/
+
+ if (o.mode == 0) // Exact match
+ return pos == o.b;
+ if (o.mode > 0) // Forward Repeat
+ return (pos < o.b) ? false : (!((pos - o.b) % o.a));
+ return (pos > o.b) ? false : (!((o.b - pos) % o.a)); // Backward Repeat
+};
+
+Spry.$$.processTokens = function(tokens, root)
+{
+ var numTokens = tokens.length;
+ var nodeSet = [ root ];
+ var combiFunc = null;
+
+ for (var i = 0; i < numTokens && nodeSet.length > 0; i++)
+ {
+ var t = tokens[i];
+ if (t.type == Spry.$$.Token.SELECTOR)
+ {
+ if (combiFunc)
+ {
+ nodeSet = combiFunc(nodeSet, t);
+ combiFunc = null;
+ }
+ else
+ nodeSet = Spry.$$.getMatchingElements(nodeSet, t);
+ }
+ else // Spry.$$.Token.COMBINATOR
+ combiFunc = Spry.$$.combinatorFuncs[t.name];
+ }
+ return nodeSet;
+};
+
+Spry.$$.getMatchingElements = function(nodes, token)
+{
+ var results = [];
+ if (token.id)
+ {
+ n = nodes[0];
+ if (n && n.ownerDocument)
+ {
+ var e = n.ownerDocument.getElementById(token.id);
+ if (e)
+ {
+ // XXX: We need to make sure that the element
+ // we found is actually underneath the root
+ // we were given!
+
+ if (token.match(e))
+ results.push(e);
+ }
+ return results;
+ }
+ }
+
+ var nn = nodes.length;
+ for (var i = 0; i < nn; i++)
+ {
+ var n = nodes[i];
+ // if (token.match(n)) results.push(n);
+
+ var ea = n.getElementsByTagName(token.name);
+ var ne = ea.length;
+ for (var j = 0; j < ne; j++)
+ {
+ var e = ea[j];
+
+ // If the token matches, add it to our results. We have
+ // to make sure e is an element because IE6 returns the DOCTYPE
+ // tag as a comment when '*' is used in the call to getElementsByTagName().
+
+ if (e.nodeType == 1 /* Node.ELEMENT_NODE */ && token.match(e, true))
+ results.push(e);
+ }
+ }
+ return results;
+};
+
+/*
+Spry.$$.dumpSequences = function(sequences)
+{
+ Spry.Debug.trace("
Number of Sequences: " + sequences.length);
+ for (var i = 0; i < sequences.length; i++)
+ {
+ var str = "";
+ var s = sequences[i];
+ Spry.Debug.trace("
Sequence " + i + " -- Tokens: " + s.length);
+ for (var j = 0; j < s.length; j++)
+ {
+ var t = s[j];
+ if (t.type == Spry.$$.Token.SELECTOR)
+ {
+ str += " SELECTOR:\n Name: " + t.name + "\n ID: " + t.id + "\n Attrs:\n";
+ for (var k = 0; k < t.classes.length; k++)
+ str += " " + t.classes[k].name + ": " + t.classes[k].value + "\n";
+ for (var k = 0; k < t.attrs.length; k++)
+ str += " " + t.attrs[k].name + ": " + t.attrs[k].value + "\n";
+ str += " Pseudos:\n";
+ for (var k = 0; k < t.pseudos.length; k++)
+ str += " " + t.pseudos[k].name + (t.pseudos[k].arg ? "(" + t.pseudos[k].arg + ")" : "") + "\n";
+ }
+ else
+ {
+ str += " COMBINATOR:\n Name: '" + t.name + "'\n";
+ }
+ }
+ Spry.Debug.trace("" + Spry.Utils.encodeEntities(str) + "
");
+ }
+};
+*/
+
+Spry.$$.addExtensions = function(a)
+{
+ for (var f in Spry.$$.Results)
+ a[f] = Spry.$$.Results[f];
+};
+
+Spry.$$.Results = {};
+
+Spry.$$.Results.forEach = function(func)
+{
+ var n = this.length;
+ for (var i = 0; i < n; i++)
+ func(this[i]);
+ return this;
+};
+
+Spry.$$.Results.setAttribute = function(name, value)
+{
+ return this.forEach(function(n) { Spry.Utils.setAttribute(n, name, value); });
+};
+
+Spry.$$.Results.removeAttribute = function(name)
+{
+ return this.forEach(function(n) { Spry.Utils.removeAttribute(n, name); });
+};
+
+Spry.$$.Results.addClassName = function(className)
+{
+ return this.forEach(function(n) { Spry.Utils.addClassName(n, className); });
+};
+
+Spry.$$.Results.removeClassName = function(className)
+{
+ return this.forEach(function(n) { Spry.Utils.removeClassName(n, className); });
+};
+
+Spry.$$.Results.toggleClassName = function(className)
+{
+ return this.forEach(function(n) { Spry.Utils.toggleClassName(n, className); });
+};
+
+Spry.$$.Results.addEventListener = function(eventType, handler, capture, bindHandler)
+{
+ return this.forEach(function(n) { Spry.Utils.addEventListener(n, eventType, handler, capture, bindHandler); });
+};
+
+Spry.$$.Results.removeEventListener = function(eventType, handler, capture)
+{
+ return this.forEach(function(n) { Spry.Utils.removeEventListener(n, eventType, handler, capture); });
+};
+
+Spry.$$.Results.setStyle = function(style)
+{
+ if (style)
+ {
+ style = Spry.Utils.styleStringToObject(style);
+ this.forEach(function(n)
+ {
+ for (var p in style)
+ try { n.style[p] = style[p]; } catch (e) {}
+ });
+ }
+ return this;
+};
+
+Spry.$$.Results.setProperty = function(prop, value)
+{
+ if (prop)
+ {
+ if (typeof prop == "string")
+ {
+ var p = {};
+ p[prop] = value;
+ prop = p;
+ }
+
+ this.forEach(function(n)
+ {
+ for (var p in prop)
+ try { n[p] = prop[p]; } catch (e) {}
+ });
+ }
+ return this;
+};
+
+})(); // EndSpryComponent
\ No newline at end of file
diff --git a/1.7/SpryProgressBar.js b/1.7/SpryProgressBar.js
new file mode 100644
index 0000000..e01e4a0
--- /dev/null
+++ b/1.7/SpryProgressBar.js
@@ -0,0 +1,234 @@
+"use strict";
+
+(function(){
+// start component
+if (typeof Spry === "undefined" || !Spry.Utils || !Spry.$$ || !Spry.Effect ){
+ throw new Error("SpryProgessbar.js requires SpryDOMUtils.js and SpryDOMEffects.js");
+}
+
+Spry.Widget.ProgressBar = function( element, opts ){
+ var that = this;
+
+ Spry.Widget.Base.call( this );
+
+ // Initialize the button object with the global defaults.
+ this.setOptions( this, Spry.Widget.ProgressBar.config );
+
+ // Override the defaults with any options passed into the constructor.
+ this.setOptions( this, opts );
+
+ // version number pattern: major, minor, bugfix
+ this.version = "0.0.0";
+ this.element = Spry.$$( element )[0];
+ this.bar = Spry.$$( "." + this.barClass, this.element );
+ this.initialWidth = parseFloat( this.getStyleProp( this.bar[0], "width" ) ); // getStylePr
+ this.currentWidth = this.initialWidth;
+ this.counter = 0;
+
+ // this activates or resets the progress with the supplied value
+ this.setPercentage(
+ // set the percentage to the supplied "default" percentage
+ this.percentage,
+
+ // just do it quick so user will not notice it
+ 1,
+
+ // do we have a auto start ? if yes, complete the progress bar with the supplied duration
+ this.autoStart ? function(){ that.setPercentage( 100, that.duration ); }: false );
+
+ // adds on oncomplete observer to show or hide the menubar
+ this.addObserver({
+ onComplete: function(){
+ if( that.hideOnComplete ){
+ that.hide();
+ }
+ }
+ });
+};
+
+// a linear transition
+Spry.Widget.ProgressBar.defaultEaseFunc = function(time, begin, change, duration){
+ if (time > duration){
+ return change + begin;
+ }
+
+ return begin + (time / duration) * change;
+};
+
+Spry.Widget.ProgressBar.config = {
+ // initial percentage of the bar
+ percentage: 0,
+
+ // default transition for the effect
+ transition: Spry.Widget.ProgressBar.defaultEaseFunc,
+
+ // the default length of the animation
+ duration: 2E3,
+
+ // is the widget enabled or disabled
+ autoStart: false,
+
+ // if the progress bar should be hidden once it's completed
+ hideOnComplete: true,
+
+ // what className is used for the bar
+ barClass: "bar"
+};
+
+Spry.Widget.ProgressBar.prototype = new Spry.Widget.Base();
+Spry.Widget.ProgressBar.prototype.constructor = Spry.Widget.ProgressBar;
+
+Spry.Widget.ProgressBar.prototype.setPercentage = function( percentage, duration, callback ){
+ // makesure its a valid value
+ percentage = this.cleanPercentage ( percentage );
+ duration = duration || this.duration;
+
+ var that = this,
+ // are we increasing or decreasing
+ increase = percentage >= this.percentage,
+
+ // target width
+ to = this.initialWidth / 100 * percentage,
+
+ // diffence between the current and new percentage
+ difference = increase ? percentage - this.percentage : this.percentage - percentage;
+
+ // create sliding effect
+ this.effect = new Spry.Effect.CSSAnimator( this.bar, "width:" + to + "px", {
+ duration: duration,
+ easeFunc: this.transition || Spry.$$.Results.defaultEaseFunc,
+ onComplete: callback || null
+ });
+
+ this.currentWidth = to;
+ this.percentage = percentage;
+
+ // add events to the effect so we can fire off our custom notifications as well
+ this.effect.addObserver({
+ onAnimationComplete: function(){
+ if( percentage === 100 ){
+ that.notifyObservers( "onComplete" ); // the progressbar has been completed
+ }
+
+ // we set the percentage
+ that.notifyObservers( "onPercentageChanged", ( that.counter = percentage ) );
+ that.notifyObservers( "onPercentageSet", that.percentage );
+ },
+
+ onPostDraw: function( effect, info ){
+ if( info.elapsed >= effect.increase && that.counter < 100 ){
+ effect.increase = effect.avg + effect.increase;
+
+ var effect_percent = Math.floor( info.elapsed / effect.avg ),
+ effect_difference;
+
+ if( !effect.percent || effect.percent < effect_percent ){
+ effect_difference = effect_percent - effect.percent || 1;
+ effect.percent = effect_percent;
+
+ that.notifyObservers(
+ "onPercentageChanged",
+ (
+ that.counter = that.cleanPercentage(
+ increase ? ( that.counter + effect_difference ) : ( that.counter - effect_difference)
+ )
+ )
+ );
+ }
+
+ }
+ }
+
+ });
+
+ // calculate the elapsed when the percentage needs to increased
+ this.effect.avg = this.effect.increase= Math.round( duration / difference );
+
+ // run the animation
+ this.effect.start();
+};
+
+// prevent race conditions, so you can stop them at will...
+Spry.Widget.ProgressBar.prototype.stop = function(){
+ if( this.effect && !this.effect.stopped){
+ this.effect.stop();
+ }
+};
+
+// when you stop, you might want to start it again.. go figure :0
+Spry.Widget.ProgressBar.prototype.start = function(){
+ if( this.effect && this.effect.stopped){
+ this.effect.start();
+ }
+};
+
+// increase the value of the progress
+Spry.Widget.ProgressBar.prototype.add = function( percentage, duration ){
+ percentage = percentage ? this.cleanPercentage( percentage ) : 5;
+ this.setPercentage( this.counter + percentage, duration );
+};
+
+// decrease the value of the progress
+Spry.Widget.ProgressBar.prototype.remove = function( percentage, duration ){
+ percentage = percentage ? this.cleanPercentage( percentage ) : 5;
+ this.setPercentage( this.counter - percentage, duration );
+};
+
+// reset the progress bar back to 0;
+Spry.Widget.ProgressBar.prototype.reset = function( ){
+ var that = this;
+
+ if( this.hidden ){
+ this.show();
+ }
+
+ this.counter = 0;
+ this.setPercentage( 0, 1, function(){ that.notifyObservers( "onReset" ); });
+};
+
+// complete the progress bar, fast
+Spry.Widget.ProgressBar.prototype.complete = function( duration ){
+ this.stop();
+ this.setPercentage( 100, duration || 200, false, true );
+};
+
+// cleans out the percentage, parses down 100% to 100 and makes sure its between 0 and 100;
+Spry.Widget.ProgressBar.prototype.cleanPercentage = function( value ){
+ value = typeof value === "number" ? value : parseFloat( value.replace(/\%/g, '' ) );
+ return value > 100 ? 100 : (value < 0 ? 0 : value); // percentage can't be higher than 100%
+};
+
+// returns the current percentage or the expected percentage
+Spry.Widget.ProgressBar.prototype.getPercentage = function( total ){
+ return total ? this.percentage : this.counter;
+};
+
+// shows the widget
+Spry.Widget.ProgressBar.prototype.show = function(){
+ this.element.style.display = "";
+ if( this.hidden ){
+ this.hidden = false;
+ (new Spry.Effect.CSSAnimator( this.element , "opacity: 1",
+ {
+ duration: 500
+ })
+ ).start();
+ }
+};
+
+Spry.Widget.ProgressBar.prototype.hide = function(){
+ var that = this;
+ this.hidden = true;
+
+ (new Spry.Effect.CSSAnimator( this.element , "opacity: 0",
+ {
+ duration: 500,
+ onComplete: function(){
+ that.element.style.display = "none";
+ }
+ })
+ ).start();
+};
+
+// end component
+}());
\ No newline at end of file
diff --git a/1.7/SpryWidget.js b/1.7/SpryWidget.js
new file mode 100644
index 0000000..dd571a8
--- /dev/null
+++ b/1.7/SpryWidget.js
@@ -0,0 +1,681 @@
+// SpryWidget.js - version 0.14 - Spry Pre-Release 1.7
+//
+// Copyright (c) 2009. Adobe Systems Incorporated.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Adobe Systems Incorporated nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+(function() { // BeginSpryComponent
+
+if (typeof Spry == "undefined" || !Spry.Utils || !Spry.$$)
+{
+ alert("SpryWidget.js requires SpryDOMUtils.js");
+ return;
+}
+
+if (!Spry.Widget) Spry.Widget = {};
+
+Spry.Widget.setOptions = function(obj, optionsObj, ignoreUndefinedProps)
+{
+ if (obj && optionsObj)
+ {
+ for (var optionName in optionsObj)
+ {
+ var v = optionsObj[optionName];
+ if (!ignoreUndefinedProps || v != undefined)
+ obj[optionName] = v;
+ }
+ }
+ return obj;
+};
+
+Spry.Widget.onLoadDidFire = false;
+Spry.Widget.onLoadQueue = [];
+
+Spry.Widget.addCallbackToOnLoadQueue = function(callbackFunc, context)
+{
+ if (callbackFunc)
+ {
+ if (context)
+ {
+ var cf = callbackFunc;
+ callbackFunc = function() { cf.call(context); };
+ }
+
+ Spry.Widget.onLoadQueue.push(callbackFunc);
+ }
+};
+
+Spry.Widget.triggerCallbackAfterOnLoad = function(callbackFunc, context)
+{
+ if (Spry.Widget.onLoadDidFire)
+ callbackFunc.call(context);
+ else
+ Spry.Widget.addCallbackToOnLoadQueue(callbackFunc, context);
+
+};
+
+Spry.Widget.processOnLoadQueue = function()
+{
+ Spry.Widget.onLoadDidFire = true;
+ var q = Spry.Widget.onLoadQueue;
+ while (q.length)
+ (q.shift())();
+};
+
+Spry.Utils.addLoadListener(Spry.Widget.processOnLoadQueue);
+
+Spry.Widget.Base = function()
+{
+ Spry.Widget.Base.Notifier.call(this);
+};
+
+Spry.Widget.Base.Notifier = function()
+{
+ this.observers = [];
+ this.suppressNotifications = 0;
+};
+
+Spry.Widget.Base.Notifier.prototype.addObserver = function(observer)
+{
+ if (!observer)
+ return;
+
+ // Make sure the observer isn't already on the list.
+
+ var len = this.observers.length;
+ for (var i = 0; i < len; i++)
+ {
+ if (this.observers[i] == observer)
+ return;
+ }
+ this.observers[len] = observer;
+};
+
+Spry.Widget.Base.Notifier.prototype.removeObserver = function(observer)
+{
+ if (!observer)
+ return;
+
+ for (var i = 0; i < this.observers.length; i++)
+ {
+ if (this.observers[i] == observer)
+ {
+ this.observers.splice(i, 1);
+ break;
+ }
+ }
+};
+
+Spry.Widget.Base.Notifier.prototype.notifyObservers = function(methodName, data)
+{
+ if (!methodName)
+ return;
+
+ if (!this.suppressNotifications)
+ {
+ var len = this.observers.length;
+ for (var i = 0; i < len; i++)
+ {
+ var obs = this.observers[i];
+ if (obs)
+ {
+ if (typeof obs == "function")
+ obs(methodName, this, data);
+ else if (obs[methodName])
+ obs[methodName](this, data);
+ }
+ }
+ }
+};
+
+Spry.Widget.Base.Notifier.prototype.enableNotifications = function()
+{
+ if (--this.suppressNotifications < 0)
+ {
+ this.suppressNotifications = 0;
+ Spry.Debug.reportError("Unbalanced enableNotifications() call!\n");
+ }
+};
+
+Spry.Widget.Base.Notifier.prototype.disableNotifications = function()
+{
+ ++this.suppressNotifications;
+};
+
+Spry.Widget.Base.prototype = new Spry.Widget.Base.Notifier();
+Spry.Widget.Base.prototype.constructor = Spry.Widget.Base;
+
+Spry.Widget.Base.getElement = function(ele)
+{
+ return Spry.$(ele);
+};
+
+Spry.Widget.Base.getElements = function(elements)
+{
+ var eType = typeof elements;
+ if (eType == "string")
+ return Spry.$$(elements);
+ else if (eType == "object")
+ {
+ if (elements.constructor == Array)
+ {
+ var result = [];
+ for (var i = 0; i < elements.length; i++)
+ result = result.concat(Spry.Widget.Base.getElements(elements[i]));
+ return result;
+ }
+ else
+ return [elements];
+ }
+
+ return [];
+};
+
+Spry.Widget.Base.getElementsByClassName = function(root, className)
+{
+ var results = [];
+
+ if (typeof root.getElementsByClassName != "undefined")
+ {
+ // Browser has a native getElementsByClassName(), so use it.
+
+ var nodeList = root.getElementsByClassName(className);
+ for (var i = 0; i < nodeList.length; i++)
+ results.push(nodeList.item(i));
+ }
+ else
+ {
+ // Browser has no native getElementsByClassName() implementation
+ // so do a manual search.
+
+ var re = new RegExp("\\b" + className + "\\b");
+ var nodeList = root.getElementsByTagName("*");
+ for (var i = 0; i < nodeList.length; i++)
+ {
+ var ele = nodeList.item(i);
+ if (ele.className.search(re) != -1)
+ results.push(ele);
+ }
+ }
+
+ return results;
+};
+
+Spry.Widget.Base.prototype.getElementChildren = function(element)
+{
+ var children = [];
+ if (element)
+ {
+ var child = element.firstChild;
+ while (child)
+ {
+ if (child.nodeType == 1 /* Node.ELEMENT_NODE */)
+ children.push(child);
+ child = child.nextSibling;
+ }
+ }
+ return children;
+};
+
+Spry.Widget.Base.prototype.groupContentByDelimeter = function(delimeterElements)
+{
+ var results = new Array();
+
+ var numDelims = delimeterElements.length;
+ for (var i = 0; i < numDelims; i++)
+ {
+ var delim = delimeterElements[i];
+ var group = new Array();
+ group.push(delim);
+
+ var nextDelim = delimeterElements[i+1];
+ var sib = delim.nextSibling;
+ while (sib && sib != nextDelim)
+ {
+ group.push(sib);
+ sib = sib.nextSibling;
+ }
+
+ results.push(group);
+ }
+
+ return results;
+};
+
+Spry.Widget.Base.prototype.createElement = function(elementName, className, parent, child)
+{
+ var ele = document.createElement(elementName);
+ if (className) ele.className = className;
+ if (parent) parent.appendChild(ele);
+ if (child) ele.appendChild(child);
+ return ele;
+};
+
+Spry.Widget.Base.prototype.sliceLeftClassStr = "Left";
+Spry.Widget.Base.prototype.sliceRightClassStr = "Right";
+Spry.Widget.Base.prototype.sliceCenterClassStr = "Center";
+Spry.Widget.Base.prototype.sliceTopClassStr = "Top";
+Spry.Widget.Base.prototype.sliceBottomClassStr = "Bottom";
+
+Spry.Widget.Base.prototype.sliceFuncs = {};
+
+Spry.Widget.Base.prototype.sliceFuncs["2slice"] = function(root, eleName, baseClassName)
+{
+ var a = root ? root : document.createElement(eleName);
+ var b = document.createElement(eleName);
+
+ this.appendChildNodes(b, this.extractChildNodes(a)); // Transfer any children into the new content container.
+
+ a.appendChild(b);
+
+ this.addClassName(a, baseClassName + this.sliceLeftClassStr);
+ b.className = baseClassName + this.sliceRightClassStr;
+
+ a.contentContainer = b;
+
+ return a;
+};
+
+Spry.Widget.Base.prototype.sliceFuncs["3slice"] = function(root, eleName, baseClassName)
+{
+ var a = root ? root : document.createElement(eleName);
+ var b = document.createElement(eleName);
+ var c = document.createElement(eleName);
+
+ this.appendChildNodes(c, this.extractChildNodes(a)); // Transfer any children into the new content container.
+
+ a.appendChild(b);
+ b.appendChild(c);
+
+ this.addClassName(a, baseClassName + this.sliceLeftClassStr);
+ b.className = baseClassName + this.sliceRightClassStr;
+ c.className = baseClassName + this.sliceCenterClassStr;
+
+ a.contentContainer = c;
+
+ return a;
+};
+
+Spry.Widget.Base.prototype.sliceFuncs["3sliceStacked"] = function(root, eleName, baseClassName)
+{
+ root = root ? root : document.createElement(eleName);
+
+ var l = document.createElement(eleName);
+ var m = document.createElement(eleName);
+ var r = document.createElement(eleName);
+
+ this.appendChildNodes(m, this.extractChildNodes(root)); // Transfer any children into the new content container.
+
+ root.appendChild(l);
+ root.appendChild(m);
+ root.appendChild(r);
+
+ this.addClassName(root, baseClassName);
+ l.className = baseClassName + this.sliceLeftClassStr;
+ m.className = baseClassName + this.sliceCenterClassStr;
+ r.className = baseClassName + this.sliceRightClassStr;
+
+ root.contentContainer = m;
+
+ return root;
+};
+
+Spry.Widget.Base.prototype.sliceFuncs["9slice"] = function(root, eleName, baseClassName)
+{
+ if (!root)
+ root = document.createElement(eleName);
+ this.addClassName(root, baseClassName);
+
+ var t = this.create3SliceStructure(null, eleName, baseClassName + this.sliceTopClassStr);
+ var m = this.create3SliceStructure(null, eleName, baseClassName);
+ var b = this.create3SliceStructure(null, eleName, baseClassName + this.sliceBottomClassStr);
+
+ this.appendChildNodes(m.contentContainer, this.extractChildNodes(root)); // Transfer any children into the new content container.
+
+ root.appendChild(t);
+ root.appendChild(m);
+ root.appendChild(b);
+
+ var contentContainer = m.contentContainer;
+ root.contentContainer = contentContainer;
+ contentContainer.rootContainer = root;
+
+ return root;
+};
+
+// XXX: REMOVE THESE AFTER WIDGETS HAVE BEEN CLEANED UP!
+Spry.Widget.Base.prototype.create3SliceStructure = Spry.Widget.Base.prototype.sliceFuncs["3slice"];
+Spry.Widget.Base.prototype.create9SliceStructure = Spry.Widget.Base.prototype.sliceFuncs["9slice"];
+// XXX
+
+Spry.Widget.Base.prototype.createOptionalSlicedStructure = function(root, eleName, className, sliceMap, childEleName)
+{
+ // root - null or the dom element that will serve as the root of the sliced structure.
+ // If null, this function will create the root container using the element name specified.
+ // eleName - The tag to use when creating the sliced structure.
+ // className - The class names placed on each element within the sliced structure will be derived from this name.
+ // sliceMap - null or a dictionary of class name keys whose values are either "9slice", "3slice", or "none".
+ // If null, the widget's sliceMap property is used.
+ // childEleName - If specified, the eleName arg will only be used for the first element created within the structure. All
+ // other elements will be created with the specified childEleName.
+
+ if (!sliceMap)
+ sliceMap = this.sliceMap ? this.sliceMap : {};
+
+ if (!childEleName)
+ childEleName = eleName;
+
+ var sliceType = sliceMap[className];
+ sliceType = sliceType ? sliceType : "none";
+
+ if (!root)
+ root = document.createElement(eleName);
+ this.addClassName(root, className);
+
+ var sliceFunc = this.sliceFuncs[sliceType];
+ if (sliceFunc)
+ root = sliceFunc.call(this, root, childEleName, className);
+ else
+ root.contentContainer = root;
+
+ return root;
+};
+
+Spry.Widget.Base.prototype.extractChildNodes = function(ele)
+{
+ var children = [];
+ while (ele.firstChild)
+ {
+ var c = ele.firstChild;
+ children.push(c);
+ ele.removeChild(c);
+ }
+ return children;
+};
+
+Spry.Widget.Base.prototype.appendChildNodes = function(ele, nodes)
+{
+ for (var i = 0; i < nodes.length; i++)
+ ele.appendChild(nodes[i]);
+};
+
+Spry.Widget.Base.prototype.setOptions = Spry.Widget.setOptions;
+Spry.Widget.Base.prototype.getOnLoadDidFire = function() { return Spry.Widget.onLoadDidFire; };
+Spry.Widget.Base.prototype.addCallbackToOnLoadQueue = Spry.Widget.addCallbackToOnLoadQueue;
+Spry.Widget.Base.prototype.triggerCallbackAfterOnLoad = Spry.Widget.triggerCallbackAfterOnLoad;
+
+Spry.Widget.Base.prototype.getElement = Spry.Widget.Base.getElement;
+Spry.Widget.Base.prototype.getElements = Spry.Widget.Base.getElements;
+Spry.Widget.Base.prototype.addClassName = Spry.Utils.addClassName;
+Spry.Widget.Base.prototype.hasClassName = Spry.Utils.hasClassName;
+Spry.Widget.Base.prototype.removeClassName = Spry.Utils.removeClassName;
+Spry.Widget.Base.prototype.addEventListener = Spry.Utils.addEventListener;
+Spry.Widget.Base.prototype.removeEventListener = Spry.Utils.removeEventListener;
+
+Spry.Widget.Base.prototype.getClientPosition = function(ele)
+{
+ var pos = new Object;
+ pos.x = ele.offsetLeft;
+ pos.y = ele.offsetTop;
+ var parent = ele.offsetParent;
+ while (parent)
+ {
+ pos.x += parent.offsetLeft;
+ pos.y += parent.offsetTop;
+ parent = parent.offsetParent;
+ }
+ return pos;
+};
+
+Spry.Widget.Base.prototype.getStyleProp = function(element, prop)
+{
+ var value;
+ var camelized = Spry.Utils.camelizeString(prop);
+ try
+ {
+ if (element.style)
+ value = element.style[camelized];
+
+ if (!value)
+ {
+ if (document.defaultView && document.defaultView.getComputedStyle)
+ {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css.getPropertyValue(prop) : null;
+ }
+ else if (element.currentStyle)
+ {
+ value = element.currentStyle[camelized];
+ }
+ }
+ }
+ catch (e) {}
+
+ return value == 'auto' ? null : value;
+};
+
+Spry.Widget.Base.prototype.makePositioned = function(element)
+{
+ var pos = this.getStyleProp(element, 'position');
+ if (!pos || pos == 'static')
+ {
+ element.style.position = 'relative';
+
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera)
+ {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+};
+
+Spry.Widget.Base.prototype.clearIEAlphaFilter = function(ele)
+{
+ var filter = ele.style.filter;
+
+ // IE uses an alpha() filter for opacity. The filter style
+ // property can contain multiple commands, so the idea here
+ // is to just strip out the alpha(filter) and append a new
+ // one, leaving any other filters untouched.
+
+ if (filter)
+ {
+ filter = filter.replace(/alpha\([^\)]*\)/, "");
+ filter = filter.replace(/^\s+|\s+$/, "");
+ ele.style.filter = filter;
+ }
+ else
+ filter = "";
+
+ return filter;
+};
+
+Spry.Widget.Base.prototype.setOpacity = function(ele, opacity)
+{
+ ele.style.opacity = "" + opacity;
+
+ var filter = this.clearIEAlphaFilter(ele);
+ if (filter)
+ filter += " ";
+
+ ele.style.filter = filter + "alpha(opacity=" + (opacity*100) + ")";
+};
+
+Spry.Widget.Event = function(widget, opts)
+{
+ this.widget = widget;
+ Spry.Widget.setOptions(this, opts);
+ this.performDefaultAction = true;
+};
+
+Spry.Widget.Event.prototype.preventDefault = function() { this.performDefaultAction = false; };
+
+////////////////////////////////////////////////////////
+
+Spry.Widget.Button = function(ele, opts)
+{
+ Spry.Widget.Base.call(this);
+
+ this.element = Spry.$$(ele)[0];
+
+ // Initialize the button object with the global defaults.
+
+ this.setOptions(this, Spry.Widget.Button.config);
+
+ // Override the defaults with any options passed into the constructor.
+
+ this.setOptions(this, opts);
+
+ var self = this;
+
+ this.addEventListener(this.element, "mousedown", function(e) { return self.handleMouseDown(e); }, false);
+ this.addEventListener(this.element, "mouseover", function(e) { return self.handleMouseOver(e); }, false);
+ this.addEventListener(this.element, "mouseout", function(e) { return self.handleMouseOut(e); }, false);
+ this.addEventListener(this.element, "focus", function(e) { return self.handleFocus(e); }, false);
+ this.addEventListener(this.element, "blur", function(e) { return self.handleBlur(e); }, false);
+
+ // We need to eat the onclick event so that buttons made
+ // from links don't follow the link.
+
+ this.addEventListener(this.element, "click", function(e) { return false; }, false);
+
+ this.mouseUpCallback = function(evt) { return self.handleMouseUp(evt); };
+};
+
+Spry.Widget.Button.config = {
+ disabled: false,
+ mouseOutCancelsClick: true,
+ onclick: null,
+ downClass: "ButtonDown",
+ hoverClass: "ButtonHover",
+ disabledClass: "ButtonDisabled",
+ focusedClass: "ButtonFocused"
+};
+
+
+Spry.Widget.Button.prototype = new Spry.Widget.Base();
+Spry.Widget.Button.prototype.constructor = Spry.Widget.Button;
+
+Spry.Widget.Button.prototype.handleMouseDown = function(evt)
+{
+ if (this.disabled)
+ return false;
+
+ this.addClassName(this.element, this.downClass);
+ this.addEventListener(document, "mouseup", this.mouseUpCallback, true);
+
+ this.notifyObservers("onButtonDown", { event: evt });
+
+ return false;
+};
+
+Spry.Widget.Button.prototype.handleMouseUp = function(evt)
+{
+ if (this.disabled)
+ return false;
+
+ this.removeClassName(this.element, this.downClass);
+ this.removeEventListener(document, "mouseup", this.mouseUpCallback, true);
+
+ if (this.onclick)
+ this.onclick(evt);
+
+ this.notifyObservers("onButtonUp");
+ this.notifyObservers("onButtonClick");
+
+ return false;
+};
+
+Spry.Widget.Button.prototype.handleMouseOver = function(evt)
+{
+ if (this.disabled)
+ return false;
+
+ this.addClassName(this.element, this.hoverClass);
+ this.notifyObservers("onButtonEnter");
+
+ return false;
+};
+
+Spry.Widget.Button.prototype.handleMouseOut = function(evt)
+{
+ if (this.disabled)
+ return false;
+
+ var ele = this.element;
+ this.removeClassName(ele, this.hoverClass);
+
+ if (this.mouseOutCancelsClick)
+ {
+ this.removeClassName(ele, this.downClass);
+ this.removeEventListener(document, "mouseup", this.mouseUpCallback, true);
+ }
+
+ this.notifyObservers("onButtonExit");
+
+ return false;
+};
+
+Spry.Widget.Button.prototype.handleFocus = function(evt)
+{
+ if (this.disabled)
+ return false;
+
+ this.addClassName(this.element, this.focusedClass);
+ this.notifyObservers("onButtonFocused");
+
+ return false;
+};
+
+Spry.Widget.Button.prototype.handleBlur = function(evt)
+{
+ if (this.disabled)
+ return false;
+
+ this.removeClassName(this.element, this.focusedClass);
+ this.notifyObservers("onButtonBlur");
+
+ return false;
+};
+
+Spry.Widget.Button.prototype.disable = function()
+{
+ this.disabled = true;
+ this.removeClassName(this.element, this.downClass);
+ this.removeClassName(this.element, this.hoverClass);
+ this.addClassName(this.element, this.disabledClass);
+ this.removeEventListener(document, "mouseup", this.mouseUpCallback, true);
+};
+
+Spry.Widget.Button.prototype.enable = function()
+{
+ this.disabled = false;
+ this.removeClassName(this.element, this.disabledClass);
+};
+
+})(); // EndSpryComponent
\ No newline at end of file