diff --git a/v3/src/checksum.js b/v3/src/checksum.js index 8d1840238..a8225ec97 100644 --- a/v3/src/checksum.js +++ b/v3/src/checksum.js @@ -1,4 +1,4 @@ var CHECKSUM = { -build: '8271a1a0-bb58-11e6-92c7-1bf1ec33cb5b' +build: 'ada471e0-bbbc-11e6-8998-8541b7b364d1' }; module.exports = CHECKSUM; \ No newline at end of file diff --git a/v3/src/events/EventBinding.js b/v3/src/events/EventBinding.js index dcbb91f93..c6d858fcf 100644 --- a/v3/src/events/EventBinding.js +++ b/v3/src/events/EventBinding.js @@ -138,15 +138,13 @@ EventBinding.prototype = { else if (this.active.length === 0) { // This was a valid dispatch call, we just had nothing to do ... - return true; + return; } this.state = CONST.DISPATCHER_DISPATCHING; var listener; - event.reset(this.dispatcher); - for (var i = 0; i < this.active.length; i++) { listener = this.active[i]; diff --git a/v3/src/events/EventDispatcher.js b/v3/src/events/EventDispatcher.js index c9ae8d146..fe34f8f4e 100644 --- a/v3/src/events/EventDispatcher.js +++ b/v3/src/events/EventDispatcher.js @@ -3,6 +3,8 @@ var EventBinding = require('./EventBinding'); var EventDispatcher = function () { this.bindings = {}; + this.filters = []; + this.hasFilters = false; }; EventDispatcher.prototype.constructor = EventDispatcher; @@ -55,6 +57,29 @@ EventDispatcher.prototype = { return this; }, + // Add a callback that is notified every time this EventDispatcher dispatches an event + // no matter what the event type is. Filters are invoked first, before any bindings, + // and can stop events if they wish (in which case they'll never reach the bindings) + filter: function (callback) + { + var i = this.filters.indexOf(callback); + + if (i === -1) + { + // Add the filter + this.filters.push(callback); + } + else + { + // Remove the filter + this.filters.splice(i, 1); + } + + this.hasFilters = (this.filters.length > 0); + + return this; + }, + has: function (type, listener) { var binding = this.getBinding(type); @@ -93,30 +118,46 @@ EventDispatcher.prototype = { return this; }, + _dispatchHandler: function (event) + { + event.reset(this); + + // Pass the event through the filters first + + if (this.hasFilters) + { + for (var i = 0; i < this.filters.length; i++) + { + this.filters[i].call(this, event); + + // Did the filter kill the event? If so, we can abort now + if (!event._propagate) + { + return; + } + } + } + + var binding = this.getBinding(event.type); + + if (binding) + { + binding.dispatch(event); + } + }, + dispatch: function (event) { - var binding; - if (Array.isArray(event)) { for (var i = 0; i < event.length; i++) { - binding = this.getBinding(event[i].type); - - if (binding) - { - return binding.dispatch(event[i]); - } + this._dispatchHandler(event[i]); } } else { - binding = this.getBinding(event.type); - - if (binding) - { - return binding.dispatch(event); - } + this._dispatchHandler(event); } }, @@ -133,6 +174,15 @@ EventDispatcher.prototype = { return this; }, + removeAllFilters: function () + { + this.filters.length = 0; + + this.hasFilters = false; + + return this; + }, + delete: function (type) { var binding = this.getBinding(type); @@ -159,7 +209,8 @@ EventDispatcher.prototype = { destroy: function () { - // What would it do any differently to deleteAll? + this.deleteAll(); + this.removeAllFilters(); } };