#1209 closed enhancement (wontfix)
Form Value Function
Reported by: | bgoldman | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | 1.2.4 |
Component: | core | Version: | 1.1.2 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description
This function sets or gets the value of a form variable as a form would interpret it. This function is useful for jQuery core because everybody uses forms. This function makes it very easy to get and set form values without having to use fancy selectors. It's basically shorthand for a bunch of alternatives.
1) For selects and options: formVal() would return the currently selected value. formVal('foo') would select the option with that value. 2) For input text fields: formVal() would return the current value. formVal('foo') would set the value to foo. 3) For textareas: formVal() would return text(). formVal('foo') would set the text() to foo. 4) For checkboxes: formVal() would return the first matched checked value. formVal('foo') would check the boxes with value foo. 5) For radios: formVal() would return the checked value. formVal('foo') would check the radio with value foo.
//gets the value of the first matched form field, or sets the value of all the matched form fields $.fn.formVal = function(newVal) { var self = this.get(0); if(newVal == null) { if(this.size() < 1) return ''; else if(self.type == 'text') return self.value; else if(self.tagName == 'TEXTAREA') return this.text(); else if(self.type == 'checkbox' || self.type == 'radio') return this.filter('input:checked').val(); else if(self.tagName == 'OPTION') return this.parent().formVal(); else if(self.tagName == 'SELECT') { var match = this.find('option:selected').eq(0); return (match.get(0).value != null) ? match.val() : match.text(); } else return ''; } if(self.type == 'text') this.val(newVal); else if(self.tagName == 'TEXTAREA') this.text(newVal); else if(self.type == 'checkbox' || self.type == 'radio') { var matches = this.filter('[@value=' + newVal + ']'); if(matches.size() < 1) return this; if(self.type == 'radio') this.filter(':checked').removeAttr('checked'); matches.attr('checked', 'checked'); } else if(self.tagName == 'OPTION') this.parent().formVal(newVal); else if(self.tagName == 'SELECT') { var match = this.find('option[@value=' + newVal + ']'); if(match.size() < 1) { if(newVal == '') match = this.find('option:empty'); else match = this.find('option').contains(newVal); } if(match.size() < 1) return this; this.find('option:selected').removeAttr('selected'); match.eq(0).attr('selected', 'selected'); } return this; };
Change History (6)
comment:1 Changed 16 years ago by
comment:2 Changed 16 years ago by
Fixed another bug... here we go:
//gets the value of the first matched form field, or sets the value of all the matched form fields $.fn.formVal = function(newVal) { var self = this.get(0); if(newVal == null) { if(this.size() < 1) return ''; else if(self.type == 'text') return self.value; else if(self.tagName == 'TEXTAREA') return this.text(); else if(self.type == 'checkbox' || self.type == 'radio') return this.filter('input:checked').val() || ''; else if(self.tagName == 'OPTION') return this.parent().formVal(); else if(self.tagName == 'SELECT') { var match = this.find('option:selected').eq(0); return (match.is('[@value]')) ? match.val() : match.text(); } else return ''; } if(self.type == 'text') this.val(newVal); else if(self.tagName == 'TEXTAREA') this.text(newVal); else if(self.type == 'checkbox' || self.type == 'radio') { this.filter(':checked').removeAttr('checked'); this.filter('[@value=' + newVal + ']').attr('checked', 'checked'); } else if(self.tagName == 'OPTION') this.parent().formVal(newVal); else if(self.tagName == 'SELECT') { var match = this.filter('option[@value=' + newVal + ']'); if(match.size() < 1) { if(newVal == '') match = this.find('option:empty'); else match = this.find('option').filter(function() { return ($(this).text() == newVal); }); } if(match.size() < 1) return this; this.find('option:selected').removeAttr('selected'); match.attr('selected', 'selected'); } return this; };
comment:3 follow-up: 4 Changed 16 years ago by
For SELECT elements, formVal() returns the wrong value when the selected OPTION is marked up with value="": Since "" is falsy, match.is('[@value]') is false and match.text() is incorrectly returned.
Pseudocode for a fix:
if (option.value) { // non-empty string return option.value; } if (! option.outerHTML) { // definitely not IE, so trust value return ''; } if (/* option.outerHTML has 'value=""' in attributes */) { // likely painful regex return ''; } else { return option.text; }
comment:4 Changed 16 years ago by
Here's a fix for setting/getting SELECT when options might have empty value attributes, but non-empty text. Is there a unit test somewhere for this plugin?
//gets the value of the first matched form field, or sets //the value of all the matched form fields $.fn.formVal = function(newVal) { var self = this.get(0); var optVal = function(opt) { if(opt.value) return opt.value; // non-empty string, use it if(!opt.outerHTML) return ''; // not IE, we should trust value // @todo: more rigorous regex to assert value="" in attributes, not text return /\svalue=""(?:\s|>)/.test(opt.outerHTML) ? '' : opt.text; }; if(newVal == null) { if(this.size() < 1) return ''; if(self.type == 'text') return self.value; if(self.tagName == 'TEXTAREA') return this.text(); if(self.type == 'checkbox' || self.type == 'radio') return this.filter('input:checked').val() || ''; if(self.tagName == 'OPTION') return this.parent().formVal(); // if a SELECT with no selection, fallthrough to return '' // or should re return null? if(self.tagName == 'SELECT' && self.selectedIndex >= 0) return optVal(self.options[self.selectedIndex]); return ''; } if(self.type == 'text') this.val(newVal); else if(self.tagName == 'TEXTAREA') this.text(newVal); else if(self.type == 'checkbox' || self.type == 'radio') { this.filter(':checked').removeAttr('checked'); this.filter('[@value=' + newVal + ']').attr('checked', 'checked'); } else if(self.tagName == 'OPTION') this.parent().formVal(newVal); else if(self.tagName == 'SELECT') { // search for matching value for (var i=0, l=self.options.length; i<l; ++i) { if(newVal == optVal(self.options[i])) { self.selectedIndex = i; break; } } } return this; };
comment:5 Changed 15 years ago by
Resolution: | → wontfix |
---|---|
Status: | new → closed |
I think jQuery.form can do all or most of this. If anything is missing you can propose it for this plugin.
comment:6 Changed 15 years ago by
Milestone: | 1.1.3 → 1.2.4 |
---|
I found a bug with selects and options. Here is the fixed code: