Merge lp:~daker/ubuntu-html5-theme/fix.1232533 into lp:ubuntu-html5-theme

Proposed by Alexandre Abreu
Status: Merged
Approved by: Alexandre Abreu
Approved revision: 103
Merged at revision: 97
Proposed branch: lp:~daker/ubuntu-html5-theme/fix.1232533
Merge into: lp:ubuntu-html5-theme
Diff against target: 575 lines (+524/-1)
5 files modified
0.1/ambiance/css/default.css (+2/-0)
0.1/ambiance/css/option-selector.css (+137/-0)
0.1/ambiance/js/core.js (+15/-1)
0.1/ambiance/js/option-selector.js (+205/-0)
examples/html5-theme/widgets/OptionSelector.html (+165/-0)
To merge this branch: bzr merge lp:~daker/ubuntu-html5-theme/fix.1232533
Reviewer Review Type Date Requested Status
Alexandre Abreu Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+197882@code.launchpad.net

Commit message

Add option selector widget

Description of the change

Add option selector widget

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandre Abreu (abreu-alexandre) wrote :

L250 use '==' for null checks (so that it accounts for 'undefined')
L255 (and after): add small checks at least to validate that the ul/lis are there, ... and should bail out if there are no <li>s (and subsequent calls should too)
L262 when expanded you dont set an active by default (as in 268)?
L270: why a global current index? it'll be shared between the option selector instances (might not matter since there might be only one but anyway)
L300 why the nodeType check?
L319-320: you can merge the 2 ifs (& same question about nodeType)
L318 might be interesting to have a var li = this.optionselector_ul_li[i] just to avoid all the property refs
L332-L340 make it a separate method/function (event raising),

review: Needs Fixing
98. By Adnane Belmadiaf

JS fixes

99. By Adnane Belmadiaf

Made the current index local

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Adnane Belmadiaf (daker) wrote :

> L250 use '==' for null checks (so that it accounts for 'undefined')
> L255 (and after): add small checks at least to validate that the ul/lis are
> there, ... and should bail out if there are no <li>s (and subsequent calls
> should too)
> L262 when expanded you dont set an active by default (as in 268)?
> L270: why a global current index? it'll be shared between the option selector
> instances (might not matter since there might be only one but anyway)
> L300 why the nodeType check?
> L319-320: you can merge the 2 ifs (& same question about nodeType)
> L318 might be interesting to have a var li = this.optionselector_ul_li[i] just
> to avoid all the property refs
> L332-L340 make it a separate method/function (event raising),

Done

100. By Adnane Belmadiaf

Fixed check mark position using :after

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
101. By Adnane Belmadiaf

Removed blank line

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
102. By Adnane Belmadiaf

Merged trunk
Fixed merge conflicts

103. By Adnane Belmadiaf

