-
Notifications
You must be signed in to change notification settings - Fork 65
/
model.js
138 lines (131 loc) · 3.89 KB
/
model.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
129
130
131
132
133
134
135
136
137
138
/*!
* backbone.iobind - Model
* Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/*!
* Version
*/
Backbone.Model.prototype.ioBindVersion = '0.4.3';
/**
* # .ioBind(event, callback, [context])
*
* Bind and handle trigger of socket.io events for models.
*
* ### Guidelines
*
* Do NOT bind to reserved backbone events, such as `change`, `remove`, and `add`.
* Proxy these events using different event tags such as `update`, `delete`, and `create`.
*
* The socket.io socket must either exist at `window.socket`, `Backbone.socket`, or
* `this.socket` or it must be passed as the second argument.
*
* ### Example
*
* * Model definition has url: `my_model`
* * Model instance has id: `abc123`
*
* #### Create a new bind (client-side):
*
* model.ioBind('update', window.io, this.updateView, this);
*
* #### Send socket.io message (server-side)
*
* socket.emit( 'my_model/abc123:update', { title: 'My New Title' } );
*
* @name ioBind
* @param {String} eventName
* @param {Object} io from active socket.io connection (optional)
* @param {Function} callback
* @param {Object} context (optional) object to interpret as this on callback
* @api public
*/
Backbone.Model.prototype.ioBind = function (eventName, io, callback, context) {
var ioEvents = this._ioEvents || (this._ioEvents = {})
, globalName = this.url() + ':' + eventName
, self = this;
if ('function' == typeof io) {
context = callback;
callback = io;
io = this.socket || window.socket || Backbone.socket;
}
var event = {
name: eventName,
global: globalName,
cbLocal: callback,
cbGlobal: function (data) {
self.trigger(eventName, data);
}
};
this.bind(event.name, event.cbLocal, (context || self));
io.on(event.global, event.cbGlobal);
if (!ioEvents[event.name]) {
ioEvents[event.name] = [event];
} else {
ioEvents[event.name].push(event);
}
return this;
};
/**
* # .ioUnbind(event, [callback])
*
* Unbind model triggers and stop listening for server events for a specific
* event and optional callback.
*
* The socket.io socket must either exist at `window.socket`, `Backbone.socket`,
* or `this.socket` or it must be passed as the second argument.
*
* @name ioUnbind
* @param {String} eventName
* @param {Object} io from active socket.io connection
* @param {Function} callback (optional) If not provided will remove all callbacks for eventname.
* @api public
*/
Backbone.Model.prototype.ioUnbind = function (eventName, io, callback) {
var ioEvents = this._ioEvents || (this._ioEvents = {})
, globalName = this.url() + ':' + eventName;
if ('function' == typeof io) {
callback = io;
io = this.socket || window.socket || Backbone.socket;
}
var events = ioEvents[eventName];
if (!_.isEmpty(events)) {
if (callback && 'function' === typeof callback) {
for (var i = 0, l = events.length; i < l; i++) {
if (callback == events[i].cbLocal) {
this.unbind(events[i].name, events[i].cbLocal);
io.removeListener(events[i].global, events[i].cbGlobal);
events[i] = false;
}
}
events = _.compact(events);
} else {
this.unbind(eventName);
io.removeAllListeners(globalName);
}
if (events.length === 0) {
delete ioEvents[eventName];
}
}
return this;
};
/**
* # .ioUnbindAll()
*
* Unbind all callbacks and server listening events for the given model.
*
* The socket.io socket must either exist at `window.socket`, `Backbone.socket`,
* or `this.socket` or it must be passed as the only argument.
*
* @name ioUnbindAll
* @param {Object} io from active socket.io connection
* @api public
*/
Backbone.Model.prototype.ioUnbindAll = function (io) {
var ioEvents = this._ioEvents || (this._ioEvents = {});
if (!io) io = this.socket || window.socket || Backbone.socket;
for (var ev in ioEvents) {
this.ioUnbind(ev, io);
}
return this;
};