forked from rotundasoftware/backbone.subviews
-
Notifications
You must be signed in to change notification settings - Fork 0
/
backbone.subviews.js
93 lines (73 loc) · 2.85 KB
/
backbone.subviews.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
/*
* Backbone.Subviews, v0.5.1
* Copyright (c)2013 Rotunda Software, LLC.
* Distributed under MIT license
* http://github.com/rotundasoftware/backbone.subviews
*/
(function( Backbone, _ ) {
Backbone.Subviews = {};
Backbone.Subviews.add = function( view ) {
var overriddenViewMethods = {
render : view.render,
remove : view.remove
};
// ****************** Overridden Backbone.View functions ******************
view.render = function() {
var args = Array.prototype.slice.call( arguments );
_prerender.call( this );
var returnValue = overriddenViewMethods.render.apply( this, args );
_postrender.call( this );
return returnValue;
};
view.remove = function() {
if( this.subviews ) {
_.each( this.subviews, function( thisSubview ) {
thisSubview.remove();
} );
delete this.subviews;
}
return overriddenViewMethods.remove.call( this );
};
// ****************** Private Utility Functions ******************
function _prerender() {
if( ! this.subviews ) this.subviews = {};
// detach each of our subviews that we have already created during previous
// renders from the DOM, so that they do not loose their DOM events when
// we re-render the contents of this view's DOM element.
_.each( this.subviews, function( thisSubview ) {
thisSubview.$el.detach();
} );
}
function _postrender() {
var _this = this;
this.subviewCreators = this.subviewCreators || {};
this.$( "div[data-subview]" ).each( function() {
var thisPlaceHolderDiv = $( this );
var subviewName = thisPlaceHolderDiv.attr( "data-subview" );
var newSubview;
if( _.isUndefined( _this.subviews[ subviewName ] ) ) {
// if the subview is not yet defined, then create it now using
// the registered creator method in this.subviewCreators
var subviewCreator = _this.subviewCreators[ subviewName ];
if( _.isUndefined( subviewCreator ) ) throw new Error( "Can not find subview creator for subview named: " + subviewName );
newSubview = subviewCreator.apply( _this );
_this.subviews[ subviewName ] = newSubview;
}
else {
// if the subview is already defined, then use the existing subview instead
// of creating a new one. This allows us to re-render a parent view without
// loosing any dynamic state data on the existing subview objects.
newSubview = _this.subviews[ subviewName ];
}
thisPlaceHolderDiv.replaceWith( newSubview.$el );
} );
// now that all subviews have been created, render them one at a time, in the
// order they occur in the DOM.
_.each( this.subviews, function( thisSubview ) {
thisSubview.render();
} );
// call this._onSubviewsRendered after everything is done (hook for application defined logic)
if( _.isFunction( this._onSubviewsRendered ) ) this._onSubviewsRendered.call( this );
}
};
} )( Backbone, _ );