1/* ========================================================= 2 * bootstrap-colorpicker.js 3 * http://www.eyecon.ro/bootstrap-colorpicker 4 * ========================================================= 5 * Copyright 2012 Stefan Petre 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * ========================================================= */ 19 20 21!function( $ ) { 22 23 // Color object 24 25 var Color = function(val) { 26 this.value = { 27 h: 1, 28 s: 1, 29 b: 1, 30 a: 1 31 }; 32 this.setColor(val); 33 }; 34 35 Color.prototype = { 36 constructor: Color, 37 38 //parse a string to HSB 39 setColor: function(val){ 40 val = val.toLowerCase(); 41 var that = this; 42 $.each( CPGlobal.stringParsers, function( i, parser ) { 43 var match = parser.re.exec( val ), 44 values = match && parser.parse( match ), 45 space = parser.space||'rgba'; 46 if ( values ) { 47 if (space === 'hsla') { 48 that.value = CPGlobal.RGBtoHSB.apply(null, CPGlobal.HSLtoRGB.apply(null, values)); 49 } else { 50 that.value = CPGlobal.RGBtoHSB.apply(null, values); 51 } 52 return false; 53 } 54 }); 55 }, 56 57 setHue: function(h) { 58 this.value.h = 1- h; 59 }, 60 61 setSaturation: function(s) { 62 this.value.s = s; 63 }, 64 65 setLightness: function(b) { 66 this.value.b = 1- b; 67 }, 68 69 setAlpha: function(a) { 70 this.value.a = parseInt((1 - a)*100, 10)/100; 71 }, 72 73 // HSBtoRGB from RaphaelJS 74 // https://github.com/DmitryBaranovskiy/raphael/ 75 toRGB: function(h, s, b, a) { 76 if (!h) { 77 h = this.value.h; 78 s = this.value.s; 79 b = this.value.b; 80 } 81 h *= 360; 82 var R, G, B, X, C; 83 h = (h % 360) / 60; 84 C = b * s; 85 X = C * (1 - Math.abs(h % 2 - 1)); 86 R = G = B = b - C; 87 88 h = ~~h; 89 R += [C, X, 0, 0, X, C][h]; 90 G += [X, C, C, X, 0, 0][h]; 91 B += [0, 0, X, C, C, X][h]; 92 return { 93 r: Math.round(R*255), 94 g: Math.round(G*255), 95 b: Math.round(B*255), 96 a: a||this.value.a 97 }; 98 }, 99 100 toHex: function(h, s, b, a){ 101 var rgb = this.toRGB(h, s, b, a); 102 return '#'+((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1); 103 }, 104 105 toHSL: function(h, s, b, a){ 106 if (!h) { 107 h = this.value.h; 108 s = this.value.s; 109 b = this.value.b; 110 } 111 var H = h, 112 L = (2 - s) * b, 113 S = s * b; 114 if (L > 0 && L <= 1) { 115 S /= L; 116 } else { 117 S /= 2 - L; 118 } 119 L /= 2; 120 if (S > 1) { 121 S = 1; 122 } 123 return { 124 h: H, 125 s: S, 126 l: L, 127 a: a||this.value.a 128 }; 129 } 130 }; 131 132 // Picker object 133 134 var Colorpicker = function(element, options){ 135 this.element = $(element); 136 var format = options.format||this.element.data('color-format')||'hex'; 137 this.format = CPGlobal.translateFormats[format]; 138 this.isInput = this.element.is('input'); 139 this.component = this.element.is('.color') ? this.element.find('.input-group-addon') : false; 140 141 this.picker = $(CPGlobal.template) 142 .appendTo('body') 143 .on('mousedown', $.proxy(this.mousedown, this)); 144 145 if (this.isInput) { 146 this.element.on({ 147 'focus': $.proxy(this.show, this), 148 'keyup': $.proxy(this.update, this) 149 }); 150 } else if (this.component){ 151 this.component.on({ 152 'click': $.proxy(this.show, this) 153 }); 154 } else { 155 this.element.on({ 156 'click': $.proxy(this.show, this) 157 }); 158 } 159 if (format === 'rgba' || format === 'hsla') {
160 this.picker.addClass('alpha'); 161 this.alpha = this.picker.find('.colorpicker-alpha')[0].style; 162 } 163 164 if (this.component){ 165 this.picker.find('.colorpicker-color').hide(); 166 this.preview = this.element.find('i')[0].style; 167 } else { 168 this.preview = this.picker.find('div:last')[0].style; 169 } 170 171 this.base = this.picker.find('div:first')[0].style; 172 this.update(); 173 }; 174 175 Colorpicker.prototype = { 176 constructor: Colorpicker, 177 178 show: function(e) { 179 this.picker.show(); 180 this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); 181 this.place(); 182 $(window).on('resize', $.proxy(this.place, this)); 183 if (!this.isInput) { 184 if (e) { 185 e.stopPropagation(); 186 e.preventDefault(); 187 } 188 } 189 $(document).on({ 190 'mousedown': $.proxy(this.hide, this) 191 }); 192 this.element.trigger({ 193 type: 'show', 194 color: this.color 195 }); 196 }, 197 198 update: function(){ 199 this.color = new Color(this.isInput ? this.element.prop('value') : this.element.data('color')); 200 this.picker.find('i') 201 .eq(0).css({left: this.color.value.s*100, top: 100 - this.color.value.b*100}).end() 202 .eq(1).css('top', 100 * (1 - this.color.value.h)).end() 203 .eq(2).css('top', 100 * (1 - this.color.value.a)); 204 this.previewColor(); 205 }, 206 207 setValue: function(newColor) { 208 this.color = new Color(newColor); 209 this.picker.find('i') 210 .eq(0).css({left: this.color.value.s*100, top: 100 - this.color.value.b*100}).end() 211 .eq(1).css('top', 100 * (1 - this.color.value.h)).end() 212 .eq(2).css('top', 100 * (1 - this.color.value.a)); 213 this.previewColor(); 214 this.element.trigger({ 215 type: 'changeColor', 216 color: this.color 217 }); 218 }, 219 220 hide: function(){ 221 this.picker.hide(); 222 $(window).off('resize', this.place); 223 if (!this.isInput) { 224 $(document).off({ 225 'mousedown': this.hide 226 }); 227 if (this.component){ 228 this.element.find('input').prop('value', this.format.call(this)); 229 } 230 this.element.data('color', this.format.call(this)); 231 } else { 232 this.element.prop('value', this.format.call(this)); 233 } 234 this.element.trigger({ 235 type: 'hide', 236 color: this.color 237 }); 238 }, 239 240 place: function(){ 241 var offset = this.component ? this.component.offset() : this.element.offset(); 242 this.picker.css({ 243 top: offset.top + this.height, 244 left: offset.left 245 }); 246 }, 247 248 //preview color change 249 previewColor: function(){
250 try { 251 this.preview.backgroundColor = this.format.call(this); 252 } catch(e) { 253 this.preview.backgroundColor = this.color.toHex(); 254 } 255 //set the color for brightness/saturation slider 256 this.base.backgroundColor = this.color.toHex(this.color.value.h, 1, 1, 1); 257 //set te color for alpha slider 258 if (this.alpha) { 259 this.alpha.backgroundColor = this.color.toHex(); 260 } 261 }, 262 263 pointer: null, 264 265 slider: null, 266 267 mousedown: function(e){ 268 e.stopPropagation(); 269 e.preventDefault(); 270 271 var target = $(e.target); 272 273 //detect the slider and set the limits and callbacks 274 var zone = target.closest('div'); 275 if (!zone.is('.colorpicker')) { 276 if (zone.is('.colorpicker-saturation')) { 277 this.slider = $.extend({}, CPGlobal.sliders.saturation); 278 } 279 else if (zone.is('.colorpicker-hue')) { 280 this.slider = $.extend({}, CPGlobal.sliders.hue); 281 } 282 else if (zone.is('.colorpicker-alpha')) { 283 this.slider = $.extend({}, CPGlobal.sliders.alpha); 284 } else { 285 return false; 286 } 287 var offset = zone.offset(); 288 //reference to knob's style 289 this.slider.knob = zone.find('i')[0].style; 290 this.slider.left = e.pageX - offset.left; 291 this.slider.top = e.pageY - offset.top; 292 this.pointer = { 293 left: e.pageX, 294 top: e.pageY 295 }; 296 //trigger mousemove to move the knob to the current position 297 $(document).on({ 298 mousemove: $.proxy(this.mousemove, this), 299 mouseup: $.proxy(this.mouseup, this) 300 }).trigger('mousemove'); 301 } 302 return false; 303 }, 304 305 mousemove: function(e){ 306 e.stopPropagation(); 307 e.preventDefault(); 308 var left = Math.max( 309 0, 310 Math.min( 311 this.slider.maxLeft, 312 this.slider.left + ((e.pageX||this.pointer.left) - this.pointer.left) 313 ) 314 ); 315 var top = Math.max( 316 0, 317 Math.min( 318 this.slider.maxTop, 319 this.slider.top + ((e.pageY||this.pointer.top) - this.pointer.top) 320 ) 321 ); 322 this.slider.knob.left = left + 'px'; 323 this.slider.knob.top = top + 'px'; 324 if (this.slider.callLeft) { 325 this.color[this.slider.callLeft].call(this.color, left/100); 326 } 327 if (this.slider.callTop) { 328 this.color[this.slider.callTop].call(this.color, top/100); 329 } 330 this.previewColor(); 331 this.element.trigger({ 332 type: 'changeColor', 333 color: this.color 334 }); 335 return false; 336 }, 337 338 mouseup: function(e){ 339 e.stopPropagation(); 340 e.preventDefault(); 341 $(document).off({ 342 mousemove: this.mousemove, 343 mouseup: this.mouseup 344 }); 345 return false; 346 } 347 } 348 349 $.fn.colorpicker = function ( option, val ) { 350 return this.each(function () { 351 var $this = $(this), 352 data = $this.data('colorpicker'), 353 options = typeof option === 'object' && option; 354 if (!data) { 355 $this.data('colorpicker', (data = new Colorpicker(this, $.extend({}, $.fn.colorpicker.defaults,options)))); 356 } 357 if (typeof option === 'string') data[option](val); 358 }); 359 }; 360 361 $.fn.colorpicker.defaults = { 362 }; 363 364 $.fn.colorpicker.Constructor = Colorpicker; 365 366 var CPGlobal = { 367 368 // translate a format from Color object to a string 369 translateFormats: { 370 'rgb': function(){ 371 var rgb = this.color.toRGB(); 372 return 'rgb('+rgb.r+','+rgb.g+','+rgb.b+')'; 373 }, 374 375 'rgba': function(){ 376 var rgb = this.color.toRGB(); 377 return 'rgba('+rgb.r+','+rgb.g+','+rgb.b+','+rgb.a+')'; 378 }, 379 380 'hsl': function(){ 381 var hsl = this.color.toHSL(); 382 return 'hsl('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%)'; 383 }, 384 385 'hsla': function(){ 386 var hsl = this.color.toHSL(); 387 return 'hsla('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%,'+hsl.a+')'; 388 }, 389 390 'hex': function(){ 391 return this.color.toHex(); 392 } 393 }, 394 395 sliders: { 396 saturation: { 397 maxLeft: 100, 398 maxTop: 100,
399 callLeft: 'setSaturation', 400 callTop: 'setLightness' 401 }, 402 403 hue: { 404 maxLeft: 0, 405 maxTop: 100, 406 callLeft: false, 407 callTop: 'setHue' 408 }, 409 410 alpha: { 411 maxLeft: 0, 412 maxTop: 100, 413 callLeft: false, 414 callTop: 'setAlpha' 415 } 416 }, 417 418 // HSBtoRGB from RaphaelJS 419 // https://github.com/DmitryBaranovskiy/raphael/ 420 RGBtoHSB: function (r, g, b, a){ 421 r /= 255; 422 g /= 255; 423 b /= 255; 424 425 var H, S, V, C; 426 V = Math.max(r, g, b); 427 C = V - Math.min(r, g, b); 428 H = (C === 0 ? null : 429 V == r ? (g - b) / C : 430 V == g ? (b - r) / C + 2 : 431 (r - g) / C + 4 432 ); 433 H = ((H + 360) % 6) * 60 / 360; 434 S = C === 0 ? 0 : C / V; 435 return {h: H||1, s: S, b: V, a: a||1}; 436 }, 437 438 HueToRGB: function (p, q, h) { 439 if (h < 0) 440 h += 1; 441 else if (h > 1) 442 h -= 1; 443 444 if ((h * 6) < 1) 445 return p + (q - p) * h * 6; 446 else if ((h * 2) < 1) 447 return q; 448 else if ((h * 3) < 2) 449 return p + (q - p) * ((2 / 3) - h) * 6; 450 else 451 return p; 452 }, 453 454 HSLtoRGB: function (h, s, l, a) 455 { 456 if (s < 0) { 457 s = 0; 458 } 459 var q; 460 if (l <= 0.5) { 461 q = l * (1 + s); 462 } else { 463 q = l + s - (l * s); 464 } 465 466 var p = 2 * l - q; 467 468 var tr = h + (1 / 3); 469 var tg = h; 470 var tb = h - (1 / 3); 471 472 var r = Math.round(CPGlobal.HueToRGB(p, q, tr) * 255); 473 var g = Math.round(CPGlobal.HueToRGB(p, q, tg) * 255); 474 var b = Math.round(CPGlobal.HueToRGB(p, q, tb) * 255); 475 return [r, g, b, a||1]; 476 }, 477 478 // a set of RE's that can match strings and generate color tuples. 479 // from John Resig color plugin 480 // https://github.com/jquery/jquery-color/ 481 stringParsers: [ 482 { 483 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, 484 parse: function( execResult ) { 485 return [ 486 execResult[ 1 ], 487 execResult[ 2 ], 488 execResult[ 3 ], 489 execResult[ 4 ] 490 ]; 491 } 492 }, { 493 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, 494 parse: function( execResult ) { 495 return [ 496 2.55 * execResult[1], 497 2.55 * execResult[2], 498 2.55 * execResult[3], 499 execResult[ 4 ] 500 ]; 501 } 502 }, { 503 re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/, 504 parse: function( execResult ) { 505 return [ 506 parseInt( execResult[ 1 ], 16 ), 507 parseInt( execResult[ 2 ], 16 ), 508 parseInt( execResult[ 3 ], 16 ) 509 ]; 510 } 511 }, { 512 re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/, 513 parse: function( execResult ) { 514 return [ 515 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 516 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 517 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) 518 ]; 519 } 520 }, { 521 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, 522 space: 'hsla', 523 parse: function( execResult ) { 524 return [ 525 execResult[1]/360, 526 execResult[2] / 100, 527 execResult[3] / 100, 528 execResult[4] 529 ]; 530 } 531 } 532 ], 533 template: '<div class="colorpicker dropdown-menu">'+ 534 '<div class="colorpicker-saturation"><i><b></b></i></div>'+ 535 '<div class="colorpicker-hue"><i></i></div>'+ 536 '<div class="colorpicker-alpha"><i></i></div>'+ 537 '<div class="colorpicker-color"><div /></div>'+ 538 '</div>' 539 }; 540 541}( window.jQuery ) 542;
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.