Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
290 lines
8.5 KiB
JavaScript
290 lines
8.5 KiB
JavaScript
'use strict';
|
|
/* global LazyLoader */
|
|
/* exported navigationStack */
|
|
|
|
function navigationStack(currentView) {
|
|
/* jshint validthis:true */
|
|
// Each transition entry includes a 'forwards' property including the
|
|
// classes which will be added to the 'current' and 'next' view when the
|
|
// transition goes forwards, as well as a 'backwards' property including the
|
|
// classes which will be added to the 'current' and 'next' view when the
|
|
// transition goes backwards.
|
|
this.transitions = {
|
|
'none': {
|
|
forwards: {},
|
|
backwards: {}
|
|
},
|
|
'right-left': {
|
|
forwards: {
|
|
next: 'app-go-in'
|
|
},
|
|
backwards: {
|
|
current: 'app-go-back-out'
|
|
}
|
|
},
|
|
'popup': {
|
|
forwards: {
|
|
next: 'app-go-up-in'
|
|
},
|
|
backwards: {
|
|
current: 'app-go-up-back-out'
|
|
}
|
|
},
|
|
'activity-popup': {
|
|
forwards: {
|
|
next: 'app-go-up-in'
|
|
},
|
|
backwards: {}
|
|
},
|
|
'fade-in': {
|
|
forwards: {
|
|
next: 'fade-in'
|
|
},
|
|
backwards: {
|
|
current: 'fade-out'
|
|
}
|
|
},
|
|
'go-deeper': {
|
|
forwards: {
|
|
current: 'app-go-deeper-out',
|
|
next: 'app-go-deeper-in'
|
|
},
|
|
backwards: {
|
|
current: 'app-go-deeper-back-out',
|
|
next: 'app-go-deeper-back-in'
|
|
}
|
|
},
|
|
'go-deeper-search': {
|
|
forwards: {
|
|
current: 'move-out-from-forward',
|
|
next: 'move-in-from-forward'
|
|
},
|
|
backwards: {
|
|
current: 'move-out-from-backward',
|
|
next: 'move-in-from-backward'
|
|
}
|
|
}
|
|
};
|
|
|
|
var COMMS_APP_ORIGIN = location.origin;
|
|
var screenshotViewId = 'view-screenshot';
|
|
var _currentView = currentView;
|
|
document.getElementById(currentView).classList.add('current');
|
|
this.stack = [];
|
|
|
|
navigationStack._zIndex = navigationStack._zIndex || 0;
|
|
|
|
this.stack.push({view: _currentView, transition: 'popup',
|
|
zIndex: ++navigationStack._zIndex});
|
|
|
|
var waitForAnimation = function ng_waitForAnimation(view, callback) {
|
|
if (!callback) {
|
|
return;
|
|
}
|
|
|
|
view.addEventListener('animationend', function ng_onAnimationEnd() {
|
|
view.removeEventListener('animationend', ng_onAnimationEnd);
|
|
setTimeout(callback, 0);
|
|
});
|
|
};
|
|
|
|
this.go = function go(nextView, transition, callback) {
|
|
if (_currentView === nextView) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
return;
|
|
}
|
|
|
|
var parent = window.parent;
|
|
if (nextView == 'view-contact-form') {
|
|
parent.postMessage({type: 'hide-navbar'}, COMMS_APP_ORIGIN);
|
|
}
|
|
|
|
// Remove items that match nextView from the stack to prevent duplicates.
|
|
this.stack = this.stack.filter(function(item) {
|
|
return item.view != nextView;
|
|
});
|
|
|
|
var current;
|
|
var currentClassList;
|
|
// Performance is very bad when there are too many contacts so we use
|
|
// -moz-element and animate this 'screenshot" element.
|
|
if (transition.indexOf('go-deeper') === 0) {
|
|
current = document.getElementById(screenshotViewId);
|
|
|
|
// Load the screenshot dom content
|
|
LazyLoader.load([current]);
|
|
|
|
current.style.zIndex = this.stack[this.stack.length - 1].zIndex;
|
|
currentClassList = current.classList;
|
|
if (transition.indexOf('search') !== -1) {
|
|
currentClassList.add('search');
|
|
} else {
|
|
currentClassList.add('contact-list');
|
|
}
|
|
currentClassList.remove('hide');
|
|
} else {
|
|
current = document.getElementById(_currentView);
|
|
currentClassList = current.classList;
|
|
}
|
|
|
|
var forwardsClasses = this.transitions[transition].forwards;
|
|
|
|
// Add forwards class to current view.
|
|
currentClassList.add('block-item');
|
|
if (forwardsClasses.current) {
|
|
currentClassList.add(forwardsClasses.current);
|
|
}
|
|
|
|
var next = document.getElementById(nextView);
|
|
// Add forwards class to next view.
|
|
if (forwardsClasses.next) {
|
|
next.classList.add(forwardsClasses.next);
|
|
next.addEventListener('animationend', function ng_onNextBackwards(ev) {
|
|
next.removeEventListener('animationend', ng_onNextBackwards);
|
|
next.classList.remove('block-item');
|
|
});
|
|
}
|
|
|
|
next.classList.add('current');
|
|
var realCurrentView = document.getElementById(_currentView);
|
|
var _callbackInner = function _callback() {
|
|
next.classList.add('current');
|
|
realCurrentView.classList.remove('current');
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
|
|
if (transition === 'none') {
|
|
setTimeout(_callbackInner, 0);
|
|
} else {
|
|
waitForAnimation(next, _callbackInner);
|
|
}
|
|
|
|
var zIndex = ++navigationStack._zIndex;
|
|
this.stack.push({ view: nextView, transition: transition,
|
|
zIndex: zIndex});
|
|
next.style.zIndex = zIndex;
|
|
_currentView = nextView;
|
|
};
|
|
|
|
this.back = function back(callback) {
|
|
if (this.stack.length < 2) {
|
|
if (typeof callback === 'function') {
|
|
setTimeout(callback, 0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
var currentView = this.stack.pop();
|
|
var current = document.getElementById(currentView.view);
|
|
var currentClassList = current.classList;
|
|
|
|
var nextView = this.stack[this.stack.length - 1];
|
|
var transition = currentView.transition;
|
|
|
|
var next = document.getElementById(nextView.view);
|
|
var nextClassList;
|
|
// Performance is very bad when there are too many contacts so we use
|
|
// -moz-element and animate this 'screenshot" element.
|
|
if (transition.indexOf('go-deeper') === 0) {
|
|
next = document.getElementById(screenshotViewId);
|
|
} else {
|
|
next = document.getElementById(nextView.view);
|
|
}
|
|
nextClassList = next.classList;
|
|
|
|
var forwardsClasses = this.transitions[transition].forwards;
|
|
var backwardsClasses = this.transitions[transition].backwards;
|
|
|
|
if (currentView.view == 'view-contact-form') {
|
|
parent.postMessage({type: 'show-navbar'}, COMMS_APP_ORIGIN);
|
|
}
|
|
|
|
// Add backwards class to current view.
|
|
if (backwardsClasses.current) {
|
|
currentClassList.add('block-item');
|
|
currentClassList.add(backwardsClasses.current);
|
|
current.addEventListener('animationend',
|
|
function ng_onCurrentBackwards() {
|
|
current.removeEventListener('animationend', ng_onCurrentBackwards);
|
|
// Once the backwards animation completes, delete the added classes
|
|
// to restore the elements to their initial state.
|
|
currentClassList.remove(forwardsClasses.next);
|
|
currentClassList.remove(backwardsClasses.current);
|
|
current.style.zIndex = null;
|
|
currentClassList.remove('block-item');
|
|
if (!backwardsClasses.next) {
|
|
nextClassList.remove('block-item');
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
current.style.zIndex = null;
|
|
currentClassList.remove('block-item');
|
|
if (!backwardsClasses.next) {
|
|
nextClassList.remove('block-item');
|
|
}
|
|
}
|
|
|
|
next.style.zIndex = nextView.zIndex;
|
|
|
|
// Add backwards class to next view.
|
|
if (backwardsClasses.next) {
|
|
nextClassList.add(backwardsClasses.next);
|
|
next.addEventListener('animationend', function ng_onNextBackwards() {
|
|
next.removeEventListener('animationend', ng_onNextBackwards);
|
|
// Once the backwards animation completes, delete the added classes
|
|
// to restore the elements to their initial state.
|
|
nextClassList.remove(forwardsClasses.current);
|
|
nextClassList.remove(backwardsClasses.next);
|
|
if (transition.indexOf('go-deeper') === 0) {
|
|
// Hide the -moz-element element once the animation completes.
|
|
nextClassList.add('hide');
|
|
nextClassList.remove('search');
|
|
nextClassList.remove('contact-list');
|
|
}
|
|
nextClassList.remove('block-item');
|
|
});
|
|
}
|
|
|
|
document.getElementById(nextView.view).classList.add('current');
|
|
var _callbackInner = function _callbackInner() {
|
|
document.getElementById(nextView.view).classList.add('current');
|
|
currentClassList.remove('current');
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
|
|
if ((!backwardsClasses.current && !backwardsClasses.next) ||
|
|
transition === 'none') {
|
|
setTimeout(_callbackInner, 0);
|
|
} else {
|
|
waitForAnimation(current, _callbackInner);
|
|
}
|
|
_currentView = nextView.view;
|
|
navigationStack._zIndex = nextView.zIndex;
|
|
};
|
|
|
|
this.home = function home(callback) {
|
|
if (this.stack.length < 2) {
|
|
if (typeof callback === 'function') {
|
|
setTimeout(callback, 0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
while (this.stack.length > 1) {
|
|
this.back(callback);
|
|
}
|
|
};
|
|
|
|
this.currentView = function currentView() {
|
|
return _currentView != null ? _currentView : '';
|
|
};
|
|
}
|