vendor: 5,599 bytes, lines 1-163
1/*jshint multistr:true, curly: false */ 2/*global jQuery:false, define: false */ 3/** 4 * jRange - Awesome range control 5 * 6 * Written by 7 * ---------- 8 * Nitin Hayaran ([email protected]) 9 * 10 * Licensed under the MIT (MIT-LICENSE.txt). 11 * 12 * @author Nitin Hayaran 13 * @version 0.1-RELEASE 14 * 15 * Dependencies 16 * ------------ 17 * jQuery (http://jquery.com) 18 * 19 **/ 20; 21(function($, window, document, undefined) { 22 'use strict'; 23 24 var jRange = function() { 25 return this.init.apply(this, arguments); 26 }; 27 jRange.prototype = { 28 defaults: { 29 onstatechange: function() {}, 30 ondragend: function() {}, 31 onbarclicked: function() {}, 32 isRange: false, 33 showLabels: true, 34 showScale: true, 35 step: 1, 36 format: '%s', 37 theme: 'theme-green', 38 width: 300, 39 disable: false, 40 snap: false 41 }, 42 template: '<div class="slider-container">\ 43 <div class="back-bar">\ 44 <div class="selected-bar"></div>\ 45 <div class="pointer low"></div><div class="pointer-label low">123456</div>\ 46 <div class="pointer high"></div><div class="pointer-label high">456789</div>\ 47 <div class="clickable-dummy"></div>\ 48 </div>\ 49 <div class="scale"></div>\ 50 </div>', 51 init: function(node, options) { 52 this.options = $.extend({}, this.defaults, options); 53 this.inputNode = $(node); 54 this.options.value = this.inputNode.val() || (this.options.isRange ? this.options.from + ',' + this.options.from : '' + this.options.from); 55 this.domNode = $(this.template); 56 this.domNode.addClass(this.options.theme); 57 this.inputNode.after(this.domNode); 58 this.domNode.on('change', this.onChange); 59 this.pointers = $('.pointer', this.domNode); 60 this.lowPointer = this.pointers.first(); 61 this.highPointer = this.pointers.last(); 62 this.labels = $('.pointer-label', this.domNode); 63 this.lowLabel = this.labels.first(); 64 this.highLabel = this.labels.last(); 65 this.scale = $('.scale', this.domNode); 66 this.bar = $('.selected-bar', this.domNode); 67 this.clickableBar = this.domNode.find('.clickable-dummy'); 68 this.interval = this.options.to - this.options.from; 69 this.render(); 70 }, 71 render: function() { 72 // Check if inputNode is visible, and have some width, so that we can set slider width accordingly. 73 if (this.inputNode.width() === 0 && !this.options.width) { 74 console.log('jRange : no width found, returning'); 75 return; 76 } else { 77 this.options.width = this.options.width || this.inputNode.width(); 78 this.domNode.width(this.options.width); 79 this.inputNode.hide(); 80 } 81 82 if (this.isSingle()) { 83 this.lowPointer.hide(); 84 this.lowLabel.hide(); 85 } 86 if (!this.options.showLabels) { 87 this.labels.hide(); 88 } 89 this.attachEvents(); 90 if (this.options.showScale) { 91 this.renderScale(); 92 } 93 this.setValue(this.options.value); 94 }, 95 isSingle: function() { 96 if (typeof(this.options.value) === 'number') { 97 return true; 98 } 99 return (this.options.value.indexOf(',') !== -1 || this.options.isRange) ? 100 false : true; 101 }, 102 attachEvents: function() { 103 this.clickableBar.click($.proxy(this.barClicked, this)); 104 this.pointers.on('mousedown touchstart', $.proxy(this.onDragStart, this)); 105 this.pointers.bind('dragstart', function(event) { 106 event.preventDefault(); 107 }); 108 }, 109 onDragStart: function(e) { 110 if ( this.options.disable || (e.type === 'mousedown' && e.which !== 1)) { 111 return; 112 } 113 e.stopPropagation(); 114 e.preventDefault(); 115 var pointer = $(e.target); 116 this.pointers.removeClass('last-active'); 117 pointer.addClass('focused last-active'); 118 this[(pointer.hasClass('low') ? 'low' : 'high') + 'Label'].addClass('focused'); 119 $(document).on('mousemove.slider touchmove.slider', $.proxy(this.onDrag, this, pointer)); 120 $(document).on('mouseup.slider touchend.slider touchcancel.slider', $.proxy(this.onDragEnd, this)); 121 }, 122 onDrag: function(pointer, e) { 123 e.stopPropagation(); 124 e.preventDefault(); 125 126 if (e.originalEvent.touches && e.originalEvent.touches.length) { 127 e = e.originalEvent.touches[0]; 128 } else if (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length) { 129 e = e.originalEvent.changedTouches[0]; 130 } 131 132 var position = e.clientX - this.domNode.offset().left; 133 this.domNode.trigger('change', [this, pointer, position]); 134 }, 135 onDragEnd: function(e) { 136 this.pointers.removeClass('focused') 137 .trigger('rangeslideend'); 138 this.labels.removeClass('focused'); 139 $(document).off('.slider'); 140 this.options.ondragend.call(this, this.options.value); 141 }, 142 barClicked: function(e) { 143 if(this.options.disable) return; 144 var x = e.pageX - this.clickableBar.offset().left; 145 if (this.isSingle()) 146 this.setPosition(this.pointers.last(), x, true, true); 147 else { 148 var firstLeft = Math.abs(parseFloat(this.pointers.first().css('left'), 10)), 149 firstHalfWidth = this.pointers.first().width() / 2, 150 lastLeft = Math.abs(parseFloat(this.pointers.last().css('left'), 10)), 151 lastHalfWidth = this.pointers.first().width() / 2, 152 leftSide = Math.abs(firstLeft - x + firstHalfWidth), 153 rightSide = Math.abs(lastLeft - x + lastHalfWidth), 154 pointer; 155 156 if(leftSide == rightSide) { 157 pointer = x < firstLeft ? this.pointers.first() : this.pointers.last(); 158 } else { 159 pointer = leftSide < rightSide ? this.pointers.first() : this.pointers.last(); 160 } 161 this.setPosition(pointer, x, true, true); 162 } 163 this.options.onbarclicked.call(this, this.options.value);
vendor: 7,651 bytes, lines 163-401
163 164 }, 165 onChange: function(e, self, pointer, position) { 166 var min, max; 167 min = 0; 168 max = self.domNode.width(); 169 170 if (!self.isSingle()) { 171 min = pointer.hasClass('high') ? parseFloat(self.lowPointer.css("left")) + (self.lowPointer.width() / 2) : 0; 172 max = pointer.hasClass('low') ? parseFloat(self.highPointer.css("left")) + (self.highPointer.width() / 2) : self.domNode.width(); 173 } 174 175 var value = Math.min(Math.max(position, min), max); 176 self.setPosition(pointer, value, true); 177 }, 178 setPosition: function(pointer, position, isPx, animate) { 179 var leftPos, rightPos, 180 lowPos = parseFloat(this.lowPointer.css("left")), 181 highPos = parseFloat(this.highPointer.css("left")) || 0, 182 circleWidth = this.highPointer.width() / 2; 183 if (!isPx) { 184 position = this.prcToPx(position); 185 } 186 if(this.options.snap){ 187 var expPos = this.correctPositionForSnap(position); 188 if(expPos === -1){ 189 return; 190 }else{ 191 position = expPos; 192 } 193 } 194 if (pointer[0] === this.highPointer[0]) { 195 highPos = Math.round(position - circleWidth); 196 } else { 197 lowPos = Math.round(position - circleWidth); 198 } 199 pointer[animate ? 'animate' : 'css']({ 200 'left': Math.round(position - circleWidth) 201 }); 202 if (this.isSingle()) { 203 leftPos = 0; 204 } else { 205 leftPos = lowPos + circleWidth; 206 rightPos = highPos + circleWidth; 207 } 208 var w = Math.round(highPos + circleWidth - leftPos); 209 this.bar[animate ? 'animate' : 'css']({ 210 'width': Math.abs(w), 211 'left': (w>0) ? leftPos : leftPos + w 212 }); 213 this.showPointerValue(pointer, position, animate); 214 this.isReadonly(); 215 }, 216 correctPositionForSnap: function(position){ 217 var currentValue = this.positionToValue(position) - this.options.from; 218 var diff = this.options.width / (this.interval / this.options.step), 219 expectedPosition = (currentValue / this.options.step) * diff; 220 if( position <= expectedPosition + diff / 2 && position >= expectedPosition - diff / 2){ 221 return expectedPosition; 222 }else{ 223 return -1; 224 } 225 }, 226 // will be called from outside 227 setValue: function(value) { 228 var values = value.toString().split(','); 229 values[0] = Math.min(Math.max(values[0], this.options.from), this.options.to) + ''; 230 if (values.length > 1){ 231 values[1] = Math.min(Math.max(values[1], this.options.from), this.options.to) + ''; 232 } 233 this.options.value = value; 234 var prc = this.valuesToPrc(values.length === 2 ? values : [0, values[0]]); 235 if (this.isSingle()) { 236 this.setPosition(this.highPointer, prc[1]); 237 } else { 238 this.setPosition(this.lowPointer, prc[0]); 239 this.setPosition(this.highPointer, prc[1]); 240 } 241 }, 242 renderScale: function() { 243 var s = this.options.scale || [this.options.from, this.options.to]; 244 var prc = Math.round((100 / (s.length - 1)) * 10) / 10; 245 var str = ''; 246 for (var i = 0; i < s.length; i++) { 247 str += '<span style="left: ' + i * prc + '%">' + (s[i] != '|' ? '<ins>' + s[i] + '</ins>' : '') + '</span>'; 248 } 249 this.scale.html(str); 250 251 $('ins', this.scale).each(function() { 252 $(this).css({ 253 marginLeft: -$(this).outerWidth() / 2 254 }); 255 }); 256 }, 257 getBarWidth: function() { 258 var values = this.options.value.split(','); 259 if (values.length > 1) { 260 return parseFloat(values[1]) - parseFloat(values[0]); 261 } else { 262 return parseFloat(values[0]); 263 } 264 }, 265 showPointerValue: function(pointer, position, animate) { 266 var label = $('.pointer-label', this.domNode)[pointer.hasClass('low') ? 'first' : 'last'](); 267 var text; 268 var value = this.positionToValue(position); 269 // Is it higer or lower than it should be? 270 271 if ($.isFunction(this.options.format)) { 272 var type = this.isSingle() ? undefined : (pointer.hasClass('low') ? 'low' : 'high'); 273 text = this.options.format(value, type); 274 } else { 275 text = this.options.format.replace('%s', value); 276 } 277 278 var width = label.html(text).width(), 279 left = position - width / 2; 280 left = Math.min(Math.max(left, 0), this.options.width - width); 281 label[animate ? 'animate' : 'css']({ 282 left: left 283 }); 284 this.setInputValue(pointer, value); 285 }, 286 valuesToPrc: function(values) { 287 var lowPrc = ((parseFloat(values[0]) - parseFloat(this.options.from)) * 100 / this.interval), 288 highPrc = ((parseFloat(values[1]) - parseFloat(this.options.from)) * 100 / this.interval); 289 return [lowPrc, highPrc]; 290 }, 291 prcToPx: function(prc) { 292 return (this.domNode.width() * prc) / 100; 293 }, 294 isDecimal: function() { 295 return ((this.options.value + this.options.from + this.options.to).indexOf(".")===-1) ? false : true; 296 }, 297 positionToValue: function(pos) { 298 var value = (pos / this.domNode.width()) * this.interval; 299 value = parseFloat(value, 10) + parseFloat(this.options.from, 10); 300 if (this.isDecimal()) { 301 var final = Math.round(Math.round(value / this.options.step) * this.options.step *100)/100; 302 if (final!==0.0) { 303 final = '' + final; 304 if (final.indexOf(".")===-1) { 305 final = final + "."; 306 } 307 while (final.length - final.indexOf('.')<3) { 308 final = final + "0"; 309 } 310 } else { 311 final = "0.00"; 312 } 313 return final; 314 } else { 315 return Math.round(value / this.options.step) * this.options.step; 316 } 317 }, 318 setInputValue: function(pointer, v) { 319 // if(!isChanged) return; 320 if (this.isSingle()) { 321 this.options.value = v.toString(); 322 } else { 323 var values = this.options.value.split(','); 324 if (pointer.hasClass('low')) { 325 this.options.value = v + ',' + values[1]; 326 } else { 327 this.options.value = values[0] + ',' + v; 328 } 329 } 330 if (this.inputNode.val() !== this.options.value) { 331 this.inputNode.val(this.options.value) 332 .trigger('change'); 333 this.options.onstatechange.call(this, this.options.value); 334 } 335 }, 336 getValue: function() { 337 return this.options.value; 338 }, 339 getOptions: function() { 340 return this.options; 341 }, 342 getRange: function() { 343 return this.options.from + "," + this.options.to; 344 }, 345 isReadonly: function(){ 346 this.domNode.toggleClass('slider-readonly', this.options.disable); 347 }, 348 disable: function(){ 349 this.options.disable = true; 350 this.isReadonly(); 351 }, 352 enable: function(){ 353 this.options.disable = false; 354 this.isReadonly(); 355 }, 356 toggleDisable: function(){ 357 this.options.disable = !this.options.disable; 358 this.isReadonly(); 359 }, 360 updateRange: function(range, value) { 361 var values = range.toString().split(','); 362 this.interval = parseInt(values[1]) - parseInt(values[0]); 363 if(value){ 364 this.setValue(value); 365 }else{ 366 this.setValue(this.getValue()); 367 } 368 } 369 }; 370 371 var pluginName = 'jRange'; 372 // A really lightweight plugin wrapper around the constructor, 373 // preventing against multiple instantiations 374 $.fn[pluginName] = function(option) { 375 var args = arguments, 376 result; 377 378 this.each(function() { 379 var $this = $(this), 380 data = $.data(this, 'plugin_' + pluginName), 381 options = typeof option === 'object' && option; 382 if (!data) { 383 $this.data('plugin_' + pluginName, (data = new jRange(this, options))); 384 $(window).resize(function() { 385 data.setValue(data.getValue()); 386 }); // Update slider position when window is resized to keep it in sync with scale 387 } 388 // if first argument is a string, call silimarly named function 389 // this gives flexibility to call functions of the plugin e.g. 390 // - $('.dial').plugin('destroy'); 391 // - $('.dial').plugin('render', $('.new-child')); 392 if (typeof option === 'string') { 393 result = data[option].apply(data, Array.prototype.slice.call(args, 1)); 394 } 395 }); 396 397 // To enable plugin returns values 398 return result || this; 399 }; 400 401})(jQuery, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.