1/** 2 * jquery.slider - Slider ui control in jQuery 3 * 4 * Written by 5 * Egor Khmelev ([email protected]) 6 * 7 * Licensed under the MIT (MIT-LICENSE.txt). 8 * 9 * @author Egor Khmelev 10 * @version 1.1.0-RELEASE ($Id$) 11 * 12 * Dependencies 13 * 14 * jQuery (http://jquery.com) 15 * jquery.numberformatter (http://code.google.com/p/jquery-numberformatter/) 16 * tmpl (http://ejohn.org/blog/javascript-micro-templating/) 17 * jquery.dependClass 18 * draggable 19 * 20 **/ 21 22(function( $ ) { 23 24 function isArray( value ){ 25 if( typeof value == "undefined" ) return false; 26 27 if (value instanceof Array || (!(value instanceof Object) && 28 (Object.prototype.toString.call((value)) == '[object Array]') || 29 typeof value.length == 'number' && 30 typeof value.splice != 'undefined' && 31 typeof value.propertyIsEnumerable != 'undefined' && 32 !value.propertyIsEnumerable('splice') 33 )) { 34 return true; 35 } 36 37 return false; 38 } 39 40 $.slider = function( node, settings ){ 41 var jNode = $(node); 42 if( !jNode.data( "jslider" ) ) 43 jNode.data( "jslider", new jSlider( node, settings ) ); 44 45 return jNode.data( "jslider" ); 46 }; 47 48 $.fn.slider = function( action, opt_value ){ 49 var returnValue, args = arguments; 50 51 function isDef( val ){ 52 return val !== undefined; 53 }; 54 55 function isDefAndNotNull( val ){ 56 return val != null; 57 }; 58 59 this.each(function(){ 60 var self = $.slider( this, action ); 61 62 // do actions 63 if( typeof action == "string" ){ 64 switch( action ){ 65 case "value": 66 if( isDef( args[ 1 ] ) && isDef( args[ 2 ] ) ){ 67 var pointers = self.getPointers(); 68 if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){ 69 pointers[0].set( args[ 1 ] ); 70 pointers[0].setIndexOver(); 71 } 72 73 if( isDefAndNotNull( pointers[1] ) && isDefAndNotNull( args[2] ) ){ 74 pointers[1].set( args[ 2 ] ); 75 pointers[1].setIndexOver(); 76 } 77 } 78 79 else if( isDef( args[ 1 ] ) ){ 80 var pointers = self.getPointers(); 81 if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){ 82 pointers[0].set( args[ 1 ] ); 83 pointers[0].setIndexOver(); 84 } 85 } 86 87 else 88 returnValue = self.getValue(); 89 90 break; 91 92 case "prc": 93 if( isDef( args[ 1 ] ) && isDef( args[ 2 ] ) ){ 94 var pointers = self.getPointers(); 95 if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){ 96 pointers[0]._set( args[ 1 ] ); 97 pointers[0].setIndexOver(); 98 } 99 100 if( isDefAndNotNull( pointers[1] ) && isDefAndNotNull( args[2] ) ){ 101 pointers[1]._set( args[ 2 ] ); 102 pointers[1].setIndexOver(); 103 } 104 } 105 106 else if( isDef( args[ 1 ] ) ){ 107 var pointers = self.getPointers(); 108 if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){ 109 pointers[0]._set( args[ 1 ] ); 110 pointers[0].setIndexOver(); 111 } 112 } 113 114 else 115 returnValue = self.getPrcValue(); 116 117 break; 118 119 case "calculatedValue": 120 var value = self.getValue().split(";"); 121 returnValue = ""; 122 for (var i=0; i < value.length; i++) { 123 returnValue += (i > 0 ? ";" : "") + self.nice( value[i] ); 124 }; 125 126 break; 127 128 case "skin": 129 self.setSkin( args[1] ); 130 131 break; 132 }; 133 134 } 135 136 // return actual object 137 else if( !action && !opt_value ){ 138 if( !isArray( returnValue ) ) 139 returnValue = []; 140 141 returnValue.push( self ); 142 } 143 }); 144 145 // flatten array just with one slider 146 if( isArray( returnValue ) && returnValue.length == 1 ) 147 returnValue = returnValue[ 0 ]; 148 149 return returnValue || this; 150 }; 151 152 var OPTIONS = { 153 154 settings: { 155 from: 1, 156 to: 10, 157 step: 1, 158 smooth: true, 159 limits: true, 160 round: 0, 161 format: { format: "#,##0.##" }, 162 value: "5;7", 163 dimension: "" 164 }, 165 166 className: "jslider", 167 selector: ".jslider-", 168 169 template: tmpl( 170 '<span class="<%=className%>">' + 171 '<table><tr><td>' + 172 '<div class="<%=className%>-bg">' + 173 '<i class="l"></i><i class="f"></i><i class="r"></i>' + 174 '<i class="v"></i>' + 175 '</div>' + 176 177 '<div class="<%=className%>-pointer"></div>' + 178 '<div class="<%=className%>-pointer <%=className%>-pointer-to"></div>' + 179 180 '<div class="<%=className%>-label"><span><%=settings.from%></span></div>' + 181 '<div class="<%=className%>-label <%=className%>-label-to"><%=settings.dimension%><span><%=settings.to%></span></div>' + 182 183 '<div class="<%=className%>-value"><%=settings.dimension%><span></span></div>' + 184 '<div class="<%=className%>-value <%=className%>-value-to"><%=settings.dimension%><span></span></div>' + 185 186 '<div class="<%=className%>-scale"><%=scale%></div>'+ 187 188 '</td></tr></table>' + 189 '</span>' 190 ) 191 192 }; 193 194 function jSlider(){ 195 return this.init.apply( this, arguments ); 196 }; 197 198 jSlider.prototype.init = function( node, settings ){ 199 this.settings = $.extend(true, {}, OPTIONS.settings, settings ? settings : {}); 200 201 // obj.sliderHandler = this; 202 this.inputNode = $( node ).hide(); 203 204 this.settings.interval = this.settings.to-this.settings.from; 205 this.settings.value = this.inputNode.attr("value"); 206 207 if( this.settings.calculate && $.isFunction( this.settings.calculate ) ) 208 this.nice = this.settings.calculate; 209 210 if( this.settings.onstatechange && $.isFunction( this.settings.onstatechange ) ) 211 this.onstatechange = this.settings.onstatechange; 212 213 this.is = { 214 init: false 215 }; 216 this.o = {}; 217 218 this.create(); 219 }; 220 221 jSlider.prototype.onstatechange = function(){ 222 223 }; 224 225 jSlider.prototype.create = function(){ 226 var $this = this; 227 228 this.domNode = $( OPTIONS.template({ 229 className: OPTIONS.className, 230 settings: { 231 from: this.nice( this.settings.from ), 232 to: this.nice( this.settings.to ), 233 dimension: this.settings.dimension 234 }, 235 scale: this.generateScale() 236 }) ); 237 238 this.inputNode.after( this.domNode ); 239 this.drawScale(); 240 241 // set skin class 242 if( this.settings.skin && this.settings.skin.length > 0 ) 243 this.setSkin( this.settings.skin ); 244 245 this.sizes = { 246 domWidth: this.domNode.width(), 247 domOffset: this.domNode.offset() 248 }; 249 250 // find some objects 251 $.extend(this.o, { 252 pointers: {}, 253 labels: { 254 0: { 255 o: this.domNode.find(OPTIONS.selector + "value").not(OPTIONS.selector + "value-to") 256 }, 257 1: { 258 o: this.domNode.find(OPTIONS.selector + "value").filter(OPTIONS.selector + "value-to") 259 } 260 }, 261 limits: { 262 0: this.domNode.find(OPTIONS.selector + "label").not(OPTIONS.selector + "label-to"), 263 1: this.domNode.find(OPTIONS.selector + "label").filter(OPTIONS.selector + "label-to") 264 } 265 }); 266 267 $.extend(this.o.labels[0], { 268 value: this.o.labels[0].o.find("span") 269 }); 270 271 $.extend(this.o.labels[1], { 272 value: this.o.labels[1].o.find("span") 273 }); 274 275 276 if( !$this.settings.value.split(";")[1] ){ 277 this.settings.single = true; 278 this.domNode.addDependClass("single"); 279 } 280 281 if( !$this.settings.limits ) 282 this.domNode.addDependClass("limitless"); 283 284 this.domNode.find(OPTIONS.selector + "pointer").each(function( i ){ 285 var value = $this.settings.value.split(";")[i]; 286 if( value ){ 287 $this.o.pointers[i] = new jSliderPointer( this, i, $this ); 288 289 var prev = $this.settings.value.split(";")[i-1];
290 if( prev && new Number(value) < new Number(prev) ) value = prev; 291 292 value = value < $this.settings.from ? $this.settings.from : value; 293 value = value > $this.settings.to ? $this.settings.to : value; 294 295 $this.o.pointers[i].set( value, true ); 296 } 297 }); 298 299 this.o.value = this.domNode.find(".v"); 300 this.is.init = true; 301 302 $.each(this.o.pointers, function(i){ 303 $this.redraw(this); 304 }); 305 306 (function(self){ 307 $(window).resize(function(){ 308 self.onresize(); 309 }); 310 })(this); 311 312 }; 313 314 jSlider.prototype.setSkin = function( skin ){ 315 if( this.skin_ ) 316 this.domNode.removeDependClass( this.skin_, "_" ); 317 318 this.domNode.addDependClass( this.skin_ = skin, "_" ); 319 }; 320 321 jSlider.prototype.setPointersIndex = function( i ){ 322 $.each(this.getPointers(), function(i){ 323 this.index( i ); 324 }); 325 }; 326 327 jSlider.prototype.getPointers = function(){ 328 return this.o.pointers; 329 }; 330 331 jSlider.prototype.generateScale = function(){ 332 if( this.settings.scale && this.settings.scale.length > 0 ){ 333 var str = ""; 334 var s = this.settings.scale; 335 var prc = Math.round((100/(s.length-1))*10)/10; 336 for( var i=0; i < s.length; i++ ){ 337 str += '<span style="left: ' + i*prc + '%">' + ( s[i] != '|' ? '<ins>' + s[i] + '</ins>' : '' ) + '</span>'; 338 }; 339 return str; 340 } else return ""; 341 342 return ""; 343 }; 344 345 jSlider.prototype.drawScale = function(){ 346 this.domNode.find(OPTIONS.selector + "scale span ins").each(function(){ 347 $(this).css({ marginLeft: -$(this).outerWidth()/2 }); 348 }); 349 }; 350 351 jSlider.prototype.onresize = function(){ 352 var self = this; 353 this.sizes = { 354 domWidth: this.domNode.width(), 355 domOffset: this.domNode.offset() 356 }; 357 358 $.each(this.o.pointers, function(i){ 359 self.redraw(this); 360 }); 361 }; 362 363 jSlider.prototype.update = function(){ 364 this.onresize(); 365 this.drawScale(); 366 }; 367 368 jSlider.prototype.limits = function( x, pointer ){ 369 // smooth 370 if( !this.settings.smooth ){ 371 var step = this.settings.step*100 / ( this.settings.interval ); 372 x = Math.round( x/step ) * step; 373 } 374 375 var another = this.o.pointers[1-pointer.uid]; 376 if( another && pointer.uid && x < another.value.prc ) x = another.value.prc; 377 if( another && !pointer.uid && x > another.value.prc ) x = another.value.prc; 378 379 // base limit 380 if( x < 0 ) x = 0; 381 if( x > 100 ) x = 100; 382 383 return Math.round( x*10 ) / 10; 384 }; 385 386 jSlider.prototype.redraw = function( pointer ){ 387 if( !this.is.init ) return false; 388 389 this.setValue(); 390 391 // redraw range line 392 if( this.o.pointers[0] && this.o.pointers[1] ) 393 this.o.value.css({ left: this.o.pointers[0].value.prc + "%", width: ( this.o.pointers[1].value.prc - this.o.pointers[0].value.prc ) + "%" }); 394 395 this.o.labels[pointer.uid].value.html( 396 this.nice( 397 pointer.value.origin 398 ) 399 ); 400 401 // redraw position of labels 402 this.redrawLabels( pointer ); 403 404 }; 405 406 jSlider.prototype.redrawLabels = function( pointer ){ 407 408 function setPosition( label, sizes, prc ){ 409 sizes.margin = -sizes.label/2; 410 411 // left limit 412 label_left = sizes.border + sizes.margin; 413 if( label_left < 0 ) 414 sizes.margin -= label_left; 415 416 // right limit 417 if( sizes.border+sizes.label / 2 > self.sizes.domWidth ){ 418 sizes.margin = 0; 419 sizes.right = true; 420 } else 421 sizes.right = false; 422 423 label.o.css({ left: prc + "%", marginLeft: sizes.margin, right: "auto" }); 424 if( sizes.right ) label.o.css({ left: "auto", right: 0 }); 425 return sizes; 426 } 427 428 var self = this; 429 var label = this.o.labels[pointer.uid]; 430 var prc = pointer.value.prc; 431 432 var sizes = { 433 label: label.o.outerWidth(), 434 right: false, 435 border: ( prc * this.sizes.domWidth ) / 100 436 }; 437 438 if( !this.settings.single ){ 439 // glue if near; 440 var another = this.o.pointers[1-pointer.uid]; 441 var another_label = this.o.labels[another.uid]; 442 443 switch( pointer.uid ){ 444 case 0: 445 if( sizes.border+sizes.label / 2 > another_label.o.offset().left-this.sizes.domOffset.left ){ 446 another_label.o.css({ visibility: "hidden" }); 447 another_label.value.html( this.nice( another.value.origin ) ); 448 449 label.o.css({ visibility: "visible" }); 450 451 prc = ( another.value.prc - prc ) / 2 + prc; 452 if( another.value.prc != pointer.value.prc ){ 453 label.value.html( this.nice(pointer.value.origin) + " – " + this.nice(another.value.origin) ); 454 sizes.label = label.o.outerWidth(); 455 sizes.border = ( prc * this.sizes.domWidth ) / 100; 456 } 457 } else { 458 another_label.o.css({ visibility: "visible" }); 459 } 460 break; 461 462 case 1: 463 if( sizes.border - sizes.label / 2 < another_label.o.offset().left - this.sizes.domOffset.left + another_label.o.outerWidth() ){ 464 another_label.o.css({ visibility: "hidden" }); 465 another_label.value.html( this.nice(another.value.origin) ); 466 467 label.o.css({ visibility: "visible" }); 468 469 prc = ( prc - another.value.prc ) / 2 + another.value.prc; 470 if( another.value.prc != pointer.value.prc ){ 471 label.value.html( this.nice(another.value.origin) + " – " + this.nice(pointer.value.origin) ); 472 sizes.label = label.o.outerWidth(); 473 sizes.border = ( prc * this.sizes.domWidth ) / 100; 474 } 475 } else { 476 another_label.o.css({ visibility: "visible" }); 477 } 478 break; 479 } 480 } 481 482 sizes = setPosition( label, sizes, prc ); 483 484 /* draw second label */ 485 if( another_label ){ 486 var sizes = { 487 label: another_label.o.outerWidth(), 488 right: false, 489 border: ( another.value.prc * this.sizes.domWidth ) / 100 490 }; 491 sizes = setPosition( another_label, sizes, another.value.prc ); 492 } 493 494 this.redrawLimits(); 495 }; 496 497 jSlider.prototype.redrawLimits = function(){ 498 if( this.settings.limits ){ 499 500 var limits = [ true, true ]; 501 502 for( key in this.o.pointers ){ 503 504 if( !this.settings.single || key == 0 ){ 505 506 var pointer = this.o.pointers[key]; 507 var label = this.o.labels[pointer.uid]; 508 var label_left = label.o.offset().left - this.sizes.domOffset.left; 509 510 var limit = this.o.limits[0]; 511 if( label_left < limit.outerWidth() ) 512 limits[0] = false;
513 514 var limit = this.o.limits[1]; 515 if( label_left + label.o.outerWidth() > this.sizes.domWidth - limit.outerWidth() ) 516 limits[1] = false; 517 } 518 519 }; 520 521 for( var i=0; i < limits.length; i++ ){ 522 if( limits[i] ) 523 this.o.limits[i].fadeIn("fast"); 524 else 525 this.o.limits[i].fadeOut("fast"); 526 }; 527 528 } 529 }; 530 531 jSlider.prototype.setValue = function(){ 532 var value = this.getValue(); 533 this.inputNode.attr( "value", value ); 534 this.onstatechange.call( this, value ); 535 }; 536 537 jSlider.prototype.getValue = function(){ 538 if(!this.is.init) return false; 539 var $this = this; 540 541 var value = ""; 542 $.each( this.o.pointers, function(i){ 543 if( this.value.prc != undefined && !isNaN(this.value.prc) ) value += (i > 0 ? ";" : "") + $this.prcToValue( this.value.prc ); 544 }); 545 return value; 546 }; 547 548 jSlider.prototype.getPrcValue = function(){ 549 if(!this.is.init) return false; 550 var $this = this; 551 552 var value = ""; 553 $.each( this.o.pointers, function(i){ 554 if( this.value.prc != undefined && !isNaN(this.value.prc) ) value += (i > 0 ? ";" : "") + this.value.prc; 555 }); 556 return value; 557 }; 558 559 jSlider.prototype.prcToValue = function( prc ){ 560 561 if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){ 562 var h = this.settings.heterogeneity; 563 564 var _start = 0; 565 var _from = this.settings.from; 566 567 for( var i=0; i <= h.length; i++ ){ 568 if( h[i] ) var v = h[i].split("/"); 569 else var v = [100, this.settings.to]; 570 571 v[0] = new Number(v[0]); 572 v[1] = new Number(v[1]); 573 574 if( prc >= _start && prc <= v[0] ) { 575 var value = _from + ( (prc-_start) * (v[1]-_from) ) / (v[0]-_start); 576 } 577 578 _start = v[0]; 579 _from = v[1]; 580 }; 581 582 } else { 583 var value = this.settings.from + ( prc * this.settings.interval ) / 100; 584 } 585 586 return this.round( value ); 587 }; 588 589 jSlider.prototype.valueToPrc = function( value, pointer ){ 590 if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){ 591 var h = this.settings.heterogeneity; 592 593 var _start = 0; 594 var _from = this.settings.from; 595 596 for (var i=0; i <= h.length; i++) { 597 if(h[i]) var v = h[i].split("/"); 598 else var v = [100, this.settings.to]; 599 v[0] = new Number(v[0]); v[1] = new Number(v[1]); 600 601 if(value >= _from && value <= v[1]){ 602 var prc = pointer.limits(_start + (value-_from)*(v[0]-_start)/(v[1]-_from)); 603 } 604 605 _start = v[0]; _from = v[1]; 606 }; 607 608 } else { 609 var prc = pointer.limits((value-this.settings.from)*100/this.settings.interval); 610 } 611 612 return prc; 613 }; 614 615 jSlider.prototype.round = function( value ){ 616 value = Math.round( value / this.settings.step ) * this.settings.step; 617 if( this.settings.round ) value = Math.round( value * Math.pow(10, this.settings.round) ) / Math.pow(10, this.settings.round); 618 else value = Math.round( value ); 619 return value; 620 }; 621 622 jSlider.prototype.nice = function( value ){ 623 value = value.toString().replace(/,/gi, ".").replace(/ /gi, "");; 624 625 if( $.formatNumber ){ 626 return $.formatNumber( new Number(value), this.settings.format || {} ).replace( /-/gi, "−" ); 627 } 628 629 else { 630 return new Number(value); 631 } 632 }; 633 634 635 function jSliderPointer(){ 636 Draggable.apply( this, arguments ); 637 } 638 jSliderPointer.prototype = new Draggable(); 639 640 jSliderPointer.prototype.oninit = function( ptr, id, _constructor ){ 641 this.uid = id; 642 this.parent = _constructor; 643 this.value = {}; 644 this.settings = this.parent.settings; 645 }; 646 647 jSliderPointer.prototype.onmousedown = function(evt){ 648 this._parent = { 649 offset: this.parent.domNode.offset(), 650 width: this.parent.domNode.width() 651 }; 652 this.ptr.addDependClass("hover"); 653 this.setIndexOver(); 654 }; 655 656 jSliderPointer.prototype.onmousemove = function( evt, x ){ 657 var coords = this._getPageCoords( evt ); 658 this._set( this.calc( coords.x ) ); 659 }; 660 661 jSliderPointer.prototype.onmouseup = function( evt ){ 662 if( this.parent.settings.callback && $.isFunction(this.parent.settings.callback) ) 663 this.parent.settings.callback.call( this.parent, this.parent.getValue() ); 664 665 this.ptr.removeDependClass("hover"); 666 }; 667 668 jSliderPointer.prototype.setIndexOver = function(){ 669 this.parent.setPointersIndex( 1 ); 670 this.index( 2 ); 671 }; 672 673 jSliderPointer.prototype.index = function( i ){ 674 this.ptr.css({ zIndex: i }); 675 }; 676 677 jSliderPointer.prototype.limits = function( x ){ 678 return this.parent.limits( x, this ); 679 }; 680 681 jSliderPointer.prototype.calc = function(coords){ 682 var x = this.limits(((coords-this._parent.offset.left)*100)/this._parent.width); 683 return x; 684 }; 685 686 jSliderPointer.prototype.set = function( value, opt_origin ){ 687 this.value.origin = this.parent.round(value); 688 this._set( this.parent.valueToPrc( value, this ), opt_origin ); 689 }; 690 691 jSliderPointer.prototype._set = function( prc, opt_origin ){ 692 if( !opt_origin ) 693 this.value.origin = this.parent.prcToValue(prc); 694 695 this.value.prc = prc; 696 this.ptr.css({ left: prc + "%" }); 697 this.parent.redraw(this); 698 }; 699 700})(jQuery);
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.