-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathevent_binder.js
128 lines (106 loc) · 3.75 KB
/
event_binder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Backbone.EventBinder, v1.0.2
// Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
// Distributed under MIT license
// http://github.com/marionettejs/backbone.eventbinder
// EventBinder
// -----------
//
// The event binder facilitates the binding and unbinding of events
// from objects that extend `Backbone.Events`. It makes
// unbinding events, even with anonymous callback functions,
// easy.
//
// Inspired by [Johnny Oshika](http://stackoverflow.com/questions/7567404/backbone-js-repopulate-or-recreate-the-view/7607853#7607853)
define(function (require) {
"use strict";
var _ = require("underscore");
var Backbone = require("backbone");
// A map of objects that support binding/unbinding events.
// This allows EventBinder to support events on arbitrary
// objects with EB's consistent api.
var handlerMap = {
// 'default' type accounts for Backbone style objects extending
// Backbone.Events
"default" : {
bindTo : function (obj, eventName, callback, context) {
context = context || this;
obj.on(eventName, callback, context);
var binding = {
type : 'default',
obj: obj,
eventName: eventName,
callback: callback,
context: context
};
return binding;
},
unbindFrom : function(binding){
binding.obj.off(binding.eventName, binding.callback, binding.context);
}
},
// 'jquery' style handlers allow us to bind to jQuery
// (or compatible) objects
jquery : {
bindTo : function (obj, eventName, callback, context) {
context = context || this;
callback = _(callback).bind(context);
obj.on(eventName, callback);
var binding = {
type : 'jquery',
obj: obj,
eventName: eventName,
callback: callback,
context: context
};
return binding;
},
unbindFrom : function(binding){
binding.obj.off(binding.eventName, binding.callback);
}
}
};
// Use whatever best logic necessary to determine the type
// of the supplied object
function getHandlerForObject(obj) {
if (_.isUndefined(obj) || _.isNull(obj)) {
throw new Error("Can't bindTo undefined");
}
if (obj.jquery) { return handlerMap.jquery; }
return handlerMap["default"];
}
// Constructor function
var EventBinder = function(){
this._eventBindings = [];
};
// Copy the `extend` function used by Backbone's classes
EventBinder.extend = Backbone.View.extend;
// Extend the EventBinder with additional methods
_.extend(EventBinder.prototype, {
// Delegate to the bindTo for the appropriate type and
// store the event binding in array so it can be unbound
// easily, at a later point in time.
bindTo: function(/* args... */) {
var obj = arguments[0];
var handlers = getHandlerForObject(obj);
var args = Array.prototype.slice.apply(arguments);
var binding = handlers.bindTo.apply(this, args);
this._eventBindings.push(binding);
return binding;
},
// Unbind from a single binding object. Binding objects are
// returned from the `bindTo` method call.
unbindFrom: function(binding) {
var args = Array.prototype.slice.apply(arguments);
handlerMap[binding.type].unbindFrom.apply(this, args);
this._eventBindings = _.reject(this._eventBindings, function(bind){return bind === binding;});
},
// Unbind all of the events that we have stored.
unbindAll: function() {
// The `unbindFrom` call removes elements from the array
// while it is being iterated, so clone it first.
var bindings = _.map(this._eventBindings, _.identity);
_.each(bindings, this.unbindFrom, this);
}
});
return EventBinder;
});