Repository: cheeriojs/cheerio
Pull request #672 (2015-03-02 03:27:38)

Added default value for checkboxes/radios
While working on #632 to find some edge cases jQuery is covering, I found a regression with checkboxes and radio inputs. In the browser, it will default to `on` as the value when no value attribute has been specified.

http://codepen.io/twolfson/pen/bNKJBZ

This PR fixes that by patching in on `.val()`. In this PR:

- Added regression test for valueless radios and checkboxes
- Added fix for valueless radios and checkboxes

fb55: LGTM. This is in-line with the HTML spec (both value attributes are set to [default/on](http://www.w3.org/html/wg/drafts/html/master/#dom-input-value-default-on)) & the overhead shouldn't be too bad.
fb55: @twolfson Sorry for the delay. This needs a rebase, should be good to merge then.

Patch:
diff --git a/lib/api/attributes.js b/lib/api/attributes.js
index a4947bdd..c7884bd3 100644
--- a/lib/api/attributes.js
+++ b/lib/api/attributes.js
@@ -44,6 +44,13 @@ var getAttr = function(elem, name) {
   if (elem.name === 'option' && name === 'value') {
     return $.text(elem.children);
   }
+
+  // Mimic DOM with default value for radios/checkboxes
+  if (elem.name === 'input' &&
+      (elem.attribs.type === 'radio' || elem.attribs.type === 'checkbox') &&
+      name === 'value') {
+    return 'on';
+  }
 };
 
 var setAttr = function(el, name, value) {


Test patch:
diff --git a/test/api/attributes.js b/test/api/attributes.js
index a5b3f1f3..c23a1ff4 100644
--- a/test/api/attributes.js
+++ b/test/api/attributes.js
@@ -399,10 +399,18 @@ describe('$(...)', function() {
       var val = $('input[name="checkbox_off"]').val();
       expect(val).to.equal('off');
     });
+    it('.val(): on valueless checkbox should get value', function() {
+      var val = $('input[name="checkbox_valueless"]').val();
+      expect(val).to.equal('on');
+    });
     it('.val(): on radio should get value', function() {
       var val = $('input[type="radio"]').val();
       expect(val).to.equal('off');
     });
+    it('.val(): on valueless radio should get value', function() {
+      var val = $('input[name="radio_valueless"]').val();
+      expect(val).to.equal('on');
+    });
     it('.val(): on multiple select should get an array of values', function() {
       var val = $('select#multi').val();
       expect(val).to.eql(['2', '3']);
diff --git a/test/fixtures.js b/test/fixtures.js
index d73df80f..b2b127d8 100644
--- a/test/fixtures.js
+++ b/test/fixtures.js
@@ -46,8 +46,10 @@ exports.inputs = [
   '<select id="one-nested"><option>Option not selected</option><option selected>Option <span>selected</span></option></select>',
   '<input type="text" value="input_text" />',
   '<input type="checkbox" name="checkbox_off" value="off" /><input type="checkbox" name="checkbox_on" value="on" checked />',
+  '<input type="checkbox" name="checkbox_valueless" />',
   '<input type="radio" value="off" name="radio" /><input type="radio" name="radio" value="on" checked />',
   '<input type="radio" value="off" name="radio[brackets]" /><input type="radio" name="radio[brackets]" value="on" checked />',
+  '<input type="radio" name="radio_valueless" />',
   '<select id="multi" multiple><option value="1">1</option><option value="2" selected>2</option><option value="3" selected>3</option><option value="4">4</option></select>',
   '<select id="multi-valueless" multiple><option>1</option><option selected>2</option><option selected>3</option><option>4</option></select>'
 ].join('');