1 /* =========================================================
\r
2 * bootstrap-slider.js v2.0.0
\r
3 * http://www.eyecon.ro/bootstrap-slider
\r
4 * =========================================================
\r
5 * Copyright 2012 Stefan Petre
\r
7 * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * you may not use this file except in compliance with the License.
\r
9 * You may obtain a copy of the License at
\r
11 * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * Unless required by applicable law or agreed to in writing, software
\r
14 * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * See the License for the specific language governing permissions and
\r
17 * limitations under the License.
\r
18 * ========================================================= */
\r
22 var Slider = function(element, options) {
\r
23 this.element = $(element);
\r
24 this.picker = $('<div class="slider">'+
\r
25 '<div class="slider-track">'+
\r
26 '<div class="slider-selection"></div>'+
\r
27 '<div class="slider-handle"></div>'+
\r
28 '<div class="slider-handle"></div>'+
\r
30 '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'+
\r
32 .insertBefore(this.element)
\r
33 .append(this.element);
\r
34 this.id = this.element.data('slider-id')||options.id;
\r
36 this.picker[0].id = this.id;
\r
39 if (typeof Modernizr !== 'undefined' && Modernizr.touch) {
\r
40 this.touchCapable = true;
\r
43 var tooltip = this.element.data('slider-tooltip')||options.tooltip;
\r
45 this.tooltip = this.picker.find('.tooltip');
\r
46 this.tooltipInner = this.tooltip.find('div.tooltip-inner');
\r
48 this.orientation = this.element.data('slider-orientation')||options.orientation;
\r
49 switch(this.orientation) {
\r
51 this.picker.addClass('slider-vertical');
\r
52 this.stylePos = 'top';
\r
53 this.mousePos = 'pageY';
\r
54 this.sizePos = 'offsetHeight';
\r
55 this.tooltip.addClass('right')[0].style.left = '100%';
\r
59 .addClass('slider-horizontal')
\r
60 .css('width', this.element.outerWidth());
\r
61 this.orientation = 'horizontal';
\r
62 this.stylePos = 'left';
\r
63 this.mousePos = 'pageX';
\r
64 this.sizePos = 'offsetWidth';
\r
65 this.tooltip.addClass('top')[0].style.top = -this.tooltip.outerHeight() - 14 + 'px';
\r
69 this.min = this.element.data('slider-min')||options.min;
\r
70 this.max = this.element.data('slider-max')||options.max;
\r
71 this.step = this.element.data('slider-step')||options.step;
\r
72 this.value = this.element.data('slider-value')||options.value;
\r
73 if (this.value[1]) {
\r
77 this.selection = this.element.data('slider-selection')||options.selection;
\r
78 this.selectionEl = this.picker.find('.slider-selection');
\r
79 if (this.selection === 'none') {
\r
80 this.selectionEl.addClass('hide');
\r
82 this.selectionElStyle = this.selectionEl[0].style;
\r
85 this.handle1 = this.picker.find('.slider-handle:first');
\r
86 this.handle1Stype = this.handle1[0].style;
\r
87 this.handle2 = this.picker.find('.slider-handle:last');
\r
88 this.handle2Stype = this.handle2[0].style;
\r
90 var handle = this.element.data('slider-handle')||options.handle;
\r
93 this.handle1.addClass('round');
\r
94 this.handle2.addClass('round');
\r
97 this.handle1.addClass('triangle');
\r
98 this.handle2.addClass('triangle');
\r
103 this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0]));
\r
104 this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1]));
\r
106 this.value = [ Math.max(this.min, Math.min(this.max, this.value))];
\r
107 this.handle2.addClass('hide');
\r
108 if (this.selection == 'after') {
\r
109 this.value[1] = this.max;
\r
111 this.value[1] = this.min;
\r
114 this.diff = this.max - this.min;
\r
115 this.percentage = [
\r
116 (this.value[0]-this.min)*100/this.diff,
\r
117 (this.value[1]-this.min)*100/this.diff,
\r
118 this.step*100/this.diff
\r
121 this.offset = this.picker.offset();
\r
122 this.size = this.picker[0][this.sizePos];
\r
124 this.formater = options.formater;
\r
128 if (this.touchCapable) {
\r
129 // Touch: Bind touch events:
\r
131 touchstart: $.proxy(this.mousedown, this)
\r
135 mousedown: $.proxy(this.mousedown, this)
\r
139 if (tooltip === 'show') {
\r
141 mouseenter: $.proxy(this.showTooltip, this),
\r
142 mouseleave: $.proxy(this.hideTooltip, this)
\r
145 this.tooltip.addClass('hide');
\r
149 Slider.prototype = {
\r
150 constructor: Slider,
\r
155 showTooltip: function(){
\r
156 this.tooltip.addClass('in');
\r
157 //var left = Math.round(this.percent*this.width);
\r
158 //this.tooltip.css('left', left - this.tooltip.outerWidth()/2);
\r
162 hideTooltip: function(){
\r
163 if (this.inDrag === false) {
\r
164 this.tooltip.removeClass('in');
\r
169 layout: function(){
\r
170 this.handle1Stype[this.stylePos] = this.percentage[0]+'%';
\r
171 this.handle2Stype[this.stylePos] = this.percentage[1]+'%';
\r
172 if (this.orientation == 'vertical') {
\r
173 this.selectionElStyle.top = Math.min(this.percentage[0], this.percentage[1]) +'%';
\r
174 this.selectionElStyle.height = Math.abs(this.percentage[0] - this.percentage[1]) +'%';
\r
176 this.selectionElStyle.left = Math.min(this.percentage[0], this.percentage[1]) +'%';
\r
177 this.selectionElStyle.width = Math.abs(this.percentage[0] - this.percentage[1]) +'%';
\r
180 this.tooltipInner.text(
\r
181 this.formater(this.value[0]) +
\r
183 this.formater(this.value[1])
\r
185 this.tooltip[0].style[this.stylePos] = this.size * (this.percentage[0] + (this.percentage[1] - this.percentage[0])/2)/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px';
\r
187 this.tooltipInner.text(
\r
188 this.formater(this.value[0])
\r
190 this.tooltip[0].style[this.stylePos] = this.size * this.percentage[0]/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px';
\r
194 mousedown: function(ev) {
\r
196 // Touch: Get the original event:
\r
197 if (this.touchCapable && ev.type === 'touchstart') {
\r
198 ev = ev.originalEvent;
\r
201 this.offset = this.picker.offset();
\r
202 this.size = this.picker[0][this.sizePos];
\r
204 var percentage = this.getPercentage(ev);
\r
207 var diff1 = Math.abs(this.percentage[0] - percentage);
\r
208 var diff2 = Math.abs(this.percentage[1] - percentage);
\r
209 this.dragged = (diff1 < diff2) ? 0 : 1;
\r
214 this.percentage[this.dragged] = percentage;
\r
217 if (this.touchCapable) {
\r
218 // Touch: Bind touch events:
\r
220 touchmove: $.proxy(this.mousemove, this),
\r
221 touchend: $.proxy(this.mouseup, this)
\r
225 mousemove: $.proxy(this.mousemove, this),
\r
226 mouseup: $.proxy(this.mouseup, this)
\r
230 this.inDrag = true;
\r
231 var val = this.calculateValue();
\r
232 this.element.trigger({
\r
233 type: 'slideStart',
\r
242 mousemove: function(ev) {
\r
244 // Touch: Get the original event:
\r
245 if (this.touchCapable && ev.type === 'touchmove') {
\r
246 ev = ev.originalEvent;
\r
249 var percentage = this.getPercentage(ev);
\r
251 if (this.dragged === 0 && this.percentage[1] < percentage) {
\r
252 this.percentage[0] = this.percentage[1];
\r
254 } else if (this.dragged === 1 && this.percentage[0] > percentage) {
\r
255 this.percentage[1] = this.percentage[0];
\r
259 this.percentage[this.dragged] = percentage;
\r
261 var val = this.calculateValue();
\r
267 .data('value', val)
\r
268 .prop('value', val);
\r
272 mouseup: function(ev) {
\r
273 if (this.touchCapable) {
\r
274 // Touch: Bind touch events:
\r
276 touchmove: this.mousemove,
\r
277 touchend: this.mouseup
\r
281 mousemove: this.mousemove,
\r
282 mouseup: this.mouseup
\r
286 this.inDrag = false;
\r
287 if (this.over == false) {
\r
288 this.hideTooltip();
\r
291 var val = this.calculateValue();
\r
297 .data('value', val)
\r
298 .prop('value', val);
\r
302 calculateValue: function() {
\r
306 (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step),
\r
307 (this.min + Math.round((this.diff * this.percentage[1]/100)/this.step)*this.step)
\r
311 val = (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step);
\r
312 this.value = [val, this.value[1]];
\r
317 getPercentage: function(ev) {
\r
318 if (this.touchCapable) {
\r
319 ev = ev.touches[0];
\r
321 var percentage = (ev[this.mousePos] - this.offset[this.stylePos])*100/this.size;
\r
322 percentage = Math.round(percentage/this.percentage[2])*this.percentage[2];
\r
323 return Math.max(0, Math.min(100, percentage));
\r
326 getValue: function() {
\r
330 return this.value[0];
\r
333 setValue: function(val) {
\r
337 this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0]));
\r
338 this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1]));
\r
340 this.value = [ Math.max(this.min, Math.min(this.max, this.value))];
\r
341 this.handle2.addClass('hide');
\r
342 if (this.selection == 'after') {
\r
343 this.value[1] = this.max;
\r
345 this.value[1] = this.min;
\r
348 this.diff = this.max - this.min;
\r
349 this.percentage = [
\r
350 (this.value[0]-this.min)*100/this.diff,
\r
351 (this.value[1]-this.min)*100/this.diff,
\r
352 this.step*100/this.diff
\r
358 $.fn.slider = function ( option, val ) {
\r
359 return this.each(function () {
\r
360 var $this = $(this),
\r
361 data = $this.data('slider'),
\r
362 options = typeof option === 'object' && option;
\r
364 $this.data('slider', (data = new Slider(this, $.extend({}, $.fn.slider.defaults,options))));
\r
366 if (typeof option == 'string') {
\r
372 $.fn.slider.defaults = {
\r
376 orientation: 'horizontal',
\r
378 selection: 'before',
\r
381 formater: function(value) {
\r
386 $.fn.slider.Constructor = Slider;
\r