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) 2000 - 2011 Samsung Electronics Co., Ltd.
9 * Copyright (c) 2011 by Intel Corporation Ltd.
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:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
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 * ***************************************************************************
30 * Authors: Kalyan Kondapally <kalyan.kondapally@intel.com>,
31 * Elliot Smith <elliot.smith@intel.com>
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.
40 // To create a swipelist, you need markup like this:
43 // <ul data-role="swipelist"><br/>
45 // <div class="ui-grid-b"><br/>
46 // <div class="ui-block-a"><br/>
47 // <a href="#" data-role="button" data-theme="a">Twitter</a><br/>
49 // <div class="ui-block-b"><br/>
50 // <a href="#" data-role="button" data-theme="b">FaceBook</a><br/>
52 // <div class="ui-block-c"><br/>
53 // <a href="#" data-role="button" data-theme="c">Google+</a><br/>
56 // <div data-role="swipelist-item-cover">Nigel</div><br/>
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
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
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).
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.
84 // animationComplete: Triggered by a cover when it finishes sliding
85 // (to either the right or left).
88 $.widget("tizen.swipelist", $.mobile.widget, {
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') ||
98 this.element.parent().jqmData('theme') ||
101 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 coverTheme = defaultCoverTheme,
127 // get the parent li element and add classes
128 item = cover.closest('li'),
131 // add swipelist CSS classes
132 item.addClass('ui-swipelist-item');
133 cover.addClass('ui-swipelist-item-cover');
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]/);
141 if (itemHasThemeClass) {
142 coverTheme = itemHasThemeClass[0];
145 cover.addClass(coverTheme);
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'));
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);
158 cover.data('animateLeft', function () {
159 self._animateCover(cover, 0);
163 // bind to synthetic events
164 item.bind('swipeleft', cover.data('animateLeft'));
165 cover.bind('swiperight', cover.data('animateRight'));
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'));
173 _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 coverTheme = defaultCoverTheme,
191 // get the parent li element and add classes
192 item = cover.closest('li'),
196 // remove swipelist CSS classes
197 item.removeClass('ui-swipelist-item');
198 cover.removeClass('ui-swipelist-item-cover');
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]/);
207 if (itemHasThemeClass) {
208 coverTheme = itemHasThemeClass[0];
211 cover.removeClass(coverTheme);
213 // remove wrapper HTML
214 wrapper = cover.find('.ui-swipelist-item-cover-inner');
215 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();