0fab979694eb09af4f04b9be002eda6c6e65e62c
[platform/framework/web/web-ui-fw.git] / src / widgets / swipelist / js / jquery.mobile.tizen.swipelist.js
1 /*
2  * jQuery Mobile Widget @VERSION
3  *
4  * This software is licensed under the MIT licence (as defined by the OSI at
5  * http://www.opensource.org/licenses/mit-license.php)
6  *
7  * ***************************************************************************
8  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
9  * Copyright (c) 2011 by Intel Corporation Ltd.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  * ***************************************************************************
29  *
30  * Authors: Kalyan Kondapally <kalyan.kondapally@intel.com>,
31  *          Elliot Smith <elliot.smith@intel.com>
32  */
33
34 // Widget which turns a list into a "swipe list":
35 // i.e. each list item has a sliding "cover" which can be swiped
36 // to the right (to reveal buttons underneath) or left (to
37 // cover the buttons again). Clicking on a button under a swipelist
38 // also moves the cover back to the left.
39 //
40 // To create a swipelist, you need markup like this:
41 //
42 // <pre>
43 // &lt;ul data-role="swipelist"&gt;<br/>
44 //     &lt;li&gt;<br/>
45 //         &lt;div class="ui-grid-b"&gt;<br/>
46 //             &lt;div class="ui-block-a"&gt;<br/>
47 //                 &lt;a href="#" data-role="button" data-theme="a"&gt;Twitter&lt;/a&gt;<br/>
48 //             &lt;/div&gt;<br/>
49 //             &lt;div class="ui-block-b"&gt;<br/>
50 //                 &lt;a href="#" data-role="button" data-theme="b"&gt;FaceBook&lt;/a&gt;<br/>
51 //             &lt;/div&gt;<br/>
52 //             &lt;div class="ui-block-c"&gt;<br/>
53 //                 &lt;a href="#" data-role="button" data-theme="c"&gt;Google+&lt;/a&gt;<br/>
54 //             &lt;/div&gt;<br/>
55 //         &lt;/div&gt;<br/>
56 //         &lt;div data-role="swipelist-item-cover"&gt;Nigel&lt;/div&gt;<br/>
57 //     &lt;/li&gt;<br/>
58 //     ...<br/>
59 // &lt;/ul&gt;
60 // </pre>
61 //
62 // In this case, the cover is over a grid of buttons;
63 // but it is should also be possible to use other types of markup under the
64 // list items.
65 //
66 // Note the use of a separate div, parented by the li element, marked
67 // up with data-role="swipelist-item-cover". This div will usually
68 // contain text. If you want other elements in your swipelist covers,
69 // you may need to style them yourself. Because the covers aren't
70 // technically list items, you may need to do some work to make them
71 // look right.
72 //
73 // WARNING: This doesn't work well inside a scrollview widget, as
74 // the touch events currently interfere with each other badly (e.g.
75 // a swipe will work but cause a scroll as well).
76 //
77 // Theme: default is to use the theme on the target element,
78 // theme passed in options, parent theme, or 'c' if none of the above.
79 // If list items are themed individually, the cover will pick up the
80 // theme of the list item which is its parent.
81 //
82 // Events:
83 //
84 //   animationComplete: Triggered by a cover when it finishes sliding
85 //                      (to either the right or left).
86 (function ($) {
87
88         $.widget("tizen.swipelist", $.mobile.widget, {
89                 options: {
90                         theme: null
91                 },
92
93                 _create: function () {
94                         // use the theme set on the element, set in options,
95                         // the parent theme, or 'c' (in that order of preference)
96                         var theme = this.element.jqmData('theme') ||
97                                 this.options.theme ||
98                                 this.element.parent().jqmData('theme') ||
99                                 'c';
100
101                         this.options.theme = theme;
102                         this.refresh();
103                 },
104
105                 refresh: function () {
106                         this._cleanupDom();
107
108                         var self = this,
109                                 defaultCoverTheme,
110                                 covers;
111
112                         defaultCoverTheme = 'ui-body-' + this.options.theme;
113
114                         // swipelist is a listview
115                         if (!this.element.hasClass('ui-listview')) {
116                                 this.element.listview();
117                         }
118
119                         this.element.addClass('ui-swipelist');
120
121                         // get the list item covers
122                         covers = this.element.find(':jqmData(role="swipelist-item-cover")');
123
124                         covers.each(function () {
125                                 var cover = $(this),
126                                         coverTheme = defaultCoverTheme,
127                                 // get the parent li element and add classes
128                                         item = cover.closest('li'),
129                                         itemHasThemeClass;
130
131                                 // add swipelist CSS classes
132                                 item.addClass('ui-swipelist-item');
133                                 cover.addClass('ui-swipelist-item-cover');
134
135                                 // set swatch on cover: if the nearest list item has
136                                 // a swatch set on it, that will be used; otherwise, use
137                                 // the swatch set for the swipelist
138                                 itemHasThemeClass = item.attr('class')
139                                         .match(/ui\-body\-[a-z]|ui\-bar\-[a-z]/);
140
141                                 if (itemHasThemeClass) {
142                                         coverTheme = itemHasThemeClass[0];
143                                 }
144
145                                 cover.addClass(coverTheme);
146
147                                 // wrap inner HTML (so it can potentially be styled)
148                                 if (cover.has('.ui-swipelist-item-cover-inner').length === 0) {
149                                         cover.wrapInner($('<span/>').addClass('ui-swipelist-item-cover-inner'));
150                                 }
151
152                                 // bind to swipe events on the cover and the item
153                                 if (!(cover.data('animateRight') && cover.data('animateLeft'))) {
154                                         cover.data('animateRight', function () {
155                                                 self._animateCover(cover, 100);
156                                         });
157
158                                         cover.data('animateLeft', function () {
159                                                 self._animateCover(cover, 0);
160                                         });
161                                 }
162
163                                 // bind to synthetic events
164                                 item.bind('swipeleft', cover.data('animateLeft'));
165                                 cover.bind('swiperight', cover.data('animateRight'));
166
167                                 // any clicks on buttons inside the item also trigger
168                                 // the cover to slide back to the left
169                                 item.find('.ui-btn').bind('vclick', cover.data('animateLeft'));
170                         });
171                 },
172
173                 _cleanupDom: function () {
174
175                         var self = this,
176                                 defaultCoverTheme,
177                                 covers;
178
179                         defaultCoverTheme = 'ui-body-' + this.options.theme;
180
181                         this.element.removeClass('ui-swipelist');
182
183                         // get the list item covers
184                         covers = this.element.find(':jqmData(role="swipelist-item-cover")');
185
186                         covers.each(function () {
187                                 var cover = $(this),
188                                         coverTheme = defaultCoverTheme,
189                                         text,
190                                         wrapper,
191                                         // get the parent li element and add classes
192                                         item = cover.closest('li'),
193                                         itemClass,
194                                         itemHasThemeClass;
195
196                                         // remove swipelist CSS classes
197                                 item.removeClass('ui-swipelist-item');
198                                 cover.removeClass('ui-swipelist-item-cover');
199
200                                 // remove swatch from cover: if the nearest list item has
201                                 // a swatch set on it, that will be used; otherwise, use
202                                 // the swatch set for the swipelist
203                                 itemClass = item.attr('class');
204                                 itemHasThemeClass = itemClass &&
205                                         itemClass.match(/ui\-body\-[a-z]|ui\-bar\-[a-z]/);
206
207                                 if (itemHasThemeClass) {
208                                         coverTheme = itemHasThemeClass[0];
209                                 }
210
211                                 cover.removeClass(coverTheme);
212
213                                 // remove wrapper HTML
214                                 wrapper = cover.find('.ui-swipelist-item-cover-inner');
215                                 wrapper.children().unwrap();
216                                 text = wrapper.text();
217
218                                 if (text) {
219                                         cover.append(text);
220                                         wrapper.remove();
221                                 }
222
223                                 // unbind swipe events
224                                 if (cover.data('animateRight') && cover.data('animateLeft')) {
225                                         cover.unbind('swiperight', cover.data('animateRight'));
226                                         item.unbind('swipeleft', cover.data('animateLeft'));
227
228                                         // unbind clicks on buttons inside the item
229                                         item.find('.ui-btn').unbind('vclick', cover.data('animateLeft'));
230
231                                         cover.data('animateRight', null);
232                                         cover.data('animateLeft', null);
233                                 }
234                         });
235                 },
236
237                 // NB I tried to use CSS animations for this, but the performance
238                 // and appearance was terrible on Android 2.2 browser;
239                 // so I reverted to jQuery animations
240                 //
241                 // once the cover animation is done, the cover emits an
242                 // animationComplete event
243                 _animateCover: function (cover, leftPercentage) {
244                         var animationOptions = {
245                                 easing: 'linear',
246                                 duration: 'fast',
247                                 queue: true,
248                                 complete: function () {
249                                         cover.trigger('animationComplete');
250                                 }
251                         };
252
253                         cover.stop();
254                         cover.clearQueue();
255                         cover.animate({left: leftPercentage + '%'}, animationOptions);
256                 },
257
258                 destroy: function () {
259                         this._cleanupDom();
260                 }
261
262         });
263
264         $(document).bind("pagecreate", function (e) {
265                 $(e.target).find(":jqmData(role='swipelist')").swipelist();
266         });
267
268 }(jQuery));