提交 c192bdfc 编写于 作者: S Sam Stephenson

Update to Prototype 1.5.0_rc2

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5497 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 79c309e4
*SVN*
* Update to Prototype 1.5.0_rc2. [Sam Stephenson]
* Remove JavaScriptLiteral in favor of ActiveSupport::JSON::Variable. [Sam Stephenson]
* Sync ActionController::StatusCodes::STATUS_CODES with http://www.iana.org/assignments/http-status-codes. #6586 [dkubb]
......
/* Prototype JavaScript framework, version 1.5.0_rc1
* (c) 2005 Sam Stephenson <sam@conio.net>
/* Prototype JavaScript framework, version 1.5.0_rc2
* (c) 2005, 2006 Sam Stephenson <sam@conio.net>
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://prototype.conio.net/
......@@ -7,7 +7,7 @@
/*--------------------------------------------------------------------------*/
var Prototype = {
Version: '1.5.0_rc1',
Version: '1.5.0_rc2',
BrowserFeatures: {
XPath: !!document.evaluate
},
......@@ -37,8 +37,8 @@ Object.extend = function(destination, source) {
Object.extend(Object, {
inspect: function(object) {
try {
if (object == undefined) return 'undefined';
if (object == null) return 'null';
if (object === undefined) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : object.toString();
} catch (e) {
if (e instanceof RangeError) return '...';
......@@ -100,7 +100,7 @@ var Try = {
these: function() {
var returnValue;
for (var i = 0; i < arguments.length; i++) {
for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
......@@ -221,13 +221,23 @@ Object.extend(String.prototype, {
return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
},
toQueryParams: function() {
var pairs = this.match(/^\??(.*)$/)[1].split('&');
return pairs.inject({}, function(params, pairString) {
var pair = pairString.split('=');
toQueryParams: function(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return {};
return match[1].split(separator || '&').inject({}, function(hash, pair) {
if ((pair = pair.split('='))[0]) {
var name = decodeURIComponent(pair[0]);
var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
params[decodeURIComponent(pair[0])] = value;
return params;
if (hash[name] !== undefined) {
if (hash[name].constructor != Array)
hash[name] = [hash[name]];
if (value) hash[name].push(value);
}
else hash[name] = value;
}
return hash;
});
},
......@@ -243,7 +253,7 @@ Object.extend(String.prototype, {
? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
: oStringList[0];
for (var i = 1, len = oStringList.length; i < len; i++) {
for (var i = 1, length = oStringList.length; i < length; i++) {
var s = oStringList[i];
camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
}
......@@ -338,7 +348,7 @@ var Enumerable = {
return results;
},
detect: function (iterator) {
detect: function(iterator) {
var result;
this.each(function(value, index) {
if (iterator(value, index)) {
......@@ -490,7 +500,7 @@ var $A = Array.from = function(iterable) {
return iterable.toArray();
} else {
var results = [];
for (var i = 0; i < iterable.length; i++)
for (var i = 0, length = iterable.length; i < length; i++)
results.push(iterable[i]);
return results;
}
......@@ -503,7 +513,7 @@ if (!Array.prototype._reverse)
Object.extend(Array.prototype, {
_each: function(iterator) {
for (var i = 0; i < this.length; i++)
for (var i = 0, length = this.length; i < length; i++)
iterator(this[i]);
},
......@@ -541,7 +551,7 @@ Object.extend(Array.prototype, {
},
indexOf: function(object) {
for (var i = 0; i < this.length; i++)
for (var i = 0, length = this.length; i < length; i++)
if (this[i] == object) return i;
return -1;
},
......@@ -568,6 +578,8 @@ Object.extend(Array.prototype, {
return '[' + this.map(Object.inspect).join(', ') + ']';
}
});
Array.prototype.toArray = Array.prototype.clone;
var Hash = {
_each: function(iterator) {
for (var key in this) {
......@@ -590,7 +602,7 @@ var Hash = {
},
merge: function(hash) {
return $H(hash).inject($H(this), function(mergedHash, pair) {
return $H(hash).inject(this, function(mergedHash, pair) {
mergedHash[pair.key] = pair.value;
return mergedHash;
});
......@@ -598,6 +610,22 @@ var Hash = {
toQueryString: function() {
return this.map(function(pair) {
if (!pair.key) return null;
if (pair.value && pair.value.constructor == Array) {
pair.value = pair.value.compact();
if (pair.value.length < 2) {
pair.value = pair.value.reduce();
} else {
var key = encodeURIComponent(pair.key);
return pair.value.map(function(value) {
return key + '=' + encodeURIComponent(value);
}).join('&');
}
}
if (pair.value == undefined) pair[1] = '';
return pair.map(encodeURIComponent).join('=');
}).join('&');
},
......@@ -664,18 +692,18 @@ Ajax.Responders = {
this.responders._each(iterator);
},
register: function(responderToAdd) {
if (!this.include(responderToAdd))
this.responders.push(responderToAdd);
register: function(responder) {
if (!this.include(responder))
this.responders.push(responder);
},
unregister: function(responderToRemove) {
this.responders = this.responders.without(responderToRemove);
unregister: function(responder) {
this.responders = this.responders.without(responder);
},
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
if (responder[callback] && typeof responder[callback] == 'function') {
if (typeof responder[callback] == 'function') {
try {
responder[callback].apply(responder, [request, transport, json]);
} catch (e) {}
......@@ -690,7 +718,6 @@ Ajax.Responders.register({
onCreate: function() {
Ajax.activeRequestCount++;
},
onComplete: function() {
Ajax.activeRequestCount--;
}
......@@ -703,19 +730,14 @@ Ajax.Base.prototype = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
parameters: ''
}
Object.extend(this.options, options || {});
},
responseIsSuccess: function() {
return this.transport.status == undefined
|| this.transport.status == 0
|| (this.transport.status >= 200 && this.transport.status < 300);
},
responseIsFailure: function() {
return !this.responseIsSuccess();
this.options.method = this.options.method.toLowerCase();
this.options.parameters = $H(typeof this.options.parameters == 'string' ?
this.options.parameters.toQueryParams() : this.options.parameters);
}
}
......@@ -731,24 +753,28 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
},
request: function(url) {
var parameters = this.options.parameters || '';
if (parameters.length > 0) parameters += '&_=';
var params = this.options.parameters;
if (params.any()) params['_'] = '';
/* Simulate other verbs over post */
if (this.options.method != 'get' && this.options.method != 'post') {
parameters += (parameters.length > 0 ? '&' : '') + '_method=' + this.options.method;
if (!['get', 'post'].include(this.options.method)) {
// simulate other verbs over post
params['_method'] = this.options.method;
this.options.method = 'post';
}
try {
this.url = url;
if (this.options.method == 'get' && parameters.length > 0)
this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
// when GET, append parameters to URL
if (this.options.method == 'get' && params.any())
this.url += (this.url.indexOf('?') >= 0 ? '&' : '?') +
params.toQueryString();
try {
Ajax.Responders.dispatch('onCreate', this, this.transport);
this.transport.open(this.options.method, this.url,
this.options.asynchronous);
this.transport.open(this.options.method.toUpperCase(), this.url,
this.options.asynchronous, this.options.username,
this.options.password);
if (this.options.asynchronous)
setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
......@@ -756,95 +782,116 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
var body = this.options.postBody ? this.options.postBody : parameters;
this.transport.send(this.options.method == 'post' ? body : null);
var body = this.options.method == 'post' ?
(this.options.postBody || params.toQueryString()) : null;
this.transport.send(body);
/* Force Firefox to handle ready state 4 for synchronous requests */
if (!this.options.asynchronous && this.transport.overrideMimeType)
this.onStateChange();
} catch (e) {
}
catch (e) {
this.dispatchException(e);
}
},
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState > 1)
this.respondToReadyState(this.transport.readyState);
},
setRequestHeaders: function() {
var requestHeaders =
['X-Requested-With', 'XMLHttpRequest',
'X-Prototype-Version', Prototype.Version,
'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
var headers = {
'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
};
if (this.options.method == 'post') {
requestHeaders.push('Content-type', this.options.contentType);
headers['Content-type'] = this.options.contentType +
(this.options.encoding ? '; charset=' + this.options.encoding : '');
/* Force "Connection: close" for Mozilla browsers to work around
* a bug where XMLHttpReqeuest sends an incorrect Content-length
* header. See Mozilla Bugzilla #246651.
/* Force "Connection: close" for older Mozilla browsers to work
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType)
requestHeaders.push('Connection', 'close');
if (this.transport.overrideMimeType &&
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
headers['Connection'] = 'close';
}
if (this.options.requestHeaders)
requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
// user-defined headers
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
for (var i = 0; i < requestHeaders.length; i += 2)
this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
},
if (typeof extras.push == 'function')
for (var i = 0, length = extras.length; i < length; i += 2)
headers[extras[i]] = extras[i+1];
else
$H(extras).each(function(pair) { headers[pair.key] = pair.value });
}
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState != 1)
this.respondToReadyState(this.transport.readyState);
for (var name in headers)
this.transport.setRequestHeader(name, headers[name]);
},
header: function(name) {
try {
return this.transport.getResponseHeader(name);
} catch (e) {}
success: function() {
return !this.transport.status
|| (this.transport.status >= 200 && this.transport.status < 300);
},
evalJSON: function() {
try {
return eval('(' + this.header('X-JSON') + ')');
} catch (e) {}
},
respondToReadyState: function(readyState) {
var state = Ajax.Request.Events[readyState];
var transport = this.transport, json = this.evalJSON();
evalResponse: function() {
if (state == 'Complete') {
try {
return eval(this.transport.responseText);
(this.options['on' + this.transport.status]
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
|| Prototype.emptyFunction)(transport, json);
} catch (e) {
this.dispatchException(e);
}
},
respondToReadyState: function(readyState) {
var event = Ajax.Request.Events[readyState];
var transport = this.transport, json = this.evalJSON();
}
if (event == 'Complete') {
try {
(this.options['on' + this.transport.status]
|| this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
|| Prototype.emptyFunction)(transport, json);
(this.options['on' + state] || Prototype.emptyFunction)(transport, json);
Ajax.Responders.dispatch('on' + state, this, transport, json);
} catch (e) {
this.dispatchException(e);
}
if ((this.header('Content-type') || '').match(/^text\/javascript/i))
if (state == 'Complete') {
if ((this.getHeader('Content-type') || '').strip().
match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
this.evalResponse();
// avoid memory leak in MSIE: clean up
this.transport.onreadystatechange = Prototype.emptyFunction;
}
},
getHeader: function(name) {
try {
return this.transport.getResponseHeader(name);
} catch (e) { return null }
},
evalJSON: function() {
try {
var json = this.getHeader('X-JSON');
return json ? eval('(' + json + ')') : null;
} catch (e) { return null }
},
evalResponse: function() {
try {
(this.options['on' + event] || Prototype.emptyFunction)(transport, json);
Ajax.Responders.dispatch('on' + event, this, transport, json);
return eval(this.transport.responseText);
} catch (e) {
this.dispatchException(e);
}
/* Avoid memory leak in MSIE: clean up the oncomplete event handler */
if (event == 'Complete')
this.transport.onreadystatechange = Prototype.emptyFunction;
},
dispatchException: function(exception) {
......@@ -857,41 +904,37 @@ Ajax.Updater = Class.create();
Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
initialize: function(container, url, options) {
this.containers = {
success: container.success ? $(container.success) : $(container),
failure: container.failure ? $(container.failure) :
(container.success ? null : $(container))
this.container = {
success: (container.success || container),
failure: (container.failure || (container.success ? null : container))
}
this.transport = Ajax.getTransport();
this.setOptions(options);
var onComplete = this.options.onComplete || Prototype.emptyFunction;
this.options.onComplete = (function(transport, object) {
this.options.onComplete = (function(transport, param) {
this.updateContent();
onComplete(transport, object);
onComplete(transport, param);
}).bind(this);
this.request(url);
},
updateContent: function() {
var receiver = this.responseIsSuccess() ?
this.containers.success : this.containers.failure;
var receiver = this.container[this.success() ? 'success' : 'failure'];
var response = this.transport.responseText;
if (!this.options.evalScripts)
response = response.stripScripts();
if (!this.options.evalScripts) response = response.stripScripts();
if (receiver) {
if (this.options.insertion) {
if (receiver = $(receiver)) {
if (this.options.insertion)
new this.options.insertion(receiver, response);
} else {
Element.update(receiver, response);
}
else
receiver.update(response);
}
if (this.responseIsSuccess()) {
if (this.success()) {
if (this.onComplete)
setTimeout(this.onComplete.bind(this), 10);
}
......@@ -940,15 +983,15 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
function $() {
var results = [], element;
for (var i = 0; i < arguments.length; i++) {
element = arguments[i];
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
elements.push($(arguments[i]));
return elements;
}
if (typeof element == 'string')
element = document.getElementById(element);
results.push(Element.extend(element));
}
return results.reduce();
return Element.extend(element);
}
if (Prototype.BrowserFeatures.XPath) {
......@@ -956,7 +999,7 @@ if (Prototype.BrowserFeatures.XPath) {
var results = [];
var query = document.evaluate(expression, $(parentElement) || document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0, len = query.snapshotLength; i < len; i++)
for (var i = 0, length = query.snapshotLength; i < length; i++)
results.push(query.snapshotItem(i));
return results;
}
......@@ -969,11 +1012,9 @@ document.getElementsByClassName = function(className, parentElement) {
} else {
var children = ($(parentElement) || document.body).getElementsByTagName('*');
var elements = [], child;
for (var i = 0, len = children.length; i < len; i++) {
for (var i = 0, length = children.length; i < length; i++) {
child = children[i];
if (child.className.length == 0) continue;
if (child.className == className ||
child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
if (Element.hasClassName(child, className))
elements.push(Element.extend(child));
}
return elements;
......@@ -997,9 +1038,11 @@ Element.extend = function(element) {
if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
Object.extend(methods, Form.Element.Methods);
Object.extend(methods, Element.Methods.Simulated);
for (var property in methods) {
var value = methods[property];
if (typeof value == 'function')
if (typeof value == 'function' && !(property in element))
element[property] = cache.findOrStore(value);
}
}
......@@ -1093,6 +1136,13 @@ Element.Methods = {
return $A(element.getElementsByTagName('*'));
},
immediateDescendants: function(element) {
if (!(element = $(element).firstChild)) return [];
while (element && element.nodeType != 1) element = element.nextSibling;
if (element) return [element].concat($(element).nextSiblings());
return [];
},
previousSiblings: function(element) {
return $(element).recursivelyCollect('previousSibling');
},
......@@ -1139,6 +1189,10 @@ Element.Methods = {
return document.getElementsByClassName(className, element);
},
readAttribute: function(element, name) {
return $(element).getAttribute(name);
},
getHeight: function(element) {
element = $(element);
return element.offsetHeight;
......@@ -1150,7 +1204,12 @@ Element.Methods = {
hasClassName: function(element, className) {
if (!(element = $(element))) return;
return Element.classNames(element).include(className);
var elementClassName = element.className;
if (elementClassName.length == 0) return false;
if (elementClassName == className ||
elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
return true;
return false;
},
addClassName: function(element, className) {
......@@ -1300,13 +1359,19 @@ Element.Methods = {
}
}
Element.Methods.Simulated = {
hasAttribute: function(element, attribute) {
return $(element).getAttributeNode(attribute).specified;
}
}
// IE is missing .innerHTML support for TABLE-related elements
if(document.all){
Element.Methods.update = function(element, html) {
element = $(element);
html = typeof html == 'undefined' ? '' : html.toString();
var tagName = element.tagName.toUpperCase();
if (['THEAD','TBODY','TR','TD'].indexOf(tagName) > -1) {
if (['THEAD','TBODY','TR','TD'].include(tagName)) {
var div = document.createElement('div');
switch (tagName) {
case 'THEAD':
......@@ -1352,16 +1417,19 @@ if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
Element.addMethods = function(methods) {
Object.extend(Element.Methods, methods || {});
function copy(methods, destination) {
function copy(methods, destination, onlyIfAbsent) {
onlyIfAbsent = onlyIfAbsent || false;
var cache = Element.extend.cache;
for (var property in methods) {
var value = methods[property];
if (!onlyIfAbsent || !(property in destination))
destination[property] = cache.findOrStore(value);
}
}
if (typeof HTMLElement != 'undefined') {
copy(Element.Methods, HTMLElement.prototype);
copy(Element.Methods.Simulated, HTMLElement.prototype, true);
copy(Form.Methods, HTMLFormElement.prototype);
[HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
copy(Form.Element.Methods, klass.prototype);
......@@ -1388,8 +1456,8 @@ Abstract.Insertion.prototype = {
try {
this.element.insertAdjacentHTML(this.adjacency, this.content);
} catch (e) {
var tagName = this.element.tagName.toLowerCase();
if (tagName == 'tbody' || tagName == 'tr') {
var tagName = this.element.tagName.toUpperCase();
if (['TBODY', 'TR'].include(tagName)) {
this.insertContent(this.contentFromAnonymousTable());
} else {
throw e;
......@@ -1488,18 +1556,16 @@ Element.ClassNames.prototype = {
add: function(classNameToAdd) {
if (this.include(classNameToAdd)) return;
this.set(this.toArray().concat(classNameToAdd).join(' '));
this.set($A(this).concat(classNameToAdd).join(' '));
},
remove: function(classNameToRemove) {
if (!this.include(classNameToRemove)) return;
this.set(this.select(function(className) {
return className != classNameToRemove;
}).join(' '));
this.set($A(this).without(classNameToRemove).join(' '));
},
toString: function() {
return this.toArray().join(' ');
return $A(this).join(' ');
}
}
......@@ -1552,7 +1618,7 @@ Selector.prototype = {
if (clause = params.tagName)
conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
if ((clause = params.classNames).length > 0)
for (var i = 0; i < clause.length; i++)
for (var i = 0, length = clause.length; i < length; i++)
conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
if (clause = params.attributes) {
clause.each(function(attribute) {
......@@ -1594,7 +1660,7 @@ Selector.prototype = {
scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
var results = [];
for (var i = 0; i < scope.length; i++)
for (var i = 0, length = scope.length; i < length; i++)
if (this.match(element = scope[i]))
results.push(Element.extend(element));
......@@ -1636,32 +1702,30 @@ var Form = {
reset: function(form) {
$(form).reset();
return form;
}
};
Form.Methods = {
serialize: function(form) {
return this.serializeElements(Form.getElements($(form)));
},
serializeElements: function(elements) {
var queryComponents = new Array();
for (var i = 0; i < elements.length; i++) {
var queryComponent = Form.Element.serialize(elements[i]);
if (queryComponent)
queryComponents.push(queryComponent);
return elements.inject([], function(queryComponents, element) {
var queryComponent = Form.Element.serialize(element);
if (queryComponent) queryComponents.push(queryComponent);
return queryComponents;
}).join('&');
}
};
return queryComponents.join('&');
Form.Methods = {
serialize: function(form) {
return Form.serializeElements($(form).getElements());
},
getElements: function(form) {
return $A($(form).getElementsByTagName('*')).inject([], function(elements, child) {
return $A($(form).getElementsByTagName('*')).inject([],
function(elements, child) {
if (Form.Element.Serializers[child.tagName.toLowerCase()])
elements.push(Element.extend(child));
return elements;
});
}
);
},
getInputs: function(form, typeName, name) {
......@@ -1672,12 +1736,12 @@ Form.Methods = {
return inputs;
var matchingInputs = new Array();
for (var i = 0; i < inputs.length; i++) {
for (var i = 0, length = inputs.length; i < length; i++) {
var input = inputs[i];
if ((typeName && input.type != typeName) ||
(name && input.name != name))
continue;
matchingInputs.push(input);
matchingInputs.push(Element.extend(input));
}
return matchingInputs;
......@@ -1685,27 +1749,23 @@ Form.Methods = {
disable: function(form) {
form = $(form);
var elements = Form.getElements(form);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
form.getElements().each(function(element) {
element.blur();
element.disabled = 'true';
}
});
return form;
},
enable: function(form) {
form = $(form);
var elements = Form.getElements(form);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
form.getElements().each(function(element) {
element.disabled = '';
}
});
return form;
},
findFirstElement: function(form) {
return Form.getElements(form).find(function(element) {
return $(form).getElements().find(function(element) {
return element.type != 'hidden' && !element.disabled &&
['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
});
......@@ -1713,7 +1773,7 @@ Form.Methods = {
focusFirstElement: function(form) {
form = $(form);
Field.activate(Form.findFirstElement(form));
form.findFirstElement().activate();
return form;
}
}
......@@ -1828,18 +1888,20 @@ Form.Element.Serializers = {
selectOne: function(element) {
var value = '', opt, index = element.selectedIndex;
if (index >= 0) {
opt = element.options[index];
value = opt.value || opt.text;
opt = Element.extend(element.options[index]);
// Uses the new potential extension if hasAttribute isn't native.
value = opt.hasAttribute('value') ? opt.value : opt.text;
}
return [element.name, value];
},
selectMany: function(element) {
var value = [];
for (var i = 0; i < element.length; i++) {
var opt = element.options[i];
for (var i = 0, length = element.length; i < length; i++) {
var opt = Element.extend(element.options[i]);
if (opt.selected)
value.push(opt.value || opt.text);
// Uses the new potential extension if hasAttribute isn't native.
value.push(opt.hasAttribute('value') ? opt.value : opt.text);
}
return [element.name, value];
}
......@@ -1913,9 +1975,7 @@ Abstract.EventObserver.prototype = {
},
registerFormCallbacks: function() {
var elements = Form.getElements(this.element);
for (var i = 0; i < elements.length; i++)
this.registerCallback(elements[i]);
Form.getElements(this.element).each(this.registerCallback.bind(this));
},
registerCallback: function(element) {
......@@ -2019,7 +2079,7 @@ Object.extend(Event, {
unloadCache: function() {
if (!Event.observers) return;
for (var i = 0; i < Event.observers.length; i++) {
for (var i = 0, length = Event.observers.length; i < length; i++) {
Event.stopObserving.apply(this, Event.observers[i]);
Event.observers[i][0] = null;
}
......
*SVN*
* Update to Prototype 1.5.0_rc2. [Sam Stephenson]
* Add grep-based fallback to reaper, to work in pidless setups [Jamis Buck]
* Only wrap request processing with our USR1 signal handler so FastCGI can trap it and raise an exception while waiting for connections. Idle processes exit immediately rather than waiting for another request; active processes gracefully exit when the request is finished. [Jeremy Kemper]
......
/* Prototype JavaScript framework, version 1.5.0_rc1
* (c) 2005 Sam Stephenson <sam@conio.net>
/* Prototype JavaScript framework, version 1.5.0_rc2
* (c) 2005, 2006 Sam Stephenson <sam@conio.net>
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://prototype.conio.net/
......@@ -7,7 +7,7 @@
/*--------------------------------------------------------------------------*/
var Prototype = {
Version: '1.5.0_rc1',
Version: '1.5.0_rc2',
BrowserFeatures: {
XPath: !!document.evaluate
},
......@@ -37,8 +37,8 @@ Object.extend = function(destination, source) {
Object.extend(Object, {
inspect: function(object) {
try {
if (object == undefined) return 'undefined';
if (object == null) return 'null';
if (object === undefined) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : object.toString();
} catch (e) {
if (e instanceof RangeError) return '...';
......@@ -100,7 +100,7 @@ var Try = {
these: function() {
var returnValue;
for (var i = 0; i < arguments.length; i++) {
for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
......@@ -221,13 +221,23 @@ Object.extend(String.prototype, {
return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
},
toQueryParams: function() {
var pairs = this.match(/^\??(.*)$/)[1].split('&');
return pairs.inject({}, function(params, pairString) {
var pair = pairString.split('=');
toQueryParams: function(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return {};
return match[1].split(separator || '&').inject({}, function(hash, pair) {
if ((pair = pair.split('='))[0]) {
var name = decodeURIComponent(pair[0]);
var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
params[decodeURIComponent(pair[0])] = value;
return params;
if (hash[name] !== undefined) {
if (hash[name].constructor != Array)
hash[name] = [hash[name]];
if (value) hash[name].push(value);
}
else hash[name] = value;
}
return hash;
});
},
......@@ -243,7 +253,7 @@ Object.extend(String.prototype, {
? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
: oStringList[0];
for (var i = 1, len = oStringList.length; i < len; i++) {
for (var i = 1, length = oStringList.length; i < length; i++) {
var s = oStringList[i];
camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
}
......@@ -338,7 +348,7 @@ var Enumerable = {
return results;
},
detect: function (iterator) {
detect: function(iterator) {
var result;
this.each(function(value, index) {
if (iterator(value, index)) {
......@@ -490,7 +500,7 @@ var $A = Array.from = function(iterable) {
return iterable.toArray();
} else {
var results = [];
for (var i = 0; i < iterable.length; i++)
for (var i = 0, length = iterable.length; i < length; i++)
results.push(iterable[i]);
return results;
}
......@@ -503,7 +513,7 @@ if (!Array.prototype._reverse)
Object.extend(Array.prototype, {
_each: function(iterator) {
for (var i = 0; i < this.length; i++)
for (var i = 0, length = this.length; i < length; i++)
iterator(this[i]);
},
......@@ -541,7 +551,7 @@ Object.extend(Array.prototype, {
},
indexOf: function(object) {
for (var i = 0; i < this.length; i++)
for (var i = 0, length = this.length; i < length; i++)
if (this[i] == object) return i;
return -1;
},
......@@ -568,6 +578,8 @@ Object.extend(Array.prototype, {
return '[' + this.map(Object.inspect).join(', ') + ']';
}
});
Array.prototype.toArray = Array.prototype.clone;
var Hash = {
_each: function(iterator) {
for (var key in this) {
......@@ -590,7 +602,7 @@ var Hash = {
},
merge: function(hash) {
return $H(hash).inject($H(this), function(mergedHash, pair) {
return $H(hash).inject(this, function(mergedHash, pair) {
mergedHash[pair.key] = pair.value;
return mergedHash;
});
......@@ -598,6 +610,22 @@ var Hash = {
toQueryString: function() {
return this.map(function(pair) {
if (!pair.key) return null;
if (pair.value && pair.value.constructor == Array) {
pair.value = pair.value.compact();
if (pair.value.length < 2) {
pair.value = pair.value.reduce();
} else {
var key = encodeURIComponent(pair.key);
return pair.value.map(function(value) {
return key + '=' + encodeURIComponent(value);
}).join('&');
}
}
if (pair.value == undefined) pair[1] = '';
return pair.map(encodeURIComponent).join('=');
}).join('&');
},
......@@ -664,18 +692,18 @@ Ajax.Responders = {
this.responders._each(iterator);
},
register: function(responderToAdd) {
if (!this.include(responderToAdd))
this.responders.push(responderToAdd);
register: function(responder) {
if (!this.include(responder))
this.responders.push(responder);
},
unregister: function(responderToRemove) {
this.responders = this.responders.without(responderToRemove);
unregister: function(responder) {
this.responders = this.responders.without(responder);
},
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
if (responder[callback] && typeof responder[callback] == 'function') {
if (typeof responder[callback] == 'function') {
try {
responder[callback].apply(responder, [request, transport, json]);
} catch (e) {}
......@@ -690,7 +718,6 @@ Ajax.Responders.register({
onCreate: function() {
Ajax.activeRequestCount++;
},
onComplete: function() {
Ajax.activeRequestCount--;
}
......@@ -703,19 +730,14 @@ Ajax.Base.prototype = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
parameters: ''
}
Object.extend(this.options, options || {});
},
responseIsSuccess: function() {
return this.transport.status == undefined
|| this.transport.status == 0
|| (this.transport.status >= 200 && this.transport.status < 300);
},
responseIsFailure: function() {
return !this.responseIsSuccess();
this.options.method = this.options.method.toLowerCase();
this.options.parameters = $H(typeof this.options.parameters == 'string' ?
this.options.parameters.toQueryParams() : this.options.parameters);
}
}
......@@ -731,24 +753,28 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
},
request: function(url) {
var parameters = this.options.parameters || '';
if (parameters.length > 0) parameters += '&_=';
var params = this.options.parameters;
if (params.any()) params['_'] = '';
/* Simulate other verbs over post */
if (this.options.method != 'get' && this.options.method != 'post') {
parameters += (parameters.length > 0 ? '&' : '') + '_method=' + this.options.method;
if (!['get', 'post'].include(this.options.method)) {
// simulate other verbs over post
params['_method'] = this.options.method;
this.options.method = 'post';
}
try {
this.url = url;
if (this.options.method == 'get' && parameters.length > 0)
this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
// when GET, append parameters to URL
if (this.options.method == 'get' && params.any())
this.url += (this.url.indexOf('?') >= 0 ? '&' : '?') +
params.toQueryString();
try {
Ajax.Responders.dispatch('onCreate', this, this.transport);
this.transport.open(this.options.method, this.url,
this.options.asynchronous);
this.transport.open(this.options.method.toUpperCase(), this.url,
this.options.asynchronous, this.options.username,
this.options.password);
if (this.options.asynchronous)
setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
......@@ -756,95 +782,116 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
var body = this.options.postBody ? this.options.postBody : parameters;
this.transport.send(this.options.method == 'post' ? body : null);
var body = this.options.method == 'post' ?
(this.options.postBody || params.toQueryString()) : null;
this.transport.send(body);
/* Force Firefox to handle ready state 4 for synchronous requests */
if (!this.options.asynchronous && this.transport.overrideMimeType)
this.onStateChange();
} catch (e) {
}
catch (e) {
this.dispatchException(e);
}
},
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState > 1)
this.respondToReadyState(this.transport.readyState);
},
setRequestHeaders: function() {
var requestHeaders =
['X-Requested-With', 'XMLHttpRequest',
'X-Prototype-Version', Prototype.Version,
'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
var headers = {
'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
};
if (this.options.method == 'post') {
requestHeaders.push('Content-type', this.options.contentType);
headers['Content-type'] = this.options.contentType +
(this.options.encoding ? '; charset=' + this.options.encoding : '');
/* Force "Connection: close" for Mozilla browsers to work around
* a bug where XMLHttpReqeuest sends an incorrect Content-length
* header. See Mozilla Bugzilla #246651.
/* Force "Connection: close" for older Mozilla browsers to work
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType)
requestHeaders.push('Connection', 'close');
if (this.transport.overrideMimeType &&
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
headers['Connection'] = 'close';
}
if (this.options.requestHeaders)
requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
// user-defined headers
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
for (var i = 0; i < requestHeaders.length; i += 2)
this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
},
if (typeof extras.push == 'function')
for (var i = 0, length = extras.length; i < length; i += 2)
headers[extras[i]] = extras[i+1];
else
$H(extras).each(function(pair) { headers[pair.key] = pair.value });
}
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState != 1)
this.respondToReadyState(this.transport.readyState);
for (var name in headers)
this.transport.setRequestHeader(name, headers[name]);
},
header: function(name) {
try {
return this.transport.getResponseHeader(name);
} catch (e) {}
success: function() {
return !this.transport.status
|| (this.transport.status >= 200 && this.transport.status < 300);
},
evalJSON: function() {
try {
return eval('(' + this.header('X-JSON') + ')');
} catch (e) {}
},
respondToReadyState: function(readyState) {
var state = Ajax.Request.Events[readyState];
var transport = this.transport, json = this.evalJSON();
evalResponse: function() {
if (state == 'Complete') {
try {
return eval(this.transport.responseText);
(this.options['on' + this.transport.status]
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
|| Prototype.emptyFunction)(transport, json);
} catch (e) {
this.dispatchException(e);
}
},
respondToReadyState: function(readyState) {
var event = Ajax.Request.Events[readyState];
var transport = this.transport, json = this.evalJSON();
}
if (event == 'Complete') {
try {
(this.options['on' + this.transport.status]
|| this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
|| Prototype.emptyFunction)(transport, json);
(this.options['on' + state] || Prototype.emptyFunction)(transport, json);
Ajax.Responders.dispatch('on' + state, this, transport, json);
} catch (e) {
this.dispatchException(e);
}
if ((this.header('Content-type') || '').match(/^text\/javascript/i))
if (state == 'Complete') {
if ((this.getHeader('Content-type') || '').strip().
match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
this.evalResponse();
// avoid memory leak in MSIE: clean up
this.transport.onreadystatechange = Prototype.emptyFunction;
}
},
getHeader: function(name) {
try {
return this.transport.getResponseHeader(name);
} catch (e) { return null }
},
evalJSON: function() {
try {
var json = this.getHeader('X-JSON');
return json ? eval('(' + json + ')') : null;
} catch (e) { return null }
},
evalResponse: function() {
try {
(this.options['on' + event] || Prototype.emptyFunction)(transport, json);
Ajax.Responders.dispatch('on' + event, this, transport, json);
return eval(this.transport.responseText);
} catch (e) {
this.dispatchException(e);
}
/* Avoid memory leak in MSIE: clean up the oncomplete event handler */
if (event == 'Complete')
this.transport.onreadystatechange = Prototype.emptyFunction;
},
dispatchException: function(exception) {
......@@ -857,41 +904,37 @@ Ajax.Updater = Class.create();
Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
initialize: function(container, url, options) {
this.containers = {
success: container.success ? $(container.success) : $(container),
failure: container.failure ? $(container.failure) :
(container.success ? null : $(container))
this.container = {
success: (container.success || container),
failure: (container.failure || (container.success ? null : container))
}
this.transport = Ajax.getTransport();
this.setOptions(options);
var onComplete = this.options.onComplete || Prototype.emptyFunction;
this.options.onComplete = (function(transport, object) {
this.options.onComplete = (function(transport, param) {
this.updateContent();
onComplete(transport, object);
onComplete(transport, param);
}).bind(this);
this.request(url);
},
updateContent: function() {
var receiver = this.responseIsSuccess() ?
this.containers.success : this.containers.failure;
var receiver = this.container[this.success() ? 'success' : 'failure'];
var response = this.transport.responseText;
if (!this.options.evalScripts)
response = response.stripScripts();
if (!this.options.evalScripts) response = response.stripScripts();
if (receiver) {
if (this.options.insertion) {
if (receiver = $(receiver)) {
if (this.options.insertion)
new this.options.insertion(receiver, response);
} else {
Element.update(receiver, response);
}
else
receiver.update(response);
}
if (this.responseIsSuccess()) {
if (this.success()) {
if (this.onComplete)
setTimeout(this.onComplete.bind(this), 10);
}
......@@ -940,15 +983,15 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
function $() {
var results = [], element;
for (var i = 0; i < arguments.length; i++) {
element = arguments[i];
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
elements.push($(arguments[i]));
return elements;
}
if (typeof element == 'string')
element = document.getElementById(element);
results.push(Element.extend(element));
}
return results.reduce();
return Element.extend(element);
}
if (Prototype.BrowserFeatures.XPath) {
......@@ -956,7 +999,7 @@ if (Prototype.BrowserFeatures.XPath) {
var results = [];
var query = document.evaluate(expression, $(parentElement) || document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0, len = query.snapshotLength; i < len; i++)
for (var i = 0, length = query.snapshotLength; i < length; i++)
results.push(query.snapshotItem(i));
return results;
}
......@@ -969,11 +1012,9 @@ document.getElementsByClassName = function(className, parentElement) {
} else {
var children = ($(parentElement) || document.body).getElementsByTagName('*');
var elements = [], child;
for (var i = 0, len = children.length; i < len; i++) {
for (var i = 0, length = children.length; i < length; i++) {
child = children[i];
if (child.className.length == 0) continue;
if (child.className == className ||
child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
if (Element.hasClassName(child, className))
elements.push(Element.extend(child));
}
return elements;
......@@ -997,9 +1038,11 @@ Element.extend = function(element) {
if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
Object.extend(methods, Form.Element.Methods);
Object.extend(methods, Element.Methods.Simulated);
for (var property in methods) {
var value = methods[property];
if (typeof value == 'function')
if (typeof value == 'function' && !(property in element))
element[property] = cache.findOrStore(value);
}
}
......@@ -1093,6 +1136,13 @@ Element.Methods = {
return $A(element.getElementsByTagName('*'));
},
immediateDescendants: function(element) {
if (!(element = $(element).firstChild)) return [];
while (element && element.nodeType != 1) element = element.nextSibling;
if (element) return [element].concat($(element).nextSiblings());
return [];
},
previousSiblings: function(element) {
return $(element).recursivelyCollect('previousSibling');
},
......@@ -1139,6 +1189,10 @@ Element.Methods = {
return document.getElementsByClassName(className, element);
},
readAttribute: function(element, name) {
return $(element).getAttribute(name);
},
getHeight: function(element) {
element = $(element);
return element.offsetHeight;
......@@ -1150,7 +1204,12 @@ Element.Methods = {
hasClassName: function(element, className) {
if (!(element = $(element))) return;
return Element.classNames(element).include(className);
var elementClassName = element.className;
if (elementClassName.length == 0) return false;
if (elementClassName == className ||
elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
return true;
return false;
},
addClassName: function(element, className) {
......@@ -1300,13 +1359,19 @@ Element.Methods = {
}
}
Element.Methods.Simulated = {
hasAttribute: function(element, attribute) {
return $(element).getAttributeNode(attribute).specified;
}
}
// IE is missing .innerHTML support for TABLE-related elements
if(document.all){
Element.Methods.update = function(element, html) {
element = $(element);
html = typeof html == 'undefined' ? '' : html.toString();
var tagName = element.tagName.toUpperCase();
if (['THEAD','TBODY','TR','TD'].indexOf(tagName) > -1) {
if (['THEAD','TBODY','TR','TD'].include(tagName)) {
var div = document.createElement('div');
switch (tagName) {
case 'THEAD':
......@@ -1352,16 +1417,19 @@ if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
Element.addMethods = function(methods) {
Object.extend(Element.Methods, methods || {});
function copy(methods, destination) {
function copy(methods, destination, onlyIfAbsent) {
onlyIfAbsent = onlyIfAbsent || false;
var cache = Element.extend.cache;
for (var property in methods) {
var value = methods[property];
if (!onlyIfAbsent || !(property in destination))
destination[property] = cache.findOrStore(value);
}
}
if (typeof HTMLElement != 'undefined') {
copy(Element.Methods, HTMLElement.prototype);
copy(Element.Methods.Simulated, HTMLElement.prototype, true);
copy(Form.Methods, HTMLFormElement.prototype);
[HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
copy(Form.Element.Methods, klass.prototype);
......@@ -1388,8 +1456,8 @@ Abstract.Insertion.prototype = {
try {
this.element.insertAdjacentHTML(this.adjacency, this.content);
} catch (e) {
var tagName = this.element.tagName.toLowerCase();
if (tagName == 'tbody' || tagName == 'tr') {
var tagName = this.element.tagName.toUpperCase();
if (['TBODY', 'TR'].include(tagName)) {
this.insertContent(this.contentFromAnonymousTable());
} else {
throw e;
......@@ -1488,18 +1556,16 @@ Element.ClassNames.prototype = {
add: function(classNameToAdd) {
if (this.include(classNameToAdd)) return;
this.set(this.toArray().concat(classNameToAdd).join(' '));
this.set($A(this).concat(classNameToAdd).join(' '));
},
remove: function(classNameToRemove) {
if (!this.include(classNameToRemove)) return;
this.set(this.select(function(className) {
return className != classNameToRemove;
}).join(' '));
this.set($A(this).without(classNameToRemove).join(' '));
},
toString: function() {
return this.toArray().join(' ');
return $A(this).join(' ');
}
}
......@@ -1552,7 +1618,7 @@ Selector.prototype = {
if (clause = params.tagName)
conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
if ((clause = params.classNames).length > 0)
for (var i = 0; i < clause.length; i++)
for (var i = 0, length = clause.length; i < length; i++)
conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
if (clause = params.attributes) {
clause.each(function(attribute) {
......@@ -1594,7 +1660,7 @@ Selector.prototype = {
scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
var results = [];
for (var i = 0; i < scope.length; i++)
for (var i = 0, length = scope.length; i < length; i++)
if (this.match(element = scope[i]))
results.push(Element.extend(element));
......@@ -1636,32 +1702,30 @@ var Form = {
reset: function(form) {
$(form).reset();
return form;
}
};
Form.Methods = {
serialize: function(form) {
return this.serializeElements(Form.getElements($(form)));
},
serializeElements: function(elements) {
var queryComponents = new Array();
for (var i = 0; i < elements.length; i++) {
var queryComponent = Form.Element.serialize(elements[i]);
if (queryComponent)
queryComponents.push(queryComponent);
return elements.inject([], function(queryComponents, element) {
var queryComponent = Form.Element.serialize(element);
if (queryComponent) queryComponents.push(queryComponent);
return queryComponents;
}).join('&');
}
};
return queryComponents.join('&');
Form.Methods = {
serialize: function(form) {
return Form.serializeElements($(form).getElements());
},
getElements: function(form) {
return $A($(form).getElementsByTagName('*')).inject([], function(elements, child) {
return $A($(form).getElementsByTagName('*')).inject([],
function(elements, child) {
if (Form.Element.Serializers[child.tagName.toLowerCase()])
elements.push(Element.extend(child));
return elements;
});
}
);
},
getInputs: function(form, typeName, name) {
......@@ -1672,12 +1736,12 @@ Form.Methods = {
return inputs;
var matchingInputs = new Array();
for (var i = 0; i < inputs.length; i++) {
for (var i = 0, length = inputs.length; i < length; i++) {
var input = inputs[i];
if ((typeName && input.type != typeName) ||
(name && input.name != name))
continue;
matchingInputs.push(input);
matchingInputs.push(Element.extend(input));
}
return matchingInputs;
......@@ -1685,27 +1749,23 @@ Form.Methods = {
disable: function(form) {
form = $(form);
var elements = Form.getElements(form);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
form.getElements().each(function(element) {
element.blur();
element.disabled = 'true';
}
});
return form;
},
enable: function(form) {
form = $(form);
var elements = Form.getElements(form);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
form.getElements().each(function(element) {
element.disabled = '';
}
});
return form;
},
findFirstElement: function(form) {
return Form.getElements(form).find(function(element) {
return $(form).getElements().find(function(element) {
return element.type != 'hidden' && !element.disabled &&
['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
});
......@@ -1713,7 +1773,7 @@ Form.Methods = {
focusFirstElement: function(form) {
form = $(form);
Field.activate(Form.findFirstElement(form));
form.findFirstElement().activate();
return form;
}
}
......@@ -1828,18 +1888,20 @@ Form.Element.Serializers = {
selectOne: function(element) {
var value = '', opt, index = element.selectedIndex;
if (index >= 0) {
opt = element.options[index];
value = opt.value || opt.text;
opt = Element.extend(element.options[index]);
// Uses the new potential extension if hasAttribute isn't native.
value = opt.hasAttribute('value') ? opt.value : opt.text;
}
return [element.name, value];
},
selectMany: function(element) {
var value = [];
for (var i = 0; i < element.length; i++) {
var opt = element.options[i];
for (var i = 0, length = element.length; i < length; i++) {
var opt = Element.extend(element.options[i]);
if (opt.selected)
value.push(opt.value || opt.text);
// Uses the new potential extension if hasAttribute isn't native.
value.push(opt.hasAttribute('value') ? opt.value : opt.text);
}
return [element.name, value];
}
......@@ -1913,9 +1975,7 @@ Abstract.EventObserver.prototype = {
},
registerFormCallbacks: function() {
var elements = Form.getElements(this.element);
for (var i = 0; i < elements.length; i++)
this.registerCallback(elements[i]);
Form.getElements(this.element).each(this.registerCallback.bind(this));
},
registerCallback: function(element) {
......@@ -2019,7 +2079,7 @@ Object.extend(Event, {
unloadCache: function() {
if (!Event.observers) return;
for (var i = 0; i < Event.observers.length; i++) {
for (var i = 0, length = Event.observers.length; i < length; i++) {
Event.stopObserving.apply(this, Event.observers[i]);
Event.observers[i][0] = null;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册