-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathviewDirective.js
134 lines (117 loc) · 4.47 KB
/
viewDirective.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
/**
* @ngdoc directive
* @name ui.router.state.diretive.ui-view
*
* @requires ui.router.state.$state
* @requires $compile
* @requires $controller
* @requires $injector
*
* @restrict ECA
*
* @description
* The ui-view directive tells $state where to place your templates.
* A view can be unnamed or named.
*
* @param {string} ui-view A view name.
*/
$ViewDirective.$inject = ['$state', '$compile', '$controller', '$injector', '$uiViewScroll'];
function $ViewDirective( $state, $compile, $controller, $injector, $uiViewScroll) {
var $animator = $injector.has('$animator') ? $injector.get('$animator') : false;
var viewIsUpdating = false;
var directive = {
restrict: 'ECA',
terminal: true,
priority: 1000,
transclude: true,
compile: function (element, attr, transclude) {
return function(scope, element, attr) {
var viewScope, viewLocals,
name = attr[directive.name] || attr.name || '',
onloadExp = attr.onload || '',
autoscrollExp = attr.autoscroll,
animate = $animator && $animator(scope, attr),
initialView = transclude(scope);
// Returns a set of DOM manipulation functions based on whether animation
// should be performed
var renderer = function(doAnimate) {
return ({
"true": {
remove: function(element) { animate.leave(element.contents(), element); },
restore: function(compiled, element) { animate.enter(compiled, element); },
populate: function(template, element) {
var contents = angular.element('<div></div>').html(template).contents();
animate.enter(contents, element);
return contents;
}
},
"false": {
remove: function(element) { element.html(''); },
restore: function(compiled, element) { element.append(compiled); },
populate: function(template, element) {
element.html(template);
return element.contents();
}
}
})[doAnimate.toString()];
};
// Put back the compiled initial view
element.append(initialView);
// Find the details of the parent view directive (if any) and use it
// to derive our own qualified view name, then hang our own details
// off the DOM so child directives can find it.
var parent = element.parent().inheritedData('$uiView');
if (name.indexOf('@') < 0) name = name + '@' + (parent ? parent.state.name : '');
var view = { name: name, state: null };
element.data('$uiView', view);
var eventHook = function() {
if (viewIsUpdating) return;
viewIsUpdating = true;
try { updateView(true); } catch (e) {
viewIsUpdating = false;
throw e;
}
viewIsUpdating = false;
};
scope.$on('$stateChangeSuccess', eventHook);
scope.$on('$viewContentLoading', eventHook);
updateView(false);
function updateView(doAnimate) {
var locals = $state.$current && $state.$current.locals[name];
if (locals === viewLocals) return; // nothing to do
var render = renderer(animate && doAnimate);
// Remove existing content
render.remove(element);
// Destroy previous view scope
if (viewScope) {
viewScope.$destroy();
viewScope = null;
}
if (!locals) {
viewLocals = null;
view.state = null;
// Restore the initial view
return render.restore(initialView, element);
}
viewLocals = locals;
view.state = locals.$$state;
var link = $compile(render.populate(locals.$template, element));
viewScope = scope.$new();
if (locals.$$controller) {
locals.$scope = viewScope;
var controller = $controller(locals.$$controller, locals);
element.children().data('$ngControllerController', controller);
}
link(viewScope);
viewScope.$emit('$viewContentLoaded');
if (onloadExp) viewScope.$eval(onloadExp);
if (!angular.isDefined(autoscrollExp) || !autoscrollExp || scope.$eval(autoscrollExp)) {
$uiViewScroll(element);
}
}
};
}
};
return directive;
}
angular.module('ui.router.state').directive('uiView', $ViewDirective);