-
Notifications
You must be signed in to change notification settings - Fork 10
/
Coccyx.js
107 lines (88 loc) · 3.38 KB
/
Coccyx.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
// Coccyx.js 0.4.1
// (c) 2012 Onsi Fakhouri
// Coccyx.js may be freely distributed under the MIT license.
// http://github.com/onsi/coccyx
(function() {
var Coccyx;
if (typeof exports !== 'undefined') {
Coccyx = exports;
} else {
Coccyx = this.Coccyx = {};
}
Coccyx.enforceContextualBinding = false;
Coccyx.enforceConstructorName = false;
Coccyx._globalTearDownCallbacks = [];
Coccyx.addTearDownCallback = function(callback) {
Coccyx._globalTearDownCallbacks.push(callback);
};
var originalExtend = Backbone.Model.extend;
var coccyxExtend = function(protoProps, classProps) {
var parent = this;
if (Coccyx.enforceConstructorName && !protoProps.constructorName) throw "Coccyx: Attempted to create a new class without passing in a constructor name."
if (protoProps.constructorName && !protoProps.hasOwnProperty('constructor')) {
eval("protoProps.constructor = function " + protoProps.constructorName + " () { parent.apply(this, arguments) };");
}
return originalExtend.call(parent, protoProps, classProps);
}
var originalOn = Backbone.Events.on;
var coccyxOn = function(events, callback, context) {
var returnValue = originalOn.apply(this, arguments);
if (Coccyx.enforceContextualBinding && !context) throw "Coccyx: Backbone event binding attempted without a context."
if (context && context.registerEventDispatcher) context.registerEventDispatcher(this);
return returnValue;
}
var coccyxViewExtensions = {
registerEventDispatcher: function(dispatcher) {
dispatcher._coccyxId = dispatcher._coccyxId || dispatcher.cid || _.uniqueId('coccyx');
this.eventDispatchers = this.eventDispatchers || {};
this.eventDispatchers[dispatcher._coccyxId] = dispatcher;
},
unregisterEventDispatcher: function(dispatcher){
dispatcher.off(null, null, this);
delete this.eventDispatchers[dispatcher._coccyxId];
},
registerSubView: function(subView) {
this.subViews = this.subViews || {};
this.subViews[subView.cid] = subView;
subView.__parentView = this;
return subView;
},
unregisterSubView: function(subView) {
subView.__parentView = undefined;
delete this.subViews[subView.cid];
},
tearDown: function() {
this._tearDown();
this.$el.remove();
return this;
},
tearDownRegisteredSubViews: function() {
_(this.subViews).invoke('_tearDown');
},
_tearDown: function() {
var that = this;
if (this.beforeTearDown) this.beforeTearDown();
if (this.__parentView) this.__parentView.unregisterSubView(this);
_(Coccyx._globalTearDownCallbacks).each(function(callback) {
callback.apply(that);
});
this.undelegateEvents();
this.__parentView = null;
_(this.eventDispatchers).invoke('off', null, null, this);
this.eventDispatchers = {};
_(this.subViews).invoke('_tearDown');
this.subViews = {};
}
}
var klassNames = ['Model', 'Collection', 'Router', 'View'];
var coccyxify = function(root) {
Coccyx.root = root;
root.Events = _.extend(root.Events, {on:coccyxOn, bind:coccyxOn});
_.each(klassNames, function(klassName) {
root[klassName].extend = coccyxExtend;
_.extend(root[klassName].prototype, root.Events);
});
_.extend(root.View.prototype, coccyxViewExtensions);
}
coccyxify(Backbone);
})();