Skip to content

Commit

Permalink
handle multiple checkboxes and checkbox value attributes; issue #40
Browse files Browse the repository at this point in the history
  • Loading branch information
delambo committed Jan 11, 2013
1 parent 6f051ea commit 8c3198f
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ The following is a list of the supported form elements, their binding details, a
- input[type=number] will update the model with a Number value
- `keyup`, `change`, `cut`, and `paste` events are used for handling
- input[type=checkbox]
- `checked` property determined by the truthiness of the model attribute or the result of `onGet`
- `checked` property determined by the truthiness of the model attribute or if the checkbox "value" attribute is defined, then its value is used to match against the model. If a binding selector matches multiple checkboxes then it is expected that the observed model attribute will be an array of values to match against the checkbox value attributes.
- `change` event is used for handling
- input[type=radio]
- model attribute value matched to a radio group `value` attribute
Expand Down
37 changes: 32 additions & 5 deletions backbone.stickit.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,25 @@
var getElVal = function($el, isHTML) {
var val;
if (isFormEl($el)) {
if (isCheckbox($el)) val = $el.prop('checked');
else if (isNumber($el)) val = Number($el.val());
if (isNumber($el)) val = Number($el.val());
else if (isRadio($el)) val = $el.filter(':checked').val();
else if (isSelect($el)) {
else if (isCheckbox($el)) {
if ($el.length > 1) {
val = _.reduce($el, function(memo, el) {
if ($(el).prop('checked')) memo.push($(el).val());
return memo;
}, []);
} else {
val = $el.prop('checked');
// If the checkbox has a value attribute defined, then
// use that value. Most browsers use "on" as a default.
var boxval = $el.val();
if (boxval != 'on' && boxval != null) {
if (val) val = $el.val();
else val = null;
}
}
} else if (isSelect($el)) {
if ($el.prop('multiple')) {
val = $el.find('option:selected').map(function() {
return $(this).data('stickit_bind_val');
Expand Down Expand Up @@ -276,8 +291,20 @@
if (!evaluateBoolean(view, config.updateView, val)) return;

if (isRadio($el)) $el.filter('[value="'+val+'"]').prop('checked', true);
else if (isCheckbox($el)) $el.prop('checked', !!val);
else if (isInput($el) || isTextarea($el)) $el.val(val);
else if (isCheckbox($el)) {
if ($el.length > 1) {
// There are multiple checkboxes so we need to go through them and check
// any that have value attributes that match what's in the array of `val`s.
val || (val = []);
_.each($el, function(el) {
if (_.indexOf(val, $(el).val()) > -1) $(el).prop('checked', true);
else $(el).prop('checked', false);
});
} else {
if (_.isBoolean(val)) $el.prop('checked', val);
else $el.prop('checked', val == $el.val());
}
} else if (isInput($el) || isTextarea($el)) $el.val(val);
else if (isContenteditable($el)) $el.html(val);
else if (isSelect($el)) {
var optList, list = selectConfig.collection, isMultiple = $el.prop('multiple');
Expand Down
44 changes: 44 additions & 0 deletions test/bindData.js
Original file line number Diff line number Diff line change
Expand Up @@ -1022,4 +1022,48 @@ $(document).ready(function() {
equal(model.get('water'), 'dasina');
});

test('checkbox multiple', function() {

model.set({'water':['fountain', 'dasina']});
view.model = model;
view.templateId = 'jst18';
view.bindings = {
'.boxes': 'water'
};
$('#qunit-fixture').html(view.render().el);

equal(view.$('.boxes[value="fountain"]').prop('checked'), true);
equal(view.$('.boxes[value="evian"]').prop('checked'), false);
equal(view.$('.boxes[value="dasina"]').prop('checked'), true);

model.set('water', ['evian']);
equal(view.$('.boxes[value="fountain"]').prop('checked'), false);
equal(view.$('.boxes[value="evian"]').prop('checked'), true);
equal(view.$('.boxes[value="dasina"]').prop('checked'), false);

view.$('.boxes[value="dasina"]').prop('checked', true).change();
equal(model.get('water').length, 2);
equal(_.indexOf(model.get('water'), 'evian') > -1, true);
equal(_.indexOf(model.get('water'), 'dasina') > -1, true);
});

test('checkbox (single with value defined)', function() {

model.set({'water':null});
view.model = model;
view.templateId = 'jst19';
view.bindings = {
'.box': 'water'
};
$('#qunit-fixture').html(view.render().el);

equal(view.$('.box').prop('checked'), false);

model.set('water', 'fountain');
equal(view.$('.box').prop('checked'), true);

view.$('.box').prop('checked', false).change();
equal(model.get('water'), null);
});

});
10 changes: 10 additions & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ <h2 id="qunit-userAgent"></h2>

<script id="jst17" type="text/jst"><div id="test17" contenteditable="true"></div></script>

<script id="jst18" type="text/jst">
<input type="checkbox" class="boxes" value="fountain">
<input type="checkbox" class="boxes" value="evian">
<input type="checkbox" class="boxes" value="dasina">
</script>

<script id="jst19" type="text/jst">
<input type="checkbox" class="box" value="fountain">
</script>

</body>

</html>

0 comments on commit 8c3198f

Please sign in to comment.