Permalink
Browse files

add in some files i didn't have added r616

git-svn-id: http://svn.php.net/repository/pear/packages/HTML_AJAX/trunk@259274 c90b9560-bf6c-de11-be94-00142212c4b1
  • Loading branch information...
1 parent 21e5a04 commit bbabc282667e76be51a24b5de9c4e0edf2226811 Joshua Eichorn committed May 7, 2008
View
142 js/behavior/cssQuery-src/cssQuery-level2.js
@@ -0,0 +1,142 @@
+/*
+ cssQuery, version 2.0.2 (2005-08-19)
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
+ License: http://creativecommons.org/licenses/LGPL/2.1/
+*/
+
+cssQuery.addModule("css-level2", function() {
+
+// -----------------------------------------------------------------------
+// selectors
+// -----------------------------------------------------------------------
+
+// child selector
+selectors[">"] = function($results, $from, $tagName, $namespace) {
+ var $element, i, j;
+ for (i = 0; i < $from.length; i++) {
+ var $subset = childElements($from[i]);
+ for (j = 0; ($element = $subset[j]); j++)
+ if (compareTagName($element, $tagName, $namespace))
+ $results.push($element);
+ }
+};
+
+// sibling selector
+selectors["+"] = function($results, $from, $tagName, $namespace) {
+ for (var i = 0; i < $from.length; i++) {
+ var $element = nextElementSibling($from[i]);
+ if ($element && compareTagName($element, $tagName, $namespace))
+ $results.push($element);
+ }
+};
+
+// attribute selector
+selectors["@"] = function($results, $from, $attributeSelectorID) {
+ var $test = attributeSelectors[$attributeSelectorID].test;
+ var $element, i;
+ for (i = 0; ($element = $from[i]); i++)
+ if ($test($element)) $results.push($element);
+};
+
+// -----------------------------------------------------------------------
+// pseudo-classes
+// -----------------------------------------------------------------------
+
+pseudoClasses["first-child"] = function($element) {
+ return !previousElementSibling($element);
+};
+
+pseudoClasses["lang"] = function($element, $code) {
+ $code = new RegExp("^" + $code, "i");
+ while ($element && !$element.getAttribute("lang")) $element = $element.parentNode;
+ return $element && $code.test($element.getAttribute("lang"));
+};
+
+// -----------------------------------------------------------------------
+// attribute selectors
+// -----------------------------------------------------------------------
+
+// constants
+AttributeSelector.NS_IE = /\\:/g;
+AttributeSelector.PREFIX = "@";
+// properties
+AttributeSelector.tests = {};
+// methods
+AttributeSelector.replace = function($match, $attribute, $namespace, $compare, $value) {
+ var $key = this.PREFIX + $match;
+ if (!attributeSelectors[$key]) {
+ $attribute = this.create($attribute, $compare || "", $value || "");
+ // store the selector
+ attributeSelectors[$key] = $attribute;
+ attributeSelectors.push($attribute);
+ }
+ return attributeSelectors[$key].id;
+};
+AttributeSelector.parse = function($selector) {
+ $selector = $selector.replace(this.NS_IE, "|");
+ var $match;
+ while ($match = $selector.match(this.match)) {
+ var $replace = this.replace($match[0], $match[1], $match[2], $match[3], $match[4]);
+ $selector = $selector.replace(this.match, $replace);
+ }
+ return $selector;
+};
+AttributeSelector.create = function($propertyName, $test, $value) {
+ var $attributeSelector = {};
+ $attributeSelector.id = this.PREFIX + attributeSelectors.length;
+ $attributeSelector.name = $propertyName;
+ $test = this.tests[$test];
+ $test = $test ? $test(this.getAttribute($propertyName), getText($value)) : false;
+ $attributeSelector.test = new Function("e", "return " + $test);
+ return $attributeSelector;
+};
+AttributeSelector.getAttribute = function($name) {
+ switch ($name.toLowerCase()) {
+ case "id":
+ return "e.id";
+ case "class":
+ return "e.className";
+ case "for":
+ return "e.htmlFor";
+ case "href":
+ if (isMSIE) {
+ // IE always returns the full path not the fragment in the href attribute
+ // so we RegExp it out of outerHTML. Opera does the same thing but there
+ // is no way to get the original attribute.
+ return "String((e.outerHTML.match(/href=\\x22?([^\\s\\x22]*)\\x22?/)||[])[1]||'')";
+ }
+ }
+ return "e.getAttribute('" + $name.replace($NAMESPACE, ":") + "')";
+};
+
+// -----------------------------------------------------------------------
+// attribute selector tests
+// -----------------------------------------------------------------------
+
+AttributeSelector.tests[""] = function($attribute) {
+ return $attribute;
+};
+
+AttributeSelector.tests["="] = function($attribute, $value) {
+ return $attribute + "==" + Quote.add($value);
+};
+
+AttributeSelector.tests["~="] = function($attribute, $value) {
+ return "/(^| )" + regEscape($value) + "( |$)/.test(" + $attribute + ")";
+};
+
+AttributeSelector.tests["|="] = function($attribute, $value) {
+ return "/^" + regEscape($value) + "(-|$)/.test(" + $attribute + ")";
+};
+
+// -----------------------------------------------------------------------
+// parsing
+// -----------------------------------------------------------------------
+
+// override parseSelector to parse out attribute selectors
+var _parseSelector = parseSelector;
+parseSelector = function($selector) {
+ return _parseSelector(AttributeSelector.parse($selector));
+};
+
+}); // addModule
View
150 js/behavior/cssQuery-src/cssQuery-level3.js
@@ -0,0 +1,150 @@
+/*
+ cssQuery, version 2.0.2 (2005-08-19)
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
+ License: http://creativecommons.org/licenses/LGPL/2.1/
+*/
+
+/* Thanks to Bill Edney */
+
+cssQuery.addModule("css-level3", function() {
+
+// -----------------------------------------------------------------------
+// selectors
+// -----------------------------------------------------------------------
+
+// indirect sibling selector
+selectors["~"] = function($results, $from, $tagName, $namespace) {
+ var $element, i;
+ for (i = 0; ($element = $from[i]); i++) {
+ while ($element = nextElementSibling($element)) {
+ if (compareTagName($element, $tagName, $namespace))
+ $results.push($element);
+ }
+ }
+};
+
+// -----------------------------------------------------------------------
+// pseudo-classes
+// -----------------------------------------------------------------------
+
+// I'm hoping these pseudo-classes are pretty readable. Let me know if
+// any need explanation.
+
+pseudoClasses["contains"] = function($element, $text) {
+ $text = new RegExp(regEscape(getText($text)));
+ return $text.test(getTextContent($element));
+};
+
+pseudoClasses["root"] = function($element) {
+ return $element == getDocument($element).documentElement;
+};
+
+pseudoClasses["empty"] = function($element) {
+ var $node, i;
+ for (i = 0; ($node = $element.childNodes[i]); i++) {
+ if (thisElement($node) || $node.nodeType == 3) return false;
+ }
+ return true;
+};
+
+pseudoClasses["last-child"] = function($element) {
+ return !nextElementSibling($element);
+};
+
+pseudoClasses["only-child"] = function($element) {
+ $element = $element.parentNode;
+ return firstElementChild($element) == lastElementChild($element);
+};
+
+pseudoClasses["not"] = function($element, $selector) {
+ var $negated = cssQuery($selector, getDocument($element));
+ for (var i = 0; i < $negated.length; i++) {
+ if ($negated[i] == $element) return false;
+ }
+ return true;
+};
+
+pseudoClasses["nth-child"] = function($element, $arguments) {
+ return nthChild($element, $arguments, previousElementSibling);
+};
+
+pseudoClasses["nth-last-child"] = function($element, $arguments) {
+ return nthChild($element, $arguments, nextElementSibling);
+};
+
+pseudoClasses["target"] = function($element) {
+ return $element.id == location.hash.slice(1);
+};
+
+// UI element states
+
+pseudoClasses["checked"] = function($element) {
+ return $element.checked;
+};
+
+pseudoClasses["enabled"] = function($element) {
+ return $element.disabled === false;
+};
+
+pseudoClasses["disabled"] = function($element) {
+ return $element.disabled;
+};
+
+pseudoClasses["indeterminate"] = function($element) {
+ return $element.indeterminate;
+};
+
+// -----------------------------------------------------------------------
+// attribute selector tests
+// -----------------------------------------------------------------------
+
+AttributeSelector.tests["^="] = function($attribute, $value) {
+ return "/^" + regEscape($value) + "/.test(" + $attribute + ")";
+};
+
+AttributeSelector.tests["$="] = function($attribute, $value) {
+ return "/" + regEscape($value) + "$/.test(" + $attribute + ")";
+};
+
+AttributeSelector.tests["*="] = function($attribute, $value) {
+ return "/" + regEscape($value) + "/.test(" + $attribute + ")";
+};
+
+// -----------------------------------------------------------------------
+// nth child support (Bill Edney)
+// -----------------------------------------------------------------------
+
+function nthChild($element, $arguments, $traverse) {
+ switch ($arguments) {
+ case "n": return true;
+ case "even": $arguments = "2n"; break;
+ case "odd": $arguments = "2n+1";
+ }
+
+ var $$children = childElements($element.parentNode);
+ function _checkIndex($index) {
+ var $index = ($traverse == nextElementSibling) ? $$children.length - $index : $index - 1;
+ return $$children[$index] == $element;
+ };
+
+ // it was just a number (no "n")
+ if (!isNaN($arguments)) return _checkIndex($arguments);
+
+ $arguments = $arguments.split("n");
+ var $multiplier = parseInt($arguments[0]);
+ var $step = parseInt($arguments[1]);
+
+ if ((isNaN($multiplier) || $multiplier == 1) && $step == 0) return true;
+ if ($multiplier == 0 && !isNaN($step)) return _checkIndex($step);
+ if (isNaN($step)) $step = 0;
+
+ var $count = 1;
+ while ($element = $traverse($element)) $count++;
+
+ if (isNaN($multiplier) || $multiplier == 1)
+ return ($traverse == nextElementSibling) ? ($count <= $step) : ($step >= $count);
+
+ return ($count % $multiplier) == $step;
+};
+
+}); // addModule
View
53 js/behavior/cssQuery-src/cssQuery-standard.js
@@ -0,0 +1,53 @@
+/*
+ cssQuery, version 2.0.2 (2005-08-19)
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
+ License: http://creativecommons.org/licenses/LGPL/2.1/
+*/
+
+cssQuery.addModule("css-standard", function() { // override IE optimisation
+
+// cssQuery was originally written as the CSS engine for IE7. It is
+// optimised (in terms of size not speed) for IE so this module is
+// provided separately to provide cross-browser support.
+
+// -----------------------------------------------------------------------
+// browser compatibility
+// -----------------------------------------------------------------------
+
+// sniff for Win32 Explorer
+isMSIE = eval("false;/*@cc_on@if(@\x5fwin32)isMSIE=true@end@*/");
+
+if (!isMSIE) {
+ getElementsByTagName = function($element, $tagName, $namespace) {
+ return $namespace ? $element.getElementsByTagNameNS("*", $tagName) :
+ $element.getElementsByTagName($tagName);
+ };
+
+ compareNamespace = function($element, $namespace) {
+ return !$namespace || ($namespace == "*") || ($element.prefix == $namespace);
+ };
+
+ isXML = document.contentType ? function($element) {
+ return /xml/i.test(getDocument($element).contentType);
+ } : function($element) {
+ return getDocument($element).documentElement.tagName != "HTML";
+ };
+
+ getTextContent = function($element) {
+ // mozilla || opera || other
+ return $element.textContent || $element.innerText || _getTextContent($element);
+ };
+
+ function _getTextContent($element) {
+ var $textContent = "", $node, i;
+ for (i = 0; ($node = $element.childNodes[i]); i++) {
+ switch ($node.nodeType) {
+ case 11: // document fragment
+ case 1: $textContent += _getTextContent($node); break;
+ case 3: $textContent += $node.nodeValue; break;
+ }
+ }
+ return $textContent;
+ };
+}
+}); // addModule
View
356 js/behavior/cssQuery-src/cssQuery.js
@@ -0,0 +1,356 @@
+/*
+ cssQuery, version 2.0.2 (2005-08-19)
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
+ License: http://creativecommons.org/licenses/LGPL/2.1/
+*/
+
+// the following functions allow querying of the DOM using CSS selectors
+var cssQuery = function() {
+var version = "2.0.2";
+
+// -----------------------------------------------------------------------
+// main query function
+// -----------------------------------------------------------------------
+
+var $COMMA = /\s*,\s*/;
+var cssQuery = function($selector, $$from) {
+try {
+ var $match = [];
+ var $useCache = arguments.callee.caching && !$$from;
+ var $base = ($$from) ? ($$from.constructor == Array) ? $$from : [$$from] : [document];
+ // process comma separated selectors
+ var $$selectors = parseSelector($selector).split($COMMA), i;
+ for (i = 0; i < $$selectors.length; i++) {
+ // convert the selector to a stream
+ $selector = _toStream($$selectors[i]);
+ // faster chop if it starts with id (MSIE only)
+ if (isMSIE && $selector.slice(0, 3).join("") == " *#") {
+ $selector = $selector.slice(2);
+ $$from = _msie_selectById([], $base, $selector[1]);
+ } else $$from = $base;
+ // process the stream
+ var j = 0, $token, $filter, $arguments, $cacheSelector = "";
+ while (j < $selector.length) {
+ $token = $selector[j++];
+ $filter = $selector[j++];
+ $cacheSelector += $token + $filter;
+ // some pseudo-classes allow arguments to be passed
+ // e.g. nth-child(even)
+ $arguments = "";
+ if ($selector[j] == "(") {
+ while ($selector[j++] != ")" && j < $selector.length) {
+ $arguments += $selector[j];
+ }
+ $arguments = $arguments.slice(0, -1);
+ $cacheSelector += "(" + $arguments + ")";
+ }
+ // process a token/filter pair use cached results if possible
+ $$from = ($useCache && cache[$cacheSelector]) ?
+ cache[$cacheSelector] : select($$from, $token, $filter, $arguments);
+ if ($useCache) cache[$cacheSelector] = $$from;
+ }
+ $match = $match.concat($$from);
+ }
+ delete cssQuery.error;
+ return $match;
+} catch ($error) {
+ cssQuery.error = $error;
+ return [];
+}};
+
+// -----------------------------------------------------------------------
+// public interface
+// -----------------------------------------------------------------------
+
+cssQuery.toString = function() {
+ return "function cssQuery() {\n [version " + version + "]\n}";
+};
+
+// caching
+var cache = {};
+cssQuery.caching = false;
+cssQuery.clearCache = function($selector) {
+ if ($selector) {
+ $selector = _toStream($selector).join("");
+ delete cache[$selector];
+ } else cache = {};
+};
+
+// allow extensions
+var modules = {};
+var loaded = false;
+cssQuery.addModule = function($name, $script) {
+ if (loaded) eval("$script=" + String($script));
+ modules[$name] = new $script();;
+};
+
+// hackery
+cssQuery.valueOf = function($code) {
+ return $code ? eval($code) : this;
+};
+
+// -----------------------------------------------------------------------
+// declarations
+// -----------------------------------------------------------------------
+
+var selectors = {};
+var pseudoClasses = {};
+// a safari bug means that these have to be declared here
+var AttributeSelector = {match: /\[([\w-]+(\|[\w-]+)?)\s*(\W?=)?\s*([^\]]*)\]/};
+var attributeSelectors = [];
+
+// -----------------------------------------------------------------------
+// selectors
+// -----------------------------------------------------------------------
+
+// descendant selector
+selectors[" "] = function($results, $from, $tagName, $namespace) {
+ // loop through current selection
+ var $element, i, j;
+ for (i = 0; i < $from.length; i++) {
+ // get descendants
+ var $subset = getElementsByTagName($from[i], $tagName, $namespace);
+ // loop through descendants and add to results selection
+ for (j = 0; ($element = $subset[j]); j++) {
+ if (thisElement($element) && compareNamespace($element, $namespace))
+ $results.push($element);
+ }
+ }
+};
+
+// ID selector
+selectors["#"] = function($results, $from, $id) {
+ // loop through current selection and check ID
+ var $element, j;
+ for (j = 0; ($element = $from[j]); j++) if ($element.id == $id) $results.push($element);
+};
+
+// class selector
+selectors["."] = function($results, $from, $className) {
+ // create a RegExp version of the class
+ $className = new RegExp("(^|\\s)" + $className + "(\\s|$)");
+ // loop through current selection and check class
+ var $element, i;
+ for (i = 0; ($element = $from[i]); i++)
+ if ($className.test($element.className)) $results.push($element);
+};
+
+// pseudo-class selector
+selectors[":"] = function($results, $from, $pseudoClass, $arguments) {
+ // retrieve the cssQuery pseudo-class function
+ var $test = pseudoClasses[$pseudoClass], $element, i;
+ // loop through current selection and apply pseudo-class filter
+ if ($test) for (i = 0; ($element = $from[i]); i++)
+ // if the cssQuery pseudo-class function returns "true" add the element
+ if ($test($element, $arguments)) $results.push($element);
+};
+
+// -----------------------------------------------------------------------
+// pseudo-classes
+// -----------------------------------------------------------------------
+
+pseudoClasses["link"] = function($element) {
+ var $document = getDocument($element);
+ if ($document.links) for (var i = 0; i < $document.links.length; i++) {
+ if ($document.links[i] == $element) return true;
+ }
+};
+
+pseudoClasses["visited"] = function($element) {
+ // can't do this without jiggery-pokery
+};
+
+// -----------------------------------------------------------------------
+// DOM traversal
+// -----------------------------------------------------------------------
+
+// IE5/6 includes comments (LOL) in it's elements collections.
+// so we have to check for this. the test is tagName != "!". LOL (again).
+var thisElement = function($element) {
+ return ($element && $element.nodeType == 1 && $element.tagName != "!") ? $element : null;
+};
+
+// return the previous element to the supplied element
+// previousSibling is not good enough as it might return a text or comment node
+var previousElementSibling = function($element) {
+ while ($element && ($element = $element.previousSibling) && !thisElement($element)) continue;
+ return $element;
+};
+
+// return the next element to the supplied element
+var nextElementSibling = function($element) {
+ while ($element && ($element = $element.nextSibling) && !thisElement($element)) continue;
+ return $element;
+};
+
+// return the first child ELEMENT of an element
+// NOT the first child node (though they may be the same thing)
+var firstElementChild = function($element) {
+ return thisElement($element.firstChild) || nextElementSibling($element.firstChild);
+};
+
+var lastElementChild = function($element) {
+ return thisElement($element.lastChild) || previousElementSibling($element.lastChild);
+};
+
+// return child elements of an element (not child nodes)
+var childElements = function($element) {
+ var $childElements = [];
+ $element = firstElementChild($element);
+ while ($element) {
+ $childElements.push($element);
+ $element = nextElementSibling($element);
+ }
+ return $childElements;
+};
+
+// -----------------------------------------------------------------------
+// browser compatibility
+// -----------------------------------------------------------------------
+
+// all of the functions in this section can be overwritten. the default
+// configuration is for IE. The functions below reflect this. standard
+// methods are included in a separate module. It would probably be better
+// the other way round of course but this makes it easier to keep IE7 trim.
+
+var isMSIE = true;
+
+var isXML = function($element) {
+ var $document = getDocument($element);
+ return (typeof $document.mimeType == "unknown") ?
+ /\.xml$/i.test($document.URL) :
+ Boolean($document.mimeType == "XML Document");
+};
+
+// return the element's containing document
+var getDocument = function($element) {
+ return $element.ownerDocument || $element.document;
+};
+
+var getElementsByTagName = function($element, $tagName) {
+ return ($tagName == "*" && $element.all) ? $element.all : $element.getElementsByTagName($tagName);
+};
+
+var compareTagName = function($element, $tagName, $namespace) {
+ if ($tagName == "*") return thisElement($element);
+ if (!compareNamespace($element, $namespace)) return false;
+ if (!isXML($element)) $tagName = $tagName.toUpperCase();
+ return $element.tagName == $tagName;
+};
+
+var compareNamespace = function($element, $namespace) {
+ return !$namespace || ($namespace == "*") || ($element.scopeName == $namespace);
+};
+
+var getTextContent = function($element) {
+ return $element.innerText;
+};
+
+function _msie_selectById($results, $from, id) {
+ var $match, i, j;
+ for (i = 0; i < $from.length; i++) {
+ if ($match = $from[i].all.item(id)) {
+ if ($match.id == id) $results.push($match);
+ else if ($match.length != null) {
+ for (j = 0; j < $match.length; j++) {
+ if ($match[j].id == id) $results.push($match[j]);
+ }
+ }
+ }
+ }
+ return $results;
+};
+
+// for IE5.0
+if (![].push) Array.prototype.push = function() {
+ for (var i = 0; i < arguments.length; i++) {
+ this[this.length] = arguments[i];
+ }
+ return this.length;
+};
+
+// -----------------------------------------------------------------------
+// query support
+// -----------------------------------------------------------------------
+
+// select a set of matching elements.
+// "from" is an array of elements.
+// "token" is a character representing the type of filter
+// e.g. ">" means child selector
+// "filter" represents the tag name, id or class name that is being selected
+// the function returns an array of matching elements
+var $NAMESPACE = /\|/;
+function select($$from, $token, $filter, $arguments) {
+ if ($NAMESPACE.test($filter)) {
+ $filter = $filter.split($NAMESPACE);
+ $arguments = $filter[0];
+ $filter = $filter[1];
+ }
+ var $results = [];
+ if (selectors[$token]) {
+ selectors[$token]($results, $$from, $filter, $arguments);
+ }
+ return $results;
+};
+
+// -----------------------------------------------------------------------
+// parsing
+// -----------------------------------------------------------------------
+
+// convert css selectors to a stream of tokens and filters
+// it's not a real stream. it's just an array of strings.
+var $STANDARD_SELECT = /^[^\s>+~]/;
+var $$STREAM = /[\s#.:>+~()@]|[^\s#.:>+~()@]+/g;
+function _toStream($selector) {
+ if ($STANDARD_SELECT.test($selector)) $selector = " " + $selector;
+ return $selector.match($$STREAM) || [];
+};
+
+var $WHITESPACE = /\s*([\s>+~(),]|^|$)\s*/g;
+var $IMPLIED_ALL = /([\s>+~,]|[^(]\+|^)([#.:@])/g;
+var parseSelector = function($selector) {
+ return $selector
+ // trim whitespace
+ .replace($WHITESPACE, "$1")
+ // e.g. ".class1" --> "*.class1"
+ .replace($IMPLIED_ALL, "$1*$2");
+};
+
+var Quote = {
+ toString: function() {return "'"},
+ match: /^('[^']*')|("[^"]*")$/,
+ test: function($string) {
+ return this.match.test($string);
+ },
+ add: function($string) {
+ return this.test($string) ? $string : this + $string + this;
+ },
+ remove: function($string) {
+ return this.test($string) ? $string.slice(1, -1) : $string;
+ }
+};
+
+var getText = function($text) {
+ return Quote.remove($text);
+};
+
+var $ESCAPE = /([\/()[\]?{}|*+-])/g;
+function regEscape($string) {
+ return $string.replace($ESCAPE, "\\$1");
+};
+
+// -----------------------------------------------------------------------
+// modules
+// -----------------------------------------------------------------------
+
+// -------- >> insert modules here for packaging << -------- \\
+
+loaded = true;
+
+// -----------------------------------------------------------------------
+// return the query function
+// -----------------------------------------------------------------------
+
+return cssQuery;
+
+}(); // cssQuery
View
5 js/behavior/cssQuery-src/readme.txt
@@ -0,0 +1,5 @@
+Source code for cssQuery-p.js
+
+See http://dean.edwards.name/my/cssQuery/ for more information
+
+This code is released under the LGPL
View
109 js/behavior/cssQuery-src/test.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+ <title>cssQuery Test Page</title>
+ <meta name="author" content="Dean Edwards"/>
+ <!-- keeping code tidy!! -->
+ <meta name="copyright" content="&copy; copyright 2005, Dean Edwards"/>
+ <style type="text/css">
+ p.test a {background-color: red;}
+ </style>
+ <script src="cssQuery.js" type="text/javascript"></script>
+ <script src="cssQuery-level2.js" type="text/javascript"></script>
+ <script src="cssQuery-level3.js" type="text/javascript"></script>
+ <script src="cssQuery-standard.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ onload = function() {
+ var styles = document.getElementsByTagName("pre");
+ for (var i = 0; i < styles.length; i++) test(styles[i]);
+
+ function test(style) {
+ var rule = style.firstChild.nodeValue;
+ var selector = rule.slice(0, rule.indexOf("{"));
+
+ var elements = cssQuery(selector);
+
+ for (var i = 0; i < elements.length; i++) {
+ elements[i].style.backgroundColor = "lime";
+ }
+ };
+ };
+ </script>
+</head>
+
+<body lang="en">
+ <h2>cssQuery Test Page</h2>
+
+ <h3><abbr>CSS</abbr> Level 1</h3>
+
+ <pre>#test1-1 p a {background-color: lime;}</pre>
+ <div id="test1-1"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test1-2 :link {background-color: lime;}</pre>
+ <div id="test1-2"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <h3><abbr>CSS</abbr> Level 2</h3>
+
+ <pre>#test2-1 p.test.link a {background-color: lime;}</pre>
+ <div id="test2-1"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test2-2 p > a {background-color: lime;}</pre>
+ <div id="test2-2"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test2-3 span + a {background-color: lime;}</pre>
+ <div id="test2-3"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test2-4 p:first-child a {background-color: lime;}</pre>
+ <div id="test2-4"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test2-5 a:lang(en) {background-color: lime;}</pre>
+ <div id="test2-5"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test2-6 a[href] {background-color: lime;}</pre>
+ <div id="test2-6"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test2-7 a[title="This is a link"] {background-color: lime;}</pre>
+ <div id="test2-7"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test2-8 a[title~="is"] {background-color: lime;}</pre>
+ <div id="test2-8"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>div[id|=test2-9] a {background-color: lime;}</pre>
+ <div id="test2-9"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <h3><abbr>CSS</abbr> Level 3</h3>
+
+ <pre>#test3-1 span ~ a {background-color: lime;}</pre>
+ <div id="test3-1"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test3-2 p:last-child a {background-color: lime;}</pre>
+ <div id="test3-2"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test3-3 a:contains("test") {background-color: lime;}</pre>
+ <div id="test3-3"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test3-4 p :not(span) {background-color: lime;}</pre>
+ <div id="test3-4"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test3-5 p:only-child a {background-color: lime;}</pre>
+ <div id="test3-5"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test3-6 p *:nth-child(even) {background-color: lime;}</pre>
+ <div id="test3-6"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test3-7 p *:nth-last-child(2n+1) {background-color: lime;}</pre>
+ <div id="test3-7"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>:root #test3-8 a {background-color: lime;}</pre>
+ <div id="test3-8"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test3-9 a[title^="This"] {background-color: lime;}</pre>
+ <div id="test3-9"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test3-10 a[title*="is a"] {background-color: lime;}</pre>
+ <div id="test3-10"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+
+ <pre>#test3-11 a[title$="link"] {background-color: lime;}</pre>
+ <div id="test3-11"><p class="test link"><span>This</span> is a <a href="#" title="This is a link">test</a> link.</p></div>
+</body>
+</html>
View
152 js/serializer/JSON.js
@@ -0,0 +1,152 @@
+/*
+Copyright (c) 2005 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+/*
+ The global object JSON contains two methods.
+
+ JSON.stringify(value) takes a JavaScript value and produces a JSON text.
+ The value must not be cyclical.
+
+ JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
+ throw a 'JSONError' exception if there is an error.
+*/
+var HTML_AJAX_JSON = {
+ copyright: '(c)2005 JSON.org',
+ license: 'http://www.crockford.com/JSON/license.html',
+/*
+ Stringify a JavaScript value, producing a JSON text.
+*/
+ stringify: function (v) {
+ var a = [];
+
+/*
+ Emit a string.
+*/
+ function e(s) {
+ a[a.length] = s;
+ }
+
+/*
+ Convert a value.
+*/
+ function g(x) {
+ var c, i, l, v;
+
+ switch (typeof x) {
+ case 'object':
+ if (x) {
+ if (x instanceof Array) {
+ e('[');
+ l = a.length;
+ for (i = 0; i < x.length; i += 1) {
+ v = x[i];
+ if (typeof v != 'undefined' &&
+ typeof v != 'function') {
+ if (l < a.length) {
+ e(',');
+ }
+ g(v);
+ }
+ }
+ e(']');
+ return;
+ } else if (typeof x.valueOf == 'function') {
+ e('{');
+ l = a.length;
+ for (i in x) {
+ v = x[i];
+ if (typeof v != 'undefined' &&
+ typeof v != 'function' &&
+ (!v || typeof v != 'object' ||
+ typeof v.valueOf == 'function')) {
+ if (l < a.length) {
+ e(',');
+ }
+ g(i);
+ e(':');
+ g(v);
+ }
+ }
+ return e('}');
+ }
+ }
+ e('null');
+ return;
+ case 'number':
+ e(isFinite(x) ? +x : 'null');
+ return;
+ case 'string':
+ l = x.length;
+ e('"');
+ for (i = 0; i < l; i += 1) {
+ c = x.charAt(i);
+ if (c >= ' ') {
+ if (c == '\\' || c == '"') {
+ e('\\');
+ }
+ e(c);
+ } else {
+ switch (c) {
+ case '\b':
+ e('\\b');
+ break;
+ case '\f':
+ e('\\f');
+ break;
+ case '\n':
+ e('\\n');
+ break;
+ case '\r':
+ e('\\r');
+ break;
+ case '\t':
+ e('\\t');
+ break;
+ default:
+ c = c.charCodeAt();
+ e('\\u00' + Math.floor(c / 16).toString(16) +
+ (c % 16).toString(16));
+ }
+ }
+ }
+ e('"');
+ return;
+ case 'boolean':
+ e(String(x));
+ return;
+ default:
+ e('null');
+ return;
+ }
+ }
+ g(v);
+ return a.join('');
+ },
+/*
+ Parse a JSON text, producing a JavaScript value.
+*/
+ parse: function (text) {
+ return
+(/^(\s+|[,:{}\[\]]|"(\\["\\\/bfnrtu]|[^\x00-\x1f"\\]+)*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)+$/.test(text))
+ &&
+ eval('(' + text + ')');
+ }
+};
View
145 js/serializer/UrlSerializer.js
@@ -0,0 +1,145 @@
+// {{{ HTML_AJAX_Serialize_Urlencoded
+/**
+ * URL-encoding serializer
+ *
+ * This class can be used to serialize and unserialize data in a
+ * format compatible with PHP's handling of HTTP query strings.
+ * Due to limitations of the format, all input is serialized as an
+ * array or a string. See examples/serialize.url.examples.php
+ *
+ * @version 0.0.1
+ * @copyright 2005 Arpad Ray <arpad@php.net>
+ * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
+ *
+ * See Main.js for Author/license details
+ */
+function HTML_AJAX_Serialize_Urlencoded() {}
+HTML_AJAX_Serialize_Urlencoded.prototype = {
+ contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
+ base: '_HTML_AJAX',
+ _keys: [],
+ error: false,
+ message: "",
+ cont: "",
+ // {{{ serialize
+ /**
+ * Serializes a variable
+ *
+ * @param mixed inp the variable to serialize
+ * @return string a string representation of the input,
+ * which can be reconstructed by unserialize()
+ */
+ serialize: function(input, _internal) {
+ if (typeof input == 'undefined') {
+ return '';
+ }
+ if (!_internal) {
+ this._keys = [];
+ }
+ var ret = '', first = true;
+ for (i = 0; i < this._keys.length; i++) {
+ ret += (first ? HTML_AJAX_Util.encodeUrl(this._keys[i]) : '[' + HTML_AJAX_Util.encodeUrl(this._keys[i]) + ']');
+ first = false;
+ }
+ ret += '=';
+ switch (HTML_AJAX_Util.getType(input)) {
+ case 'string':
+ case 'number':
+ ret += HTML_AJAX_Util.encodeUrl(input.toString());
+ break;
+ case 'boolean':
+ ret += (input ? '1' : '0');
+ break;
+ case 'array':
+ case 'object':
+ ret = '';
+ for (i in input) {
+ this._keys.push(i);
+ ret += this.serialize(input[i], true) + '&';
+ this._keys.pop();
+ }
+ ret = ret.substr(0, ret.length - 1);
+ }
+ return ret;
+ },
+ // }}}
+ // {{{ unserialize
+ /**
+ * Reconstructs a serialized variable
+ *
+ * @param string inp the string to reconstruct
+ * @return array an array containing the variable represented by the input string, or void on failure
+ */
+ unserialize: function(input) {
+ if (!input.length || input.length == 0) {
+ // null
+ return;
+ }
+ if (!/^(\w+(\[[^\[\]]*\])*=[^&]*(&|$))+$/.test(input)) {
+ this.raiseError("invalidly formed input", input);
+ return;
+ }
+ input = input.split("&");
+ var pos, key, keys, val, _HTML_AJAX = [];
+ if (input.length == 1) {
+ return HTML_AJAX_Util.decodeUrl(input[0].substr(this.base.length + 1));
+ }
+ for (var i in input) {
+ pos = input[i].indexOf("=");
+ if (pos < 1 || input[i].length - pos - 1 < 1) {
+ this.raiseError("input is too short", input[i]);
+ return;
+ }
+ key = HTML_AJAX_Util.decodeUrl(input[i].substr(0, pos));
+ val = HTML_AJAX_Util.decodeUrl(input[i].substr(pos + 1));
+ key = key.replace(/\[((\d*\D+)+)\]/g, '["$1"]');
+ keys = key.split(']');
+ for (j in keys) {
+ if (!keys[j].length || keys[j].length == 0) {
+ continue;
+ }
+ try {
+ if (eval('typeof ' + keys[j] + ']') == 'undefined') {
+ var ev = keys[j] + ']=[];';
+ eval(ev);
+ }
+ } catch (e) {
+ this.raiseError("error evaluating key", ev);
+ return;
+ }
+ }
+ try {
+ eval(key + '="' + val + '";');
+ } catch (e) {
+ this.raiseError("error evaluating value", input);
+ return;
+ }
+ }
+ return _HTML_AJAX;
+ },
+ // }}}
+ // {{{ getError
+ /**
+ * Gets the last error message
+ *
+ * @return string the last error message from unserialize()
+ */
+ getError: function() {
+ return this.message + "\n" + this.cont;
+ },
+ // }}}
+ // {{{ raiseError
+ /**
+ * Raises an eror (called by unserialize().)
+ *
+ * @param string message the error message
+ * @param string cont the remaining unserialized content
+ */
+ raiseError: function(message, cont) {
+ this.error = 1;
+ this.message = message;
+ this.cont = cont;
+ }
+ // }}}
+}
+// }}}
View
301 js/serializer/haSerializer.js
@@ -0,0 +1,301 @@
+/**
+ * HTML_AJAX_Serialize_HA - custom serialization
+ *
+ * This class is used with the JSON serializer and the HTML_AJAX_Action php class
+ * to allow users to easily write data handling and dom manipulation related to
+ * ajax actions directly from their php code
+ *
+ * See Main.js for Author/license details
+ */
+function HTML_AJAX_Serialize_HA() { }
+HTML_AJAX_Serialize_HA.prototype =
+{
+ /**
+ * Takes data from JSON - which should be parseable into a nice array
+ * reads the action to take and pipes it to the right method
+ *
+ * @param string payload incoming data from php
+ * @return true on success, false on failure
+ */
+ unserialize: function(payload)
+ {
+ var actions = eval(payload);
+ for(var i = 0; i < actions.length; i++)
+ {
+ var action = actions[i];
+ switch(action.action)
+ {
+ case 'prepend':
+ this._prependAttr(action.id, action.attributes);
+ break;
+ case 'append':
+ this._appendAttr(action.id, action.attributes);
+ break;
+ case 'assign':
+ this._assignAttr(action.id, action.attributes);
+ break;
+ case 'clear':
+ this._clearAttr(action.id, action.attributes);
+ break;
+ case 'create':
+ this._createNode(action.id, action.tag, action.attributes, action.type);
+ break;
+ case 'replace':
+ this._replaceNode(action.id, action.tag, action.attributes);
+ break;
+ case 'remove':
+ this._removeNode(action.id);
+ break;
+ case 'script':
+ this._insertScript(action.data);
+ break;
+ case 'alert':
+ this._insertAlert(action.data);
+ break;
+ }
+ }
+ },
+ /* Dispatch Methods */
+ _prependAttr: function(id, attributes)
+ {
+ var node = document.getElementById(id);
+ this._setAttrs(node, attributes, 'prepend');
+ },
+ _appendAttr: function(id, attributes)
+ {
+ var node = document.getElementById(id);
+ this._setAttrs(node, attributes, 'append');
+ },
+ _assignAttr: function(id, attributes)
+ {
+ var node = document.getElementById(id);
+ this._setAttrs(node, attributes);
+ },
+ _clearAttr: function(id, attributes)
+ {
+ var node = document.getElementById(id);
+ for(var i = 0; i < attributes.length; i++)
+ {
+ if(attributes[i] == 'innerHTML')
+ {
+ HTML_AJAX_Util.setInnerHTML(node, '');
+ }
+ // value can't be removed
+ else if(attributes[i] == 'value')
+ {
+ node.value = '';
+ }
+ // I'd use hasAttribute first but IE is stupid stupid stupid
+ else
+ {
+ try
+ {
+ node.removeAttribute(attributes[i]);
+ }
+ catch(e)
+ {
+ node[i] = undefined;
+ }
+ }
+ }
+ },
+ _createNode: function(id, tag, attributes, type)
+ {
+ var newnode = document.createElement(tag);
+ this._setAttrs(newnode, attributes);
+ switch(type)
+ {
+ case 'append':
+ document.getElementById(id).appendChild(newnode);
+ break
+ case 'prepend':
+ var parent = document.getElementById(id);
+ var sibling = parent.firstChild;
+ parent.insertBefore(newnode, sibling);
+ break;
+ case 'insertBefore':
+ var sibling = document.getElementById(id);
+ var parent = sibling.parentNode;
+ parent.insertBefore(newnode, sibling);
+ break;
+ //this one is tricky, if it's the last one we use append child...ewww
+ case 'insertAfter':
+ var sibling = document.getElementById(id);
+ var parent = sibling.parentNode;
+ var next = sibling.nextSibling;
+ if(next == null)
+ {
+ parent.appendChild(newnode);
+ }
+ else
+ {
+ parent.insertBefore(newnode, next);
+ }
+ break;
+ }
+ },
+ _replaceNode: function(id, tag, attributes)
+ {
+ var node = document.getElementById(id);
+ var parent = node.parentNode;
+ var newnode = document.createElement(tag);
+ this._setAttrs(newnode, attributes);
+ parent.replaceChild(newnode, node);
+ },
+ _removeNode: function(id)
+ {
+ var node = document.getElementById(id);
+ if(node)
+ {
+ var parent = node.parentNode;
+ parent.removeChild(node);
+ }
+ },
+ _insertScript: function(data)
+ {
+ eval(data);
+ },
+ _insertAlert: function(data)
+ {
+ alert(data);
+ },
+ /* Helper Methods */
+ // should we move this to HTML_AJAX_Util???, just does the - case which we need for style
+ _camelize: function(instr)
+ {
+ var p = instr.split('-');
+ var out = p[0];
+ for(var i = 1; i < p.length; i++) {
+ out += p[i].charAt(0).toUpperCase()+p[i].substring(1);
+ }
+ return out;
+ },
+ _setAttrs: function(node, attributes, type)
+ {
+ switch(type)
+ {
+ case 'prepend':
+ for (var i in attributes)
+ {
+ // innerHTML is extremely flakey - use util method for it
+ if(i == 'innerHTML')
+ {
+ HTML_AJAX_Util.setInnerHTML(node, attributes[i], 'append');
+ }
+ //IE doesn't support setAttribute on style so we need to break it out and set each property individually
+ else if(i == 'style')
+ {
+ var styles = [];
+ if(attributes[i].indexOf(';'))
+ {
+ styles = attributes[i].split(';');
+ }
+ else
+ {
+ styles.push(attributes[i]);
+ }
+ for(var i = 0; i < styles.length; i++)
+ {
+ var r = styles[i].match(/^\s*(.+)\s*:\s*(.+)\s*$/);
+ if(r)
+ {
+ node.style[this._camelize(r[1])] = r[2] + node.style[this._camelize(r[1])];
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ node[i] = attributes[i] + node[i];
+ }
+ catch(e){}
+ node.setAttribute(i, attributes[i] + node[i]);
+ }
+ }
+ break;
+ case 'append':
+ {
+ for (var i in attributes)
+ {
+ // innerHTML is extremely flakey - use util method for it
+ if(i == 'innerHTML')
+ {
+ HTML_AJAX_Util.setInnerHTML(node, attributes[i], 'append');
+ }
+ //IE doesn't support setAttribute on style so we need to break it out and set each property individually
+ else if(i == 'style')
+ {
+ var styles = [];
+ if(attributes[i].indexOf(';'))
+ {
+ styles = attributes[i].split(';');
+ }
+ else
+ {
+ styles.push(attributes[i]);
+ }
+ for(var i = 0; i < styles.length; i++)
+ {
+ var r = styles[i].match(/^\s*(.+)\s*:\s*(.+)\s*$/);
+ if(r)
+ {
+ node.style[this._camelize(r[1])] = node.style[this._camelize(r[1])] + r[2];
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ node[i] = node[i] + attributes[i];
+ }
+ catch(e){}
+ node.setAttribute(i, node[i] + attributes[i]);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ for (var i in attributes)
+ {
+ //innerHTML hack bailout
+ if(i == 'innerHTML')
+ {
+ HTML_AJAX_Util.setInnerHTML(node, attributes[i]);
+ }
+ else if(i == 'style')
+ {
+ var styles = [];
+ if(attributes[i].indexOf(';'))
+ {
+ styles = attributes[i].split(';');
+ }
+ else
+ {
+ styles.push(attributes[i]);
+ }
+ for(var i = 0; i < styles.length; i++)
+ {
+ var r = styles[i].match(/^\s*(.+)\s*:\s*(.+)\s*$/);
+ if(r)
+ {
+ node.style[this._camelize(r[1])] = r[2];
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ node[i] = attributes[i];
+ }
+ catch(e){}
+ node.setAttribute(i, attributes[i]);
+ }
+ }
+ }
+ }
+ }
+}
View
244 js/serializer/phpSerializer.js
@@ -0,0 +1,244 @@
+// {{{ HTML_AJAX_Serialize_PHP
+/**
+ * PHP serializer
+ *
+ * This class can be used to serialize and unserialize data in a
+ * format compatible with PHP's native serialization functions.
+ *
+ * @version 0.0.3
+ * @copyright 2005 Arpad Ray <arpad@php.net>
+ * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
+ *
+ * See Main.js for Author/license details
+ */
+
+function HTML_AJAX_Serialize_PHP() {}
+HTML_AJAX_Serialize_PHP.prototype = {
+ error: false,
+ message: "",
+ cont: "",
+ defaultEncoding: 'UTF-8',
+ contentType: 'application/php-serialized; charset: UTF-8',
+ // {{{ serialize
+ /**
+ * Serializes a variable
+ *
+ * @param mixed inp the variable to serialize
+ * @return string a string representation of the input,
+ * which can be reconstructed by unserialize()
+ * @author Arpad Ray <arpad@rajeczy.com>
+ * @author David Coallier <davidc@php.net>
+ */
+ serialize: function(inp) {
+ var type = HTML_AJAX_Util.getType(inp);
+ var val;
+ switch (type) {
+ case "undefined":
+ val = "N";
+ break;
+ case "boolean":
+ val = "b:" + (inp ? "1" : "0");
+ break;
+ case "number":
+ val = (Math.round(inp) == inp ? "i" : "d") + ":" + inp;
+ break;
+ case "string":
+ val = "s:" + inp.length + ":\"" + inp + "\"";
+ break;
+ case "array":
+ val = "a";
+ case "object":
+ if (type == "object") {
+ var objname = inp.constructor.toString().match(/(\w+)\(\)/);
+ if (objname == undefined) {
+ return;
+ }
+ objname[1] = this.serialize(objname[1]);
+ val = "O" + objname[1].substring(1, objname[1].length - 1);
+ }
+ var count = 0;
+ var vals = "";
+ var okey;
+ for (key in inp) {
+ okey = (key.match(/^[0-9]+$/) ? parseInt(key) : key);
+ vals += this.serialize(okey) +
+ this.serialize(inp[key]);
+ count++;
+ }
+ val += ":" + count + ":{" + vals + "}";
+ break;
+ }
+ if (type != "object" && type != "array") val += ";";
+ return val;
+ },
+ // }}}
+ // {{{ unserialize
+ /**
+ * Reconstructs a serialized variable
+ *
+ * @param string inp the string to reconstruct
+ * @return mixed the variable represented by the input string, or void on failure
+ */
+ unserialize: function(inp) {
+ this.error = 0;
+ if (inp == "" || inp.length < 2) {
+ this.raiseError("input is too short");
+ return;
+ }
+ var val, kret, vret, cval;
+ var type = inp.charAt(0);
+ var cont = inp.substring(2);
+ var size = 0, divpos = 0, endcont = 0, rest = "", next = "";
+
+ switch (type) {
+ case "N": // null
+ if (inp.charAt(1) != ";") {
+ this.raiseError("missing ; for null", cont);
+ }
+ // leave val undefined
+ rest = cont;
+ break;
+ case "b": // boolean
+ if (!/[01];/.test(cont.substring(0,2))) {
+ this.raiseError("value not 0 or 1, or missing ; for boolean", cont);
+ }
+ val = (cont.charAt(0) == "1");
+ rest = cont.substring(1);
+ break;
+ case "s": // string
+ val = "";
+ divpos = cont.indexOf(":");
+ if (divpos == -1) {
+ this.raiseError("missing : for string", cont);
+ break;
+ }
+ size = parseInt(cont.substring(0, divpos));
+ if (size == 0) {
+ if (cont.length - divpos < 4) {
+ this.raiseError("string is too short", cont);
+ break;
+ }
+ rest = cont.substring(divpos + 4);
+ break;
+ }
+ if ((cont.length - divpos - size) < 4) {
+ this.raiseError("string is too short", cont);
+ break;
+ }
+ if (cont.substring(divpos + 2 + size, divpos + 4 + size) != "\";") {
+ this.raiseError("string is too long, or missing \";", cont);
+ }
+ val = cont.substring(divpos + 2, divpos + 2 + size);
+ rest = cont.substring(divpos + 4 + size);
+ break;
+ case "i": // integer
+ case "d": // float
+ var dotfound = 0;
+ for (var i = 0; i < cont.length; i++) {
+ cval = cont.charAt(i);
+ if (isNaN(parseInt(cval)) && !(type == "d" && cval == "." && !dotfound++)) {
+ endcont = i;
+ break;
+ }
+ }
+ if (!endcont || cont.charAt(endcont) != ";") {
+ this.raiseError("missing or invalid value, or missing ; for int/float", cont);
+ }
+ val = cont.substring(0, endcont);
+ val = (type == "i" ? parseInt(val) : parseFloat(val));
+ rest = cont.substring(endcont + 1);
+ break;
+ case "a": // array
+ if (cont.length < 4) {
+ this.raiseError("array is too short", cont);
+ return;
+ }
+ divpos = cont.indexOf(":", 1);
+ if (divpos == -1) {
+ this.raiseError("missing : for array", cont);
+ return;
+ }
+ size = parseInt(cont.substring(0, divpos));
+ cont = cont.substring(divpos + 2);
+ val = new Array();
+ if (cont.length < 1) {
+ this.raiseError("array is too short", cont);
+ return;
+ }
+ for (var i = 0; i < size; i++) {
+ kret = this.unserialize(cont, 1);
+ if (this.error || kret[0] == undefined || kret[1] == "") {
+ this.raiseError("missing or invalid key, or missing value for array", cont);
+ return;
+ }
+ vret = this.unserialize(kret[1], 1);
+ if (this.error) {
+ this.raiseError("invalid value for array", cont);
+ return;
+ }
+ val[kret[0]] = vret[0];
+ cont = vret[1];
+ }
+ if (cont.charAt(0) != "}") {
+ this.raiseError("missing ending }, or too many values for array", cont);
+ return;
+ }
+ rest = cont.substring(1);
+ break;
+ case "O": // object
+ divpos = cont.indexOf(":");
+ if (divpos == -1) {
+ this.raiseError("missing : for object", cont);
+ return;
+ }
+ size = parseInt(cont.substring(0, divpos));
+ var objname = cont.substring(divpos + 2, divpos + 2 + size);
+ if (cont.substring(divpos + 2 + size, divpos + 4 + size) != "\":") {
+ this.raiseError("object name is too long, or missing \":", cont);
+ return;
+ }
+ var objprops = this.unserialize("a:" + cont.substring(divpos + 4 + size), 1);
+ if (this.error) {
+ this.raiseError("invalid object properties", cont);
+ return;
+ }
+ rest = objprops[1];
+ var objout = "function " + objname + "(){";
+ for (key in objprops[0]) {
+ objout += "this." + key + "=objprops[0]['" + key + "'];";
+ }
+ objout += "}val=new " + objname + "();";
+ eval(objout);
+ break;
+ default:
+ this.raiseError("invalid input type", cont);
+ }
+ return (arguments.length == 1 ? val : [val, rest]);
+ },
+ // }}}
+ // {{{ getError
+ /**
+ * Gets the last error message
+ *
+ * @return string the last error message from unserialize()
+ */
+ getError: function() {
+ return this.message + "\n" + this.cont;
+ },
+ // }}}
+ // {{{ raiseError
+ /**
+ * Raises an eror (called by unserialize().)
+ *
+ * @param string message the error message
+ * @param string cont the remaining unserialized content
+ */
+ raiseError: function(message, cont) {
+ this.error = 1;
+ this.message = message;
+ this.cont = cont;
+ }
+ // }}}
+}
+// }}}
+

0 comments on commit bbabc28

Please sign in to comment.