rivets.js 4.6 KB
// Generated by CoffeeScript 1.3.1
(function() {
  var Rivets, attributeBinding, bidirectionals, getInputValue, rivets, stateBinding,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  Rivets = {};

  Rivets.Binding = (function() {

    Binding.name = 'Binding';

    function Binding(el, type, context, keypath) {
      this.el = el;
      this.type = type;
      this.context = context;
      this.keypath = keypath;
      this.bind = __bind(this.bind, this);

      this.set = __bind(this.set, this);

      this.routine = Rivets.bindings[this.type] || attributeBinding(this.type);
    }

    Binding.prototype.set = function(value) {
      if (value == null) {
        value = null;
      }
      return this.routine(this.el, value || Rivets.config.adapter.read(this.context, this.keypath));
    };

    Binding.prototype.bind = function() {
      var _ref,
        _this = this;
      if (Rivets.config.preloadData) {
        this.set();
      }
      Rivets.config.adapter.subscribe(this.context, this.keypath, function(value) {
        return _this.set(value);
      });
      if (_ref = this.type, __indexOf.call(bidirectionals, _ref) >= 0) {
        return this.el.addEventListener('change', function(el) {
          return Rivets.config.adapter.publish(_this.context, _this.keypath, getInputValue(el));
        });
      }
    };

    return Binding;

  })();

  getInputValue = function(el) {
    switch (el.type) {
      case 'text':
      case 'textarea':
      case 'password':
      case 'select-one':
        return el.value;
      case 'checkbox':
      case 'radio':
        return el.checked;
    }
  };

  attributeBinding = function(attr) {
    return function(el, value) {
      if (value) {
        return el.setAttribute(attr, value);
      } else {
        return el.removeAttribute(attr);
      }
    };
  };

  stateBinding = function(attr, inverse) {
    if (inverse == null) {
      inverse = false;
    }
    return function(el, value) {
      var binding;
      binding = attributeBinding(attr);
      return binding(el, inverse === !value ? attr : false);
    };
  };

  bidirectionals = ['value', 'checked', 'unchecked', 'selected', 'unselected'];

  Rivets.bindings = {
    checked: stateBinding('checked'),
    selected: stateBinding('selected'),
    disabled: stateBinding('disabled'),
    unchecked: stateBinding('checked', true),
    unselected: stateBinding('selected', true),
    enabled: stateBinding('disabled', true),
    text: function(el, value) {
      return el.innerText = value || '';
    },
    html: function(el, value) {
      return el.innerHTML = value || '';
    },
    value: function(el, value) {
      return el.value = value;
    },
    show: function(el, value) {
      return el.style.display = value ? '' : 'none';
    },
    hide: function(el, value) {
      return el.style.display = value ? 'none' : '';
    }
  };

  Rivets.config = {
    preloadData: true
  };

  rivets = {
    configure: function(options) {
      var property, value, _results;
      if (options == null) {
        options = {};
      }
      _results = [];
      for (property in options) {
        value = options[property];
        _results.push(Rivets.config[property] = value);
      }
      return _results;
    },
    register: function(routine, routineFunction) {
      return Rivets.bindings[routine] = routineFunction;
    },
    bind: function(el, contexts) {
      var attribute, binding, bindings, context, keypath, node, path, type, _i, _j, _k, _len, _len1, _len2, _ref, _ref1;
      if (contexts == null) {
        contexts = {};
      }
      bindings = [];
      _ref = el.getElementsByTagName('*');
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        node = _ref[_i];
        _ref1 = node.attributes;
        for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
          attribute = _ref1[_j];
          if (/^data-/.test(attribute.name)) {
            type = attribute.name.replace('data-', '');
            path = attribute.value.split('.');
            context = path.shift();
            keypath = path.join('.');
            bindings.push(new Rivets.Binding(node, type, contexts[context], keypath));
          }
        }
      }
      for (_k = 0, _len2 = bindings.length; _k < _len2; _k++) {
        binding = bindings[_k];
        binding.bind();
      }
      return bindings.length;
    }
  };

  if (typeof module !== "undefined" && module !== null) {
    module.exports = rivets;
  } else {
    this.rivets = rivets;
  }

}).call(this);