mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
797 lines
25 KiB
JavaScript
797 lines
25 KiB
JavaScript
/**
|
|
* @ngdoc service
|
|
* @name $ionicHistory
|
|
* @module ionic
|
|
* @description
|
|
* $ionicHistory keeps track of views as the user navigates through an app. Similar to the way a
|
|
* browser behaves, an Ionic app is able to keep track of the previous view, the current view, and
|
|
* the forward view (if there is one). However, a typical web browser only keeps track of one
|
|
* history stack in a linear fashion.
|
|
*
|
|
* Unlike a traditional browser environment, apps and webapps have parallel independent histories,
|
|
* such as with tabs. Should a user navigate few pages deep on one tab, and then switch to a new
|
|
* tab and back, the back button relates not to the previous tab, but to the previous pages
|
|
* visited within _that_ tab.
|
|
*
|
|
* `$ionicHistory` facilitates this parallel history architecture.
|
|
*/
|
|
|
|
IonicModule
|
|
.factory('$ionicHistory', [
|
|
'$rootScope',
|
|
'$state',
|
|
'$location',
|
|
'$window',
|
|
'$timeout',
|
|
'$ionicViewSwitcher',
|
|
'$ionicNavViewDelegate',
|
|
function($rootScope, $state, $location, $window, $timeout, $ionicViewSwitcher, $ionicNavViewDelegate) {
|
|
|
|
// history actions while navigating views
|
|
var ACTION_INITIAL_VIEW = 'initialView';
|
|
var ACTION_NEW_VIEW = 'newView';
|
|
var ACTION_MOVE_BACK = 'moveBack';
|
|
var ACTION_MOVE_FORWARD = 'moveForward';
|
|
|
|
// direction of navigation
|
|
var DIRECTION_BACK = 'back';
|
|
var DIRECTION_FORWARD = 'forward';
|
|
var DIRECTION_ENTER = 'enter';
|
|
var DIRECTION_EXIT = 'exit';
|
|
var DIRECTION_SWAP = 'swap';
|
|
var DIRECTION_NONE = 'none';
|
|
|
|
var stateChangeCounter = 0;
|
|
var lastStateId, nextViewOptions, nextViewExpireTimer, forcedNav;
|
|
|
|
var viewHistory = {
|
|
histories: { root: { historyId: 'root', parentHistoryId: null, stack: [], cursor: -1 } },
|
|
views: {},
|
|
backView: null,
|
|
forwardView: null,
|
|
currentView: null
|
|
};
|
|
|
|
var View = function() {};
|
|
View.prototype.initialize = function(data) {
|
|
if (data) {
|
|
for (var name in data) this[name] = data[name];
|
|
return this;
|
|
}
|
|
return null;
|
|
};
|
|
View.prototype.go = function() {
|
|
|
|
if (this.stateName) {
|
|
return $state.go(this.stateName, this.stateParams);
|
|
}
|
|
|
|
if (this.url && this.url !== $location.url()) {
|
|
|
|
if (viewHistory.backView === this) {
|
|
return $window.history.go(-1);
|
|
} else if (viewHistory.forwardView === this) {
|
|
return $window.history.go(1);
|
|
}
|
|
|
|
$location.url(this.url);
|
|
return;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
View.prototype.destroy = function() {
|
|
if (this.scope) {
|
|
this.scope.$destroy && this.scope.$destroy();
|
|
this.scope = null;
|
|
}
|
|
};
|
|
|
|
|
|
function getViewById(viewId) {
|
|
return (viewId ? viewHistory.views[ viewId ] : null);
|
|
}
|
|
|
|
function getBackView(view) {
|
|
return (view ? getViewById(view.backViewId) : null);
|
|
}
|
|
|
|
function getForwardView(view) {
|
|
return (view ? getViewById(view.forwardViewId) : null);
|
|
}
|
|
|
|
function getHistoryById(historyId) {
|
|
return (historyId ? viewHistory.histories[ historyId ] : null);
|
|
}
|
|
|
|
function getHistory(scope) {
|
|
var histObj = getParentHistoryObj(scope);
|
|
|
|
if (!viewHistory.histories[ histObj.historyId ]) {
|
|
// this history object exists in parent scope, but doesn't
|
|
// exist in the history data yet
|
|
viewHistory.histories[ histObj.historyId ] = {
|
|
historyId: histObj.historyId,
|
|
parentHistoryId: getParentHistoryObj(histObj.scope.$parent).historyId,
|
|
stack: [],
|
|
cursor: -1
|
|
};
|
|
}
|
|
return getHistoryById(histObj.historyId);
|
|
}
|
|
|
|
function getParentHistoryObj(scope) {
|
|
var parentScope = scope;
|
|
while (parentScope) {
|
|
if (parentScope.hasOwnProperty('$historyId')) {
|
|
// this parent scope has a historyId
|
|
return { historyId: parentScope.$historyId, scope: parentScope };
|
|
}
|
|
// nothing found keep climbing up
|
|
parentScope = parentScope.$parent;
|
|
}
|
|
// no history for the parent, use the root
|
|
return { historyId: 'root', scope: $rootScope };
|
|
}
|
|
|
|
function setNavViews(viewId) {
|
|
viewHistory.currentView = getViewById(viewId);
|
|
viewHistory.backView = getBackView(viewHistory.currentView);
|
|
viewHistory.forwardView = getForwardView(viewHistory.currentView);
|
|
}
|
|
|
|
function getCurrentStateId() {
|
|
var id;
|
|
if ($state && $state.current && $state.current.name) {
|
|
id = $state.current.name;
|
|
if ($state.params) {
|
|
for (var key in $state.params) {
|
|
if ($state.params.hasOwnProperty(key) && $state.params[key]) {
|
|
id += "_" + key + "=" + $state.params[key];
|
|
}
|
|
}
|
|
}
|
|
return id;
|
|
}
|
|
// if something goes wrong make sure its got a unique stateId
|
|
return ionic.Utils.nextUid();
|
|
}
|
|
|
|
function getCurrentStateParams() {
|
|
var rtn;
|
|
if ($state && $state.params) {
|
|
for (var key in $state.params) {
|
|
if ($state.params.hasOwnProperty(key)) {
|
|
rtn = rtn || {};
|
|
rtn[key] = $state.params[key];
|
|
}
|
|
}
|
|
}
|
|
return rtn;
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
register: function(parentScope, viewLocals) {
|
|
|
|
var currentStateId = getCurrentStateId(),
|
|
hist = getHistory(parentScope),
|
|
currentView = viewHistory.currentView,
|
|
backView = viewHistory.backView,
|
|
forwardView = viewHistory.forwardView,
|
|
viewId = null,
|
|
action = null,
|
|
direction = DIRECTION_NONE,
|
|
historyId = hist.historyId,
|
|
url = $location.url(),
|
|
tmp, x, ele;
|
|
|
|
if (lastStateId !== currentStateId) {
|
|
lastStateId = currentStateId;
|
|
stateChangeCounter++;
|
|
}
|
|
|
|
if (forcedNav) {
|
|
// we've previously set exactly what to do
|
|
viewId = forcedNav.viewId;
|
|
action = forcedNav.action;
|
|
direction = forcedNav.direction;
|
|
forcedNav = null;
|
|
|
|
} else if (backView && backView.stateId === currentStateId) {
|
|
// they went back one, set the old current view as a forward view
|
|
viewId = backView.viewId;
|
|
historyId = backView.historyId;
|
|
action = ACTION_MOVE_BACK;
|
|
if (backView.historyId === currentView.historyId) {
|
|
// went back in the same history
|
|
direction = DIRECTION_BACK;
|
|
|
|
} else if (currentView) {
|
|
direction = DIRECTION_EXIT;
|
|
|
|
tmp = getHistoryById(backView.historyId);
|
|
if (tmp && tmp.parentHistoryId === currentView.historyId) {
|
|
direction = DIRECTION_ENTER;
|
|
|
|
} else {
|
|
tmp = getHistoryById(currentView.historyId);
|
|
if (tmp && tmp.parentHistoryId === hist.parentHistoryId) {
|
|
direction = DIRECTION_SWAP;
|
|
}
|
|
}
|
|
}
|
|
|
|
} else if (forwardView && forwardView.stateId === currentStateId) {
|
|
// they went to the forward one, set the forward view to no longer a forward view
|
|
viewId = forwardView.viewId;
|
|
historyId = forwardView.historyId;
|
|
action = ACTION_MOVE_FORWARD;
|
|
if (forwardView.historyId === currentView.historyId) {
|
|
direction = DIRECTION_FORWARD;
|
|
|
|
} else if (currentView) {
|
|
direction = DIRECTION_EXIT;
|
|
|
|
if (currentView.historyId === hist.parentHistoryId) {
|
|
direction = DIRECTION_ENTER;
|
|
|
|
} else {
|
|
tmp = getHistoryById(currentView.historyId);
|
|
if (tmp && tmp.parentHistoryId === hist.parentHistoryId) {
|
|
direction = DIRECTION_SWAP;
|
|
}
|
|
}
|
|
}
|
|
|
|
tmp = getParentHistoryObj(parentScope);
|
|
if (forwardView.historyId && tmp.scope) {
|
|
// if a history has already been created by the forward view then make sure it stays the same
|
|
tmp.scope.$historyId = forwardView.historyId;
|
|
historyId = forwardView.historyId;
|
|
}
|
|
|
|
} else if (currentView && currentView.historyId !== historyId &&
|
|
hist.cursor > -1 && hist.stack.length > 0 && hist.cursor < hist.stack.length &&
|
|
hist.stack[hist.cursor].stateId === currentStateId) {
|
|
// they just changed to a different history and the history already has views in it
|
|
var switchToView = hist.stack[hist.cursor];
|
|
viewId = switchToView.viewId;
|
|
historyId = switchToView.historyId;
|
|
action = ACTION_MOVE_BACK;
|
|
direction = DIRECTION_SWAP;
|
|
|
|
tmp = getHistoryById(currentView.historyId);
|
|
if (tmp && tmp.parentHistoryId === historyId) {
|
|
direction = DIRECTION_EXIT;
|
|
|
|
} else {
|
|
tmp = getHistoryById(historyId);
|
|
if (tmp && tmp.parentHistoryId === currentView.historyId) {
|
|
direction = DIRECTION_ENTER;
|
|
}
|
|
}
|
|
|
|
// if switching to a different history, and the history of the view we're switching
|
|
// to has an existing back view from a different history than itself, then
|
|
// it's back view would be better represented using the current view as its back view
|
|
tmp = getViewById(switchToView.backViewId);
|
|
if (tmp && switchToView.historyId !== tmp.historyId) {
|
|
hist.stack[hist.cursor].backViewId = currentView.viewId;
|
|
}
|
|
|
|
} else {
|
|
|
|
// create an element from the viewLocals template
|
|
ele = $ionicViewSwitcher.createViewEle(viewLocals);
|
|
if (this.isAbstractEle(ele, viewLocals)) {
|
|
console.log('VIEW', 'abstractView', DIRECTION_NONE, viewHistory.currentView);
|
|
return {
|
|
action: 'abstractView',
|
|
direction: DIRECTION_NONE,
|
|
ele: ele
|
|
};
|
|
}
|
|
|
|
// set a new unique viewId
|
|
viewId = ionic.Utils.nextUid();
|
|
|
|
if (currentView) {
|
|
// set the forward view if there is a current view (ie: if its not the first view)
|
|
currentView.forwardViewId = viewId;
|
|
|
|
action = ACTION_NEW_VIEW;
|
|
|
|
// check if there is a new forward view within the same history
|
|
if (forwardView && currentView.stateId !== forwardView.stateId &&
|
|
currentView.historyId === forwardView.historyId) {
|
|
// they navigated to a new view but the stack already has a forward view
|
|
// since its a new view remove any forwards that existed
|
|
tmp = getHistoryById(forwardView.historyId);
|
|
if (tmp) {
|
|
// the forward has a history
|
|
for (x = tmp.stack.length - 1; x >= forwardView.index; x--) {
|
|
// starting from the end destroy all forwards in this history from this point
|
|
var stack_x = tmp.stack[x];
|
|
stack_x && stack_x.destroy && stack_x.destroy();
|
|
tmp.stack.splice(x);
|
|
}
|
|
historyId = forwardView.historyId;
|
|
}
|
|
}
|
|
|
|
// its only moving forward if its in the same history
|
|
if (hist.historyId === currentView.historyId) {
|
|
direction = DIRECTION_FORWARD;
|
|
|
|
} else if (currentView.historyId !== hist.historyId) {
|
|
direction = DIRECTION_ENTER;
|
|
|
|
tmp = getHistoryById(currentView.historyId);
|
|
if (tmp && tmp.parentHistoryId === hist.parentHistoryId) {
|
|
direction = DIRECTION_SWAP;
|
|
|
|
} else {
|
|
tmp = getHistoryById(tmp.parentHistoryId);
|
|
if (tmp && tmp.historyId === hist.historyId) {
|
|
direction = DIRECTION_EXIT;
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
// there's no current view, so this must be the initial view
|
|
action = ACTION_INITIAL_VIEW;
|
|
}
|
|
|
|
if (stateChangeCounter < 2) {
|
|
// views that were spun up on the first load should not animate
|
|
direction = DIRECTION_NONE;
|
|
}
|
|
|
|
// add the new view
|
|
viewHistory.views[viewId] = this.createView({
|
|
viewId: viewId,
|
|
index: hist.stack.length,
|
|
historyId: hist.historyId,
|
|
backViewId: (currentView && currentView.viewId ? currentView.viewId : null),
|
|
forwardViewId: null,
|
|
stateId: currentStateId,
|
|
stateName: this.currentStateName(),
|
|
stateParams: getCurrentStateParams(),
|
|
url: url
|
|
});
|
|
|
|
// add the new view to this history's stack
|
|
hist.stack.push(viewHistory.views[viewId]);
|
|
}
|
|
|
|
$timeout.cancel(nextViewExpireTimer);
|
|
if (nextViewOptions) {
|
|
if (nextViewOptions.disableAnimate) direction = DIRECTION_NONE;
|
|
if (nextViewOptions.disableBack) viewHistory.views[viewId].backViewId = null;
|
|
if (nextViewOptions.historyRoot) {
|
|
for (x = 0; x < hist.stack.length; x++) {
|
|
if (hist.stack[x].viewId === viewId) {
|
|
hist.stack[x].index = 0;
|
|
hist.stack[x].backViewId = hist.stack[x].forwardViewId = null;
|
|
} else {
|
|
delete viewHistory.views[hist.stack[x].viewId];
|
|
}
|
|
}
|
|
hist.stack = [viewHistory.views[viewId]];
|
|
}
|
|
nextViewOptions = null;
|
|
}
|
|
|
|
setNavViews(viewId);
|
|
|
|
if (viewHistory.backView && historyId == viewHistory.backView.historyId && currentStateId == viewHistory.backView.stateId && url == viewHistory.backView.url) {
|
|
for (x = 0; x < hist.stack.length; x++) {
|
|
if (hist.stack[x].viewId == viewId) {
|
|
action = 'dupNav';
|
|
direction = DIRECTION_NONE;
|
|
if (x > 0) {
|
|
hist.stack[x - 1].forwardViewId = null;
|
|
}
|
|
viewHistory.forwardView = null;
|
|
viewHistory.currentView.index = viewHistory.backView.index;
|
|
viewHistory.currentView.backViewId = viewHistory.backView.backViewId;
|
|
viewHistory.backView = getBackView(viewHistory.backView);
|
|
hist.stack.splice(x, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('VIEW', action, direction, viewHistory.currentView);
|
|
|
|
hist.cursor = viewHistory.currentView.index;
|
|
|
|
return {
|
|
viewId: viewId,
|
|
action: action,
|
|
direction: direction,
|
|
historyId: historyId,
|
|
enableBack: this.enabledBack(viewHistory.currentView),
|
|
isHistoryRoot: (viewHistory.currentView.index === 0),
|
|
ele: ele
|
|
};
|
|
},
|
|
|
|
registerHistory: function(scope) {
|
|
scope.$historyId = ionic.Utils.nextUid();
|
|
},
|
|
|
|
createView: function(data) {
|
|
var newView = new View();
|
|
return newView.initialize(data);
|
|
},
|
|
|
|
getViewById: getViewById,
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#viewHistory
|
|
* @description The app's view history data, such as all the views and histories, along
|
|
* with how they are ordered and linked together within the navigation stack.
|
|
* @returns {object} Returns an object containing the apps view history data.
|
|
*/
|
|
viewHistory: function() {
|
|
return viewHistory;
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#currentView
|
|
* @description The app's current view.
|
|
* @returns {object} Returns the current view.
|
|
*/
|
|
currentView: function(view) {
|
|
if (arguments.length) {
|
|
viewHistory.currentView = view;
|
|
}
|
|
return viewHistory.currentView;
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#currentHistoryId
|
|
* @description The ID of the history stack which is the parent container of the current view.
|
|
* @returns {string} Returns the current history ID.
|
|
*/
|
|
currentHistoryId: function() {
|
|
return viewHistory.currentView ? viewHistory.currentView.historyId : null;
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#currentTitle
|
|
* @description Gets and sets the current view's title.
|
|
* @param {string=} val The title to update the current view with.
|
|
* @returns {string} Returns the current view's title.
|
|
*/
|
|
currentTitle: function(val) {
|
|
if (viewHistory.currentView) {
|
|
if (arguments.length) {
|
|
viewHistory.currentView.title = val;
|
|
}
|
|
return viewHistory.currentView.title;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#backView
|
|
* @description Returns the view that was before the current view in the history stack.
|
|
* If the user navigated from View A to View B, then View A would be the back view, and
|
|
* View B would be the current view.
|
|
* @returns {object} Returns the back view.
|
|
*/
|
|
backView: function(view) {
|
|
if (arguments.length) {
|
|
viewHistory.backView = view;
|
|
}
|
|
return viewHistory.backView;
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#backTitle
|
|
* @description Gets the back view's title.
|
|
* @returns {string} Returns the back view's title.
|
|
*/
|
|
backTitle: function(view) {
|
|
var backView = (view && getViewById(view.backViewId)) || viewHistory.backView;
|
|
return backView && backView.title;
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#forwardView
|
|
* @description Returns the view that was in front of the current view in the history stack.
|
|
* A forward view would exist if the user navigated from View A to View B, then
|
|
* navigated back to View A. At this point then View B would be the forward view, and View
|
|
* A would be the current view.
|
|
* @returns {object} Returns the forward view.
|
|
*/
|
|
forwardView: function(view) {
|
|
if (arguments.length) {
|
|
viewHistory.forwardView = view;
|
|
}
|
|
return viewHistory.forwardView;
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#currentStateName
|
|
* @description Returns the current state name.
|
|
* @returns {string}
|
|
*/
|
|
currentStateName: function() {
|
|
return ($state && $state.current ? $state.current.name : null);
|
|
},
|
|
|
|
isCurrentStateNavView: function(navView) {
|
|
return !!($state && $state.current && $state.current.views && $state.current.views[navView]);
|
|
},
|
|
|
|
goToHistoryRoot: function(historyId) {
|
|
if (historyId) {
|
|
var hist = getHistoryById(historyId);
|
|
if (hist && hist.stack.length) {
|
|
if (viewHistory.currentView && viewHistory.currentView.viewId === hist.stack[0].viewId) {
|
|
return;
|
|
}
|
|
forcedNav = {
|
|
viewId: hist.stack[0].viewId,
|
|
action: ACTION_MOVE_BACK,
|
|
direction: DIRECTION_BACK
|
|
};
|
|
hist.stack[0].go();
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#goBack
|
|
* @description Navigates the app to the back view, if a back view exists.
|
|
*/
|
|
goBack: function() {
|
|
viewHistory.backView && viewHistory.backView.go();
|
|
},
|
|
|
|
|
|
enabledBack: function(view) {
|
|
var backView = getBackView(view);
|
|
return !!(backView && backView.historyId === view.historyId);
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#clearHistory
|
|
* @description Clears out the app's entire history, except for the current view.
|
|
*/
|
|
clearHistory: function() {
|
|
var
|
|
histories = viewHistory.histories,
|
|
currentView = viewHistory.currentView;
|
|
|
|
if (histories) {
|
|
for (var historyId in histories) {
|
|
|
|
if (histories[historyId].stack) {
|
|
histories[historyId].stack = [];
|
|
histories[historyId].cursor = -1;
|
|
}
|
|
|
|
if (currentView && currentView.historyId === historyId) {
|
|
currentView.backViewId = currentView.forwardViewId = null;
|
|
histories[historyId].stack.push(currentView);
|
|
} else if (histories[historyId].destroy) {
|
|
histories[historyId].destroy();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
for (var viewId in viewHistory.views) {
|
|
if (viewId !== currentView.viewId) {
|
|
delete viewHistory.views[viewId];
|
|
}
|
|
}
|
|
|
|
if (currentView) {
|
|
setNavViews(currentView.viewId);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#clearCache
|
|
* @description Removes all cached views within every {@link ionic.directive:ionNavView}.
|
|
* This both removes the view element from the DOM, and destroy it's scope.
|
|
*/
|
|
clearCache: function() {
|
|
$ionicNavViewDelegate._instances.forEach(function(instance) {
|
|
instance.clearCache();
|
|
});
|
|
},
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $ionicHistory#nextViewOptions
|
|
* @description Sets options for the next view. This method can be useful to override
|
|
* certain view/transition defaults right before a view transition happens. For example,
|
|
* the {@link ionic.directive:menuClose} directive uses this method internally to ensure
|
|
* an animated view transition does not happen when a side menu is open, and also sets
|
|
* the next view as the root of its history stack. After the transition these options
|
|
* are set back to null.
|
|
*
|
|
* Available options:
|
|
*
|
|
* * `disableAnimate`: Do not animate the next transition.
|
|
* * `disableBack`: The next view should forget its back view, and set it to null.
|
|
* * `historyRoot`: The next view should become the root view in its history stack.
|
|
*
|
|
* ```js
|
|
* $ionicHistory.nextViewOptions({
|
|
* disableAnimate: true,
|
|
* disableBack: true
|
|
* });
|
|
* ```
|
|
*/
|
|
nextViewOptions: function(opts) {
|
|
if (arguments.length) {
|
|
$timeout.cancel(nextViewExpireTimer);
|
|
if (opts === null) {
|
|
nextViewOptions = opts;
|
|
} else {
|
|
nextViewOptions = nextViewOptions || {};
|
|
extend(nextViewOptions, opts);
|
|
if (nextViewOptions.expire) {
|
|
nextViewExpireTimer = $timeout(function() {
|
|
nextViewOptions = null;
|
|
}, nextViewOptions.expire);
|
|
}
|
|
}
|
|
}
|
|
return nextViewOptions;
|
|
},
|
|
|
|
isAbstractEle: function(ele, viewLocals) {
|
|
if (viewLocals && viewLocals.$$state && viewLocals.$$state.self.abstract) {
|
|
return true;
|
|
}
|
|
return !!(ele && (isAbstractTag(ele) || isAbstractTag(ele.children())));
|
|
},
|
|
|
|
isActiveScope: function(scope) {
|
|
if (!scope) return false;
|
|
|
|
var climbScope = scope;
|
|
var currentHistoryId = this.currentHistoryId();
|
|
var foundHistoryId;
|
|
|
|
while (climbScope) {
|
|
if (climbScope.$$disconnected) {
|
|
return false;
|
|
}
|
|
|
|
if (!foundHistoryId && climbScope.hasOwnProperty('$historyId')) {
|
|
foundHistoryId = true;
|
|
}
|
|
|
|
if (currentHistoryId) {
|
|
if (climbScope.hasOwnProperty('$historyId') && currentHistoryId == climbScope.$historyId) {
|
|
return true;
|
|
}
|
|
if (climbScope.hasOwnProperty('$activeHistoryId')) {
|
|
if (currentHistoryId == climbScope.$activeHistoryId) {
|
|
if (climbScope.hasOwnProperty('$historyId')) {
|
|
return true;
|
|
}
|
|
if (!foundHistoryId) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (foundHistoryId && climbScope.hasOwnProperty('$activeHistoryId')) {
|
|
foundHistoryId = false;
|
|
}
|
|
|
|
climbScope = climbScope.$parent;
|
|
}
|
|
|
|
return currentHistoryId ? currentHistoryId == 'root' : true;
|
|
}
|
|
|
|
};
|
|
|
|
function isAbstractTag(ele) {
|
|
return ele && ele.length && /ion-side-menus|ion-tabs/i.test(ele[0].tagName);
|
|
}
|
|
|
|
}])
|
|
|
|
.run([
|
|
'$rootScope',
|
|
'$state',
|
|
'$location',
|
|
'$document',
|
|
'$ionicPlatform',
|
|
'$ionicHistory',
|
|
function($rootScope, $state, $location, $document, $ionicPlatform, $ionicHistory) {
|
|
|
|
// always reset the keyboard state when change stage
|
|
$rootScope.$on('$ionicView.beforeEnter', function() {
|
|
ionic.keyboard && ionic.keyboard.hide && ionic.keyboard.hide();
|
|
});
|
|
|
|
$rootScope.$on('$ionicHistory.change', function(e, data) {
|
|
if (!data) return;
|
|
|
|
var viewHistory = $ionicHistory.viewHistory();
|
|
|
|
var hist = (data.historyId ? viewHistory.histories[ data.historyId ] : null);
|
|
if (hist && hist.cursor > -1 && hist.cursor < hist.stack.length) {
|
|
// the history they're going to already exists
|
|
// go to it's last view in its stack
|
|
var view = hist.stack[ hist.cursor ];
|
|
return view.go(data);
|
|
}
|
|
|
|
// this history does not have a URL, but it does have a uiSref
|
|
// figure out its URL from the uiSref
|
|
if (!data.url && data.uiSref) {
|
|
data.url = $state.href(data.uiSref);
|
|
}
|
|
|
|
if (data.url) {
|
|
// don't let it start with a #, messes with $location.url()
|
|
if (data.url.indexOf('#') === 0) {
|
|
data.url = data.url.replace('#', '');
|
|
}
|
|
if (data.url !== $location.url()) {
|
|
// we've got a good URL, ready GO!
|
|
$location.url(data.url);
|
|
}
|
|
}
|
|
});
|
|
|
|
$rootScope.$ionicGoBack = function() {
|
|
$ionicHistory.goBack();
|
|
};
|
|
|
|
// Set the document title when a new view is shown
|
|
$rootScope.$on('$ionicView.afterEnter', function(ev, data) {
|
|
if (data && data.title) {
|
|
$document[0].title = data.title;
|
|
}
|
|
});
|
|
|
|
// Triggered when devices with a hardware back button (Android) is clicked by the user
|
|
// This is a Cordova/Phonegap platform specifc method
|
|
function onHardwareBackButton(e) {
|
|
var backView = $ionicHistory.backView();
|
|
if (backView) {
|
|
// there is a back view, go to it
|
|
backView.go();
|
|
} else {
|
|
// there is no back view, so close the app instead
|
|
ionic.Platform.exitApp();
|
|
}
|
|
e.preventDefault();
|
|
return false;
|
|
}
|
|
$ionicPlatform.registerBackButtonAction(
|
|
onHardwareBackButton,
|
|
PLATFORM_BACK_BUTTON_PRIORITY_VIEW
|
|
);
|
|
|
|
}]);
|