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
=== modified file '0.1/ambiance/css/default.css'
--- 0.1/ambiance/css/default.css 2013-11-27 16:48:37 +0000
+++ 0.1/ambiance/css/default.css 2013-12-16 18:05:54 +0000
@@ -34,6 +34,8 @@
34@import url("toolbars.css");34@import url("toolbars.css");
35@import url("shapes.css");35@import url("shapes.css");
36@import url("indexbar.css");36@import url("indexbar.css");
37@import url("option-selector.css");
38
3739
38* {40* {
39 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);41 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
4042
=== added file '0.1/ambiance/css/option-selector.css'
--- 0.1/ambiance/css/option-selector.css 1970-01-01 00:00:00 +0000
+++ 0.1/ambiance/css/option-selector.css 2013-12-16 18:05:54 +0000
@@ -0,0 +1,137 @@
1/*
2 * Copyright (C) 2013 Adnane Belmadiaf <daker@ubuntu.com>
3 * License granted by Canonical Limited
4 *
5 * This file is part of ubuntu-html5-theme.
6 *
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
10 * License, or
11 * (at your option) any later version.
12
13 * This package is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 */
22
23[data-role="option-selector"] {
24 width: 100%;
25 height: auto;
26 margin: 0 auto;
27 border: 1px solid #C7C7C7;
28 overflow: hidden;
29 -webkit-transition: height 0.4s;
30 transition: height 0.4s;
31 margin-top: 15px;
32 margin-bottom: 15px;
33 -webkit-border-radius: 10px;
34 -moz-border-radius: 10px;
35 border-radius: 10px;
36 -webkit-box-shadow: inset 0 2px 2px 0 #D5D5D5;
37 box-shadow: inset 0 2px 2px 0 #D5D5D5;
38}
39
40[data-role="option-selector"] li {
41 text-decoration: none;
42 color: #787878;
43 display: block;
44 height: 3rem;
45 position: relative;
46 line-height: 3rem;
47 padding-left: 1rem;
48 padding-right: 1.5rem;
49 border: none;
50 border-top: 1px solid #C7C7C7;
51 font-size: 0.9rem;
52 white-space: nowrap;
53 overflow: hidden;
54 text-overflow: ellipsis;
55 cursor: pointer;
56}
57
58[data-role="option-selector"] ul li:first-child {
59 border-top: 0!important;
60}
61
62[data-role="option-selector"] li.active:after{
63 background: transparent url(../img/tick@30.png) no-repeat center center;
64 background-size: 15px 15px;
65 display: block;
66 position: absolute;
67 width: 2rem;
68 height: 3rem;
69 right: 0.5rem;
70 content: "";
71 top: 0;
72}
73
74[data-role="option-selector"] li.closed:after {
75 background: transparent url(../img/chevron_down@30.png) no-repeat center center;
76 background-size: 15px 15px;
77 display: block;
78 position: absolute;
79 width: 2rem;
80 height: 3rem;
81 right: 0.5rem;
82 content: "";
83 top: 0;
84}
85
86[data-role="option-selector"] li aside {
87 float: left;
88 margin: -1.2em 0 0 0;
89 max-width: 100%;
90 vertical-align: bottom;
91 position: relative;
92 top: 50%;
93 z-index: 2;
94}
95
96[data-role="option-selector"] li aside img {
97 border-radius: 6px;
98 margin-bottom: 0;
99 float: left;
100}
101
102[data-role="option-selector"] li aside:after {
103 background: url(../img/ubuntushape_medium_radius_idle@18.png) no-repeat;
104 background-size: 100% 100%;
105 content: ' ';
106 width: 100%;
107 height: 100%;
108 position: absolute;
109 top: 0;
110 left: 0;
111}
112
113[data-role="option-selector"] li aside+p {
114 padding-left: 1rem;
115}
116
117[data-role="option-selector"] li p {
118 white-space: nowrap;
119 overflow: hidden;
120 text-overflow: ellipsis;
121 border: none;
122 display: block;
123 color: #787878;
124 font-size: 0.9rem;
125 padding-top: 0.5rem;
126 line-height: 1rem;
127}
128
129[data-role="option-selector"] li p:only-child,
130[data-role="option-selector"] li p:first-of-type:last-of-type {
131 line-height: 2rem;
132}
133
134[data-role="option-selector"] li p+p {
135 padding-top: 0.2rem;
136 font-size: 0.7rem;
137}
0\ No newline at end of file138\ No newline at end of file
1139
=== modified file '0.1/ambiance/img/back@18.png'
2Binary 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 differ140Binary 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
=== added file '0.1/ambiance/img/chevron_down@30.png'
3Binary 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 differ141Binary 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
=== modified file '0.1/ambiance/img/tick@30.png'
4Binary 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 differ142Binary 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
=== modified file '0.1/ambiance/js/core.js'
--- 0.1/ambiance/js/core.js 2013-12-11 10:13:17 +0000
+++ 0.1/ambiance/js/core.js 2013-12-16 18:05:54 +0000
@@ -344,13 +344,27 @@
344 },344 },
345345
346 /**346 /**
347 * Gets an Ubuntu Option Selector
348 * @method optionselector
349 * @param {ID} id - The element's id attrubute
350 * @param {Boolean} expanded - Specifies whether the list is always expanded
351 * @param {Boolean} multiSelection - If multiple choice selection is enabled the list is always expanded.
352 * @return {OptionSelector}
353 */
354 optionselector: function (id, expanded, multiSelection) {
355 if (typeof OptionSelector != 'undefined' && OptionSelector) {
356 return new OptionSelector(id, expanded, multiSelection);
357 }
358 },
359
360 /**
347 * Gets the DOM element from a given selector361 * Gets the DOM element from a given selector
348 * @method element362 * @method element
349 * @return {Element} - The DOM element363 * @return {Element} - The DOM element
350 * Gets the HTML element associated with an Ubuntu HTML5 JavaScript object364 * Gets the HTML element associated with an Ubuntu HTML5 JavaScript object
351 */365 */
352 element: function(selector) {366 element: function(selector) {
353 return document.querySelector(selector);367 return document.querySelector(selector);
354 },368 },
355369
356 /**370 /**
357371
=== added file '0.1/ambiance/js/option-selector.js'
--- 0.1/ambiance/js/option-selector.js 1970-01-01 00:00:00 +0000
+++ 0.1/ambiance/js/option-selector.js 2013-12-16 18:05:54 +0000
@@ -0,0 +1,205 @@
1/*
2 * Copyright (C) 2013 Adnane Belmadiaf <daker@ubuntu.com>
3 * License granted by Canonical Limited
4 *
5 * This file is part of ubuntu-html5-theme.
6 *
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
10 * License, or
11 * (at your option) any later version.
12
13 * This package is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>
21 */
22
23/**
24 * 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
25 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.
26
27 * @class OptionSelector
28 * @constructor
29 * @namespace UbuntuUI
30 * @example
31 <section data-role="option-selector" id="OptionSelectorID">
32 <ul>
33 <li data-value="0">
34 <p>Label 1</p>
35 </li>
36 <li data-value="1">
37 <p>Label 2</p>
38 </li>
39 <li data-value="3">
40 <p>Label 3</p>
41 </li>
42 </ul>
43 </section>
44
45 JavaScript:
46 UI.optionselector.METHOD();
47*/
48var OptionSelector = (function () {
49
50 var __values = "";
51
52 function OptionSelector (id, expanded, multiSelection) {
53 this.currentIndex = 0;
54 this.currentlyExpanded = false;
55 this.expanded = typeof expanded !== 'undefined' ? expanded : false;
56 this.multiSelection = typeof multiSelection !== 'undefined' ? multiSelection : false;
57
58 if (this.multiSelection)
59 this.expanded = true;
60
61 this.optionselector = document.getElementById(id);
62
63 if (this.optionselector == null) {
64 console.error('The OptionSelector with the ID #' + this.id + ' doesn\'t exist');
65 return;
66 }
67
68 this.optionselector_ul = this.optionselector.querySelectorAll('ul')[0];
69 if (this.optionselector_ul == null)
70 return;
71
72 if (this.optionselector_ul.length == 0)
73 return;
74
75
76 this.optionselector_ul_li = this.optionselector.querySelectorAll('li');
77 if (this.optionselector_ul == null)
78 return;
79 if (this.optionselector_ul_li.length == 0)
80 return;
81
82 [].forEach.call(this.optionselector_ul_li, function (elm) {
83 elm.addEventListener('click', this.__onClicked.bind(this, elm), false);
84 }.bind(this));
85
86 if (this.expanded) {
87 this.__open();
88 this.optionselector_ul_li[0].classList.add('active');
89 }
90 else {
91 if (this.currentlyExpanded) {
92 this.__open();
93 this.optionselector_ul_li[0].classList.add('active');
94 } else {
95 this.__close(this.currentIndex);
96 this.optionselector_ul_li[0].classList.add('closed');
97 }
98 }
99 }
100
101 OptionSelector.prototype = {
102
103 /**
104 * @private
105 */
106 __onClicked: function (elm, e) {
107 __values = "";
108 this.currentIndex = 0;
109
110 if (this.expanded) {
111 if (!this.multiSelection) {
112 [].forEach.call(this.optionselector_ul_li, function (elm) {
113 elm.classList.remove('active');
114 });
115 elm.classList.toggle('active');
116 }
117 else {
118 elm.classList.toggle('active');
119 }
120 }
121 else {
122
123 for(i = 0, max = this.optionselector_ul_li.length; i < max; i++) {
124 if (this.optionselector_ul_li[i]==elm) break;
125 this.currentIndex++;
126 }
127
128 if (this.currentlyExpanded) {
129 this.__close(this.currentIndex);
130 elm.classList.add('active');
131 elm.classList.add('closed');
132 elm.style.borderTop = '0';
133 }
134 else {
135 elm.classList.add('active');
136 elm.classList.remove('closed');
137 this.__open();
138 elm.style.borderTop = '1px solid #C7C7C7';
139 }
140 }
141
142 k = 0;
143 for (i = 0, max = this.optionselector_ul_li.length; i < max; i++) {
144 var li = this.optionselector_ul_li[i];
145 if ((li.className).indexOf('active') > -1) {
146 if (k === 0) {
147 __values = li.getAttribute("data-value");
148 } else {
149 __values = __values + ", " + li.getAttribute("data-value");
150 }
151 k++;
152 }
153 }
154
155 if (!this.currentlyExpanded && !this.expanded) {
156 this.__ClickEvent(elm);
157 }
158 else {
159 if (this.expanded) {
160 this.__ClickEvent(elm);
161 }
162 }
163
164 e.preventDefault();
165 },
166
167 /**
168 * @private
169 */
170 __ClickEvent: function (elm) {
171 elm._evt = document.createEvent('Event');
172 elm._evt.initEvent('onclicked', true, true);
173 elm._evt.values = __values;
174 elm.dispatchEvent(elm._evt);
175 },
176
177 /**
178 * @private
179 */
180 __open: function () {
181 this.optionselector_ul.style['-webkit-transition-duration'] = '.4s';
182 this.optionselector_ul.style.webkitTransform = 'translate3d(0, 0rem,0)';
183 this.optionselector.style.height = 3.07*this.optionselector_ul_li.length + 'rem';
184 this.currentlyExpanded = true;
185 },
186
187 /**
188 * @private
189 */
190 __close: function (currentIndex) {
191 this.optionselector_ul.style['-webkit-transition-duration'] = '.4s';
192 this.optionselector_ul.style.webkitTransform = 'translate3d(0,' + -3*currentIndex + 'rem,0)';
193 this.optionselector.style.height = '3rem';
194 [].forEach.call(this.optionselector_ul_li, function (elm) {
195 elm.classList.remove('active');
196 });
197 this.currentlyExpanded = false;
198 },
199
200 onClicked : function(callback){
201 this.optionselector_ul.addEventListener("onclicked", callback);
202 }
203 };
204 return OptionSelector;
205})();
0206
=== added file 'examples/html5-theme/widgets/OptionSelector.html'
--- examples/html5-theme/widgets/OptionSelector.html 1970-01-01 00:00:00 +0000
+++ examples/html5-theme/widgets/OptionSelector.html 2013-12-16 18:05:54 +0000
@@ -0,0 +1,165 @@
1<!--
2 Copyright (C) 2013 Adnane Belmadiaf <daker@ubuntu.com>
3 License granted by Canonical Limited
4
5 This file is part of ubuntu-html5-theme.
6
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
10 License, or
11 (at your option) any later version.
12
13 This package is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this program. If not, see
20 <http://www.gnu.org/licenses/>.
21-->
22
23<!DOCTYPE html>
24<html>
25<head>
26 <meta charset="utf-8" />
27 <meta name="copyright" content="Adnane Belmadiaf <daker@ubuntu.com>">
28 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
29 <title>Ubuntu UI HTML5 Theme: ListItems</title>
30 <link href="../../../0.1/ambiance/css/appTemplate.css" rel="stylesheet" type="text/css" />
31 <!-- Ubuntu UI javascript imports - Ambiance theme -->
32 <script src="../../../0.1/ambiance/js/option-selector.js"></script>
33 <script src="../../../0.1/ambiance/js/fast-buttons.js"></script>
34 <script src="../../../0.1/ambiance/js/core.js"></script>
35 <script src="../../../0.1/ambiance/js/pagestacks.js"></script>
36 <script>
37 var UI = new UbuntuUI();
38 window.onload = function() {
39 UI.init();
40 os1 = UI.optionselector('os1');
41
42 os1.onClicked(function (e) {
43 console.log("optionselector1 values: " + e.values);
44 })
45
46 os2 = UI.optionselector('os2', expanded=false, multiSelection=true);
47
48 os2.onClicked(function (e) {
49 console.log("optionselector2 values: " + e.values);
50 })
51
52 os3 = UI.optionselector('os3', expanded=true, multiSelection=false);
53
54 os3.onClicked(function (e) {
55 console.log("optionselector3 values: " + e.values);
56 })
57 };
58 </script>
59</head>
60<body>
61 <div data-role="page">
62 <header data-role="header">
63 <nav data-role="navbar" class="tabs">
64 <div class="tabs-inner">
65 <ul data-role="tabs">
66 <li class="active" data-role="tab">
67 <a href="#item1">Tab 1</a>
68 </li>
69 <li class="inactive" data-role="tab">
70 <a href="#item2">Tab 2</a>
71 </li>
72 <li class="inactive" data-role="tab">
73 <a href="#item3">Tab 3</a>
74 </li>
75 </ul>
76 </div>
77 </nav>
78 </header>
79
80 <div data-role="content">
81 <div class="inset" style="margin: 15px;">
82 <h1>Collapsed</h1>
83 <section data-role="option-selector" id="os1">
84 <ul>
85 <li data-value="0">
86 <aside>
87 <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
88 <p>Label 1</p>
89 </li>
90 <li data-value="1">
91 <aside>
92 <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
93 <p>Label 2</p>
94 </li>
95 <li data-value="3">
96 <aside>
97 <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
98 <p>Label 3</p>
99 </li>
100 <li data-value="4">
101 <aside>
102 <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
103 <p>Label 4</p>
104 </li>
105 <li data-value="5">
106 <aside>
107 <img alt="placeholder" src="../../../0.1/ambiance/img/avatar_contacts_list@8.png"></aside>
108 <p>Label 5</p>
109 </li>
110 </ul>
111 </section>
112 </div>
113 <div class="inset" style="margin: 15px;">
114 <h1>Expanded with a multiple selections</h1>
115 <section data-role="option-selector" id="os2">
116 <ul>
117 <li data-value="0">
118 <p>Label 1</p>
119 <p>Subtext 1</p>
120 </li>
121 <li data-value="1">
122 <p>Label 2</p>
123 <p>Subtext 2</p>
124 </li>
125 <li data-value="3">
126 <p>Label 3</p>
127 <p>Subtext 3</p>
128 </li>
129 <li data-value="4">
130 <p>Label 4</p>
131 <p>Subtext 4</p>
132 </li>
133 <li data-value="5">
134 <p>Label 5</p>
135 <p>Subtext 5</p>
136 </li>
137 </ul>
138 </section>
139 </div>
140 <div class="inset" style="margin: 15px;">
141 <h1>Expanded with a unique selection</h1>
142 <section data-role="option-selector" id="os3">
143 <ul>
144 <li data-value="0">
145 <p>Label 1</p>
146 </li>
147 <li data-value="1">
148 <p>Label 2</p>
149 </li>
150 <li data-value="3">
151 <p>Label 3</p>
152 </li>
153 <li data-value="4">
154 <p>Label 4</p>
155 </li>
156 <li data-value="5">
157 <p>Label 5</p>
158 </li>
159 </ul>
160 </section>
161 </div>
162 </div>
163 </div>
164</body>
165</html>
0\ No newline at end of file166\ No newline at end of file

Subscribers

People subscribed via source and target branches