11/**
2- * @license scalyr v1.0.2
2+ * @license scalyr v1.0.3
33 * (c) 2013 Scalyr, Inc. http://scalyr.com
44 * License: MIT
55 */
@@ -352,9 +352,10 @@ function defineScalyrAngularModule(moduleName, dependencies) {
352352 *
353353 * slyEvaluateOnlyWhen: A directive that prevents updating / evaluating
354354 * all bindings for the current element and its children unless
355- * the expression has changed values. It currently assumes the
355+ * the expression has changed values. If new children are added, they
356+ * are always evaluated at least once. It currently assumes the
356357 * expression evaluates to an object and detects changes only by
357- * a change in object reference.
358+ * a change in object reference.
358359 *
359360 * slyAlwaysEvaluate: Can only be used in conjunction with the
360361 * slyEvaluateOnlyWhen directive. This directive will ensure that
@@ -419,7 +420,7 @@ defineScalyrAngularModule('slyEvaluate', ['gatedScope'])
419420 // be gated.
420421 return isNull ( alwaysEvaluateString ) ||
421422 ! ( isStringNonempty ( watchExpression ) && ( watchExpression . indexOf ( alwaysEvaluateString ) >= 0 ) ) ;
422- } ) ;
423+ } , true /* Evaluate any newly added watchers when they are added */ ) ;
423424 } ,
424425 } ;
425426 } ,
@@ -755,6 +756,7 @@ defineScalyrAngularModule('gatedScope', [])
755756 result . $$parentGatingFunction = this . $$gatingFunction ;
756757 result . $$shouldGateFunction = this . $$shouldGateFunction ;
757758 result . $$gatedWatchers = [ ] ;
759+ result . $$cleanUpQueue = this . $$cleanUpQueue ;
758760
759761 return result ;
760762 } ;
@@ -786,6 +788,14 @@ defineScalyrAngularModule('gatedScope', [])
786788 if ( watch . gatingFunction !== targetGatingFunction )
787789 continue ;
788790
791+ // Since we are about to execute the watcher as part of a digestGated
792+ // call, we can remove it from the normal digest queue if it was placed
793+ // there because the watcher was added after the gate function's first
794+ // evaluation.
795+ if ( watch && ! isNull ( watch . cleanUp ) ) {
796+ watch . cleanUp ( ) ;
797+ watch . cleanUp = null ;
798+ }
789799 // Most common watches are on primitives, in which case we can short
790800 // circuit it with === operator, only when === fails do we use .equals
791801 if ( watch && ( value = watch . get ( current ) ) !== ( last = watch . last ) &&
@@ -820,6 +830,8 @@ defineScalyrAngularModule('gatedScope', [])
820830 }
821831 } while ( ( current = next ) ) ;
822832
833+ // Mark that this gating function has digested all children.
834+ targetGatingFunction . hasDigested = true ;
823835 return dirty ;
824836 } ;
825837
@@ -844,11 +856,38 @@ defineScalyrAngularModule('gatedScope', [])
844856 var result = scopePrototype . $watch . call ( this , watchExpression , listener , objectEquality ) ;
845857 this . $$watchers = tmp ;
846858 this . $$gatedWatchers [ 0 ] . gatingFunction = this . $$gatingFunction ;
859+ this . $$gatedWatchers [ 0 ] . cleanUp = null ;
847860
848861 // We know that the last field of the watcher object will be set to initWatchVal, so we
849862 // grab it here.
850863 initWatchVal = this . $$gatedWatchers [ 0 ] . last ;
864+ var watch = this . $$gatedWatchers [ 0 ] ;
865+
866+ // We should make sure the watch expression gets evaluated fully on at least one
867+ // digest cycle even if the gate function is now closed if requested by the gating function's
868+ // value for shouldEvalNewWatchers. We do this by adding in normal watcher that will execute
869+ // the watcher we just added and remove itself after the digest cycle completes.
870+ if ( this . $$gatingFunction . shouldEvalNewWatchers && this . $$gatingFunction . hasDigested ) {
871+ var self = this ;
872+ watch . cleanUp = scopePrototype . $watch . call ( self , function ( ) {
873+ if ( ! isNull ( watch . cleanUp ) ) {
874+ self . $$cleanUpQueue . unshift ( watch . cleanUp ) ;
875+ watch . cleanUp = null ;
876+ }
877+ var value ;
878+ var last = initWatchVal ;
851879
880+ if ( watch && ( value = watch . get ( self ) ) !== ( last = watch . last ) &&
881+ ! ( watch . eq
882+ ? areEqual ( value , last )
883+ : ( typeof value == 'number' && typeof last == 'number'
884+ && isNaN ( value ) && isNaN ( last ) ) ) ) {
885+ watch . last = watch . eq ? copy ( value ) : value ;
886+ watch . fn ( value , ( ( last === initWatchVal ) ? value : last ) , self ) ;
887+ }
888+ return watch . last ;
889+ } ) ;
890+ }
852891 return result ;
853892 } else {
854893 return scopePrototype . $watch . call ( this , watchExpression , listener , objectEquality ) ;
@@ -871,8 +910,8 @@ defineScalyrAngularModule('gatedScope', [])
871910 // functions and should be evaluated at all. However, if a caller is invoking
872911 // $digest on a particular scope, we assume the caller is doing that because it
873912 // knows the watchers should be evaluated.
913+ var dirty = false ;
874914 if ( ! isNull ( this . $$parentGatingFunction ) && this . $$parentGatingFunction ( ) ) {
875- var dirty = false ;
876915 var ttl = 5 ;
877916 do {
878917 dirty = this . $digestGated ( this . $$parentGatingFunction ) ;
@@ -884,7 +923,19 @@ defineScalyrAngularModule('gatedScope', [])
884923 }
885924 } while ( dirty ) ;
886925 }
887- return scopePrototype . $digest . call ( this ) || dirty ;
926+
927+ dirty = scopePrototype . $digest . call ( this ) || dirty ;
928+
929+ var cleanUpQueue = this . $$cleanUpQueue ;
930+
931+ while ( cleanUpQueue . length )
932+ try {
933+ cleanUpQueue . shift ( ) ( ) ;
934+ } catch ( e ) {
935+ $exceptionHandler ( e ) ;
936+ }
937+
938+ return dirty ;
888939 }
889940
890941 /**
@@ -901,8 +952,13 @@ defineScalyrAngularModule('gatedScope', [])
901952 * a new watcher will be gated using gatingFunction. It is evaluated with the
902953 * arguments to $watch and should return true if the watcher created by those
903954 * arguments should be gated
955+ * @param {Boolean } shouldEvalNewWatchers If true, if a watcher is added
956+ * after the gating function has returned true on a previous digest cycle, the
957+ * the new watcher will be evaluated on the next digest cycle even if the
958+ * gating function is currently return false.
904959 */
905- methodsToAdd . $addWatcherGate = function ( gatingFunction , shouldGateFunction ) {
960+ methodsToAdd . $addWatcherGate = function ( gatingFunction , shouldGateFunction ,
961+ shouldEvalNewWatchers ) {
906962 var changeCount = 0 ;
907963 var self = this ;
908964
@@ -918,30 +974,36 @@ defineScalyrAngularModule('gatedScope', [])
918974 // true (which we can tell if the watcher we register here is evaluated), then
919975 // we always evaluate our watcher until our gating function returns true.
920976 var hasNestedGates = ! isNull ( this . $$gatingFunction ) ;
921- var promotedWatcher = null ;
922-
923- this . $watch ( function ( ) {
924- if ( gatingFunction ( ) ) {
925- if ( self . $digestGated ( gatingFunction ) )
926- ++ changeCount ;
927- } else if ( hasNestedGates && isNull ( promotedWatcher ) ) {
928- promotedWatcher = scopePrototype . $watch . call ( self , function ( ) {
929- if ( gatingFunction ( ) ) {
930- promotedWatcher ( ) ;
931- promotedWatcher = null ;
932- if ( self . $digestGated ( gatingFunction ) )
933- ++ changeCount ;
934- }
935- return changeCount ;
936- } ) ;
937- }
938- return changeCount ;
939- } ) ;
977+
978+ ( function ( ) {
979+ var promotedWatcher = null ;
980+
981+ self . $watch ( function ( ) {
982+ if ( gatingFunction ( ) ) {
983+ if ( self . $digestGated ( gatingFunction ) )
984+ ++ changeCount ;
985+ } else if ( hasNestedGates && isNull ( promotedWatcher ) ) {
986+ promotedWatcher = scopePrototype . $watch . call ( self , function ( ) {
987+ if ( gatingFunction ( ) ) {
988+ promotedWatcher ( ) ;
989+ promotedWatcher = null ;
990+ if ( self . $digestGated ( gatingFunction ) )
991+ ++ changeCount ;
992+ }
993+ return changeCount ;
994+ } ) ;
995+ }
996+ return changeCount ;
997+ } ) ;
998+ } ) ( ) ;
940999
9411000
9421001 if ( isUndefined ( shouldGateFunction ) )
9431002 shouldGateFunction = null ;
1003+ if ( isUndefined ( shouldEvalNewWatchers ) )
1004+ shouldEvalNewWatchers = false ;
9441005 this . $$gatingFunction = gatingFunction ;
1006+ this . $$gatingFunction . shouldEvalNewWatchers = shouldEvalNewWatchers ;
9451007 this . $$shouldGateFunction = shouldGateFunction ;
9461008 } ;
9471009
@@ -957,6 +1019,7 @@ defineScalyrAngularModule('gatedScope', [])
9571019 $rootScope . $$parentGatingFunction = null ;
9581020 $rootScope . $$shouldGateFunction = null ;
9591021 $rootScope . $$gatedWatchers = [ ] ;
1022+ $rootScope . $$cleanUpQueue = [ ] ;
9601023
9611024 return $rootScope ;
9621025 } ] ) ;
0 commit comments