c417681fb2dd0778bb3c27364c921e893fc14f61
[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 (function ($, window, undefined) {
77         $.widget("tizen.tizenslider", $.mobile.widget, {
78                 options: {
79                         popup: 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                                 slider_bar,
94                                 handle_press,
95                                 popupEnabledAttr,
96                                 icon,
97                                 text_right,
98                                 text_left;
99
100                         // apply jqm slider
101                         inputElement.slider();
102
103                         // hide the slider input element proper
104                         inputElement.hide();
105
106                         // FIXME: workaround for list elipse
107                         if ( inputElement.parent().hasClass("ui-li") ) {
108                                 inputElement.parent().css( "overflow", "visible" );
109                         }
110
111                         self.popup = $('<div class="ui-slider-popup"></div>');
112
113                         // set the popup according to the html attribute
114                         popupEnabledAttr = inputElement.jqmData('popup');
115                         if ( popupEnabledAttr !== undefined ) {
116                                 self.options.popup = ( popupEnabledAttr == true );
117                         }
118
119                         // get the actual slider added by jqm
120                         slider = inputElement.next('.ui-slider');
121
122                         icon = inputElement.attr('data-icon');
123
124                         // wrap the background
125                         if ( icon === undefined ) {
126                                 slider.wrap('<div class="ui-slider-bg"></div>');
127                         } else {
128                                 slider.wrap('<div class="ui-slider-icon-bg"></div>');
129                         }
130
131                         // get the handle
132                         self.handle = slider.find('.ui-slider-handle');
133
134                         // remove the rounded corners from the slider and its children
135                         slider.removeClass('ui-btn-corner-all');
136                         slider.find('*').removeClass('ui-btn-corner-all');
137
138                         // add icon
139
140                         switch ( icon ) {
141                         case 'bright':
142                         case 'volume':
143                                 slider.before( $('<div class="ui-slider-left-' +
144                                                         icon + '"></div>') );
145                                 slider.after( $('<div class="ui-slider-right-' +
146                                                         icon + '"></div>') );
147                                 break;
148
149                         case 'text':
150                                 text_left = ( inputElement.attr('data-text-left') === undefined ) ? '' : inputElement.attr('data-text-left').substring( 0, 3 );
151                                 text_right = ( inputElement.attr('data-text-right') === undefined ) ? '' : inputElement.attr('data-text-right').substring( 0, 3 );
152                                 slider.before( $('<div class="ui-slider-left-text">' +
153                                         '<span style="position:relative;top:0.4em;">' +
154                                         text_left +
155                                         '</span></div>') );
156                                 slider.after( $('<div class="ui-slider-right-text">' +
157                                         '<span style="position:relative;top:0.4em;">' +
158                                         text_right +
159                                         '</span></div>') );
160                                 break;
161                         }
162
163                         // slider bar
164                         slider.append($('<div class="ui-slider-bar"></div>'));
165                         self.slider_bar = slider.find('.ui-slider-bar');
166
167                         // handle press
168                         slider.append($('<div class="ui-slider-handle-press"></div>'));
169                         self.handle_press = slider.find('.ui-slider-handle-press');
170                         self.handle_press.css('display', 'none');
171
172                         // add a popup element (hidden initially)
173                         slider.before( self.popup );
174                         self.popup.hide();
175
176                         // get the element where value can be displayed
177                         self.handleText = slider.find('.ui-btn-text');
178
179                         // set initial value
180                         self.updateSlider();
181
182                         // bind to changes in the slider's value to update handle text
183                         this.element.bind('change', function () {
184                                 self.updateSlider();
185                         });
186
187                         // bind clicks on the handle to show the popup
188                         self.handle.bind('vmousedown', function () {
189                                 self.showPopup();
190                         });
191
192                         // watch events on the document to turn off the slider popup
193                         slider.add( document ).bind('vmouseup', function () {
194                                 self.hidePopup();
195                         });
196                 },
197
198                 _handle_press_show: function () {
199                         this.handle_press.css('display', '');
200                 },
201
202                 _handle_press_hide: function () {
203                         this.handle_press.css('display', 'none');
204                 },
205
206                 // position the popup
207                 positionPopup: function () {
208                         var dstOffset = this.handle.offset();
209
210                         this.popup.offset({
211                                 left: dstOffset.left + ( this.handle.width() - this.popup.width() ) / 2,
212                                 top: dstOffset.top  - this.popup.outerHeight() + 15
213                         });
214
215                         this.handle_press.offset({
216                                 left: dstOffset.left,
217                                 top: dstOffset.top
218                         });
219                 },
220
221                 // show value on the handle and in popup
222                 updateSlider: function () {
223                         var font_size,
224                                 newValue;
225
226                         if ( this.popupVisible ) {
227                                 this.positionPopup();
228                         }
229
230                         // remove the title attribute from the handle (which is
231                         // responsible for the annoying tooltip); NB we have
232                         // to do it here as the jqm slider sets it every time
233                         // the slider's value changes :(
234                         this.handle.removeAttr('title');
235
236                         this.slider_bar.width( this.handle.css('left') );
237
238                         newValue = this.element.val();
239
240                         if ( newValue === this.currentValue ) {
241                                 return;
242                         }
243
244                         if ( newValue > 999 ) {
245                                 font_size = '0.7em';
246                         } else if ( newValue > 99 ) {
247                                 font_size = '0.8em';
248                         } else if ( newValue > 9 ) {
249                                 font_size = '0.9em';
250                         } else {
251                                 font_size = '1em';
252                         }
253
254                         if ( font_size != this.handleText.css('font-size') ) {
255                                 this.handleText.css( 'font-size', font_size );
256                         }
257
258                         this.currentValue = newValue;
259                         this.handleText.text( newValue );
260                         this.popup.html( newValue );
261
262                         this.element.trigger( 'update', newValue );
263                 },
264
265                 // show the popup
266                 showPopup: function () {
267                         if ( !this.options.popup || this.popupVisible ) {
268                                 return;
269                         }
270
271                         this.popup.show();
272                         this.popupVisible = true;
273                         this._handle_press_show();
274                 },
275
276                 // hide the popup
277                 hidePopup: function () {
278                         if ( !this.options.popup || !this.popupVisible ) {
279                                 return;
280                         }
281
282                         this.popup.hide();
283                         this.popupVisible = false;
284                         this._handle_press_hide();
285                 },
286
287                 _setOption: function (key, value) {
288                         var needToChange = ( value !== this.options[key] );
289
290                         if ( !needToChange ) {
291                                 return;
292                         }
293
294                         switch ( key ) {
295                         case 'popup':
296                                 this.options.popup = value;
297
298                                 if ( this.options.popup) {
299                                         this.updateSlider();
300                                 } else {
301                                         this.hidePopup();
302                                 }
303
304                                 break;
305                         }
306                 }
307         });
308
309         // stop jqm from initialising sliders
310         $( document ).bind( "pagebeforecreate", function ( e ) {
311                 if ( $.data( window, "jqmSliderInitSelector" ) === undefined ) {
312                         $.data( window, "jqmSliderInitSelector",
313                                 $.mobile.slider.prototype.options.initSelector );
314                         $.mobile.slider.prototype.options.initSelector = null;
315                 }
316         });
317
318         // initialise sliders with our own slider
319         $( document ).bind( "pagecreate", function ( e ) {
320                 var jqmSliderInitSelector = $.data( window, "jqmSliderInitSelector" );
321                 $( e.target ).find(jqmSliderInitSelector).not('select').tizenslider();
322                 $( e.target ).find(jqmSliderInitSelector).filter('select').slider();
323         });
324
325 }( jQuery, this ));