Skip to content

Commit b401b84

Browse files
committed
Merge pull request #2597 from christopherthielen/legacy
Expose animation promises
2 parents 9698ec4 + fde64e1 commit b401b84

File tree

2 files changed

+84
-126
lines changed

2 files changed

+84
-126
lines changed

src/viewDirective.js

+52-71
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
var ngMajorVer = angular.version.major;
2-
var ngMinorVer = angular.version.minor;
31
/**
42
* @ngdoc directive
53
* @name ui.router.state.directive:ui-view
@@ -24,33 +22,30 @@ var ngMinorVer = angular.version.minor;
2422
* service, {@link ui.router.state.$uiViewScroll}. This custom service let's you
2523
* scroll ui-view elements into view when they are populated during a state activation.
2624
*
27-
* @param {string=} noanimation If truthy, the non-animated renderer will be selected (no animations
28-
* will be applied to the ui-view)
29-
*
3025
* *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll)
3126
* functionality, call `$uiViewScrollProvider.useAnchorScroll()`.*
3227
*
3328
* @param {string=} onload Expression to evaluate whenever the view updates.
34-
*
29+
*
3530
* @example
36-
* A view can be unnamed or named.
31+
* A view can be unnamed or named.
3732
* <pre>
3833
* <!-- Unnamed -->
39-
* <div ui-view></div>
40-
*
34+
* <div ui-view></div>
35+
*
4136
* <!-- Named -->
4237
* <div ui-view="viewName"></div>
4338
* </pre>
4439
*
45-
* You can only have one unnamed view within any template (or root html). If you are only using a
40+
* You can only have one unnamed view within any template (or root html). If you are only using a
4641
* single view and it is unnamed then you can populate it like so:
4742
* <pre>
48-
* <div ui-view></div>
43+
* <div ui-view></div>
4944
* $stateProvider.state("home", {
5045
* template: "<h1>HELLO!</h1>"
5146
* })
5247
* </pre>
53-
*
48+
*
5449
* The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#methods_state `views`}
5550
* config property, by name, in this case an empty name:
5651
* <pre>
@@ -62,13 +57,13 @@ var ngMinorVer = angular.version.minor;
6257
* }
6358
* })
6459
* </pre>
65-
*
66-
* But typically you'll only use the views property if you name your view or have more than one view
67-
* in the same template. There's not really a compelling reason to name a view if its the only one,
60+
*
61+
* But typically you'll only use the views property if you name your view or have more than one view
62+
* in the same template. There's not really a compelling reason to name a view if its the only one,
6863
* but you could if you wanted, like so:
6964
* <pre>
7065
* <div ui-view="main"></div>
71-
* </pre>
66+
* </pre>
7267
* <pre>
7368
* $stateProvider.state("home", {
7469
* views: {
@@ -78,14 +73,14 @@ var ngMinorVer = angular.version.minor;
7873
* }
7974
* })
8075
* </pre>
81-
*
76+
*
8277
* Really though, you'll use views to set up multiple views:
8378
* <pre>
8479
* <div ui-view></div>
85-
* <div ui-view="chart"></div>
86-
* <div ui-view="data"></div>
80+
* <div ui-view="chart"></div>
81+
* <div ui-view="data"></div>
8782
* </pre>
88-
*
83+
*
8984
* <pre>
9085
* $stateProvider.state("home", {
9186
* views: {
@@ -116,8 +111,8 @@ var ngMinorVer = angular.version.minor;
116111
* <ui-view autoscroll='scopeVariable'/>
117112
* </pre>
118113
*/
119-
$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate'];
120-
function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) {
114+
$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate', '$q'];
115+
function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate, $q) {
121116

122117
function getService() {
123118
return ($injector.has) ? function(service) {
@@ -138,35 +133,24 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
138133
// Returns a set of DOM manipulation functions based on which Angular version
139134
// it should use
140135
function getRenderer(attrs, scope) {
141-
var statics = {
142-
enter: function (element, target, cb) { target.after(element); cb(); },
143-
leave: function (element, cb) { element.remove(); cb(); }
136+
var statics = function() {
137+
return {
138+
enter: function (element, target, cb) { target.after(element); cb(); },
139+
leave: function (element, cb) { element.remove(); cb(); }
140+
};
144141
};
145142

146-
if (!!attrs.noanimation) return statics;
147-
148-
function animEnabled(element) {
149-
if (ngMajorVer === 1 && ngMinorVer >= 4) return !!$animate.enabled(element);
150-
if (ngMajorVer === 1 && ngMinorVer >= 2) return !!$animate.enabled();
151-
return (!!$animator);
152-
}
153-
154-
// ng 1.2+
155143
if ($animate) {
156144
return {
157145
enter: function(element, target, cb) {
158-
if (!animEnabled(element)) {
159-
statics.enter(element, target, cb);
160-
} else if (angular.version.minor > 2) {
146+
if (angular.version.minor > 2) {
161147
$animate.enter(element, null, target).then(cb);
162148
} else {
163149
$animate.enter(element, null, target, cb);
164150
}
165151
},
166152
leave: function(element, cb) {
167-
if (!animEnabled(element)) {
168-
statics.leave(element, cb);
169-
} else if (angular.version.minor > 2) {
153+
if (angular.version.minor > 2) {
170154
$animate.leave(element).then(cb);
171155
} else {
172156
$animate.leave(element, cb);
@@ -175,7 +159,6 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
175159
};
176160
}
177161

178-
// ng 1.1.5
179162
if ($animator) {
180163
var animate = $animator && $animator(scope, attrs);
181164

@@ -185,7 +168,7 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
185168
};
186169
}
187170

188-
return statics;
171+
return statics();
189172
}
190173

191174
var directive = {
@@ -198,7 +181,8 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
198181
var previousEl, currentEl, currentScope, latestLocals,
199182
onloadExp = attrs.onload || '',
200183
autoScrollExp = attrs.autoscroll,
201-
renderer = getRenderer(attrs, scope);
184+
renderer = getRenderer(attrs, scope),
185+
inherited = $element.inheritedData('$uiView');
202186

203187
scope.$on('$stateChangeSuccess', function() {
204188
updateView(false);
@@ -207,45 +191,34 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
207191
updateView(true);
208192

209193
function cleanupLastView() {
210-
var _previousEl = previousEl;
211-
var _currentScope = currentScope;
212-
213-
if (_currentScope) {
214-
_currentScope._willBeDestroyed = true;
194+
if (previousEl) {
195+
previousEl.remove();
196+
previousEl = null;
215197
}
216198

217-
function cleanOld() {
218-
if (_previousEl) {
219-
_previousEl.remove();
220-
}
221-
222-
if (_currentScope) {
223-
_currentScope.$destroy();
224-
}
199+
if (currentScope) {
200+
currentScope.$destroy();
201+
currentScope = null;
225202
}
226203

227204
if (currentEl) {
205+
var $uiViewData = currentEl.data('$uiView');
228206
renderer.leave(currentEl, function() {
229-
cleanOld();
207+
$uiViewData.$$animLeave.resolve();
230208
previousEl = null;
231209
});
232210

233211
previousEl = currentEl;
234-
} else {
235-
cleanOld();
236-
previousEl = null;
212+
currentEl = null;
237213
}
238-
239-
currentEl = null;
240-
currentScope = null;
241214
}
242215

243216
function updateView(firstTime) {
244217
var newScope,
245-
name = getUiViewName(scope, attrs, $element, $interpolate),
218+
name = getUiViewName(scope, attrs, inherited, $interpolate),
246219
previousLocals = name && $state.$current && $state.$current.locals[name];
247220

248-
if (!firstTime && previousLocals === latestLocals || scope._willBeDestroyed) return; // nothing to do
221+
if (!firstTime && previousLocals === latestLocals) return; // nothing to do
249222
newScope = scope.$new();
250223
latestLocals = $state.$current.locals[name];
251224

@@ -264,7 +237,16 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
264237
newScope.$emit('$viewContentLoading', name);
265238

266239
var clone = $transclude(newScope, function(clone) {
267-
renderer.enter(clone, $element, function onUiViewEnter() {
240+
var animEnter = $q.defer(), animLeave = $q.defer();
241+
var viewData = {
242+
name: name,
243+
$animEnter: animEnter.promise,
244+
$animLeave: animLeave.promise,
245+
$$animLeave: animLeave
246+
};
247+
248+
renderer.enter(clone.data('$uiView', viewData), $element, function onUiViewEnter() {
249+
animEnter.resolve();
268250
if(currentScope) {
269251
currentScope.$emit('$viewContentAnimationEnded');
270252
}
@@ -308,14 +290,14 @@ function $ViewDirectiveFill ( $compile, $controller, $state, $interpolate
308290
var initial = tElement.html();
309291
return function (scope, $element, attrs) {
310292
var current = $state.$current,
311-
name = getUiViewName(scope, attrs, $element, $interpolate),
312-
locals = current && current.locals[name];
293+
$uiViewData = $element.data('$uiView'),
294+
locals = current && current.locals[$uiViewData.name];
313295

314296
if (! locals) {
315297
return;
316298
}
317299

318-
$element.data('$uiView', { name: name, state: locals.$$state });
300+
extend($uiViewData, { state: locals.$$state });
319301
$element.html(locals.$template ? locals.$template : initial);
320302

321303
var link = $compile($element.contents());
@@ -341,9 +323,8 @@ function $ViewDirectiveFill ( $compile, $controller, $state, $interpolate
341323
* Shared ui-view code for both directives:
342324
* Given scope, element, and its attributes, return the view's name
343325
*/
344-
function getUiViewName(scope, attrs, element, $interpolate) {
326+
function getUiViewName(scope, attrs, inherited, $interpolate) {
345327
var name = $interpolate(attrs.uiView || attrs.name || '')(scope);
346-
var inherited = element.inheritedData('$uiView');
347328
return name.indexOf('@') >= 0 ? name : (name + '@' + (inherited ? inherited.state.name : ''));
348329
}
349330

0 commit comments

Comments
 (0)