Skip to content

Commit

Permalink
Prototype: merges from form branch. Closes #5031, #5902, #7595, #8401…
Browse files Browse the repository at this point in the history
…, #8483, #8767. [Mislav Marohnić, Tomas, Christophe Porteneuve, Jonathan Viney]
  • Loading branch information
madrobby committed Jun 27, 2007
1 parent f2d304b commit 9e7efd5
Show file tree
Hide file tree
Showing 3 changed files with 359 additions and 240 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG
@@ -1,5 +1,20 @@
*SVN*

* The action for Form#request defaults to the current URL if the "action" attribute is empty. (This is what most of the major browsers do.) Fixes #8483. [Tomas, Mislav Marohnić]

* In form serialization, change the way submit buttons are handled. Previously all submit buttons were serialized; now Prototype serializes only the first one. Change Form#serialize and Form.serializeElements to accept a params hash. With the "hash: false" option, a serialized string is returned instead of the hash data object. With the "submit: 'foo'" option, only the submit button with the name "foo" is serialized. References #5031. [Mislav Marohnić]
Examples:
$('form').serialize({ submit: 'delete' })
$('form').serialize({ hash: false }) //-> equivalent to $('form').serialize()

* Form#findFirstElement respects HTML tabindexes. Closes #7595. [Christophe Porteneuve]

* Added Form.Element#setValue method for setting values on various form controls. Checkboxes and radio buttons respond to a boolean and multiple select boxes expect an array of values. Closes #5902. [Jonathan Viney, Mislav Marohnić]
Examples:
$('text_input').setValue('hello world!')
$('remember_me').setValue(true)
$('attend_classes').setValue(['cheese rolling', 'evil chemistry'])

* Make document.getElementsByClassName match a subset of the WHATWG Web Applications 1.0 specification which was adopted in Firefox 3 (http://www.whatwg.org/specs/web-apps/current-work/#getelementsbyclassname). It now supports multiple class names given as a whitespace-separated list in a string. Array argument is not supported. The method will only return the nodes that match all the class names. In browsers that implement the method natively it will not be overwritten. Closes #8401. [Mislav Marohnić]
Example:
document.getElementsByClassName('foo bar')
Expand Down
83 changes: 60 additions & 23 deletions src/form.js
Expand Up @@ -4,12 +4,18 @@ var Form = {
return form;
},

serializeElements: function(elements, getHash) {
serializeElements: function(elements, options) {
if (typeof options != 'object') options = { hash: !!options };
else if (options.hash === undefined) options.hash = true;
var key, value, submitted = false, submit = options.submit;

var data = elements.inject({}, function(result, element) {
if (!element.disabled && element.name) {
var key = element.name, value = $(element).getValue();
if (value != null) {
if (key in result) {
key = element.name; value = $(element).getValue();
if (value != null && (element.type != 'submit' || (!submitted &&
submit !== false && (!submit || key == submit) && (submitted = true)))) {
if (key in result) {
// a key is already present; construct an array of values
if (result[key].constructor != Array) result[key] = [result[key]];
result[key].push(value);
}
Expand All @@ -19,13 +25,13 @@ var Form = {
return result;
});

return getHash ? data : Hash.toQueryString(data);
return options.hash ? data : Hash.toQueryString(data);
}
};

Form.Methods = {
serialize: function(form, getHash) {
return Form.serializeElements(Form.getElements(form), getHash);
serialize: function(form, options) {
return Form.serializeElements(Form.getElements(form), options);
},

getElements: function(form) {
Expand Down Expand Up @@ -67,9 +73,15 @@ Form.Methods = {
},

findFirstElement: function(form) {
return $(form).getElements().find(function(element) {
return element.type != 'hidden' && !element.disabled &&
['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
var elements = $(form).getElements().findAll(function(element) {
return 'hidden' != element.type && !element.disabled;
});
var firstByIndex = elements.findAll(function(element) {
return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
}).sortBy(function(element) { return element.tabIndex }).first();

return firstByIndex ? firstByIndex : elements.find(function(element) {
return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
});
},

Expand All @@ -82,7 +94,8 @@ Form.Methods = {
request: function(form, options) {
form = $(form), options = Object.clone(options || {});

var params = options.parameters;
var params = options.parameters, action = form.readAttribute('action') || '';
if (action.blank()) action = window.location.href;
options.parameters = form.serialize(true);

if (params) {
Expand All @@ -93,7 +106,7 @@ Form.Methods = {
if (form.hasAttribute('method') && !options.method)
options.method = form.method;

return new Ajax.Request(form.readAttribute('action'), options);
return new Ajax.Request(action, options);
}
}

Expand Down Expand Up @@ -131,6 +144,13 @@ Form.Element.Methods = {
return Form.Element.Serializers[method](element);
},

setValue: function(element, value) {
element = $(element);
var method = element.tagName.toLowerCase();
Form.Element.Serializers[method](element, value);
return element;
},

clear: function(element) {
$(element).value = '';
return element;
Expand All @@ -145,7 +165,7 @@ Form.Element.Methods = {
try {
element.focus();
if (element.select && (element.tagName.toLowerCase() != 'input' ||
!['button', 'reset', 'submit'].include(element.type)))
!['button', 'reset', 'submit'].include(element.type)))
element.select();
} catch (e) {}
return element;
Expand Down Expand Up @@ -173,27 +193,44 @@ var $F = Form.Element.Methods.getValue;
/*--------------------------------------------------------------------------*/

Form.Element.Serializers = {
input: function(element) {
input: function(element, value) {
switch (element.type.toLowerCase()) {
case 'checkbox':
case 'radio':
return Form.Element.Serializers.inputSelector(element);
return Form.Element.Serializers.inputSelector(element, value);
default:
return Form.Element.Serializers.textarea(element);
return Form.Element.Serializers.textarea(element, value);
}
},

inputSelector: function(element) {
return element.checked ? element.value : null;
inputSelector: function(element, value) {
if (value === undefined) return element.checked ? element.value : null;
else element.checked = !!value;
},

textarea: function(element) {
return element.value;
textarea: function(element, value) {
if (value === undefined) return element.value;
else element.value = value;
},

select: function(element) {
return this[element.type == 'select-one' ?
'selectOne' : 'selectMany'](element);
select: function(element, index) {
if (index === undefined)
return this[element.type == 'select-one' ?
'selectOne' : 'selectMany'](element);
else {
var opt, value, single = index.constructor != Array;
for (var i = 0, length = element.length; i < length; i++) {
opt = element.options[i];
value = this.optionValue(opt);
if (single) {
if (value == index) {
opt.selected = true;
return;
}
}
else opt.selected = index.include(value);
}
}
},

selectOne: function(element) {
Expand Down

0 comments on commit 9e7efd5

Please sign in to comment.