Export 0.1.63
[platform/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  *     popup: boolean; controls whether the popup is displayed or not
47  *                   specify if the popup is enabled using the 'data-popup' attribute
48  *                   set from javascript using .tizenslider('option','popup',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-popup='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','popup',false);
66  *
67  *     // from buttons
68  *     $('#popupEnabler').bind('vclick', function() {
69  *         $('#mySlider').tizenslider('option','popup',true);
70  *     });
71  *     $('#popupDisabler').bind('vclick', function() {
72  *         $('#mySlider').tizenslider('option','popup',false);
73  *     });
74  */
75
76 /**
77         @class Slider
78         The slider widget shows a control on the screen that you can use to change values by dragging a handle on a horizontal scale. Sliders can be used in Tizen as described in the jQueryMobile documentation for sliders.
79
80         To add a slider widget to the application, use the following code:
81
82                 <input data-popup='false' type="range" name="slider" value="5" min="0" max="10" data-icon="text" data-text-left="Min" data-text-right="Max" />
83
84         The slider can define callbacks for events as described in the jQueryMobile documentation for slider events.
85         You can use methods with the slider as described in the jQueryMobile documentation for slider methods.
86 */
87 /**
88         @property {String} data-icon
89         Defines the icon style for the slider ends. The icon options are bright, volume, and text.
90         The default value is text.
91 */
92 /**
93         @property {Boolean} data-popup
94         Enables or disables a pop-up showing the current value while the handle is dragged.
95         The default value is true.
96 */
97 /**
98         @property {String} data-text-left
99         Defines the text displayed on the left side of the slider.
100         The data-icon option must be set to text.
101 */
102 /**
103         @property {String} data-text-right
104         Defines the text displayed on the right side of the slider.
105         The data-icon option must be set to text.
106 */
107
108 (function ($, window, undefined) {
109         $.widget("tizen.tizenslider", $.mobile.widget, {
110                 options: {
111                         popup: true
112                 },
113
114                 popup: null,
115                 handle: null,
116                 handleText: null,
117
118                 _create: function () {
119                         this.currentValue = null;
120                         this.popupVisible = false;
121
122                         var self = this,
123                                 inputElement = $( this.element ),
124                                 slider,
125                                 slider_bar,
126                                 handle_press,
127                                 popupEnabledAttr,
128                                 icon,
129                                 text_right,
130                                 text_left;
131
132                         // apply jqm slider
133                         inputElement.slider();
134
135                         // hide the slider input element proper
136                         inputElement.hide();
137
138                         self.popup = $('<div class="ui-slider-popup"></div>');
139
140                         // set the popup according to the html attribute
141                         popupEnabledAttr = inputElement.jqmData('popup');
142                         if ( popupEnabledAttr !== undefined ) {
143                                 self.options.popup = ( popupEnabledAttr == true );
144                         }
145
146                         // get the actual slider added by jqm
147                         slider = inputElement.next('.ui-slider');
148
149                         icon = inputElement.attr('data-icon');
150
151                         // wrap the background
152                         if ( icon === undefined ) {
153                                 slider.wrap('<div class="ui-slider-bg"></div>');
154                         } else {
155                                 slider.wrap('<div class="ui-slider-icon-bg"></div>');
156                         }
157
158                         // get the handle
159                         self.handle = slider.find('.ui-slider-handle');
160
161                         // remove the rounded corners from the slider and its children
162                         slider.removeClass('ui-btn-corner-all');
163                         slider.find('*').removeClass('ui-btn-corner-all');
164
165                         // add icon
166
167                         switch ( icon ) {
168                         case 'bright':
169                         case 'volume':
170                                 slider.before( $('<div class="ui-slider-left-' +
171                                                         icon + '"></div>') );
172                                 slider.after( $('<div class="ui-slider-right-' +
173                                                         icon + '"></div>') );
174                                 break;
175
176                         case 'text':
177                                 text_left = ( inputElement.attr('data-text-left') === undefined ) ? '' : inputElement.attr('data-text-left').substring( 0, 3 );
178                                 text_right = ( inputElement.attr('data-text-right') === undefined ) ? '' : inputElement.attr('data-text-right').substring( 0, 3 );
179                                 slider.before( $('<div class="ui-slider-left-text">' +
180                                         '<span style="position:relative;top:0.4em;">' +
181                                         text_left +
182                                         '</span></div>') );
183                                 slider.after( $('<div class="ui-slider-right-text">' +
184                                         '<span style="position:relative;top:0.4em;">' +
185                                         text_right +
186                                         '</span></div>') );
187                                 break;
188                         }
189
190                         // slider bar
191                         slider.append($('<div class="ui-slider-bar"></div>'));
192                         self.slider_bar = slider.find('.ui-slider-bar');
193
194                         // handle press
195                         slider.append($('<div class="ui-slider-handle-press"></div>'));
196                         self.handle_press = slider.find('.ui-slider-handle-press');
197                         self.handle_press.css('display', 'none');
198
199                         // add a popup element (hidden initially)
200                         slider.before( self.popup );
201                         self.popup.hide();
202
203                         // get the element where value can be displayed
204                         self.handleText = slider.find('.ui-btn-text');
205
206                         // set initial value
207                         self.updateSlider();
208
209                         // bind to changes in the slider's value to update handle text
210                         this.element.bind('change', function () {
211                                 self.updateSlider();
212                         });
213
214                         // bind clicks on the handle to show the popup
215                         self.handle.bind('vmousedown', function () {
216                                 self.showPopup();
217                         });
218
219                         // watch events on the document to turn off the slider popup
220                         slider.add( document ).bind('vmouseup', function () {
221                                 self.hidePopup();
222                         });
223                 },
224
225                 _handle_press_show: function () {
226                         this.handle_press.css('display', '');
227                 },
228
229                 _handle_press_hide: function () {
230                         this.handle_press.css('display', 'none');
231                 },
232
233                 // position the popup
234                 positionPopup: function () {
235                         var dstOffset = this.handle.offset();
236
237                         this.popup.offset({
238                                 left: dstOffset.left + ( this.handle.width() - this.popup.width() ) / 2
239                         });
240
241                         this.handle_press.offset({
242                                 left: dstOffset.left,
243                                 top: dstOffset.top
244                         });
245                 },
246
247                 // show value on the handle and in popup
248                 updateSlider: function () {
249                         var font_size,
250                                 padding_size,
251                                 newValue;
252
253                         // remove the title attribute from the handle (which is
254                         // responsible for the annoying tooltip); NB we have
255                         // to do it here as the jqm slider sets it every time
256                         // the slider's value changes :(
257                         this.handle.removeAttr('title');
258
259                         this.slider_bar.width( this.handle.css('left') );
260
261                         newValue = this.element.val();
262
263                         if ( this.popupVisible ) {
264                                 this.positionPopup();
265
266                                 if ( newValue > 999 ) {
267                                         font_size = '0.8rem';
268                                         padding_size = '0.5rem';
269                                 } else if ( newValue > 99 ) {
270                                         font_size = '1rem';
271                                         padding_size = '0.5rem';
272                                 } else {
273                                         font_size = '1.5rem';
274                                         padding_size = '0.15rem';
275                                 }
276
277                                 this.popup.css({
278                                         "font-size": font_size,
279                                         "padding-top": padding_size
280                                 });
281                         }
282
283                         if ( newValue === this.currentValue ) {
284                                 return;
285                         }
286
287                         if ( newValue > 999 ) {
288                                 font_size = '0.5rem';
289                         } else if ( newValue > 99 ) {
290                                 font_size = '0.7rem';
291                         } else if ( newValue > 9 ) {
292                                 font_size = '0.85rem';
293                         } else {
294                                 font_size = '0.95rem';
295                         }
296
297                         if ( font_size != this.handleText.css('font-size') ) {
298                                 this.handleText.css( 'font-size', font_size );
299                         }
300
301                         this.currentValue = newValue;
302                         this.handleText.text( newValue );
303                         this.popup.html( newValue );
304
305                         this.element.trigger( 'update', newValue );
306                 },
307
308                 // show the popup
309                 showPopup: function () {
310                         if ( !this.options.popup || this.popupVisible ) {
311                                 return;
312                         }
313
314                         this.popup.show();
315                         this.popupVisible = true;
316                         this._handle_press_show();
317                 },
318
319                 // hide the popup
320                 hidePopup: function () {
321                         if ( !this.options.popup || !this.popupVisible ) {
322                                 return;
323                         }
324
325                         this.popup.hide();
326                         this.popupVisible = false;
327                         this._handle_press_hide();
328                 },
329
330                 _setOption: function (key, value) {
331                         var needToChange = ( value !== this.options[key] );
332
333                         if ( !needToChange ) {
334                                 return;
335                         }
336
337                         switch ( key ) {
338                         case 'popup':
339                                 this.options.popup = value;
340
341                                 if ( this.options.popup) {
342                                         this.updateSlider();
343                                 } else {
344                                         this.hidePopup();
345                                 }
346
347                                 break;
348                         }
349                 }
350         });
351
352         // stop jqm from initialising sliders
353         $( document ).bind( "pagebeforecreate", function ( e ) {
354                 if ( $.data( window, "jqmSliderInitSelector" ) === undefined ) {
355                         $.data( window, "jqmSliderInitSelector",
356                                 $.mobile.slider.prototype.options.initSelector );
357                         $.mobile.slider.prototype.options.initSelector = null;
358                 }
359         });
360
361         // initialise sliders with our own slider
362         $( document ).bind( "pagecreate", function ( e ) {
363                 var jqmSliderInitSelector = $.data( window, "jqmSliderInitSelector" );
364                 $( e.target ).find(jqmSliderInitSelector).not('select').tizenslider();
365                 $( e.target ).find(jqmSliderInitSelector).filter('select').slider();
366         });
367
368 }( jQuery, this ));