ADDED CODE UPDATES
You can use two syntaxes with reactIf() (Hat tip: RoToRa)
supply a function or helper, as original, or
reference a helper with a string followed by arguments
$('.cities')
.reactIf($('#zip'), IS.NotBlank)
.reactIf('#zip', 'Between', 19100, 19400);
helpers use this instead of $(this) (Hat tip: RoToRa)
checks for a data reference instead of class to find if initialized (still adds class) (Hat tip: RoToRa)
short-circuiting the $.each() loop (Hat tip: RoToRa)
verified using jquery objects as well as selector strings to find the element to watch (Hat tip: meo)
Links
Git Hub: https://github.com/natedavisolds/react.js
Here's the demo page: http://natedavisolds.com/workshop/react.js/demo/react.htmlHere's the demo page
- use as jQuery pluinplugin
- easy to chain rules together
- understandable by reading a line of code
- can build/add custom conditions
$('.elements_to_display')
.reactIf( '#some_form_element', SatisfiesFirstCondition)
.reactIf( '#some_other_form_element', 'SatisfiesAnotherCondition'SatisfiesAnotherCondition)
.reactIf( '#some_other_form_element', 'SatisfiesAnotherCondition', argsSatisfiesAnotherCondition);
The Code
Page JS [UPDATED]
var IS = $.extend({}, $.fn.reactor.helpers);
$('.cities')
.reactIf('#zip', 'Between', IS.Between(19100, 19400))
.reactIf($('#zip'), IS.NotBlank);
$('.philly_middle_to_low_income')
.reactIf('#income_2011', 'LessThan', IS.LessThan(40000))
.reactIf($('#cities_select'), IS.EqualTo('philadelphia'));
$('.low_income_select_zips')
.reactIf('#income_2011', IS.LessThan(15000))
.reactIf('#zip', 'Between', IS.BetweenSameLength(19000, 20000))
.reactIf($('#zip'), IS.NotBlank);
$('.reactor').trigger('change.reactor');
Plugin react.js [UPDATED]
(function($){
$.fn.reactTo = function(selector) {
var $elements = $(selector),
$reactor_element = $(this),
_proxy_event = function() {
$reactor_element.trigger('change.reactor');
};
$elements.filter('select').bind('change.reactor', _proxy_event);
$elements.filter('input').bind('keyup.reactor', _proxy_event);
return this;
};
$.fn.reactIf = function(sel, exp_func) {
var $sel = $(sel);
var args = Array.prototype.slice.call( arguments, 2 );
var _func = function() {
if ($.isFunction(exp_func)) {
return exp_func.apply($sel);
} else {
var _returned = $.fn.reactor.helpers[exp_func].apply($sel, args);
if ($.isFunction(_returned)) {
return _returned.apply($sel)
} else {
return _returned;
}
}
};
this.each(function() {
if (!$(this).hasClass('reactor')) { $(this).reactor(); }
var conditions_arry = $(this).data('conditions.reactor');
if (!$.isArray(conditions_arry)) { conditions_arry = []};
conditions_arry.push(_func);
$(this).data('conditions.reactor', conditions_arry);
});
$(this).reactTo(sel);
return this;
};
$.fn.react = function() {
this.each(function() {
$(this).trigger('change.reactor')
});
return this;
};
$.fn.reactor = function(options) {
var settings = $.extend({}, $.fn.reactor.defaults, options);
this.each(function() {
// var opts = $.meta ? $.extend({}, settings, $this.data()) : settings;
var $element = $(this);
if (!$.isArray($element.datahasClass('conditions.reactor')'reactor')) { $element.data('conditions.reactor', []).addClass('reactor'); }
var isReactionaryis_reactionary = function() {
var conditionalArray = $(this).data('conditions.reactor');
var r = true;
$.each(conditionalArray, function() {
r = (r && this.call());
return r; // short circuits the loop when any value is false
});
return r;
}
var reaction = function(evt) {
evt.stopPropagation();
if (isReactionaryis_reactionary.apply(this)) {
settings.compliant.apply($element);
} else {
settings.uncompliant.apply($element);
}
}
$element.bind('change.reactor', reaction);
});
return this;
};
$.fn.reactor.defaults = {
compliant: function() {
$(this).show();
},
uncompliant: function() {
$(this).hide();
}
};
$.fn.reactor.helpers = {
NotBlank: function() {
return( $(this).val().toString() != "" )
},
Blank: function() {
return( $(this).val().toString() == "" )
},
Disabled: function() {
return( this.filter(':disable').length > 0 );
},
Enabled: function() {
return( this.filter(':enabled').length > 0 );
},
EqualTo: function(matchStr) {
var _func = function() {
var v = $(this).val();
if (v) { return( v.toString() == matchStr ); }
else { return false; }
}
return _func;
},
LessThan: function(number) {
var _func = function() {
var v = $(this).val();
return(!(v && parseInt(v) > number));
}
return _func;
},
MoreThan: function(number) {
var _func = function() {
var v = $(this).val();
return(!(v && parseInt(v) < number));
}
return _func;
},
Between: function(min, max) {
var _func = function() {
var v = $(this).val();
return(!(v && (parseInt(v) > max || parseInt(v) < min)));
}
return _func;
},
BetweenSameLength: function(min, max) {
var len = min.toString().length;
var _func = function() {
var v = $(this).val();
return(!(v && v.length == len && (parseInt(v) > max || parseInt(v) < min)));
}
return _func;
}
};
})(jQuery);
<form id="portfolio_form">
<fieldset>
<label>Zip</label>
<input id="zip" type="text" value="" /><br />
<label>2011 Income</label>
<input id="income_2011" name="income[2011]" />
</fieldset>
<p>Display cities only when zip is between 19100 and 19400</p>
<fieldset class="cities">
<label>Cities</label>
<select id="cities_select">
<option value=""></option>
<option value="philadelphia">Philadelphia</option>
<option value="media">Media</option>
<option value="doylestown">Doylestown</option>
</select>
</fieldset>
<p>Display checkboxes only for Philadelphia and income less than 40000</p>
<fieldset class="philly_middle_to_low_income">
<input type="checkbox" /> Check One<br />
<input type="checkbox" /> Check Two<br />
<input type="checkbox" /> Check Three<br />
<input type="checkbox" /> Check Four<br />
</fieldset>
<p>Display checkboxes when zip is between 19000 and 20000 and income is lower than 15000<25000</p>
<fieldset class="low_income_select_zips">
<input type="checkbox" /> Check One<br />
<input type="checkbox" /> Check Two<br />
<input type="checkbox" /> Check Three<br />
<input type="checkbox" /> Check Four<br />
</fieldset>
</form>