-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathviewDirective.js
119 lines (101 loc) · 4.13 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
$ViewDirective.$inject = ['$state', '$compile', '$controller', '$injector', '$anchorScroll'];
function $ViewDirective( $state, $compile, $controller, $injector, $anchorScroll) {
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))) {
$anchorScroll();
}
}
};
}
};
return directive;
}
angular.module('ui.router.state').directive('uiView', $ViewDirective);