5
5
* This file is part of ubuntu-html5-theme.
7
7
* This package is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU Lesser General Public License as
9
* published by the Free Software Foundation; either version 3 of the
8
* it under the terms of the GNU Lesser General Public License as
9
* published by the Free Software Foundation; either version 3 of the
11
11
* (at your option) any later version.
13
13
* This package is distributed in the hope that it will be useful,
14
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this program. If not, see
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this program. If not, see
20
20
* <http://www.gnu.org/licenses/>.
24
* The Pagestack manages all Pages in a stack data structure. Initially, the Pagestack contains no Pages. The <em>push()</em> method is normally executed on load to display the app starting page.
26
UI.pagestack.push("pageID")
28
The topmost Page on the Pagestack is always displayed.
30
The Pagestack is declared as a direct child of the <em>content</em> div.
32
#####Default application wide footer
33
The Pagestack contains a default <em>footer</em> (represented in JavaScript as a Toolbar), even if you do not declare one in HTML. The <em>footer</em> has a single Back button.
34
#####Customized application wide footer
35
This application-wide <em>footer</em> can be customized (for example, you can add Buttons) by declaring a <em>footer</em> as a direct child of the <em>pagestack</em> div (see example).
36
######Page specific footers
37
A <em>page</em> may declare a page-specific <em>footer</em> as a child element.
44
<div data-role="page">
45
<header data-role="header">
48
<div data-role="content">
49
<div data-role="pagestack">
50
<div data-role="page" id="main">
52
<div data-role="page" id="page2">
54
<footer data-role="footer" class="revealed" id="footerPage2">
58
<footer data-role="footer" class="revealed" id="footerAppWide">
61
</div> <!-- end of Pagestack div -->
66
UI.pagestack.METHOD();
24
69
var Pagestack = (function () {
26
71
function __safeCall(f, args, errorfunc) {
27
if (typeof(f) !== 'function')
32
catch(e) { if (errorfunc && typeof(errorfunc) === 'function') errorfunc(e) }
72
if (typeof (f) !== 'function')
77
if (errorfunc && typeof (errorfunc) === 'function') errorfunc(e)
35
function Pagestack () {
81
function Pagestack(pagestack) {
83
this._pagestack = pagestack;
39
86
Pagestack.prototype = {
40
__setAllPagesVisibility: function (visible) {
41
var visibility = visible ? "block" : "none";
42
[].forEach.call(document.querySelectorAll("[data-role='pagestack'] [data-role='page']"), function(el) {
43
el.style.display = visibility;
45
// treat footers separately
46
var footer = el.querySelector('footer');
48
footer.style.display = visibility;
51
__isPage: function (element) {
52
return element.getAttribute('data-role') === 'page';
54
__deactivate: function (id) {
55
if (!id || typeof(id) !== 'string')
57
var page = document.getElementById(id);
58
if ( ! this.__isPage(page)) {
61
page.style.display = "none";
62
if (page.querySelector('footer')) {
63
var footer = page.querySelector('footer');
64
footer.style.display = 'none';
65
footer.classList.remove('revealed');
68
__activate: function (id) {
69
if (!id || typeof(id) !== 'string')
71
var page = document.getElementById(id);
72
if ( ! this.__isPage(page)) {
75
page.style.display = "block";
76
if (page.querySelector('footer')) {
77
var footer = page.querySelector('footer');
78
footer.style.display = 'block';
79
footer.classList.add('revealed');
82
push: function (id, properties) {
84
__safeCall(this.__setAllPagesVisibility.bind(this), [false]);
91
isEmpty: function () {
92
return this._pages.length === 0;
94
currentPage: function () {
95
return this.isEmpty() ? null : this._pages[this._pages.length-1];
98
return this._pages.length;
103
__safeCall(this.__deactivate.bind(this), [this.currentPage()]);
109
__safeCall(this.__deactivate.bind(this), [this.currentPage()]);
111
__safeCall(this.__activate.bind(this), [this.currentPage()]);
88
* Push a page to the top of this pagestack
90
* @param {String} id - The id attribute of the page element to be pushed
91
* @param {Object} properties - This param is not currently used
93
push: function (id, properties) {
95
__safeCall(this.__setAllPagesVisibility.bind(this), [false]);
96
(new Page(id)).activate(id);
99
this.__dispatchPageChanged(this.currentPage());
104
* Checks for zero pages in this pagestack
106
* @return {Boolean} - True when this pagestack has no pages, else false
108
isEmpty: function () {
109
return this._pages.length === 0;
113
* Gets the id attribute of the page element on top of this pagestack
114
* @method currentPage
115
* @return {PageID|Null} - The topmost page's id attribute, else null when there are no pages on this pagestack
117
currentPage: function () {
118
return this.isEmpty() ? null : this._pages[this._pages.length - 1];
122
* Gets the number of pages in this pagestack
124
* @return {Number} - The number of pages in this pagestack
127
return this._pages.length;
131
* Clears the whole page stack
137
__safeCall(Page.prototype.deactivate.bind(new Page(this.currentPage())), []);
142
* Pops the current page off this pagestack, which causes the next page to become the top page and to display
148
__safeCall(Page.prototype.deactivate.bind(new Page(this.currentPage())), []);
150
__safeCall(Page.prototype.activate.bind(new Page(this.currentPage())), []);
152
this.__dispatchPageChanged(this.currentPage());
155
onPageChanged : function(callback){
156
this._pagestack.addEventListener("pagechanged", callback);
162
__setAllPagesVisibility: function (visible) {
163
var visibility = visible ? "block" : "none";
165
var children = [].slice.call(this._pagestack.children);
166
children.forEach(function(element) {
167
var pageHelper = new Page();
168
if (pageHelper.isPage(element)) {
169
el.style.display = visibility;
170
// treat footers separately
171
var footer = el.querySelector('footer');
173
footer.style.display = visibility;
181
__isPage: function (element) {
182
return element.getAttribute('data-role') === 'page';
188
__dispatchPageChanged: function (page) {
189
var event = document.createEvent('Event');
190
event.initEvent('pagechanged',true,true);
192
this._pagestack.dispatchEvent(event);
115
196
return Pagestack;