Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
175 lines
5.1 KiB
JavaScript
Executable file
175 lines
5.1 KiB
JavaScript
Executable file
/* global Apps, Pages */
|
|
'use strict';
|
|
|
|
(function(exports) {
|
|
|
|
/**
|
|
* Time after receiving a handled hashchange that we ignore hashchange
|
|
* events for.
|
|
*/
|
|
const HASH_CHANGE_DEBOUNCE = 100;
|
|
|
|
function AppWindow() {
|
|
this.header = document.getElementById('page-indicator-header');
|
|
this.indicator = document.getElementById('page-indicator');
|
|
this.panels = document.getElementById('panels');
|
|
this.shadow = document.getElementById('shadow');
|
|
|
|
this.apps = new Apps();
|
|
this.pages = new Pages();
|
|
|
|
// Panel visibility state
|
|
this.appsVisible = undefined;
|
|
|
|
// Home-button handling
|
|
this.ignoreHashChangeTimeout = null;
|
|
|
|
// Signal handlers
|
|
this.indicator.addEventListener('keypress', this);
|
|
this.panels.addEventListener('scroll', this);
|
|
window.addEventListener('hashchange', this, true);
|
|
window.addEventListener('localized', this);
|
|
document.addEventListener('visibilitychange', this);
|
|
|
|
// Update the panel indicator
|
|
this.updatePanelIndicator();
|
|
|
|
// Application has finished initialisation
|
|
window.performance.mark('navigationInteractive');
|
|
}
|
|
|
|
AppWindow.prototype = {
|
|
updatePanelIndicator: function() {
|
|
var appsVisible =
|
|
Math.abs(this.panels.scrollLeft) <= this.panels.scrollWidth / 4;
|
|
if (this.appsVisible !== appsVisible) {
|
|
this.appsVisible = appsVisible;
|
|
|
|
this.header.setAttribute('data-l10n-id', appsVisible ?
|
|
'apps-panel' : 'pages-panel');
|
|
|
|
this.indicator.children[0].classList.toggle('active', appsVisible);
|
|
this.indicator.children[1].classList.toggle('active', !appsVisible);
|
|
this.indicator.setAttribute('aria-valuenow', appsVisible ? 1 : 2);
|
|
this.indicator.setAttribute('data-l10n-args', JSON.stringify({
|
|
currentPage: appsVisible ? 1 : 2,
|
|
totalPages: 2
|
|
}));
|
|
|
|
this.apps.panel.setAttribute('aria-hidden', !appsVisible);
|
|
this.pages.panel.setAttribute('aria-hidden', appsVisible);
|
|
|
|
if (appsVisible) {
|
|
this.pages.scrollable.removeEventListener('scroll', this);
|
|
this.apps.scrollable.addEventListener('scroll', this);
|
|
} else {
|
|
this.apps.scrollable.removeEventListener('scroll', this);
|
|
this.pages.scrollable.addEventListener('scroll', this);
|
|
}
|
|
|
|
this.updateShadowState();
|
|
}
|
|
},
|
|
|
|
updateShadowState: function() {
|
|
var position = this.appsVisible ?
|
|
this.apps.scrollable.scrollTop : this.pages.scrollable.scrollTop;
|
|
var scrolled = position > 1;
|
|
if (this.shadow.classList.contains('visible') !== scrolled) {
|
|
this.shadow.classList.toggle('visible', scrolled);
|
|
}
|
|
},
|
|
|
|
handleEvent: function(e) {
|
|
switch (e.type) {
|
|
// Switch between panels
|
|
case 'keypress':
|
|
if (!e.ctrlKey) {
|
|
return;
|
|
}
|
|
|
|
switch (e.keyCode) {
|
|
case e.DOM_VK_RIGHT:
|
|
this.panels.scrollTo(
|
|
{ left: this.panels.scrollLeftMax, top: 0, behavior: 'smooth' });
|
|
return;
|
|
case e.DOM_VK_LEFT:
|
|
this.panels.scrollTo(
|
|
{ left: 0, top: 0, behavior: 'smooth' });
|
|
return;
|
|
}
|
|
return;
|
|
|
|
// Display the top shadow when scrolling down
|
|
case 'scroll':
|
|
if (e.target === this.panels) {
|
|
this.updatePanelIndicator();
|
|
} else {
|
|
this.updateShadowState();
|
|
}
|
|
return;
|
|
|
|
// Cancel edit modes/scroll to the top/scroll to apps on home-button
|
|
case 'hashchange':
|
|
if (document.hidden || this.ignoreHashChangeTimeout !== null) {
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopImmediatePropagation();
|
|
|
|
this.ignoreHashChangeTimeout = setTimeout(() => {
|
|
this.ignoreHashChangeTimeout = null;
|
|
}, HASH_CHANGE_DEBOUNCE);
|
|
|
|
// If a dialog is showing, cancel the dialog
|
|
for (var dialog of this.apps.dialogs.concat(this.pages.dialogs)) {
|
|
if (!dialog.opened) {
|
|
continue;
|
|
}
|
|
|
|
dialog.close();
|
|
return;
|
|
}
|
|
|
|
// If we're in edit mode, cancel edit mode
|
|
if (this.apps.editMode) {
|
|
this.apps.exitEditMode();
|
|
return;
|
|
}
|
|
if (this.pages.editMode) {
|
|
this.pages.exitEditMode();
|
|
return;
|
|
}
|
|
|
|
// If we're on the pages panel and scrolled to the top, show apps
|
|
if (!this.appsVisible && this.pages.scrollable.scrollTop === 0) {
|
|
this.panels.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
|
|
return;
|
|
}
|
|
|
|
// Otherwise, scroll the visible panel to the top
|
|
var visiblePanel = this.appsVisible ?
|
|
this.apps.scrollable : this.pages.scrollable;
|
|
visiblePanel.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
|
|
return;
|
|
|
|
case 'localized':
|
|
this.updatePanelIndicator();
|
|
return;
|
|
|
|
// Exit edit mode if the user switches away from the home screen (e.g.
|
|
// by locking the phone).
|
|
case 'visibilitychange':
|
|
if (document.hidden) {
|
|
this.apps.exitEditMode();
|
|
this.pages.exitEditMode();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.AppWindow = AppWindow;
|
|
|
|
}(window));
|