aboutsummaryrefslogtreecommitdiffstats
path: root/src/ngRoute/directive
diff options
context:
space:
mode:
authorMatias Niemelàˆ2013-07-11 20:58:23 -0400
committerMisko Hevery2013-07-26 23:49:54 -0700
commit7d69d52acff8578e0f7d6fe57a6c45561a05b182 (patch)
tree8751bfd8856d33363592f5da8adfb466a2142499 /src/ngRoute/directive
parentaa2133ad818d2e5c27cbd3933061797096356c8a (diff)
downloadangular.js-7d69d52acff8578e0f7d6fe57a6c45561a05b182.tar.bz2
chore(ngView): $animate refactoring + transclusion & tests
BREAKING CHANGE: previously ngView only updated its content, after this change ngView will recreate itself every time a new content is included. This ensures that a single rootElement for all the included contents always exists, which makes definition of css styles for animations much easier.
Diffstat (limited to 'src/ngRoute/directive')
-rw-r--r--src/ngRoute/directive/ngView.js139
1 files changed, 73 insertions, 66 deletions
diff --git a/src/ngRoute/directive/ngView.js b/src/ngRoute/directive/ngView.js
index 3074df49..c4add9ce 100644
--- a/src/ngRoute/directive/ngView.js
+++ b/src/ngRoute/directive/ngView.js
@@ -15,8 +15,10 @@ ngRouteModule.directive('ngView', ngViewFactory);
* configuration of the `$route` service.
*
* @animations
- * enter - happens just after the ngView contents are changed (when the new view DOM element is inserted into the DOM)
- * leave - happens just after the current ngView contents change and just before the former contents are removed from the DOM
+ * enter - animation is used to bring new content into the browser.
+ * leave - animation is used to animate existing content away.
+ *
+ * The enter and leave animation occur concurrently.
*
* @scope
* @example
@@ -30,10 +32,9 @@ ngRouteModule.directive('ngView', ngViewFactory);
<a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
<a href="Book/Scarlet">Scarlet Letter</a><br/>
- <div
- ng-view
- class="example-$animate-container"
- ng-$animate="{enter: 'example-enter', leave: 'example-leave'}"></div>
+ <div class="example-animate-container">
+ <div ng-view class="view-example"></div>
+ </div>
<hr />
<pre>$location.path() = {{main.$location.path()}}</pre>
@@ -60,20 +61,13 @@ ngRouteModule.directive('ngView', ngViewFactory);
</file>
<file name="animations.css">
- .example-leave, .example-enter {
+ .view-example {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
-moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
-ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
-o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
- }
-
- .example-$animate-container {
- position:relative;
- height:100px;
- }
- .example-$animate-container > * {
display:block;
width:100%;
border-left:1px solid black;
@@ -86,15 +80,20 @@ ngRouteModule.directive('ngView', ngViewFactory);
padding:10px;
}
- .example-enter {
+ .example-animate-container {
+ position:relative;
+ height:100px;
+ }
+
+ .view-example.ng-enter {
left:100%;
}
- .example-enter.example-enter-active {
+ .view-example.ng-enter.ng-enter-active {
left:0;
}
- .example-leave { }
- .example-leave.example-leave-active {
+ .view-example.ng-leave { }
+ .view-example.ng-leave.ng-leave-active {
left:-100%;
}
</file>
@@ -164,57 +163,65 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
return {
restrict: 'ECA',
terminal: true,
- link: function(scope, element, attr) {
- var lastScope,
- onloadExp = attr.onload || '';
-
- scope.$on('$routeChangeSuccess', update);
- update();
-
-
- function destroyLastScope() {
- if (lastScope) {
- lastScope.$destroy();
- lastScope = null;
+ transclude: 'element',
+ compile: function(element, attr, linker) {
+ return function(scope, $element, attr) {
+ var currentScope,
+ currentElement,
+ onloadExp = attr.onload || '';
+
+ scope.$on('$routeChangeSuccess', update);
+ update();
+
+ function cleanupLastView() {
+ if (currentScope) {
+ currentScope.$destroy();
+ currentScope = null;
+ }
+ if(currentElement) {
+ $animate.leave(currentElement);
+ currentElement = null;
+ }
}
- }
-
- function clearContent() {
- $animate.leave(element.contents());
- destroyLastScope();
- }
- function update() {
- var locals = $route.current && $route.current.locals,
- template = locals && locals.$template;
-
- if (template) {
- clearContent();
- var enterElements = jqLite('<div></div>').html(template).contents();
- $animate.enter(enterElements, element);
-
- var link = $compile(enterElements),
- current = $route.current,
- controller;
-
- lastScope = current.scope = scope.$new();
- if (current.controller) {
- locals.$scope = lastScope;
- controller = $controller(current.controller, locals);
- if (current.controllerAs) {
- lastScope[current.controllerAs] = controller;
- }
- element.children().data('$ngControllerController', controller);
+ function update() {
+ var locals = $route.current && $route.current.locals,
+ template = locals && locals.$template;
+
+ if (template) {
+ var newScope = scope.$new();
+ linker(newScope, function(clone) {
+ cleanupLastView();
+
+ clone.html(template);
+ $animate.enter(clone, null, $element);
+
+ var link = $compile(clone.contents()),
+ current = $route.current;
+
+ currentScope = current.scope = newScope;
+ currentElement = clone;
+
+ if (current.controller) {
+ locals.$scope = currentScope;
+ var controller = $controller(current.controller, locals);
+ if (current.controllerAs) {
+ currentScope[current.controllerAs] = controller;
+ }
+ clone.data('$ngControllerController', controller);
+ clone.contents().data('$ngControllerController', controller);
+ }
+
+ link(currentScope);
+ currentScope.$emit('$viewContentLoaded');
+ currentScope.$eval(onloadExp);
+
+ // $anchorScroll might listen on event...
+ $anchorScroll();
+ });
+ } else {
+ cleanupLastView();
}
-
- link(lastScope);
- lastScope.$emit('$viewContentLoaded');
- lastScope.$eval(onloadExp);
-
- // $anchorScroll might listen on event...
- $anchorScroll();
- } else {
- clearContent();
}
}
}