~ubuntu-branches/ubuntu/wily/ubuntu-html5-theme/wily

« back to all changes in this revision

Viewing changes to 0.1/ambiance/js/core.js

  • Committer: Package Import Robot
  • Author(s): CI Train Bot, Alexandre Abreu, CI Train Bot, David Barth, daker
  • Date: 2015-03-04 21:32:05 UTC
  • mfrom: (1.1.31)
  • Revision ID: package-import@ubuntu.com-20150304213205-k6ce05kxm2w8aozz
Tags: 0.1.2+15.04.20150304-0ubuntu1
[ Alexandre Abreu ]
* revert revision 196: push to trunk instead of usual landing

[ CI Train Bot ]
* New rebuild forced.

[ David Barth ]
* Fixes Uncaught ReferenceError: ActionBar is not defined

[ daker ]
* Removed ActionsBar deps Fixed the back button in PageStack Fixed
  PageStack actions (LP: #1427729, #1427909)

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
        [...]
39
39
      };
40
40
 */
41
 
var UbuntuUI = (function () {
 
41
var UbuntuUI = (function() {
42
42
 
43
43
    PAGESTACK_BACK_ID = 'ubuntu-pagestack-back';
44
44
 
45
45
    function __hasPageStack(document) {
46
 
        return document.querySelectorAll("[data-role='pagestack']") != null;
 
46
        return document.querySelectorAll("[data-role='pagestack']").length >= 1;
47
47
    };
48
48
 
49
49
    function __hasTabs(document) {
50
 
         return document.querySelectorAll("[data-role='tabs']") != null;
 
50
        return document.querySelectorAll("[data-role='tabs']").length >= 1;
51
51
    };
52
52
 
53
53
    function __createBackButtonListItem() {
54
54
        var backBtn = document.createElement('button');
55
55
        backBtn.setAttribute('data-role', 'back-btn');
56
 
        backBtn.setAttribute('id', PAGESTACK_BACK_ID + '-' + Math.random());
 
56
        backBtn.setAttribute('id', PAGESTACK_BACK_ID + '-' + Math.floor(Math.random()));
 
57
        backBtn.disabled = true;
57
58
        return backBtn;
58
59
    };
59
60
 
61
62
        var U = this;
62
63
        U.isTouch = "ontouchstart" in window;
63
64
        U.touchEvents = {
64
 
            touchStart: ['touchstart','mousedown'],
65
 
            touchMove: ['touchmove','mousemove'],
66
 
            touchEnd: ['touchend','mouseup'],
 
65
            touchStart: ['touchstart', 'mousedown'],
 
66
            touchMove: ['touchmove', 'mousemove'],
 
67
            touchEnd: ['touchend', 'mouseup'],
67
68
            touchLeave: ['mouseleave'],
68
69
        };
69
70
 
75
76
        this._content.style.paddingTop = this._headerHeight + "px";
76
77
 
77
78
        var self = this;
78
 
        window.onscroll = function(event){
 
79
        window.onscroll = function(event) {
79
80
            var scrollTop = window.pageYOffset;
80
81
            var y = Math.min(self._headerHeight, Math.max(0, (self._y + scrollTop - self._prevScrollTop)));
81
82
 
93
94
    };
94
95
 
95
96
    UbuntuUI.prototype = {
96
 
        __setupPageStack: function (d) {
97
 
            // TODO validate no more than one page stack etc.
98
 
            // d.querySelectorAll("[data-role='pagestack']")
99
 
 
100
 
            // FIXME: support multiple page stack & complex docs?
101
 
            var pagestacks = d.querySelectorAll("[data-role='pagestack']");
102
 
            if (pagestacks.length == 0)
103
 
                return;
104
 
            var pagestack = pagestacks[0];
105
 
 
106
 
            this._pageStack = new Pagestack(pagestack);
107
 
 
108
 
            var pages = pagestack.querySelectorAll("[data-role='page']");
109
 
            if (pages.length > 0) {
110
 
                this._pageStack.push(pages[0].getAttribute('id'));
111
 
            }
 
97
        __setupPageStack: function(d) {
112
98
 
113
99
            var header = d.querySelector("[data-role='header']");
114
100
 
122
108
            header.insertBefore(backBtn, header.firstChild);
123
109
 
124
110
            var self = this;
125
 
            backBtn.onclick = function (e) {
126
 
                if (self._pageStack.depth() > 1){
 
111
            backBtn.onclick = function(e) {
 
112
                if (self._pageStack.depth() > 1) {
127
113
                    self._pageStack.pop();
128
114
                }
129
115
                e.preventDefault();
130
116
            };
131
117
 
 
118
            this._content = document.querySelector('[data-role="content"]');
 
119
            this._overlay = document.createElement('div');
 
120
            this._overlay.setAttribute('data-role', 'overlay');
 
121
            this._content.appendChild(this._overlay);
 
122
 
 
123
            // FIXME: support multiple page stack & complex docs?
 
124
            var pagestacks = d.querySelectorAll("[data-role='pagestack']");
 
125
            if (pagestacks.length == 0)
 
126
                return;
 
127
            var pagestack = pagestacks[0];
 
128
 
 
129
            this._pageStack = new Pagestack(pagestack);
 
130
 
 
131
            var pages = pagestack.querySelectorAll("[data-role='page']");
 
132
            if (pages.length > 0) {
 
133
                this._pageStack.push(pages[0].getAttribute('id'));
 
134
            }
 
135
 
132
136
            this._pageActions = d.createElement('div');
133
137
            this._pageActions.setAttribute('data-role', 'actions');
134
138
 
145
149
            s.webkitTransform = s.transform = 'translate3d(0, ' + y + 'px, 0)';
146
150
        },
147
151
 
148
 
        __setupPage: function (document) {
 
152
        __setupPage: function(document) {
149
153
            if (this._pageStack != null)
150
154
                return;
151
155
            if (__hasPageStack(document)) {
163
167
                    var footers = apptabsElements[idx].querySelectorAll("[data-role='footer']");
164
168
                    if (footers.length >= 0) {
165
169
                        // TODO: validate footer count: should be 1 footer
166
 
                        actionBar = new ActionBar(this._tabs, footers[0], apptabsElements[idx]);
 
170
                        actionBar = this.__setupTabAction(footers[0], apptabsElements[idx]);
167
171
                        if (footers[0] != null) footers[0].remove();
168
172
                    }
169
173
                }
175
179
                    var footers = apppagesElements[idx].querySelectorAll("[data-role='footer']");
176
180
                    if (footers.length >= 0) {
177
181
                        // TODO: validate footer count: should be 1 footer
178
 
                        actionBar = new ActionBar(this._tabs, footers[0], apppagesElements[idx]);
 
182
                        actionBar = this.__setupPageAction(footers[0], apppagesElements[idx]);
179
183
                        if (footers[0] != null) footers[0].remove();
180
184
                    }
181
185
                }
182
186
            }
183
187
        },
184
188
 
185
 
        __setupTabs: function (document) {
 
189
        __setupTabs: function(document) {
186
190
            if (this._tabs != null)
187
191
                return;
188
192
            if (__hasTabs(document)) {
191
195
                    if (apptabsElements.length == 0)
192
196
                        return;
193
197
                    this._tabs = new Tabs(apptabsElements[0]);
194
 
                    this._tabs.onTabChanged(function (e) {
 
198
                    this._tabs.onTabChanged(function(e) {
195
199
                        if (!e || !e.infos)
196
200
                            return;
197
201
                        if (e.infos.tabId) {
199
203
                        }
200
204
                    }.bind(this));
201
205
                }
202
 
             }
 
206
            }
 
207
        },
 
208
 
 
209
 
 
210
        __setupTabAction: function(oldFooter, parent) {
 
211
            this._oldFooter = oldFooter;
 
212
            this._oldFooterParent = parent;
 
213
 
 
214
            this._overlay = document.querySelector('[data-role="overlay"]');
 
215
 
 
216
            var newActionsBar = document.querySelector('[data-role="actions"]');
 
217
 
 
218
            if (!this._oldFooter)
 
219
                return;
 
220
 
 
221
            var actionBar = this._oldFooter,
 
222
                actions = actionBar.querySelector('ul'),
 
223
                actionButtons = actionBar.querySelectorAll('ul li'),
 
224
                i = actionButtons.length;
 
225
            newActionsBarWrapper = document.createElement('div');
 
226
            newActionsBarWrapper.setAttribute("data-role", "actions-wrapper");
 
227
            newActionsBarWrapper.setAttribute("id", "actions_" + this._oldFooterParent.id);
 
228
 
 
229
            if (actionButtons.length > 2) {
 
230
                // Maintain the first item then replace the rest with an action overflow
 
231
                var firstAction = actionButtons[0],
 
232
                    overflowList = document.createElement('ul'),
 
233
                    /* Action Button */
 
234
                    firstButton = document.createElement('button'),
 
235
                    overflowButton = document.createElement('button'),
 
236
                    /* Icon */
 
237
                    firstIcon = firstAction.querySelector('img').getAttribute('src'),
 
238
                    /* ID*/
 
239
                    firstId = firstAction.querySelector('a').getAttribute('id'),
 
240
                    k = 1;
 
241
 
 
242
                if (this._tabs != 'undefined' && this._tabs) {
 
243
                    if (this._tabs._tabsItems.length == 1) {
 
244
                        k = 2;
 
245
                        this._tabs._tabTitle.style.width = "calc(100% - 155px)";
 
246
 
 
247
                        // Maintain the second item
 
248
                        var secondAction = actionButtons[1],
 
249
                            /* Action Button */
 
250
                            secondButton = document.createElement('button'),
 
251
                            /* Icon */
 
252
                            secondIcon = secondAction.querySelector('img').getAttribute('src'),
 
253
                            /* ID*/
 
254
                            secondId = secondAction.querySelector('a').getAttribute('id');
 
255
                    }
 
256
                }
 
257
 
 
258
                overflowList.setAttribute('data-role', 'actions-overflow-list');
 
259
 
 
260
                // Hide the overflow
 
261
                for (var x = k; x < i; x++) {
 
262
                    var li = document.createElement('li'),
 
263
                        a_id = actionButtons[x].querySelector('a').getAttribute('id'),
 
264
                        lbl = actionButtons[x].querySelector('span').innerHTML,
 
265
                        icon = actionButtons[x].querySelector('img').getAttribute('src');
 
266
 
 
267
                    li.innerHTML = lbl;
 
268
                    li.setAttribute('id', a_id);
 
269
 
 
270
                    li.style.backgroundImage = 'url( ' + icon + ' )';
 
271
                    overflowList.appendChild(li);
 
272
 
 
273
                    li.onclick = function(e) {
 
274
                        overflowList.classList.toggle('opened');
 
275
                        self._overlay.classList.toggle('active');
 
276
                        e.preventDefault();
 
277
                    };
 
278
                }
 
279
 
 
280
                // Add the action overflow button
 
281
                overflowButton.setAttribute('data-role', 'actions-overflow-icon');
 
282
 
 
283
                //firstButton.style.backgroundImage = 'url( ' + firstIcon + ' )';
 
284
                firstButton.setAttribute('id', firstId);
 
285
                document.styleSheets[0].addRule('#' + firstId + ':after', 'background-image: url("' + firstIcon + '");');
 
286
 
 
287
                newActionsBarWrapper.appendChild(firstButton);
 
288
                if (this._tabs != 'undefined' && this._tabs) {
 
289
                    if (this._tabs._tabsItems.length == 1) {
 
290
                        secondButton.setAttribute('id', secondId);
 
291
                        document.styleSheets[0].addRule('#' + secondId + ':after', 'background-image: url("' + secondIcon + '");');
 
292
                        newActionsBarWrapper.appendChild(secondButton);
 
293
                    }
 
294
                }
 
295
                newActionsBarWrapper.appendChild(overflowButton);
 
296
                newActionsBarWrapper.appendChild(overflowList);
 
297
 
 
298
                self = this;
 
299
                overflowButton.onclick = function(e) {
 
300
                    overflowList.classList.toggle('opened');
 
301
                    self._overlay.classList.toggle('active');
 
302
                    self._tabs._tabs.classList.remove('opened');
 
303
                    e.preventDefault();
 
304
                };
 
305
            } else {
 
306
 
 
307
                for (var y = 0; y < i; y++) {
 
308
                    var actionButton = document.createElement('button'),
 
309
                        actionButton_lbl = actionButtons[y].querySelector('span').innerHTML,
 
310
                        actionButton_icon = actionButtons[y].querySelector('img').getAttribute('src'),
 
311
                        actionButton_id = actionButtons[y].querySelector('a').getAttribute('id');
 
312
 
 
313
                    actionButton.setAttribute('id', actionButton_id);
 
314
                    document.styleSheets[0].addRule('#' + actionButton_id + ':after', 'background-image: url("' + actionButton_icon + '");');
 
315
                    newActionsBarWrapper.appendChild(actionButton);
 
316
                }
 
317
            }
 
318
 
 
319
            newActionsBar.appendChild(newActionsBarWrapper);
 
320
        },
 
321
 
 
322
 
 
323
        __setupPageAction: function(oldFooter, parent) {
 
324
            this._oldFooter = oldFooter;
 
325
            this._oldFooterParent = parent;
 
326
            this._overlay = document.querySelector('[data-role="overlay"]');
 
327
 
 
328
            var newActionsBar = document.querySelector('[data-role="actions"]');
 
329
 
 
330
            if (!this._oldFooter)
 
331
                return;
 
332
 
 
333
            var actionBar = this._oldFooter,
 
334
                actions = actionBar.querySelector('ul'),
 
335
                actionButtons = actionBar.querySelectorAll('ul li'),
 
336
                i = actionButtons.length;
 
337
 
 
338
            newActionsBarWrapper = document.createElement('div');
 
339
            newActionsBarWrapper.setAttribute("data-role", "actions-wrapper");
 
340
            newActionsBarWrapper.setAttribute("id", "actions_" + this._oldFooterParent.id);
 
341
 
 
342
            if (actionButtons.length > 2) {
 
343
                // Maintain the first then replace the rest with an action overflow
 
344
                var firstAction = actionButtons[0],
 
345
                    overflowList = document.createElement('ul'),
 
346
                    /* Actions Button */
 
347
                    firstButton = document.createElement('button'),
 
348
                    overflowButton = document.createElement('button'),
 
349
                    /* Icon */
 
350
                    firstIcon = firstAction.querySelector('img').getAttribute('src'),
 
351
                    /* ID*/
 
352
                    firstId = firstAction.querySelector('a').getAttribute('id'),
 
353
                    k = 2;
 
354
 
 
355
                this._tabTitle.style.width = "calc(100% - 155px)";
 
356
 
 
357
                // Maintain the second item
 
358
                var secondAction = actionButtons[1],
 
359
                    /* Action Button */
 
360
                    secondButton = document.createElement('button'),
 
361
                    /* Icon */
 
362
                    secondIcon = secondAction.querySelector('img').getAttribute('src'),
 
363
                    /* ID*/
 
364
                    secondId = secondAction.querySelector('a').getAttribute('id');
 
365
 
 
366
                overflowList.setAttribute('data-role', 'actions-overflow-list');
 
367
 
 
368
                // Hide the overflow
 
369
                for (var x = k; x < i; x++) {
 
370
                    var li = document.createElement('li'),
 
371
                        a_id = actionButtons[x].querySelector('a').getAttribute('id'),
 
372
                        lbl = actionButtons[x].querySelector('span').innerHTML,
 
373
                        icon = actionButtons[x].querySelector('img').getAttribute('src');
 
374
 
 
375
                    li.innerHTML = lbl;
 
376
                    li.setAttribute('id', a_id);
 
377
 
 
378
                    li.style.backgroundImage = 'url( ' + icon + ' )';
 
379
                    overflowList.appendChild(li);
 
380
 
 
381
                    li.onclick = function(e) {
 
382
                        overflowList.classList.toggle('opened');
 
383
                        self._overlay.classList.toggle('active');
 
384
                        e.preventDefault();
 
385
                    };
 
386
                }
 
387
 
 
388
                // Add the action overflow button
 
389
                overflowButton.setAttribute('data-role', 'actions-overflow-icon');
 
390
 
 
391
                firstButton.setAttribute('id', firstId);
 
392
                document.styleSheets[0].addRule('#' + firstId + ':after', 'background-image: url("' + firstIcon + '");');
 
393
 
 
394
                newActionsBarWrapper.appendChild(firstButton);
 
395
                secondButton.setAttribute('id', secondId);
 
396
                document.styleSheets[0].addRule('#' + secondId + ':after', 'background-image: url("' + secondIcon + '");');
 
397
                newActionsBarWrapper.appendChild(secondButton);
 
398
                newActionsBarWrapper.appendChild(overflowButton);
 
399
                newActionsBarWrapper.appendChild(overflowList);
 
400
 
 
401
                self = this;
 
402
                overflowButton.onclick = function(e) {
 
403
                    overflowList.classList.toggle('opened');
 
404
                    self._overlay.classList.toggle('active');
 
405
                    e.preventDefault();
 
406
                };
 
407
            } else {
 
408
 
 
409
                for (var y = 0; y < i; y++) {
 
410
                    var actionButton = document.createElement('button'),
 
411
                        actionButton_lbl = actionButtons[y].querySelector('span').innerHTML,
 
412
                        actionButton_icon = actionButtons[y].querySelector('img').getAttribute('src'),
 
413
                        actionButton_id = actionButtons[y].querySelector('a').getAttribute('id');
 
414
 
 
415
                    actionButton.setAttribute('id', actionButton_id);
 
416
                    document.styleSheets[0].addRule('#' + actionButton_id + ':after', 'background-image: url("' + actionButton_icon + '");');
 
417
                    newActionsBarWrapper.appendChild(actionButton);
 
418
                }
 
419
            }
 
420
 
 
421
            newActionsBar.appendChild(newActionsBarWrapper);
203
422
        },
204
423
 
205
424
        /**
206
425
         * Required call that initializes the UbuntuUI object
207
426
         * @method {} init
208
427
         */
209
 
        init: function () {
 
428
        init: function() {
210
429
            this.__setupTabs(document);
211
430
            this.__setupPage(document);
212
431
            this.__setupActionsBar(document);
218
437
         * @param {ID} id - The element's id attribute
219
438
         * @return {Page} - The Page with the specified id
220
439
         */
221
 
        page: function (id) {
222
 
            if (typeof Page != 'undefined' && Page ) {
 
440
        page: function(id) {
 
441
            if (typeof Page != 'undefined' && Page) {
223
442
                return new Page(id);
224
 
            }
225
 
            else {
 
443
            } else {
226
444
                console.error('Could not find the Page element. You might be missing the "page.js" Page definition script. Please add a <script> declaration to include it.');
227
445
            }
228
446
        },
233
451
         * @param {ID} id - The element's id attribute
234
452
         * @return {Tab} - The Tab with the specified id
235
453
         */
236
 
        tab: function (id) {
237
 
            if (typeof Tab != 'undefined' && Tab ) {
 
454
        tab: function(id) {
 
455
            if (typeof Tab != 'undefined' && Tab) {
238
456
                return new Tab(id);
239
 
            }
240
 
            else {
 
457
            } else {
241
458
                console.error('Could not find the Tab element. You might be missing the "tab.js" Tab definition script. Please add a <script> declaration to include it.');
242
459
            }
243
460
        },
248
465
         * @param {ID} id - The element's id attribute
249
466
         * @return {Shape} - The Shape with the specified id
250
467
         */
251
 
        shape: function (id) {
252
 
            if (typeof Shape != 'undefined' && Shape ) {
 
468
        shape: function(id) {
 
469
            if (typeof Shape != 'undefined' && Shape) {
253
470
                return new Shape(id);
254
 
            }
255
 
            else {
 
471
            } else {
256
472
                console.error('Could not find the Shape element. You might be missing the "shape.js" Shape definition script. Please add a <script> declaration to include it.');
257
473
            }
258
474
        },
263
479
         * @param {ID} id - The element's id attribute
264
480
         * @return {Button} - The Button with the specified id
265
481
         */
266
 
        button: function (id) {
 
482
        button: function(id) {
267
483
            if (typeof Button != 'undefined' && Button) {
268
484
                return new Button(id);
269
 
            }
270
 
            else {
 
485
            } else {
271
486
                console.error('Could not find the Button element. You might be missing the "button.js" Button definition script. Please add a <script> declaration to include it.');
272
487
            }
273
488
        },
278
493
         * @param {ID} id - The element's id attribute
279
494
         * @return {Progress} - The Progress with the specified id
280
495
         */
281
 
        progress: function (id) {
 
496
        progress: function(id) {
282
497
            if (typeof Progress != 'undefined' && Progress) {
283
498
                return new Progress(id);
284
499
            }
290
505
         * @param {ID} id - The element's id attribute
291
506
         * @return {Dialog} - The Dialog with the specified id
292
507
         */
293
 
        dialog: function (id) {
 
508
        dialog: function(id) {
294
509
            if (typeof Dialog != 'undefined' && Dialog) {
295
510
                return new Dialog(id);
296
 
            }
297
 
            else {
 
511
            } else {
298
512
                console.error('Could not find the Dialog element. You might be missing the "dialog.js" Dialog definition script. Please add a <script> declaration to include it.');
299
513
            }
300
514
        },
306
520
         * @param {ID} id - The element's id attribute
307
521
         * @return {Popover} - The Popover with the specified id
308
522
         */
309
 
        popover: function (elem, id) {
 
523
        popover: function(elem, id) {
310
524
            if (typeof Popover != 'undefined' && Popover) {
311
525
                return new Popover(elem, id);
312
 
            }
313
 
            else {
 
526
            } else {
314
527
                console.error('Could not find the Popover element. You might be missing the "popover.js" Popover definition script. Please add a <script> declaration to include it.');
315
528
            }
316
529
        },
321
534
         * @param {ID} id - The element's id attribute
322
535
         * @return {Header} - The Header with the specified id
323
536
         */
324
 
        header: function (id) {
 
537
        header: function(id) {
325
538
            if (typeof Header != 'undefined' && Header) {
326
539
                return new Header(id);
327
 
            }
328
 
            else {
 
540
            } else {
329
541
                console.error('Could not find the Header element. You might be missing the "header.js" Header definition script. Please add a <script> declaration to include it.');
330
542
            }
331
543
        },
336
548
         * @param {ID} id - The element's id attribute
337
549
         * @return {Toolbar} - The Toolbar with the specified id
338
550
         */
339
 
        toolbar: function (id) {
 
551
        toolbar: function(id) {
340
552
            if (typeof Toolbar != 'undefined' && Toolbar) {
341
553
                return new Toolbar(id, this.__getTabInfosDelegate());
342
 
            }
343
 
            else {
 
554
            } else {
344
555
                console.error('Could not find the Toolbar element. You might be missing the "toolbar.js" Toolbar definition script. Please add a <script> declaration to include it.');
345
556
            }
346
557
        },
351
562
         * @param {Selector} selector - A selector that JavaScript querySelector method understands
352
563
         * @return {List}
353
564
         */
354
 
        list: function (selector) {
 
565
        list: function(selector) {
355
566
            if (typeof List != 'undefined' && List) {
356
567
                return new List(selector);
357
 
            }
358
 
            else {
 
568
            } else {
359
569
                console.error('Could not find the List element. You might be missing the "list.js" List definition script. Please add a <script> declaration to include it.');
360
570
            }
361
571
        },
368
578
         * @param {Boolean} multiSelection - If multiple choice selection is enabled the list is always expanded.
369
579
         * @return {OptionSelector}
370
580
         */
371
 
        optionselector: function (id, expanded, multiSelection) {
 
581
        optionselector: function(id, expanded, multiSelection) {
372
582
            if (typeof OptionSelector != 'undefined' && OptionSelector) {
373
583
                return new OptionSelector(id, expanded, multiSelection);
374
 
            }
375
 
            else {
 
584
            } else {
376
585
                console.error('Could not find the OptionSelector element. You might be missing the "option-selector.js" OptionSelector definition script. Please add a <script> declaration to include it.');
377
586
            }
378
587
        },