Skip to content

Commit

Permalink
[BUGFIX canary] Honor customEvents opting out of event listeners.
Browse files Browse the repository at this point in the history
Setting `customEvents` to a hash in an application is a way to add new
listeners that the `EventDispatcher` knows about.

Often, users see this and decide that they want to disable a given event
(for example `mouseenter` and `mouseleave` events) and think they can do
something like:

```javascript
var App = Ember.Application.create({
  customEvents: {
    mouseenter: null,
    mouseleave: null
  }
});
```

Unfortunately, that just makes the `EventDispatcher` call a method named
`null` on the view/component instances (LOL).

This fixes that bug by allowing a `null` value to disable the event
listener.
  • Loading branch information
rwjblue committed Aug 12, 2015
1 parent c490566 commit acbb0b2
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 9 deletions.
31 changes: 30 additions & 1 deletion packages/ember-application/lib/system/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,20 @@ var librariesRegistered = false;
});
```
To prevent Ember from setting up a listener for a default event,
specify the event name with a `null` value in the `customEvents`
property:
```javascript
var App = Ember.Application.create({
customEvents: {
// prevent listeners for mouseenter/mouseleave events
mouseenter: null,
mouseleave: null
}
});
```
By default, the application sets up these event listeners on the document
body. However, in cases where you are embedding an Ember application inside
an existing page, you may want it to set up the listeners on an element
Expand Down Expand Up @@ -243,7 +257,11 @@ var Application = Namespace.extend(RegistryProxy, {
If you would like additional bubbling events to be delegated to your
views, set your `Ember.Application`'s `customEvents` property
to a hash containing the DOM event name as the key and the
corresponding view method name as the value. For example:
corresponding view method name as the value. Setting an event to
a value of `null` will prevent a default event listener from being
added for that event.
To add new events to be listened to:
```javascript
var App = Ember.Application.create({
Expand All @@ -254,6 +272,17 @@ var Application = Namespace.extend(RegistryProxy, {
});
```
To prevent default events from being listened to:
```javascript
var App = Ember.Application.create({
customEvents: {
// remove support for mouseenter / mouseleave events
mouseenter: null,
mouseleave: null
}
});
```
@property customEvents
@type Object
@default null
Expand Down
35 changes: 27 additions & 8 deletions packages/ember-views/lib/system/event_dispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import EmberObject from 'ember-runtime/system/object';
import jQuery from 'ember-views/system/jquery';
import ActionManager from 'ember-views/system/action_manager';
import View from 'ember-views/views/view';
import merge from 'ember-metal/merge';
import assign from 'ember-metal/assign';

/**
`Ember.EventDispatcher` handles delegating browser events to their
Expand All @@ -29,12 +29,29 @@ export default EmberObject.extend({

/**
The set of events names (and associated handler function names) to be setup
and dispatched by the `EventDispatcher`. Custom events can added to this list at setup
time, generally via the `Ember.Application.customEvents` hash. Only override this
default set to prevent the EventDispatcher from listening on some events all together.
and dispatched by the `EventDispatcher`. Modifications to this list can be done
at setup time, generally via the `Ember.Application.customEvents` hash.
This set will be modified by `setup` to also include any events added at that time.
To add new events to be listened to:
```javascript
var App = Ember.Application.create({
customEvents: {
paste: 'paste'
}
});
```
To prevent default events from being listened to:
```javascript
var App = Ember.Application.create({
customEvents: {
mouseenter: null,
mouseleave: null
}
});
```
@property events
@type Object
@private
Expand Down Expand Up @@ -129,9 +146,7 @@ export default EmberObject.extend({
*/
setup(addedEvents, rootElement) {
var event;
var events = get(this, 'events');

merge(events, addedEvents || {});
var events = assign({}, get(this, 'events'), addedEvents);

if (!isNone(rootElement)) {
set(this, 'rootElement', rootElement);
Expand Down Expand Up @@ -172,6 +187,10 @@ export default EmberObject.extend({
var self = this;
var viewRegistry = this.container && this.container.lookup('-view-registry:main') || View.views;

if (eventName === null) {
return;
}

rootElement.on(event + '.ember', '.ember-view', function(evt, triggeringManager) {
var view = viewRegistry[this.id];
var result = true;
Expand Down
31 changes: 31 additions & 0 deletions packages/ember-views/tests/system/event_dispatcher_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,34 @@ QUnit.test('additional events and rootElement can be specified', function () {

jQuery('#leView').trigger('myevent');
});

QUnit.test('default events can be disabled via `customEvents`', function () {
expect(1);

run(function () {
dispatcher.setup({
click: null
});

view = View.create({
elementId: 'leView',

null() {
// yes, at one point `click: null` made an event handler
// for `click` that called `null` on the view
ok(false, 'null event has been triggered');
},

click() {
ok(false, 'click event has been triggered');
},

doubleClick() {
ok(true, 'good event was still triggered');
}
}).appendTo(dispatcher.get('rootElement'));
});

jQuery('#leView').trigger('click');
jQuery('#leView').trigger('dblclick');
});

0 comments on commit acbb0b2

Please sign in to comment.