watch.js & if.js

Simple watch

Your name:

Hello !

<p>Your name: <input type="text" name="name"</p>
<p>Hello <span id="name-out"></span>!</p>
<script type="text/javascript">
  watch.add('name', function(value) { $('#name-out').text(value); }); 
</script>
   

Simple if

How many wheels does a bicycle have? (in words)

Correct! Try again :(

<p>How many wheels does a bicycle have? <input type="text" name="wheels"> (in words)</p>
<p>
 <span class="if" data-if="wheels=two">Correct!</span>
 <span class="if" data-if="wheels!=two">Try again :(</span>
</p>
   

Advanced example

Choose a make:

Volkswagen Options Color:
Toyota Options Color:

Your car will be .

Warning: Red paint will cost an extra $150.00

<p>Choose a make: <select name="make"><option value="vw">Volkswagen</option><option value="toyota">Toyota</option></select></p>

<fieldset class="if" data-if="make=vw"><legend>Volkswagen Options</legend>
  Color: <select name="color"><option value="black">Black</option><option value="silver">Silver</option>;<option value="red">Red</option></select>
</fieldset>

<fieldset class="if" data-if="make=toyota"><legend>Toyota Options</legend>
  Color: <select name="color"><option value="white">White</option><option value="red">Red</option></select>
</fieldset>

<p>Your car will be <span id="color-out"></span>.</p>
<p style="color:#f00;" class="if" data-if="color=red"><strong>Warning</strong>: Red paint will cost an extra $150.00</p>
<script type="text/javascript">
  watch.add('color', function(value) { $('#color-out').text(value); }); 
</script>
   

Source

watch.js
var watch = {

  check_input: function() {
    if (!$(this).is(':enabled')) return;
    watch.set($(this).attr('name'), $(this).val(), this);
  },

  values: {},
  triggers: {},

  add: function(name, fn) {
    if ($.type(name) == 'array') {
      return $.each(name, function() { watch.add(this, fn); });
    }

    if (this.triggers[name] == undefined) {
      this.triggers[name] = [];
      $(':input[name='+name+']').change(watch.check_input).keyup(watch.check_input).each(watch.check_input);
    }
    this.triggers[name].push(fn);
    if (this.values[name]) {
      fn.call(this.values[name][1], this.values[name][0]);
    }
    return watch;
  },

  get: function(name) {
    return this.values[name] && this.values[name][0];
  },
  set: function(name, value, el) {
    this.values[name] = [value, el];

    for (k in this.triggers[name]) {
      this.triggers[name][k].call(el, value);
    }
    return watch;
  }
};
   
if.js
$(function() {
  $('.if').each(function() {
    var div = $(this); // div
    var full = div.data('if');
    
    var parts = [];
    $.each(full.split(/ or /i), function(i, condition) {

      condition = condition.split('='); // condition
      var not = condition[0][condition[0].length-1] == '!';
      if (not) condition[0] = condition[0].substring(0,condition[0].length-1);

      var test = function(val) {
        var v = (val == condition[1]);
        parts[i]['test'] = not ? !v : v;

        v = false;
        for (var k = 0; k < parts.length; k++) {
          v = v || parts[k]['test'];
        }

        toggle($(div), v);
      }

      parts.push({'test': false, 'watch': condition[0], 'fn': test});
    });

    for (var i = 0; i < parts.length; i++) watch.add(parts[i]['watch'], parts[i]['fn']);

    div.data('check', function() {
      for (var i = 0; i < parts.length; i++) {
        parts[i]['fn'](watch.get(parts[i]['watch']));
      }
    });
  });

  function toggle($el, show) {
    if (show===undefined) show = true;

    $el.toggleClass('disabled', !show);
    if (!$el.hasClass('control') || $el.hasClass('if-hide')) {
      $el.css('display', show ? ($el.is('span') ? 'inline' : 'block') :'none');
    }

    if (show && $el.parents('.disabled').length) {
      $el.find(':input').attr('disabled','disabled');
    }else{
      $el.find(':input').attr('disabled',show ? false :'disabled');
      $el.find('.disabled :input').attr('disabled','disabled');
      // recursively run check if showing el
      if (show) {
        $el.find(':input').trigger('change');
        $el.find('.if').each(function() { $el.data('check') && $el.data('check')(); });
      }
    }
  }
});