| |   |
| 36 | 36 | if (Prototype.Browser.MobileSafari) |
| 37 | 37 | Prototype.BrowserFeatures.SpecificElementExtensions = false; |
| 38 | 38 | |
| 39 | | if (Prototype.Browser.WebKit) |
| 40 | | Prototype.BrowserFeatures.XPath = false; |
| 41 | 39 | |
| 42 | 40 | /* Based on Alex Arnell's inheritance implementation. */ |
| 43 | 41 | var Class = { |
| … | … | |
| 108 | 108 | Object.extend(Object, { |
| 109 | 109 | inspect: function(object) { |
| 110 | 110 | try { |
| 111 | | if (object === undefined) return 'undefined'; |
| 111 | if (Object.isUndefined(object)) return 'undefined'; |
| 112 | 112 | if (object === null) return 'null'; |
| 113 | 113 | return object.inspect ? object.inspect() : object.toString(); |
| 114 | 114 | } catch (e) { |
| … | … | |
| 133 | 133 | var results = []; |
| 134 | 134 | for (var property in object) { |
| 135 | 135 | var value = Object.toJSON(object[property]); |
| 136 | | if (value !== undefined) |
| 136 | if (!Object.isUndefined(value)) |
| 137 | 137 | results.push(property.toJSON() + ': ' + value); |
| 138 | 138 | } |
| 139 | 139 | |
| … | … | |
| 202 | 202 | }, |
| 203 | 203 | |
| 204 | 204 | bind: function() { |
| 205 | | if (arguments.length < 2 && arguments[0] === undefined) return this; |
| 205 | if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; |
| 206 | 206 | var __method = this, args = $A(arguments), object = args.shift(); |
| 207 | 207 | return function() { |
| 208 | 208 | return __method.apply(object, args.concat($A(arguments))); |
| … | … | |
| 349 | 349 | |
| 350 | 350 | sub: function(pattern, replacement, count) { |
| 351 | 351 | replacement = this.gsub.prepareReplacement(replacement); |
| 352 | | count = count === undefined ? 1 : count; |
| 352 | count = Object.isUndefined(count) ? 1 : count; |
| 353 | 353 | |
| 354 | 354 | return this.gsub(pattern, function(match) { |
| 355 | 355 | if (--count < 0) return match[0]; |
| … | … | |
| 364 | 364 | |
| 365 | 365 | truncate: function(length, truncation) { |
| 366 | 366 | length = length || 30; |
| 367 | | truncation = truncation === undefined ? '...' : truncation; |
| 367 | truncation = Object.isUndefined(truncation) ? '...' : truncation; |
| 368 | 368 | return this.length > length ? |
| 369 | 369 | this.slice(0, length - truncation.length) + truncation : String(this); |
| 370 | 370 | }, |
| … | … | |
| 484 | 484 | }, |
| 485 | 485 | |
| 486 | 486 | isJSON: function() { |
| 487 | | var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); |
| 487 | var str = this; |
| 488 | if (str.blank()) return false; |
| 489 | str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); |
| 488 | 490 | return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); |
| 489 | 491 | }, |
| 490 | 492 | |
| … | … | |
| 565 | 565 | if (before == '\\') return match[2]; |
| 566 | 566 | |
| 567 | 567 | var ctx = object, expr = match[3]; |
| 568 | | var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); |
| 568 | var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; |
| 569 | match = pattern.exec(expr); |
| 569 | 570 | if (match == null) return before; |
| 570 | 571 | |
| 571 | 572 | while (match != null) { |
| … | … | |
| 687 | 687 | }, |
| 688 | 688 | |
| 689 | 689 | inGroupsOf: function(number, fillWith) { |
| 690 | | fillWith = fillWith === undefined ? null : fillWith; |
| 690 | fillWith = Object.isUndefined(fillWith) ? null : fillWith; |
| 691 | 691 | return this.eachSlice(number, function(slice) { |
| 692 | 692 | while(slice.length < number) slice.push(fillWith); |
| 693 | 693 | return slice; |
| … | … | |
| 714 | 714 | var result; |
| 715 | 715 | this.each(function(value, index) { |
| 716 | 716 | value = iterator(value, index); |
| 717 | | if (result == undefined || value >= result) |
| 717 | if (result == null || value >= result) |
| 718 | 718 | result = value; |
| 719 | 719 | }); |
| 720 | 720 | return result; |
| … | … | |
| 725 | 725 | var result; |
| 726 | 726 | this.each(function(value, index) { |
| 727 | 727 | value = iterator(value, index); |
| 728 | | if (result == undefined || value < result) |
| 728 | if (result == null || value < result) |
| 729 | 729 | result = value; |
| 730 | 730 | }); |
| 731 | 731 | return result; |
| … | … | |
| 905 | 905 | var results = []; |
| 906 | 906 | this.each(function(object) { |
| 907 | 907 | var value = Object.toJSON(object); |
| 908 | | if (value !== undefined) results.push(value); |
| 908 | if (!Object.isUndefined(value)) results.push(value); |
| 909 | 909 | }); |
| 910 | 910 | return '[' + results.join(', ') + ']'; |
| 911 | 911 | } |
| … | … | |
| 985 | 985 | }; |
| 986 | 986 | |
| 987 | 987 | var Hash = Class.create(Enumerable, (function() { |
| 988 | | if (function() { |
| 989 | | var i = 0, Test = function(value) { this.key = value }; |
| 990 | | Test.prototype.key = 'foo'; |
| 991 | | for (var property in new Test('bar')) i++; |
| 992 | | return i > 1; |
| 993 | | }()) { |
| 994 | | function each(iterator) { |
| 995 | | var cache = []; |
| 996 | | for (var key in this._object) { |
| 997 | | var value = this._object[key]; |
| 998 | | if (cache.include(key)) continue; |
| 999 | | cache.push(key); |
| 1000 | | var pair = [key, value]; |
| 1001 | | pair.key = key; |
| 1002 | | pair.value = value; |
| 1003 | | iterator(pair); |
| 1004 | | } |
| 1005 | | } |
| 1006 | | } else { |
| 1007 | | function each(iterator) { |
| 1008 | | for (var key in this._object) { |
| 1009 | | var value = this._object[key], pair = [key, value]; |
| 1010 | | pair.key = key; |
| 1011 | | pair.value = value; |
| 1012 | | iterator(pair); |
| 1013 | | } |
| 1014 | | } |
| 1015 | | } |
| 1016 | 988 | |
| 1017 | 989 | function toQueryPair(key, value) { |
| 1018 | 990 | if (Object.isUndefined(value)) return key; |
| … | … | |
| 996 | 996 | this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); |
| 997 | 997 | }, |
| 998 | 998 | |
| 999 | | _each: each, |
| 999 | _each: function(iterator) { |
| 1000 | for (var key in this._object) { |
| 1001 | var value = this._object[key], pair = [key, value]; |
| 1002 | pair.key = key; |
| 1003 | pair.value = value; |
| 1004 | iterator(pair); |
| 1005 | } |
| 1006 | }, |
| 1000 | 1007 | |
| 1001 | 1008 | set: function(key, value) { |
| 1002 | 1009 | return this._object[key] = value; |
| … | … | |
| 1167 | 1167 | Object.extend(this.options, options || { }); |
| 1168 | 1168 | |
| 1169 | 1169 | this.options.method = this.options.method.toLowerCase(); |
| 1170 | |
| 1170 | 1171 | if (Object.isString(this.options.parameters)) |
| 1171 | 1172 | this.options.parameters = this.options.parameters.toQueryParams(); |
| 1173 | else if (Object.isHash(this.options.parameters)) |
| 1174 | this.options.parameters = this.options.parameters.toObject(); |
| 1172 | 1175 | } |
| 1173 | 1176 | }); |
| 1174 | 1177 | |
| … | … | |
| 1354 | 1354 | |
| 1355 | 1355 | if(readyState == 4) { |
| 1356 | 1356 | var xml = transport.responseXML; |
| 1357 | | this.responseXML = xml === undefined ? null : xml; |
| 1357 | this.responseXML = Object.isUndefined(xml) ? null : xml; |
| 1358 | 1358 | this.responseJSON = this._getResponseJSON(); |
| 1359 | 1359 | } |
| 1360 | 1360 | }, |
| … | … | |
| 1400 | 1400 | _getResponseJSON: function() { |
| 1401 | 1401 | var options = this.request.options; |
| 1402 | 1402 | if (!options.evalJSON || (options.evalJSON != 'force' && |
| 1403 | | !(this.getHeader('Content-type') || '').include('application/json'))) |
| 1404 | | return null; |
| 1403 | !(this.getHeader('Content-type') || '').include('application/json')) || |
| 1404 | this.responseText.blank()) |
| 1405 | return null; |
| 1405 | 1406 | try { |
| 1406 | | return this.transport.responseText.evalJSON(options.sanitizeJSON); |
| 1407 | return this.responseText.evalJSON(options.sanitizeJSON); |
| 1407 | 1408 | } catch (e) { |
| 1408 | 1409 | this.request.dispatchException(e); |
| 1409 | 1410 | } |
| … | … | |
| 1418 | 1418 | failure: (container.failure || (container.success ? null : container)) |
| 1419 | 1419 | }; |
| 1420 | 1420 | |
| 1421 | | options = options || { }; |
| 1421 | options = Object.clone(options); |
| 1422 | 1422 | var onComplete = options.onComplete; |
| 1423 | | options.onComplete = (function(response, param) { |
| 1423 | options.onComplete = (function(response, json) { |
| 1424 | 1424 | this.updateContent(response.responseText); |
| 1425 | | if (Object.isFunction(onComplete)) onComplete(response, param); |
| 1425 | if (Object.isFunction(onComplete)) onComplete(response, json); |
| 1426 | 1426 | }).bind(this); |
| 1427 | 1427 | |
| 1428 | 1428 | $super(url, options); |
| … | … | |
| 1444 | 1444 | } |
| 1445 | 1445 | else receiver.update(responseText); |
| 1446 | 1446 | } |
| 1447 | | |
| 1448 | | if (this.success()) { |
| 1449 | | if (this.onComplete) this.onComplete.bind(this).defer(); |
| 1450 | | } |
| 1451 | 1447 | } |
| 1452 | 1448 | }); |
| 1453 | 1449 | |
| … | … | |
| 1670 | 1670 | }, |
| 1671 | 1671 | |
| 1672 | 1672 | descendants: function(element) { |
| 1673 | | return $A($(element).getElementsByTagName('*')).each(Element.extend); |
| 1673 | return $(element).getElementsBySelector("*"); |
| 1674 | 1674 | }, |
| 1675 | 1675 | |
| 1676 | 1676 | firstDescendant: function(element) { |
| … | … | |
| 1775 | 1775 | var attributes = { }, t = Element._attributeTranslations.write; |
| 1776 | 1776 | |
| 1777 | 1777 | if (typeof name == 'object') attributes = name; |
| 1778 | | else attributes[name] = value === undefined ? true : value; |
| 1778 | else attributes[name] = Object.isUndefined(value) ? true : value; |
| 1779 | 1779 | |
| 1780 | 1780 | for (var attr in attributes) { |
| 1781 | | var name = t.names[attr] || attr, value = attributes[attr]; |
| 1781 | name = t.names[attr] || attr; |
| 1782 | value = attributes[attr]; |
| 1782 | 1783 | if (t.values[attr]) name = t.values[attr](element, value); |
| 1783 | 1784 | if (value === false || value === null) |
| 1784 | 1785 | element.removeAttribute(name); |
| … | … | |
| 1848 | 1848 | |
| 1849 | 1849 | descendantOf: function(element, ancestor) { |
| 1850 | 1850 | element = $(element), ancestor = $(ancestor); |
| 1851 | var originalAncestor = ancestor; |
| 1851 | 1852 | |
| 1852 | 1853 | if (element.compareDocumentPosition) |
| 1853 | 1854 | return (element.compareDocumentPosition(ancestor) & 8) === 8; |
| … | … | |
| 1864 | 1864 | } |
| 1865 | 1865 | |
| 1866 | 1866 | while (element = element.parentNode) |
| 1867 | | if (element == ancestor) return true; |
| 1867 | if (element == originalAncestor) return true; |
| 1868 | 1868 | return false; |
| 1869 | 1869 | }, |
| 1870 | 1870 | |
| … | … | |
| 1903 | 1903 | if (property == 'opacity') element.setOpacity(styles[property]); |
| 1904 | 1904 | else |
| 1905 | 1905 | elementStyle[(property == 'float' || property == 'cssFloat') ? |
| 1906 | | (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : |
| 1906 | (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : |
| 1907 | 1907 | property] = styles[property]; |
| 1908 | 1908 | |
| 1909 | 1909 | return element; |
| … | … | |
| 2283 | 2283 | return node ? node.value : ""; |
| 2284 | 2284 | }, |
| 2285 | 2285 | _getEv: function(element, attribute) { |
| 2286 | | var attribute = element.getAttribute(attribute); |
| 2286 | attribute = element.getAttribute(attribute); |
| 2287 | 2287 | return attribute ? attribute.toString().slice(23, -2) : null; |
| 2288 | 2288 | }, |
| 2289 | 2289 | _flag: function(element, attribute) { |
| … | … | |
| 2701 | 2701 | this.compileMatcher(); |
| 2702 | 2702 | }, |
| 2703 | 2703 | |
| 2704 | shouldUseXPath: function() { |
| 2705 | if (!Prototype.BrowserFeatures.XPath) return false; |
| 2706 | |
| 2707 | var e = this.expression; |
| 2708 | |
| 2709 | // Safari 3 chokes on :*-of-type and :empty |
| 2710 | if (Prototype.Browser.WebKit && |
| 2711 | (e.include("-of-type") || e.include(":empty"))) |
| 2712 | return false; |
| 2713 | |
| 2714 | // XPath can't do namespaced attributes, nor can it read |
| 2715 | // the "checked" property from DOM nodes |
| 2716 | if ((/(\[[\w-]*?:|:checked)/).test(this.expression)) |
| 2717 | return false; |
| 2718 | |
| 2719 | return true; |
| 2720 | }, |
| 2721 | |
| 2704 | 2722 | compileMatcher: function() { |
| 2705 | | // Selectors with namespaced attributes can't use the XPath version |
| 2706 | | if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression)) |
| 2723 | if (this.shouldUseXPath()) |
| 2707 | 2724 | return this.compileXPathMatcher(); |
| 2708 | 2725 | |
| 2709 | 2726 | var e = this.expression, ps = Selector.patterns, h = Selector.handlers, |
| … | … | |
| 2843 | 2843 | }, |
| 2844 | 2844 | className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", |
| 2845 | 2845 | id: "[@id='#{1}']", |
| 2846 | | attrPresence: "[@#{1}]", |
| 2846 | attrPresence: function(m) { |
| 2847 | m[1] = m[1].toLowerCase(); |
| 2848 | return new Template("[@#{1}]").evaluate(m); |
| 2849 | }, |
| 2847 | 2850 | attr: function(m) { |
| 2851 | m[1] = m[1].toLowerCase(); |
| 2848 | 2852 | m[3] = m[5] || m[6]; |
| 2849 | 2853 | return new Template(Selector.xpath.operators[m[2]]).evaluate(m); |
| 2850 | 2854 | }, |
| … | … | |
| 2877 | 2877 | 'enabled': "[not(@disabled)]", |
| 2878 | 2878 | 'not': function(m) { |
| 2879 | 2879 | var e = m[6], p = Selector.patterns, |
| 2880 | | x = Selector.xpath, le, m, v; |
| 2880 | x = Selector.xpath, le, v; |
| 2881 | 2881 | |
| 2882 | 2882 | var exclusion = []; |
| 2883 | 2883 | while (e && le != e && (/\S/).test(e)) { |
| … | … | |
| 3054 | 3054 | child: function(nodes) { |
| 3055 | 3055 | var h = Selector.handlers; |
| 3056 | 3056 | for (var i = 0, results = [], node; node = nodes[i]; i++) { |
| 3057 | | for (var j = 0, children = [], child; child = node.childNodes[j]; j++) |
| 3057 | for (var j = 0, child; child = node.childNodes[j]; j++) |
| 3058 | 3058 | if (child.nodeType == 1 && child.tagName != '!') results.push(child); |
| 3059 | 3059 | } |
| 3060 | 3060 | return results; |
| … | … | |
| 3326 | 3326 | }, |
| 3327 | 3327 | |
| 3328 | 3328 | findChildElements: function(element, expressions) { |
| 3329 | | var exprs = expressions.join(','), expressions = []; |
| 3329 | var exprs = expressions.join(','); |
| 3330 | expressions = []; |
| 3330 | 3331 | exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { |
| 3331 | 3332 | expressions.push(m[1].strip()); |
| 3332 | 3333 | }); |
| … | … | |
| 3340 | 3340 | } |
| 3341 | 3341 | }); |
| 3342 | 3342 | |
| 3343 | if (Prototype.Browser.IE) { |
| 3344 | // IE returns comment nodes on getElementsByTagName("*"). |
| 3345 | // Filter them out. |
| 3346 | Selector.handlers.concat = function(a, b) { |
| 3347 | for (var i = 0, node; node = b[i]; i++) |
| 3348 | if (node.tagName !== "!") a.push(node); |
| 3349 | return a; |
| 3350 | }; |
| 3351 | } |
| 3352 | |
| 3343 | 3353 | function $$() { |
| 3344 | 3354 | return Selector.findChildElements(document, $A(arguments)); |
| 3345 | 3355 | } |
| … | … | |
| 3361 | 3361 | |
| 3362 | 3362 | serializeElements: function(elements, options) { |
| 3363 | 3363 | if (typeof options != 'object') options = { hash: !!options }; |
| 3364 | | else if (options.hash === undefined) options.hash = true; |
| 3364 | else if (Object.isUndefined(options.hash)) options.hash = true; |
| 3365 | 3365 | var key, value, submitted = false, submit = options.submit; |
| 3366 | 3366 | |
| 3367 | 3367 | var data = elements.inject({ }, function(result, element) { |
| … | … | |
| 3559 | 3559 | }, |
| 3560 | 3560 | |
| 3561 | 3561 | inputSelector: function(element, value) { |
| 3562 | | if (value === undefined) return element.checked ? element.value : null; |
| 3562 | if (Object.isUndefined(value)) return element.checked ? element.value : null; |
| 3563 | 3563 | else element.checked = !!value; |
| 3564 | 3564 | }, |
| 3565 | 3565 | |
| 3566 | 3566 | textarea: function(element, value) { |
| 3567 | | if (value === undefined) return element.value; |
| 3567 | if (Object.isUndefined(value)) return element.value; |
| 3568 | 3568 | else element.value = value; |
| 3569 | 3569 | }, |
| 3570 | 3570 | |
| 3571 | 3571 | select: function(element, index) { |
| 3572 | | if (index === undefined) |
| 3572 | if (Object.isUndefined(index)) |
| 3573 | 3573 | return this[element.type == 'select-one' ? |
| 3574 | 3574 | 'selectOne' : 'selectMany'](element); |
| 3575 | 3575 | else { |
| … | … | |
| 3760 | 3760 | |
| 3761 | 3761 | findElement: function(event, expression) { |
| 3762 | 3762 | var element = Event.element(event); |
| 3763 | | return element.match(expression) ? element : element.up(expression); |
| 3763 | if (!expression) return element; |
| 3764 | var elements = [element].concat(element.ancestors()); |
| 3765 | return Selector.findElement(elements, expression, 0); |
| 3764 | 3766 | }, |
| 3765 | 3767 | |
| 3766 | 3768 | pointer: function(event) { |
| … | … | |
| 3954 | 3954 | element.fireEvent(event.eventType, event); |
| 3955 | 3955 | } |
| 3956 | 3956 | |
| 3957 | | return event; |
| 3957 | return Event.extend(event); |
| 3958 | 3958 | } |
| 3959 | 3959 | }; |
| 3960 | 3960 | })()); |
| toggle raw diff |
--- a/public/javascripts/prototype.js
+++ b/public/javascripts/prototype.js
@@ -36,8 +36,6 @@ var Prototype = {
if (Prototype.Browser.MobileSafari)
Prototype.BrowserFeatures.SpecificElementExtensions = false;
-if (Prototype.Browser.WebKit)
- Prototype.BrowserFeatures.XPath = false;
/* Based on Alex Arnell's inheritance implementation. */
var Class = {
@@ -110,7 +108,7 @@ Object.extend = function(destination, source) {
Object.extend(Object, {
inspect: function(object) {
try {
- if (object === undefined) return 'undefined';
+ if (Object.isUndefined(object)) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : object.toString();
} catch (e) {
@@ -135,7 +133,7 @@ Object.extend(Object, {
var results = [];
for (var property in object) {
var value = Object.toJSON(object[property]);
- if (value !== undefined)
+ if (!Object.isUndefined(value))
results.push(property.toJSON() + ': ' + value);
}
@@ -204,7 +202,7 @@ Object.extend(Function.prototype, {
},
bind: function() {
- if (arguments.length < 2 && arguments[0] === undefined) return this;
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
var __method = this, args = $A(arguments), object = args.shift();
return function() {
return __method.apply(object, args.concat($A(arguments)));
@@ -351,7 +349,7 @@ Object.extend(String.prototype, {
sub: function(pattern, replacement, count) {
replacement = this.gsub.prepareReplacement(replacement);
- count = count === undefined ? 1 : count;
+ count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
@@ -366,7 +364,7 @@ Object.extend(String.prototype, {
truncate: function(length, truncation) {
length = length || 30;
- truncation = truncation === undefined ? '...' : truncation;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
this.slice(0, length - truncation.length) + truncation : String(this);
},
@@ -486,7 +484,9 @@ Object.extend(String.prototype, {
},
isJSON: function() {
- var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
},
@@ -565,7 +565,8 @@ var Template = Class.create({
if (before == '\\') return match[2];
var ctx = object, expr = match[3];
- var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
if (match == null) return before;
while (match != null) {
@@ -686,7 +687,7 @@ var Enumerable = {
},
inGroupsOf: function(number, fillWith) {
- fillWith = fillWith === undefined ? null : fillWith;
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
return this.eachSlice(number, function(slice) {
while(slice.length < number) slice.push(fillWith);
return slice;
@@ -713,7 +714,7 @@ var Enumerable = {
var result;
this.each(function(value, index) {
value = iterator(value, index);
- if (result == undefined || value >= result)
+ if (result == null || value >= result)
result = value;
});
return result;
@@ -724,7 +725,7 @@ var Enumerable = {
var result;
this.each(function(value, index) {
value = iterator(value, index);
- if (result == undefined || value < result)
+ if (result == null || value < result)
result = value;
});
return result;
@@ -904,7 +905,7 @@ Object.extend(Array.prototype, {
var results = [];
this.each(function(object) {
var value = Object.toJSON(object);
- if (value !== undefined) results.push(value);
+ if (!Object.isUndefined(value)) results.push(value);
});
return '[' + results.join(', ') + ']';
}
@@ -984,34 +985,6 @@ function $H(object) {
};
var Hash = Class.create(Enumerable, (function() {
- if (function() {
- var i = 0, Test = function(value) { this.key = value };
- Test.prototype.key = 'foo';
- for (var property in new Test('bar')) i++;
- return i > 1;
- }()) {
- function each(iterator) {
- var cache = [];
- for (var key in this._object) {
- var value = this._object[key];
- if (cache.include(key)) continue;
- cache.push(key);
- var pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
- }
- }
- } else {
- function each(iterator) {
- for (var key in this._object) {
- var value = this._object[key], pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
- }
- }
- }
function toQueryPair(key, value) {
if (Object.isUndefined(value)) return key;
@@ -1023,7 +996,14 @@ var Hash = Class.create(Enumerable, (function() {
this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
},
- _each: each,
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
set: function(key, value) {
return this._object[key] = value;
@@ -1187,8 +1167,11 @@ Ajax.Base = Class.create({
Object.extend(this.options, options || { });
this.options.method = this.options.method.toLowerCase();
+
if (Object.isString(this.options.parameters))
this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
}
});
@@ -1371,7 +1354,7 @@ Ajax.Response = Class.create({
if(readyState == 4) {
var xml = transport.responseXML;
- this.responseXML = xml === undefined ? null : xml;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
this.responseJSON = this._getResponseJSON();
}
},
@@ -1417,10 +1400,11 @@ Ajax.Response = Class.create({
_getResponseJSON: function() {
var options = this.request.options;
if (!options.evalJSON || (options.evalJSON != 'force' &&
- !(this.getHeader('Content-type') || '').include('application/json')))
- return null;
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
try {
- return this.transport.responseText.evalJSON(options.sanitizeJSON);
+ return this.responseText.evalJSON(options.sanitizeJSON);
} catch (e) {
this.request.dispatchException(e);
}
@@ -1434,11 +1418,11 @@ Ajax.Updater = Class.create(Ajax.Request, {
failure: (container.failure || (container.success ? null : container))
};
- options = options || { };
+ options = Object.clone(options);
var onComplete = options.onComplete;
- options.onComplete = (function(response, param) {
+ options.onComplete = (function(response, json) {
this.updateContent(response.responseText);
- if (Object.isFunction(onComplete)) onComplete(response, param);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
}).bind(this);
$super(url, options);
@@ -1460,10 +1444,6 @@ Ajax.Updater = Class.create(Ajax.Request, {
}
else receiver.update(responseText);
}
-
- if (this.success()) {
- if (this.onComplete) this.onComplete.bind(this).defer();
- }
}
});
@@ -1690,7 +1670,7 @@ Element.Methods = {
},
descendants: function(element) {
- return $A($(element).getElementsByTagName('*')).each(Element.extend);
+ return $(element).getElementsBySelector("*");
},
firstDescendant: function(element) {
@@ -1795,10 +1775,11 @@ Element.Methods = {
var attributes = { }, t = Element._attributeTranslations.write;
if (typeof name == 'object') attributes = name;
- else attributes[name] = value === undefined ? true : value;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
for (var attr in attributes) {
- var name = t.names[attr] || attr, value = attributes[attr];
+ name = t.names[attr] || attr;
+ value = attributes[attr];
if (t.values[attr]) name = t.values[attr](element, value);
if (value === false || value === null)
element.removeAttribute(name);
@@ -1867,6 +1848,7 @@ Element.Methods = {
descendantOf: function(element, ancestor) {
element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
if (element.compareDocumentPosition)
return (element.compareDocumentPosition(ancestor) & 8) === 8;
@@ -1882,7 +1864,7 @@ Element.Methods = {
}
while (element = element.parentNode)
- if (element == ancestor) return true;
+ if (element == originalAncestor) return true;
return false;
},
@@ -1921,7 +1903,7 @@ Element.Methods = {
if (property == 'opacity') element.setOpacity(styles[property]);
else
elementStyle[(property == 'float' || property == 'cssFloat') ?
- (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
property] = styles[property];
return element;
@@ -2301,7 +2283,7 @@ else if (Prototype.Browser.IE) {
return node ? node.value : "";
},
_getEv: function(element, attribute) {
- var attribute = element.getAttribute(attribute);
+ attribute = element.getAttribute(attribute);
return attribute ? attribute.toString().slice(23, -2) : null;
},
_flag: function(element, attribute) {
@@ -2719,9 +2701,26 @@ var Selector = Class.create({
this.compileMatcher();
},
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
compileMatcher: function() {
- // Selectors with namespaced attributes can't use the XPath version
- if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression))
+ if (this.shouldUseXPath())
return this.compileXPathMatcher();
var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
@@ -2844,8 +2843,12 @@ Object.extend(Selector, {
},
className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
id: "[@id='#{1}']",
- attrPresence: "[@#{1}]",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
attr: function(m) {
+ m[1] = m[1].toLowerCase();
m[3] = m[5] || m[6];
return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
},
@@ -2874,7 +2877,7 @@ Object.extend(Selector, {
'enabled': "[not(@disabled)]",
'not': function(m) {
var e = m[6], p = Selector.patterns,
- x = Selector.xpath, le, m, v;
+ x = Selector.xpath, le, v;
var exclusion = [];
while (e && le != e && (/\S/).test(e)) {
@@ -3051,7 +3054,7 @@ Object.extend(Selector, {
child: function(nodes) {
var h = Selector.handlers;
for (var i = 0, results = [], node; node = nodes[i]; i++) {
- for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
+ for (var j = 0, child; child = node.childNodes[j]; j++)
if (child.nodeType == 1 && child.tagName != '!') results.push(child);
}
return results;
@@ -3323,7 +3326,8 @@ Object.extend(Selector, {
},
findChildElements: function(element, expressions) {
- var exprs = expressions.join(','), expressions = [];
+ var exprs = expressions.join(',');
+ expressions = [];
exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
expressions.push(m[1].strip());
});
@@ -3336,6 +3340,16 @@ Object.extend(Selector, {
}
});
+if (Prototype.Browser.IE) {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ Selector.handlers.concat = function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ };
+}
+
function $$() {
return Selector.findChildElements(document, $A(arguments));
}
@@ -3347,7 +3361,7 @@ var Form = {
serializeElements: function(elements, options) {
if (typeof options != 'object') options = { hash: !!options };
- else if (options.hash === undefined) options.hash = true;
+ else if (Object.isUndefined(options.hash)) options.hash = true;
var key, value, submitted = false, submit = options.submit;
var data = elements.inject({ }, function(result, element) {
@@ -3545,17 +3559,17 @@ Form.Element.Serializers = {
},
inputSelector: function(element, value) {
- if (value === undefined) return element.checked ? element.value : null;
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
else element.checked = !!value;
},
textarea: function(element, value) {
- if (value === undefined) return element.value;
+ if (Object.isUndefined(value)) return element.value;
else element.value = value;
},
select: function(element, index) {
- if (index === undefined)
+ if (Object.isUndefined(index))
return this[element.type == 'select-one' ?
'selectOne' : 'selectMany'](element);
else {
@@ -3746,7 +3760,9 @@ Event.Methods = (function() {
findElement: function(event, expression) {
var element = Event.element(event);
- return element.match(expression) ? element : element.up(expression);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
},
pointer: function(event) {
@@ -3938,7 +3954,7 @@ Object.extend(Event, (function() {
element.fireEvent(event.eventType, event);
}
- return event;
+ return Event.extend(event);
}
};
})()); |