UNPKG

silk-gui

Version:

GUI for developers and Node OS

174 lines (160 loc) 3.64 kB
var _ = require('../util') /** * Listen on the given `event` with `fn`. * * @param {String} event * @param {Function} fn */ exports.$on = function (event, fn) { (this._events[event] || (this._events[event] = [])) .push(fn) modifyListenerCount(this, event, 1) return this } /** * Adds an `event` listener that will be invoked a single * time then automatically removed. * * @param {String} event * @param {Function} fn */ exports.$once = function (event, fn) { var self = this function on () { self.$off(event, on) fn.apply(this, arguments) } on.fn = fn this.$on(event, on) return this } /** * Remove the given callback for `event` or all * registered callbacks. * * @param {String} event * @param {Function} fn */ exports.$off = function (event, fn) { var cbs // all if (!arguments.length) { if (this.$parent) { for (event in this._events) { cbs = this._events[event] if (cbs) { modifyListenerCount(this, event, -cbs.length) } } } this._events = {} return this } // specific event cbs = this._events[event] if (!cbs) { return this } if (arguments.length === 1) { modifyListenerCount(this, event, -cbs.length) this._events[event] = null return this } // specific handler var cb var i = cbs.length while (i--) { cb = cbs[i] if (cb === fn || cb.fn === fn) { modifyListenerCount(this, event, -1) cbs.splice(i, 1) break } } return this } /** * Trigger an event on self. * * @param {String} event */ exports.$emit = function (event) { this._eventCancelled = false var cbs = this._events[event] if (cbs) { // avoid leaking arguments: // http://jsperf.com/closure-with-arguments var i = arguments.length - 1 var args = new Array(i) while (i--) { args[i] = arguments[i + 1] } i = 0 cbs = cbs.length > 1 ? _.toArray(cbs) : cbs for (var l = cbs.length; i < l; i++) { if (cbs[i].apply(this, args) === false) { this._eventCancelled = true } } } return this } /** * Recursively broadcast an event to all children instances. * * @param {String} event * @param {...*} additional arguments */ exports.$broadcast = function (event) { // if no child has registered for this event, // then there's no need to broadcast. if (!this._eventsCount[event]) return var children = this._children for (var i = 0, l = children.length; i < l; i++) { var child = children[i] child.$emit.apply(child, arguments) if (!child._eventCancelled) { child.$broadcast.apply(child, arguments) } } return this } /** * Recursively propagate an event up the parent chain. * * @param {String} event * @param {...*} additional arguments */ exports.$dispatch = function () { var parent = this.$parent while (parent) { parent.$emit.apply(parent, arguments) parent = parent._eventCancelled ? null : parent.$parent } return this } /** * Modify the listener counts on all parents. * This bookkeeping allows $broadcast to return early when * no child has listened to a certain event. * * @param {Vue} vm * @param {String} event * @param {Number} count */ var hookRE = /^hook:/ function modifyListenerCount (vm, event, count) { var parent = vm.$parent // hooks do not get broadcasted so no need // to do bookkeeping for them if (!parent || !count || hookRE.test(event)) return while (parent) { parent._eventsCount[event] = (parent._eventsCount[event] || 0) + count parent = parent.$parent } }