b7ac4ad2b5eb59ad8e026dca12f249d2033ee023
[framework/web/web-ui-fw.git] / src / widgets / slider / js / jquery.mobile.tizen.slider.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: Max Waterman <max.waterman@intel.com>
31  * Authors: Minkyu Kang <mk7.kang@samsung.com>
32  */
33
34 /**
35  * tizenslider modifies the JQuery Mobile slider and is created in the same way.
36  *
37  * See the JQuery Mobile slider widget for more information :
38  *     http://jquerymobile.com/demos/1.0a4.1/docs/forms/forms-slider.html
39  *
40  * The JQuery Mobile slider option:
41  *     theme: specify the theme using the 'data-theme' attribute
42  *
43  * Options:
44  *     theme: string; the theme to use if none is specified using the 'data-theme' attribute
45  *            default: 'c'
46  *     popupEnabled: boolean; controls whether the popup is displayed or not
47  *                   specify if the popup is enabled using the 'data-popupEnabled' attribute
48  *                   set from javascript using .tizenslider('option','popupEnabled',newValue)
49  *
50  * Events:
51  *     changed: triggers when the value is changed (rather than when the handle is moved)
52  *
53  * Examples:
54  *
55  *     <a href="#" id="popupEnabler" data-role="button" data-inline="true">Enable popup</a>
56  *     <a href="#" id="popupDisabler" data-role="button" data-inline="true">Disable popup</a>
57  *     <div data-role="fieldcontain">
58  *         <input id="mySlider" data-theme='a' data-popupenabled='false' type="range" name="slider" value="7" min="0" max="9" />
59  *     </div>
60  *     <div data-role="fieldcontain">
61  *         <input id="mySlider2" type="range" name="slider" value="77" min="0" max="777" />
62  *     </div>
63  *
64  *     // disable popup from javascript
65  *     $('#mySlider').tizenslider('option','popupEnabled',false);
66  *
67  *     // from buttons
68  *     $('#popupEnabler').bind('vclick', function() {
69  *         $('#mySlider').tizenslider('option','popupEnabled',true);
70  *     });
71  *     $('#popupDisabler').bind('vclick', function() {
72  *         $('#mySlider').tizenslider('option','popupEnabled',false);
73  *     });
74  */
75
76 (function ($, window, undefined) {
77         $.widget("tizen.tizenslider", $.mobile.widget, {
78                 options: {
79                         popupEnabled: true
80                 },
81
82                 popup: null,
83                 handle: null,
84                 handleText: null,
85
86                 _create: function () {
87                         this.currentValue = null;
88                         this.popupVisible = false;
89
90                         var self = this,
91                                 inputElement = $(this.element),
92                                 slider,
93                                 showPopup,
94                                 hidePopup,
95                                 positionPopup,
96                                 updateSlider,
97                                 slider_bar,
98                                 handle_press,
99                                 popupEnabledAttr,
100                                 icon;
101
102                         // apply jqm slider
103                         inputElement.slider();
104
105                         // hide the slider input element proper
106                         inputElement.hide();
107
108                         self.popup = $('<div class="ui-slider-popup"></div>');
109
110                         // set the popupEnabled according to the html attribute
111                         popupEnabledAttr = inputElement.attr('data-popupenabled');
112                         if ( popupEnabledAttr !== undefined ) {
113                                 self.options.popupEnabled = (popupEnabledAttr === 'true');
114                         }
115
116                         // get the actual slider added by jqm
117                         slider = inputElement.next('.ui-slider');
118
119                         icon = inputElement.attr('data-icon');
120
121                         // wrap the background
122                         if ( icon === undefined ) {
123                                 slider.wrap('<div class="ui-slider-bg"></div>');
124                         } else {
125                                 slider.wrap('<div class="ui-slider-icon-bg"></div>');
126                         }
127
128                         // get the handle
129                         self.handle = slider.find('.ui-slider-handle');
130
131                         // remove the rounded corners from the slider and its children
132                         slider.removeClass('ui-btn-corner-all');
133                         slider.find('*').removeClass('ui-btn-corner-all');
134
135                         // add icon
136
137                         switch ( icon ) {
138                         case 'bright':
139                         case 'volume':
140                                 slider.before( $('<div class="ui-slider-left-' +
141                                                         icon + '"></div>') );
142                                 slider.after( $('<div class="ui-slider-right-' +
143                                                         icon + '"></div>') );
144                                 break;
145
146                         case 'text':
147                                 slider.before( $('<div class="ui-slider-left-text">' +
148                                         '<span style="position:relative;top:0.4em;">' +
149                                         inputElement.attr('data-text-left') +
150                                         '</span></div>') );
151                                 slider.after( $('<div class="ui-slider-right-text">' +
152                                         '<span style="position:relative;top:0.4em;">' +
153                                         inputElement.attr('data-text-right') +
154                                         '</span></div>') );
155                                 break;
156                         }
157
158                         // slider bar
159                         slider.append($('<div class="ui-slider-bar"></div>'));
160                         self.slider_bar = slider.find('.ui-slider-bar');
161
162                         // handle press
163                         slider.append($('<div class="ui-slider-handle-press"></div>'));
164                         self.handle_press = slider.find('.ui-slider-handle-press');
165                         self.handle_press.css('display', 'none');
166
167                         // add a popup element (hidden initially)
168                         slider.before(self.popup);
169                         self.popup.hide();
170
171                         // get the element where value can be displayed
172                         self.handleText = slider.find('.ui-btn-text');
173                         if ( inputElement.attr('max') > 999 ) {
174                                 self.handleText.css('font-size', '0.8em');
175                         }
176
177                         // set initial value
178                         self.updateSlider();
179
180                         // bind to changes in the slider's value to update handle text
181                         this.element.bind('change', function () {
182                                 self.updateSlider();
183                         });
184
185                         // bind clicks on the handle to show the popup
186                         self.handle.bind('vmousedown', function () {
187                                 self.showPopup();
188                         });
189
190                         // watch events on the document to turn off the slider popup
191                         slider.add(document).bind('vmouseup', function () {
192                                 self.hidePopup();
193                         });
194                 },
195
196                 _handle_press_show: function () {
197                         this.handle_press.css('display', '');
198                 },
199
200                 _handle_press_hide: function () {
201                         this.handle_press.css('display', 'none');
202                 },
203
204                 // position the popup
205                 positionPopup: function () {
206                         var dstOffset = this.handle.offset();
207
208                         this.popup.offset({
209                                 left: dstOffset.left + (this.handle.width() - this.popup.width()) / 2,
210                                 top: dstOffset.top  - this.popup.outerHeight() + 15
211                         });
212
213                         this.handle_press.offset({
214                                 left: dstOffset.left,
215                                 top: dstOffset.top
216                         });
217                 },
218
219                 // show value on the handle and in popup
220                 updateSlider: function () {
221                         if ( this.popupVisible ) {
222                                 this.positionPopup();
223                         }
224
225                         // remove the title attribute from the handle (which is
226                         // responsible for the annoying tooltip); NB we have
227                         // to do it here as the jqm slider sets it every time
228                         // the slider's value changes :(
229                         this.handle.removeAttr('title');
230
231                         this.slider_bar.width(this.handle.css('left'));
232
233                         var newValue = this.element.val();
234
235                         if ( newValue === this.currentValue ) {
236                                 return;
237                         }
238
239                         this.currentValue = newValue;
240                         this.handleText.text(newValue);
241                         this.popup.html(newValue);
242
243                         this.element.trigger('update', newValue);
244                 },
245
246                 // show the popup
247                 showPopup: function () {
248                         if ( !(this.options.popupEnabled && !this.popupVisible) ) {
249                                 return;
250                         }
251
252                         this.handleText.hide();
253                         this.popup.show();
254                         this.popupVisible = true;
255                         this._handle_press_show();
256                 },
257
258                 // hide the popup
259                 hidePopup: function () {
260                         if ( !(this.options.popupEnabled && this.popupVisible) ) {
261                                 return;
262                         }
263
264                         this.handleText.show();
265                         this.popup.hide();
266                         this.popupVisible = false;
267                         this._handle_press_hide();
268                 },
269
270                 _setOption: function (key, value) {
271                         var needToChange = ( value !== this.options[key] );
272
273                         if ( !needToChange ) {
274                                 return;
275                         }
276
277                         switch ( key ) {
278                         case 'popupEnabled':
279                                 this.options.popupEnabled = value;
280
281                                 if ( this.options.popupEnabled ) {
282                                         this.updateSlider();
283                                 } else {
284                                         this.hidePopup();
285                                 }
286
287                                 break;
288                         }
289                 }
290         });
291
292         // stop jqm from initialising sliders
293         $(document).bind("pagebeforecreate", function ( e ) {
294                 if ($.data(window, "jqmSliderInitSelector") === undefined ) {
295                         $.data(window, "jqmSliderInitSelector",
296                                 $.mobile.slider.prototype.options.initSelector);
297                         $.mobile.slider.prototype.options.initSelector = null;
298                 }
299         });
300
301         // initialise sliders with our own slider
302         $(document).bind("pagecreate", function ( e ) {
303                 var jqmSliderInitSelector = $.data(window, "jqmSliderInitSelector");
304                 $(e.target).find(jqmSliderInitSelector).not('select').tizenslider();
305                 $(e.target).find(jqmSliderInitSelector).filter('select').slider();
306         });
307
308 }( jQuery, this ));