2 * jQuery Mobile Widget @VERSION
4 * This software is licensed under the MIT licence (as defined by the OSI at
5 * http://www.opensource.org/licenses/mit-license.php)
7 * ***************************************************************************
8 * Copyright (C) 2011 by Intel Corporation Ltd.
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 * ***************************************************************************
29 * Authors: Kalyan Kondapally <kalyan.kondapally@intel.com>,
30 * Elliot Smith <elliot.smith@intel.com>
33 // Widget which turns a list into a "swipe list":
34 // i.e. each list item has a sliding "cover" which can be swiped
35 // to the right (to reveal buttons underneath) or left (to
36 // cover the buttons again). Clicking on a button under a swipelist
37 // also moves the cover back to the left.
39 // To create a swipelist, you need markup like this:
42 // <ul data-role="swipelist"><br/>
44 // <div class="ui-grid-b"><br/>
45 // <div class="ui-block-a"><br/>
46 // <a href="#" data-role="button" data-theme="a">Twitter</a><br/>
48 // <div class="ui-block-b"><br/>
49 // <a href="#" data-role="button" data-theme="b">FaceBook</a><br/>
51 // <div class="ui-block-c"><br/>
52 // <a href="#" data-role="button" data-theme="c">Google+</a><br/>
55 // <div data-role="swipelist-item-cover">Nigel</div><br/>
61 // In this case, the cover is over a grid of buttons;
62 // but it is should also be possible to use other types of markup under the
65 // Note the use of a separate div, parented by the li element, marked
66 // up with data-role="swipelist-item-cover". This div will usually
67 // contain text. If you want other elements in your swipelist covers,
68 // you may need to style them yourself. Because the covers aren't
69 // technically list items, you may need to do some work to make them
72 // WARNING: This doesn't work well inside a scrollview widget, as
73 // the touch events currently interfere with each other badly (e.g.
74 // a swipe will work but cause a scroll as well).
76 // Theme: default is to use the theme on the target element,
77 // theme passed in options, parent theme, or 'c' if none of the above.
78 // If list items are themed individually, the cover will pick up the
79 // theme of the list item which is its parent.
83 // animationComplete: Triggered by a cover when it finishes sliding
84 // (to either the right or left).
87 $.widget("tizen.swipelist", $.mobile.widget, {
92 _create: function () {
93 // use the theme set on the element, set in options,
94 // the parent theme, or 'c' (in that order of preference)
95 var theme = this.element.jqmData('theme') ||
97 this.element.parent().jqmData('theme') ||
100 this.options.theme = theme;
105 refresh: function () {
112 defaultCoverTheme = 'ui-body-' + this.options.theme;
114 // swipelist is a listview
115 if (!this.element.hasClass('ui-listview')) {
116 this.element.listview();
119 this.element.addClass('ui-swipelist');
121 // get the list item covers
122 covers = this.element.find(':jqmData(role="swipelist-item-cover")');
124 covers.each(function () {
126 var coverTheme = defaultCoverTheme;
128 // get the parent li element and add classes
129 var item = cover.closest('li');
131 // add swipelist CSS classes
132 item.addClass('ui-swipelist-item');
134 cover.addClass('ui-swipelist-item-cover');
136 // set swatch on cover: if the nearest list item has
137 // a swatch set on it, that will be used; otherwise, use
138 // the swatch set for the swipelist
139 var itemHasThemeClass = item.attr('class')
140 .match(/ui\-body\-[a-z]|ui\-bar\-[a-z]/);
142 if (itemHasThemeClass) {
143 coverTheme = itemHasThemeClass[0];
146 cover.addClass(coverTheme);
148 // wrap inner HTML (so it can potentially be styled)
149 if (cover.has('.ui-swipelist-item-cover-inner').length === 0) {
150 cover.wrapInner($('<span/>').addClass('ui-swipelist-item-cover-inner'));
153 // bind to swipe events on the cover and the item
154 if (!(cover.data('animateRight') && cover.data('animateLeft'))) {
155 cover.data('animateRight', function () {
156 self._animateCover(cover, 100);
159 cover.data('animateLeft', function () {
160 self._animateCover(cover, 0);
164 // bind to synthetic events
165 item.bind('swipeleft', cover.data('animateLeft'));
166 cover.bind('swiperight', cover.data('animateRight'));
168 // any clicks on buttons inside the item also trigger
169 // the cover to slide back to the left
170 item.find('.ui-btn').bind('vclick', cover.data('animateLeft'));
174 _cleanupDom: function () {
179 defaultCoverTheme = 'ui-body-' + this.options.theme;
181 this.element.removeClass('ui-swipelist');
183 // get the list item covers
184 covers = this.element.find(':jqmData(role="swipelist-item-cover")');
186 covers.each(function () {
188 var coverTheme = defaultCoverTheme;
191 // get the parent li element and add classes
192 var item = cover.closest('li');
194 // remove swipelist CSS classes
195 item.removeClass('ui-swipelist-item');
196 cover.removeClass('ui-swipelist-item-cover');
198 // remove swatch from cover: if the nearest list item has
199 // a swatch set on it, that will be used; otherwise, use
200 // the swatch set for the swipelist
201 var itemClass = item.attr('class');
202 var itemHasThemeClass = itemClass &&
203 itemClass.match(/ui\-body\-[a-z]|ui\-bar\-[a-z]/);
205 if (itemHasThemeClass) {
206 coverTheme = itemHasThemeClass[0];
209 cover.removeClass(coverTheme);
211 // remove wrapper HTML
212 wrapper = cover.find('.ui-swipelist-item-cover-inner');
214 wrapper.children().unwrap();
216 text = wrapper.text()
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'));
228 // unbind clicks on buttons inside the item
229 item.find('.ui-btn').unbind('vclick', cover.data('animateLeft'));
231 cover.data('animateRight', null);
232 cover.data('animateLeft', null);
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
241 // once the cover animation is done, the cover emits an
242 // animationComplete event
243 _animateCover: function (cover, leftPercentage) {
244 var animationOptions = {
248 complete: function () {
249 cover.trigger('animationComplete');
255 cover.animate({left: '' + leftPercentage + '%'}, animationOptions);
258 destroy: function () {
264 $(document).bind("pagecreate", function (e) {
265 $(e.target).find(":jqmData(role='swipelist')").swipelist();