Fixed the js path

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandre Abreu (abreu-alexandre) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '0.1/ambiance/css/default.css'
2--- 0.1/ambiance/css/default.css 2013-11-27 16:48:37 +0000
3+++ 0.1/ambiance/css/default.css 2013-12-16 18:05:54 +0000
4@@ -34,6 +34,8 @@
5 @import url("toolbars.css");
6 @import url("shapes.css");
7 @import url("indexbar.css");
8+@import url("option-selector.css");
9+
10
11 * {
12 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
13
14=== added file '0.1/ambiance/css/option-selector.css'
15--- 0.1/ambiance/css/option-selector.css 1970-01-01 00:00:00 +0000
16+++ 0.1/ambiance/css/option-selector.css 2013-12-16 18:05:54 +0000
17@@ -0,0 +1,137 @@
18+/*
19+ * Copyright (C) 2013 Adnane Belmadiaf <daker@ubuntu.com>
20+ * License granted by Canonical Limited
21+ *
22+ * This file is part of ubuntu-html5-theme.
23+ *
24+ * This package is free software; you can redistribute it and/or modify
25+ * it under the terms of the GNU Lesser General Public License as
26+ * published by the Free Software Foundation; either version 3 of the
27+ * License, or
28+ * (at your option) any later version.
29+
30+ * This package is distributed in the hope that it will be useful,
31+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
32+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33+ * GNU General Public License for more details.
34+
35+ * You should have received a copy of the GNU Lesser General Public
36+ * License along with this program. If not, see
37+ * <http://www.gnu.org/licenses/>.
38+ */
39+
40+[data-role="option-selector"] {
41+ width: 100%;
42+ height: auto;
43+ margin: 0 auto;
44+ border: 1px solid #C7C7C7;
45+ overflow: hidden;
46+ -webkit-transition: height 0.4s;
47+ transition: height 0.4s;
48+ margin-top: 15px;
49+ margin-bottom: 15px;
50+ -webkit-border-radius: 10px;
51+ -moz-border-radius: 10px;
52+ border-radius: 10px;
53+ -webkit-box-shadow: inset 0 2px 2px 0 #D5D5D5;
54+ box-shadow: inset 0 2px 2px 0 #D5D5D5;
55+}
56+
57+[data-role="option-selector"] li {
58+ text-decoration: none;
59+ color: #787878;
60+ display: block;
61+ height: 3rem;
62+ position: relative;
63+ line-height: 3rem;
64+ padding-left: 1rem;
65+ padding-right: 1.5rem;
66+ border: none;
67+ border-top: 1px solid #C7C7C7;
68+ font-size: 0.9rem;
69+ white-space: nowrap;
70+ overflow: hidden;
71+ text-overflow: ellipsis;
72+ cursor: pointer;
73+}
74+
75+[data-role="option-selector"] ul li:first-child {
76+ border-top: 0!important;
77+}
78+
79+[data-role="option-selector"] li.active:after{
80+ background: transparent url(../img/tick@30.png) no-repeat center center;
81+ background-size: 15px 15px;
82+ display: block;
83+ position: absolute;
84+ width: 2rem;
85+ height: 3rem;
86+ right: 0.5rem;
87+ content: "";
88+ top: 0;
89+}
90+
91+[data-role="option-selector"] li.closed:after {
92+ background: transparent url(../img/chevron_down@30.png) no-repeat center center;
93+ background-size: 15px 15px;
94+ display: block;
95+ position: absolute;
96+ width: 2rem;
97+ height: 3rem;
98+ right: 0.5rem;
99+ content: "";
100+ top: 0;
101+}
102+
103+[data-role="option-selector"] li aside {
104+ float: left;
105+ margin: -1.2em 0 0 0;
106+ max-width: 100%;
107+ vertical-align: bottom;
108+ position: relative;
109+ top: 50%;
110+ z-index: 2;
111+}
112+
113+[data-role="option-selector"] li aside img {
114+ border-radius: 6px;
115+ margin-bottom: 0;
116+ float: left;
117+}
118+
119+[data-role="option-selector"] li aside:after {
120+ background: url(../img/ubuntushape_medium_radius_idle@18.png) no-repeat;
121+ background-size: 100% 100%;
122+ content: ' ';
123+ width: 100%;
124+ height: 100%;
125+ position: absolute;
126+ top: 0;
127+ left: 0;
128+}
129+
130+[data-role="option-selector"] li aside+p {
131+ padding-left: 1rem;
132+}
133+
134+[data-role="option-selector"] li p {
135+ white-space: nowrap;
136+ overflow: hidden;
137+ text-overflow: ellipsis;
138+ border: none;
139+ display: block;
140+ color: #787878;
141+ font-size: 0.9rem;
142+ padding-top: 0.5rem;
143+ line-height: 1rem;
144+}
145+
146+[data-role="option-selector"] li p:only-child,
147+[data-role="option-selector"] li p:first-of-type:last-of-type {
148+ line-height: 2rem;
149+}
150+
151+[data-role="option-selector"] li p+p {
152+ padding-top: 0.2rem;
153+ font-size: 0.7rem;
154+}
155\ No newline at end of file
156
157=== modified file '0.1/ambiance/img/back@18.png'
158Binary files 0.1/ambiance/img/back@18.png 2013-06-22 14:52:18 +0000 and 0.1/ambiance/img/back@18.png 2013-12-16 18:05:54 +0000 differ
159=== added file '0.1/ambiance/img/chevron_down@30.png'
160Binary files 0.1/ambiance/img/chevron_down@30.png 1970-01-01 00:00:00 +0000 and 0.1/ambiance/img/chevron_down@30.png 2013-12-16 18:05:54 +0000 differ
161=== modified file '0.1/ambiance/img/tick@30.png'
162Binary files 0.1/ambiance/img/tick@30.png 2013-09-11 22:59:59 +0000 and 0.1/ambiance/img/tick@30.png 2013-12-16 18:05:54 +0000 differ
163=== modified file '0.1/ambiance/js/core.js'
164--- 0.1/ambiance/js/core.js 2013-12-11 10:13:17 +0000
165+++ 0.1/ambiance/js/core.js 2013-12-16 18:05:54 +0000
166@@ -344,13 +344,27 @@
167 },
168
169 /**
170+ * Gets an Ubuntu Option Selector
171+ * @method optionselector
172+ * @param {ID} id - The element's id attrubute
173+ * @param {Boolean} expanded - Specifies whether the list is always expanded
174+ * @param {Boolean} multiSelection - If multiple choice selection is enabled the list is always expanded.
175+ * @return {OptionSelector}
176+ */
177+ optionselector: function (id, expanded, multiSelection) {
178+ if (typeof OptionSelector != 'undefined' && OptionSelector) {
179+ return new OptionSelector(id, expanded, multiSelection);
180+ }
181+ },
182+
183+ /**
184 * Gets the DOM element from a given selector
185 * @method element
186 * @return {Element} - The DOM element
187 * Gets the HTML element associated with an Ubuntu HTML5 JavaScript object
188 */
189 element: function(selector) {
190- return document.querySelector(selector);
191+ return document.querySelector(selector);
192 },
193
194 /**
195
196=== added file '0.1/ambiance/js/option-selector.js'
197--- 0.1/ambiance/js/option-selector.js 1970-01-01 00:00:00 +0000
198+++ 0.1/ambiance/js/option-selector.js 2013-12-16 18:05:54 +0000
199@@ -0,0 +1,205 @@
200+/*
201+ * Copyright (C) 2013 Adnane Belmadiaf <daker@ubuntu.com>
202+ * License granted by Canonical Limited
203+ *
204+ * This file is part of ubuntu-html5-theme.
205+ *
206+ * This package is free software; you can redistribute it and/or modify
207+ * it under the terms of the GNU Lesser General Public License as
208+ * published by the Free Software Foundation; either version 3 of the
209+ * License, or
210+ * (at your option) any later version.
211+
212+ * This package is distributed in the hope that it will be useful,
213+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
214+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
215+ * GNU General Public License for more details.
216+
217+ * You should have received a copy of the GNU Lesser General Public
218+ * License along with this program. If not, see
219+ * <http://www.gnu.org/licenses/>
220+ */
221+
222+/**
223+ * OptionSelector is a component displaying either a single selected value or expanded multiple choice with an optional image and subtext when not expanded, when expanding it opens a
224+ listing of all the possible values for selection with an additional option of always being expanded. If multiple choice is selected the list is expanded automatically.
225+
226+ * @class OptionSelector
227+ * @constructor
228+ * @namespace UbuntuUI
229+ * @example
230+ <section data-role="option-selector" id="OptionSelectorID">
231+ <ul>
232+ <li data-value="0">
233+ <p>Label 1</p>
234+ </li>
235+ <li data-value="1">
236+ <p>Label 2</p>
237+ </li>
238+ <li data-value="3">
239+ <p>Label 3</p>
240+ </li>
241+ </ul>
242+ </section>
243+
244+ JavaScript:
245+ UI.optionselector.METHOD();
246+*/
247+var OptionSelector = (function () {
248+
249+ var __values = "";
250+
251+ function OptionSelector (id, expanded, multiSelection) {
252+ this.currentIndex = 0;
253+ this.currentlyExpanded = false;
254+ this.expanded = typeof expanded !== 'undefined' ? expanded : false;
255+ this.multiSelection = typeof multiSelection !== 'undefined' ? multiSelection : false;
256+
257+ if (this.multiSelection)
258+ this.expanded = true;
259+
260+ this.optionselector = document.getElementById(id);
261+
262+ if (this.optionselector == null) {
263+ console.error('The OptionSelector with the ID #' + this.id + ' doesn\'t exist');
264+ return;
265+ }
266+
267+ this.optionselector_ul = this.optionselector.querySelectorAll('ul')[0];
268+ if (this.optionselector_ul == null)
269+ return;
270+
271+ if (this.optionselector_ul.length == 0)
272+ return;
273+
274+
275+ this.optionselector_ul_li = this.optionselector.querySelectorAll('li');
276+ if (this.optionselector_ul == null)
277+ return;
278+ if (this.optionselector_ul_li.length == 0)
279+ return;
280+
281+ [].forEach.call(this.optionselector_ul_li, function (elm) {
282+ elm.addEventListener('click', this.__onClicked.bind(this, elm), false);
283+ }.bind(this));
284+
285+ if (this.expanded) {
286+ this.__open();
287+ this.optionselector_ul_li[0].classList.add('active');
288+ }
289+ else {
290+ if (this.currentlyExpanded) {
291+ this.__open();
292+ this.optionselector_ul_li[0].classList.add('active');
293+ } else {
294+ this.__close(this.currentIndex);
295+ this.optionselector_ul_li[0].classList.add('closed');
296+ }
297+ }
298+ }
299+
300+ OptionSelector.prototype = {
301+
302+ /**
303+ * @private
304+ */
305+ __onClicked: function (elm, e) {
306+ __values = "";
307+ this.currentIndex = 0;
308+
309+ if (this.expanded) {
310+ if (!this.multiSelection) {
311+ [].forEach.call(this.optionselector_ul_li, function (elm) {
312+ elm.classList.remove('active');
313+ });
314+ elm.classList.toggle('active');
315+ }
316+ else {
317+ elm.classList.toggle('active');
318+ }
319+ }
320+ else {
321+
322+ for(i = 0, max = this.optionselector_ul_li.length; i < max; i++) {
323+ if (this.optionselector_ul_li[i]==elm) break;
324+ this.currentIndex++;
325+ }
326+
327+ if (this.currentlyExpanded) {
328+ this.__close(this.currentIndex);
329+ elm.classList.add('active');
330+ elm.classList.add('closed');
331+ elm.style.borderTop = '0';
332+ }
333+ else {
334+ elm.classList.add('active');
335+ elm.classList.remove('closed');
336+ this.__open();
337+ elm.style.borderTop = '1px solid #C7C7C7';
338+ }
339+ }
340+
341+ k = 0;
342+ for (i = 0, max = this.optionselector_ul_li.length; i < max; i++) {
343+ var li = this.optionselector_ul_li[i];
344+ if ((li.className).indexOf('active') > -1) {
345+ if (k === 0) {
346+ __values = li.getAttribute("data-value");
347+ } else {
348+ __values = __values + ", " + li.getAttribute("data-value");
349+ }
350+ k++;
351+ }
352+ }
353+
354+ if (!this.currentlyExpanded && !this.expanded) {
355+ this.__ClickEvent(elm);
356+ }
357+ else {
358+ if (this.expanded) {
359+ this.__ClickEvent(elm);
360+ }
361+ }
362+
363+ e.preventDefault();
364+ },
365+
366+ /**
367+ * @private
368+ */
369+ __ClickEvent: function (elm) {
370+ elm._evt = document.createEvent('Event');
371+ elm._evt.initEvent('onclicked', true, true);
372+ elm._evt.values = __values;
373+ elm.dispatchEvent(elm._evt);
374+ },
375+
376+ /**
377+ * @private
378+ */
379+ __open: function () {
380+ this.optionselector_ul.style['-webkit-transition-duration'] = '.4s';
381+ this.optionselector_ul.style.webkitTransform = 'translate3d(0, 0rem,0)';
382+ this.optionselector.style.height = 3.07*this.optionselector_ul_li.length + 'rem';
383+ this.currentlyExpanded = true;
384+ },
385+
386+ /**
387+ * @private
388+ */
389+ __close: function (currentIndex) {
390+ this.optionselector_ul.style['-webkit-transition-duration'] = '.4s';
391+ this.optionselector_ul.style.webkitTransform = 'translate3d(0,' + -3*currentIndex + 'rem,0)';
392+ this.optionselector.style.height = '3rem';
393+ [].forEach.call(this.optionselector_ul_li, function (elm) {
394+ elm.classList.remove('active');
395+ });
396+ this.currentlyExpanded = false;
397+ },
398+
399+ onClicked : function(callback){
400+ this.optionselector_ul.addEventListener("onclicked", callback);
401+ }
402+ };
403+ return OptionSelector;
404+})();
405
406=== added file 'examples/html5-theme/widgets/OptionSelector.html'
407--- examples/html5-theme/widgets/OptionSelector.html 1970-01-01 00:00:00 +0000
408+++ examples/html5-theme/widgets/OptionSelector.html 2013-12-16 18:05:54 +0000
409@@ -0,0 +1,165 @@
410+<!--
411+ Copyright (C) 2013 Adnane Belmadiaf <daker@ubuntu.com>
412+ License granted by Canonical Limited
413+
414+ This file is part of ubuntu-html5-theme.
415+
416+ This package is free software; you can redistribute it and/or modify
417+ it under the terms of the GNU Lesser General Public License as
418+ published by the Free Software Foundation; either version 3 of the
419+ License, or
420+ (at your option) any later version.
421+
422+ This package is distributed in the hope that it will be useful,
423+ but WITHOUT ANY WARRANTY; without even the implied warranty of
424+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
425+ GNU General Public License for more details.
426+
427+ You should have received a copy of the GNU Lesser General Public
428+ License along with this program. If not, see
429+ <http://www.gnu.org/licenses/>.
430+-->
431+
432+<!DOCTYPE html>
433+<html>
434+<head>
435+ <meta charset="utf-8" />
436+ <meta name="copyright" content="Adnane Belmadiaf <daker@ubuntu.com>">
437+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
438+ <title>Ubuntu UI HTML5 Theme: ListItems</title>
439+ <link href="../../../0.1/ambiance/css/appTemplate.css" rel="stylesheet" type="text/css" />
440+ <!-- Ubuntu UI javascript imports - Ambiance theme -->
441+ <script src="../../../0.1/ambiance/js/option-selector.js"></script>
442+ <script src="../../../0.1/ambiance/js/fast-buttons.js"></script>
443+ <script src="../../../0.1/ambiance/js/core.js"></script>
444+ <script src="../../../0.1/ambiance/js/pagestacks.js"></script>
445+ <script>
446+ var UI = new UbuntuUI();
447+ window.onload = function() {
448+ UI.init();
449+ os1 = UI.optionselector('os1');
450+
451+ os1.onClicked(function (e) {
452+ console.log("optionselector1 values: " + e.values);
453+ })
454+
455+ os2 = UI.optionselector('os2', expanded=false, multiSelection=true);
456+
457+ os2.onClicked(function (e) {
458+ console.log("optionselector2 values: " + e.values);
459+ })
460+
461+ os3 = UI.optionselector('os3', expanded=true, multiSelection=false);
462+
463+ os3.onClicked(function (e) {
464+ console.log("optionselector3 values: " + e.values);
465+ })
466+ };
467+ </script>
468+</head>
469+<body>
470+ <div data-role="page">
471+ <header data-role="header">
472+ <nav data-role="navbar" class="tabs">
473+ <div class="tabs-inner">
474+ <ul data-role="tabs">
475+ <li class="active" data-role="tab">
476+ <a href="#item1">Tab 1</a>
477+ </li>
478+ <li class="inactive" data-role="tab">
479+ <a href="#item2">Tab 2</a>
480+ </li>
481+ <li class="inactive" data-role="tab">
482+ <a href="#item3">Tab 3</a>
483+ </li>
484+ </ul>
485+ </div>
486+ </nav>
487+ </header>
488+
489+ <div data-role="content">
490+ <div class="inset" style="margin: 15px;">
491+ <h1>Collapsed</h1>
492+ <section data-role="option-selector" id="os1">
493+ <ul>
494+ <li data-value="0">
495+ <aside>
496+ <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
497+ <p>Label 1</p>
498+ </li>
499+ <li data-value="1">
500+ <aside>
501+ <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
502+ <p>Label 2</p>
503+ </li>
504+ <li data-value="3">
505+ <aside>
506+ <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
507+ <p>Label 3</p>
508+ </li>
509+ <li data-value="4">
510+ <aside>
511+ <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
512+ <p>Label 4</p>
513+ </li>
514+ <li data-value="5">
515+ <aside>
516+ <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
517+ <p>Label 5</p>
518+ </li>
519+ </ul>
520+ </section>
521+ </div>
522+ <div class="inset" style="margin: 15px;">
523+ <h1>Expanded with a multiple selections</h1>
524+ <section data-role="option-selector" id="os2">
525+ <ul>
526+ <li data-value="0">
527+ <p>Label 1</p>
528+ <p>Subtext 1</p>
529+ </li>
530+ <li data-value="1">
531+ <p>Label 2</p>
532+ <p>Subtext 2</p>
533+ </li>
534+ <li data-value="3">
535+ <p>Label 3</p>
536+ <p>Subtext 3</p>
537+ </li>
538+ <li data-value="4">
539+ <p>Label 4</p>
540+ <p>Subtext 4</p>
541+ </li>
542+ <li data-value="5">
543+ <p>Label 5</p>
544+ <p>Subtext 5</p>
545+ </li>
546+ </ul>
547+ </section>
548+ </div>
549+ <div class="inset" style="margin: 15px;">
550+ <h1>Expanded with a unique selection</h1>
551+ <section data-role="option-selector" id="os3">
552+ <ul>
553+ <li data-value="0">
554+ <p>Label 1</p>
555+ </li>
556+ <li data-value="1">
557+ <p>Label 2</p>
558+ </li>
559+ <li data-value="3">
560+ <p>Label 3</p>
561+ </li>
562+ <li data-value="4">
563+ <p>Label 4</p>
564+ </li>
565+ <li data-value="5">
566+ <p>Label 5</p>
567+ </li>
568+ </ul>
569+ </section>
570+ </div>
571+ </div>
572+ </div>
573+</body>
574+</html>
575\ No newline at end of file

Subscribers

People subscribed via source and target branches