1
1
angular . module ( 'ionic.service.view' , [ 'ui.router' ] )
2
2
3
3
4
- . run ( [ '$rootScope' , '$state' , '$location' , '$document' ,
5
- function ( $rootScope , $state , $location , $document ) {
4
+ . run ( [ '$rootScope' , '$state' , '$location' , '$document' , '$animate' ,
5
+ function ( $rootScope , $state , $location , $document , $animate ) {
6
6
7
7
// init the variables that keep track of the view history
8
8
$rootScope . $viewHistory = {
9
9
histories : { root : { historyId : 'root' , parentHistoryId : null , stack : [ ] , cursor : - 1 } } ,
10
10
backView : null ,
11
11
forwardView : null ,
12
- currentView : null
12
+ currentView : null ,
13
+ disabledRegistrableTagNames : [ ]
13
14
} ;
14
15
15
16
$rootScope . $on ( 'viewState.changeHistory' , function ( e , data ) {
@@ -95,7 +96,8 @@ angular.module('ionic.service.view', ['ui.router'])
95
96
96
97
return {
97
98
98
- register : function ( containerScope ) {
99
+ register : function ( containerScope , element ) {
100
+
99
101
var viewHistory = $rootScope . $viewHistory ,
100
102
currentStateId = this . getCurrentStateId ( ) ,
101
103
hist = this . _getHistory ( containerScope ) ,
@@ -109,6 +111,15 @@ angular.module('ionic.service.view', ['ui.router'])
109
111
historyId : hist . historyId
110
112
} ;
111
113
114
+ if ( element && ! this . isTagNameRegistrable ( element ) ) {
115
+ // first check to see if this element can even be registered as a view.
116
+ // Certain tags are only containers for views, but are not views themselves.
117
+ // For example, the <tabs> directive contains a <tab> and the <tab> is the
118
+ // view, but the <tabs> directive itself should not be registered as a view.
119
+ rsp . navAction = 'disabledByTagName' ;
120
+ return rsp ;
121
+ }
122
+
112
123
if ( currentView &&
113
124
currentView . stateId === currentStateId &&
114
125
currentView . historyId === hist . historyId ) {
@@ -328,67 +339,105 @@ angular.module('ionic.service.view', ['ui.router'])
328
339
return { historyId : 'root' , scope : $rootScope } ;
329
340
} ,
330
341
331
- transition : function ( opts ) {
332
- if ( ! opts || ! opts . enteringElement ) return ;
342
+ getRenderer : function ( navViewElement , navViewAttrs , navViewScope ) {
343
+ var service = this ;
344
+ var registerData ;
345
+ var doAnimation ;
346
+
347
+ // climb up the DOM and see which animation classname to use, if any
348
+ var animationClass = null ;
349
+ var el = navViewElement [ 0 ] ;
350
+ while ( ! animationClass && el ) {
351
+ animationClass = el . getAttribute ( 'animation' ) ;
352
+ el = el . parentElement ;
353
+ }
354
+ el = null ;
355
+
356
+ function setAnimationClass ( ) {
357
+ // add the animation CSS class we're gonna use to transition between views
358
+ navViewElement [ 0 ] . classList . add ( animationClass ) ;
333
359
334
- if ( opts . leavingScope ) {
335
- opts . leavingScope . $destroy ( ) ;
336
- opts . leavingScope = null ;
360
+ if ( registerData . navDirection === 'back' ) {
361
+ // animate like we're moving backward
362
+ navViewElement [ 0 ] . classList . add ( 'reverse' ) ;
363
+ } else {
364
+ // defaults to animate forward
365
+ // make sure the reverse class isn't already added
366
+ navViewElement [ 0 ] . classList . remove ( 'reverse' ) ;
367
+ }
337
368
}
338
369
339
- // use the directive's animation attribute first
340
- // if it doesn't exist, then use the given animation
341
- var animationClass = opts . animation || getAnimationClass ( ) ;
370
+ return function ( shouldAnimate ) {
342
371
343
- if ( $animate && animationClass && opts . doAnimation !== false && opts . navDirection ) {
344
- // set the animation we're gonna use
345
- this . setAnimationClass ( opts . parentElement , animationClass , opts . navDirection ) ;
346
- opts . enteringElement . addClass ( 'ng-enter' ) ;
372
+ return {
373
+
374
+ enter : function ( element ) {
347
375
348
- // disable any pointer-events from being able to fire
349
- document . body . classList . add ( 'disable-pointer-events' ) ;
376
+ if ( doAnimation && shouldAnimate ) {
377
+ // enter with an animation
378
+ setAnimationClass ( ) ;
350
379
351
- // start the animations
352
- if ( opts . leavingElement ) {
353
- $animate . leave ( opts . leavingElement , function ( ) {
354
- // re-enable pointer-events
355
- document . body . classList . remove ( 'disable-pointer-events' ) ;
356
- } ) ;
357
- }
358
- $animate . enter ( opts . enteringElement , opts . parentElement ) ;
380
+ element . addClass ( 'ng-enter' ) ;
381
+ document . body . classList . add ( 'disable-pointer-events' ) ;
359
382
360
- } else {
361
- // no animation, just plain ol' add/remove DOM elements
362
- if ( opts . leavingElement ) {
363
- opts . leavingElement . remove ( ) ;
364
- }
365
- opts . parentElement . append ( opts . enteringElement ) ;
366
- }
383
+ $animate . enter ( element , navViewElement , null , function ( ) {
384
+ document . body . classList . remove ( 'disable-pointer-events' ) ;
385
+ } ) ;
386
+ return ;
387
+ }
388
+
389
+ // no animation
390
+ navViewElement . append ( element ) ;
391
+ } ,
367
392
368
- function getAnimationClass ( ) {
369
- // go up the ancestors looking for an animation value
370
- var climbScope = opts . enteringScope ;
371
- while ( climbScope ) {
372
- if ( climbScope . animation ) {
373
- return climbScope . animation ;
393
+ leave : function ( ) {
394
+ var element = navViewElement . contents ( ) ;
395
+
396
+ if ( doAnimation && shouldAnimate ) {
397
+ // leave with an animation
398
+ setAnimationClass ( ) ;
399
+
400
+ $animate . leave ( element , function ( ) {
401
+ element . remove ( ) ;
402
+ } ) ;
403
+ return ;
404
+ }
405
+
406
+ // no animation
407
+ element . remove ( ) ;
408
+ } ,
409
+
410
+ register : function ( element ) {
411
+ // register a new view
412
+ registerData = service . register ( navViewScope , element ) ;
413
+ doAnimation = ( animationClass !== null && registerData . navDirection !== null ) ;
374
414
}
375
- climbScope = climbScope . $parent ;
376
- }
377
- }
415
+
416
+ } ;
417
+ } ;
378
418
} ,
379
419
380
- setAnimationClass : function ( element , animationClass , navDirection ) {
381
- // add the animation we're gonna use
382
- element [ 0 ] . classList . add ( animationClass ) ;
420
+ disableRegisterByTagName : function ( tagName ) {
421
+ // not every element should animate betwee transitions
422
+ // For example, the <tabs> directive should not animate when it enters,
423
+ // but instead the <tabs> directve would just show, and its children
424
+ // <tab> directives would do the animating, but <tabs> itself is not a view
425
+ $rootScope . $viewHistory . disabledRegistrableTagNames . push ( tagName . toUpperCase ( ) ) ;
426
+ } ,
383
427
384
- if ( navDirection === 'back' ) {
385
- // animate backward
386
- element [ 0 ] . classList . add ( 'reverse' ) ;
387
- } else {
388
- // defaults to animate forward
389
- // make sure the reverse class isn't already added
390
- element [ 0 ] . classList . remove ( 'reverse' ) ;
428
+ isTagNameRegistrable : function ( element ) {
429
+ // check if this element has a tagName (at its root, not recursively)
430
+ // that shouldn't be animated, like <tabs> or <side-menu>
431
+ var x , y , disabledTags = $rootScope . $viewHistory . disabledRegistrableTagNames ;
432
+ for ( x = 0 ; x < element . length ; x ++ ) {
433
+ if ( element [ x ] . nodeType !== 1 ) continue ;
434
+ for ( y = 0 ; y < disabledTags . length ; y ++ ) {
435
+ if ( element [ x ] . tagName === disabledTags [ y ] ) {
436
+ return false ;
437
+ }
438
+ }
391
439
}
440
+ return true ;
392
441
} ,
393
442
394
443
clearHistory : function ( ) {
0 commit comments