Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
chore(ngView): $animate refactoring + transclusion & tests
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
matsko authored and mhevery committed Jul 27, 2013
1 parent aa2133a commit 7d69d52
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 183 deletions.
139 changes: 73 additions & 66 deletions src/ngRoute/directive/ngView.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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>
Expand All @@ -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;
Expand All @@ -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>
Expand Down Expand Up @@ -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();
}
}
}
Expand Down
Loading

0 comments on commit 7d69d52

Please sign in to comment.