Created
August 16, 2016 13:54
-
-
Save jamesmfriedman/c769fbabd79e34bf46cb0c744757b6e7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var mod = angular.module('CacheView', []); | |
function addScope(child, parent){ | |
child.$parent = parent; | |
child.$$prevSibling = parent.$$childTail; | |
if(child.$$prevSibling) child.$$prevSibling.$$nextSibling = child; | |
parent.$$childTail = child; | |
if(!parent.$$childHead) parent.$$childHead = child; | |
// works, but screws up the watcher count for some reason | |
parent.$$watchersCount += child.$$watchersCount; | |
child.__proto__ = parent; | |
return child; | |
} | |
function removeScope(scope){ | |
if (scope.$$prevSibling){ | |
scope.$$prevSibling.$$nextSibling = scope.$$nextSibling; | |
scope.$$prevSibling = null; | |
} else if (scope.$parent) { | |
scope.$parent.$$childHead = null; | |
} | |
if (scope.$$nextSibling){ | |
scope.$$nextSibling.$$prevSibling = scope.$$prevSibling; | |
scope.$$nextSibling = null; | |
} else if (scope.$parent) { | |
scope.$parent.$$childTail = null; | |
} | |
if (scope.$parent) { | |
if(scope.$parent.$$childHead && !scope.$parent.$$childTail) scope.$parent.$$childTail = scope.$parent.$$childHead; | |
if(!scope.$parent.$$childHead && scope.$parent.$$childTail) scope.$parent.$$childHead = scope.$parent.$$childTail; | |
} | |
scope.$parent = null; | |
return scope; | |
} | |
mod.directive('edesiaCacheView', function ($compile, cacheView, $stateParams) { | |
return { | |
restrict: 'E', | |
priority: 10000, | |
transclude: true, | |
compile: function(element, attrs, transcludeFn){ | |
var childScope; | |
var cacheName = attrs.name; | |
var cached = cacheView.get(cacheName); | |
return function(scope, element, attrs) { | |
var valid = true; | |
var stateParamsCopy; | |
// If we have a cache, we need to check on whether or not to invalide it | |
// base on the cacheInvalidateOn array in routes. | |
if (cached && attrs.cacheInvalidateOn) { | |
var keys = attrs.cacheInvalidateOn.split(','); | |
var results = keys.filter(function(key){ | |
// check our new state params against the cached version | |
return cached.params[key] === $stateParams[key]; | |
}); | |
// if our params match, we are still valid | |
valid = results.length === keys.length; | |
} | |
scope.$on('$stateChangeStart', function(){ | |
stateParamsCopy = _.assign({}, $stateParams); | |
}); | |
// cache mode | |
if (cached && valid){ | |
childScope = cached.scope; | |
element.append(cached.element); | |
// wait till the animation is done to bring our scope back | |
var unbind = scope.$on('$viewContentAnimationEnded', function(){ | |
addScope(childScope, scope); | |
childScope.$broadcast('$outCache', childScope); | |
scope.$evalAsync(); | |
unbind(); | |
}); | |
} | |
// no cache | |
else { | |
childScope = scope.$new(); | |
transcludeFn(childScope, function(clone){ | |
element.append(clone); | |
}); | |
} | |
// This is bound to the original DOM node being destroyed | |
// in this case, we know the parent is always the ui-view node. | |
// If we wanted to use this generically | |
// we would have to select UI-VIEW or NG-VIEW | |
element.parent().on('$destroy', function(){ | |
cacheView.put(cacheName, { | |
element: element.children().detach(), | |
scope: childScope, | |
params: stateParamsCopy | |
}); | |
}); | |
// grab the scope as soon as the state changes | |
// this helps performance since digest cycles get called multiple times | |
// while the views are animating. | |
setTimeout(function() { | |
scope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState){ | |
var isChildState = fromState.name.split('.').shift() === toState.name.split('.').shift(); | |
if (!isChildState) { | |
removeScope(childScope); | |
childScope.$broadcast('$inCache', childScope); | |
} | |
}); | |
}); | |
}; | |
} | |
}; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment