/**
* @private
* TODO document
*/
IonicModule
.factory('$ionicViewSwitcher',[
'$timeout',
'$compile',
'$controller',
'$ionicClickBlock',
'$ionicConfig',
'$ionicNavBarDelegate',
function($timeout, $compile, $controller, $ionicClickBlock, $ionicConfig, $ionicNavBarDelegate) {
var TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';
var DATA_NO_CACHE = '$noCache';
var DATA_ELE_IDENTIFIER = '$eleId';
var DATA_ACTIVE_ELE_IDENTIFIER = '$activeEleId';
var DATA_VIEW_ACCESSED = '$accessed';
var DATA_FALLBACK_TIMER = '$fallbackTimer';
var NAV_VIEW_ATTR = 'nav-view';
var HISTORY_CURSOR_ATTR = 'history-cursor';
var HISTORY_ROOT = 'root';
var HISTORY_AFTER_ROOT = 'after-root';
var VIEW_STATUS_ACTIVE = 'active';
var VIEW_STATUS_CACHED = 'cached';
var VIEW_STATUS_STAGED = 'stage';
var transitionCounter = 0;
var nextTransition;
var nextDirection;
ionic.transition = ionic.transition || {};
ionic.transition.isActive = false;
var isActiveTimer;
function createViewElement(viewLocals) {
var div = jqLite('
');
if (viewLocals && viewLocals.$template) {
div.html(viewLocals.$template);
var nodes = div.contents();
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].nodeType == 1) {
// first try to get just a child element
return nodes.eq(i);
}
}
}
// fallback to return the div so it has one parent element
return div;
}
function getViewElementIdentifier(locals, view) {
if ( viewState(locals).abstract ) return viewState(locals).name;
if ( view ) return view.stateId || view.viewId;
return ionic.Utils.nextUid();
}
function viewState(locals) {
return locals && locals.$$state && locals.$$state.self || {};
}
function getTransitionData(viewLocals, enteringEle, direction, enteringView, showBack) {
// Priority
// 1) attribute directive on the button/link to this view
// 2) entering element's attribute
// 3) entering view's $state config property
// 4) view registration data
// 5) global config
// 6) fallback value
var state = viewState(viewLocals);
enteringView = enteringView || {};
var transition = nextTransition || ionic.DomUtil.cachedAttr(enteringEle, 'view-transition') || state.viewTransition || $ionicConfig.views.transition() || 'none';
direction = nextDirection || ionic.DomUtil.cachedAttr(enteringEle, 'view-direction') || state.viewDirection || direction || 'none';
var shouldAnimate = (transition !== 'none' && direction !== 'none');
return {
transition: transition,
direction: direction,
shouldAnimate: shouldAnimate,
viewId: enteringView.viewId,
stateId: enteringView.stateId,
stateName: enteringView.stateName,
stateParams: enteringView.stateParams,
showBack: !!showBack
};
}
function navViewAttr(ele, value) {
ionic.DomUtil.cachedAttr(ele, NAV_VIEW_ATTR, value);
}
function historyCursorAttr(ele, value) {
ionic.DomUtil.cachedAttr(ele, HISTORY_CURSOR_ATTR, value);
}
var ionicViewSwitcher = {
create: function(navViewScope, navViewElement, viewLocals, enteringView) {
// get a reference to an entering/leaving element if they exist
// loop through to see if the view is already in the navViewElement
var enteringEle, leavingEle;
var transitionId = ++transitionCounter;
var alreadyInDom;
var switcher = {
init: function(registerData, callback) {
ionicViewSwitcher.isTransitioning(true);
$ionicClickBlock.show();
switcher.loadViewElements();
switcher.render(registerData, function(){
callback && callback();
});
},
loadViewElements: function() {
var viewEle, viewElements = navViewElement.children();
var enteringEleIdentifier = getViewElementIdentifier(viewLocals, enteringView);
var navViewActiveEleId = navViewElement.data(DATA_ACTIVE_ELE_IDENTIFIER);
for (var x=0, l=viewElements.length; x $ionicConfig.views.maxCache() ) {
// check to see if we have more cached views than we should
// the total number of child elements has exceeded how many to keep in the DOM
var oldestAccess = Date.now();
for (x=0; x