text: 
  riot.observable = function(el) {
  
    el = el || {}
  
    var callbacks = {},
        _id = 0
  
    el.on = function(events, fn) {
      if (isFunction(fn)) {
        if (typeof fn.id === T_UNDEF) fn._id = _id++
  
        events.replace(/\S+/g, function(name, pos) {
          (callbacks[name] = callbacks[name] || []).push(fn)
          fn.typed = pos > 0
        })
      }
      return el
    }
  
    el.off = function(events, fn) {
      if (events == '*') callbacks = {}
      else {
        events.replace(/\S+/g, function(name) {
          if (fn) {
            var arr = callbacks[name]
            for (var i = 0, cb; (cb = arr && arr[i]); ++i) {
              if (cb._id == fn._id) arr.splice(i--, 1)
            }
          } else {
            callbacks[name] = []
          }
        })
      }
      return el
    }
  
    // only single event supported
    el.one = function(name, fn) {
      function on() {
        el.off(name, on)
        fn.apply(el, arguments)
      }
      return el.on(name, on)
    }
  
    el.trigger = function(name) {
      var args = [].slice.call(arguments, 1),
          fns = callbacks[name] || []
  
      for (var i = 0, fn; (fn = fns[i]); ++i) {
        if (!fn.busy) {
          fn.busy = 1
          fn.apply(el, fn.typed ? [name].concat(args) : args)
          if (fns[i] !== fn) { i-- }
          fn.busy = 0
        }
      }
  
      if (callbacks.all && name != 'all') {
        el.trigger.apply(el, ['all', name].concat(args))
      }
  
      return el
    }
  
    return el
  
  }