vendor: 42,615 bytes, lines 1-1224
1// Spectrum Colorpicker v1.5.1 2// https://github.com/bgrins/spectrum 3// Author: Brian Grinstead 4// License: MIT 5 6(function (window, $, undefined) { 7 "use strict"; 8 9 var defaultOpts = { 10 11 // Callbacks 12 beforeShow: noop, 13 move: noop, 14 change: noop, 15 show: noop, 16 hide: noop, 17 18 // Options 19 color: false, 20 flat: false, 21 showInput: false, 22 allowEmpty: false, 23 showButtons: true, 24 clickoutFiresChange: false, 25 showInitial: false, 26 showPalette: false, 27 showPaletteOnly: false, 28 hideAfterPaletteSelect: false, 29 togglePaletteOnly: false, 30 showSelectionPalette: true, 31 localStorageKey: false, 32 appendTo: "body", 33 maxSelectionSize: 7, 34 cancelText: "cancel", 35 chooseText: "choose", 36 togglePaletteMoreText: "more", 37 togglePaletteLessText: "less", 38 clearText: "Clear Color Selection", 39 noColorSelectedText: "No Color Selected", 40 preferredFormat: false, 41 className: "", // Deprecated - use containerClassName and replacerClassName instead. 42 containerClassName: "", 43 replacerClassName: "", 44 showAlpha: false, 45 theme: "sp-light", 46 palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]], 47 selectionPalette: [], 48 disabled: false 49 }, 50 spectrums = [], 51 IE = !!/msie/i.exec( window.navigator.userAgent ), 52 rgbaSupport = (function() { 53 function contains( str, substr ) { 54 return !!~('' + str).indexOf(substr); 55 } 56 57 var elem = document.createElement('div'); 58 var style = elem.style; 59 style.cssText = 'background-color:rgba(0,0,0,.5)'; 60 return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla'); 61 })(), 62 inputTypeColorSupport = (function() { 63 var colorInput = $("<input type='color' value='!' />")[0]; 64 return colorInput.type === "color" && colorInput.value !== "!"; 65 })(), 66 replaceInput = [ 67 "<div class='sp-replacer'>", 68 "<div class='sp-preview'><div class='sp-preview-inner'></div></div>", 69 "<div class='sp-dd'>▼</div>", 70 "</div>" 71 ].join(''), 72 markup = (function () { 73 74 // IE does not support gradients with multiple stops, so we need to simulate 75 // that for the rainbow slider with 8 divs that each have a single gradient 76 var gradientFix = ""; 77 if (IE) { 78 for (var i = 1; i <= 6; i++) { 79 gradientFix += "<div class='sp-" + i + "'></div>"; 80 } 81 } 82 83 return [ 84 "<div class='sp-container sp-hidden'>", 85 "<div class='sp-palette-container'>", 86 "<div class='sp-palette sp-thumb sp-cf'></div>", 87 "<div class='sp-palette-button-container sp-cf'>", 88 "<button type='button' class='sp-palette-toggle'></button>", 89 "</div>", 90 "</div>", 91 "<div class='sp-picker-container'>", 92 "<div class='sp-top sp-cf'>", 93 "<div class='sp-fill'></div>", 94 "<div class='sp-top-inner'>", 95 "<div class='sp-color'>", 96 "<div class='sp-sat'>", 97 "<div class='sp-val'>", 98 "<div class='sp-dragger'></div>", 99 "</div>", 100 "</div>", 101 "</div>", 102 "<div class='sp-clear sp-clear-display'>", 103 "</div>", 104 "<div class='sp-hue'>", 105 "<div class='sp-slider'></div>", 106 gradientFix, 107 "</div>", 108 "</div>", 109 "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>", 110 "</div>", 111 "<div class='sp-input-container sp-cf'>", 112 "<input class='sp-input' type='text' spellcheck='false' />", 113 "</div>", 114 "<div class='sp-initial sp-thumb sp-cf'></div>", 115 "<div class='sp-button-container sp-cf'>", 116 "<a class='sp-cancel' href='#'></a>", 117 "<button type='button' class='sp-choose'></button>", 118 "</div>", 119 "</div>", 120 "</div>" 121 ].join(""); 122 })(); 123 124 function paletteTemplate (p, color, className, opts) { 125 var html = []; 126 for (var i = 0; i < p.length; i++) { 127 var current = p[i]; 128 if(current) { 129 var tiny = tinycolor(current); 130 var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light"; 131 c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : ""; 132 var formattedString = tiny.toString(opts.preferredFormat || "rgb"); 133 var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter(); 134 html.push('<span title="' + formattedString + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';" /></span>'); 135 } else { 136 var cls = 'sp-clear-display'; 137 html.push($('<div />') 138 .append($('<span data-color="" style="background-color:transparent;" class="' + cls + '"></span>') 139 .attr('title', opts.noColorSelectedText) 140 ) 141 .html() 142 ); 143 } 144 } 145 return "<div class='sp-cf " + className + "'>" + html.join('') + "</div>"; 146 } 147 148 function hideAll() { 149 for (var i = 0; i < spectrums.length; i++) { 150 if (spectrums[i]) { 151 spectrums[i].hide(); 152 } 153 } 154 } 155 156 function instanceOptions(o, callbackContext) { 157 var opts = $.extend({}, defaultOpts, o); 158 opts.callbacks = { 159 'move': bind(opts.move, callbackContext), 160 'change': bind(opts.change, callbackContext), 161 'show': bind(opts.show, callbackContext), 162 'hide': bind(opts.hide, callbackContext), 163 'beforeShow': bind(opts.beforeShow, callbackContext) 164 }; 165 166 return opts; 167 } 168 169 function spectrum(element, o) { 170 171 var opts = instanceOptions(o, element), 172 flat = opts.flat, 173 showSelectionPalette = opts.showSelectionPalette, 174 localStorageKey = opts.localStorageKey, 175 theme = opts.theme, 176 callbacks = opts.callbacks, 177 resize = throttle(reflow, 10), 178 visible = false, 179 dragWidth = 0, 180 dragHeight = 0, 181 dragHelperHeight = 0, 182 slideHeight = 0, 183 slideWidth = 0, 184 alphaWidth = 0, 185 alphaSlideHelperWidth = 0, 186 slideHelperHeight = 0, 187 currentHue = 0, 188 currentSaturation = 0, 189 currentValue = 0, 190 currentAlpha = 1, 191 palette = [], 192 paletteArray = [], 193 paletteLookup = {}, 194 selectionPalette = opts.selectionPalette.slice(0), 195 maxSelectionSize = opts.maxSelectionSize, 196 draggingClass = "sp-dragging", 197 shiftMovementDirection = null; 198 199 var doc = element.ownerDocument, 200 body = doc.body, 201 boundElement = $(element), 202 disabled = false, 203 container = $(markup, doc).addClass(theme), 204 pickerContainer = container.find(".sp-picker-container"), 205 dragger = container.find(".sp-color"), 206 dragHelper = container.find(".sp-dragger"), 207 slider = container.find(".sp-hue"), 208 slideHelper = container.find(".sp-slider"), 209 alphaSliderInner = container.find(".sp-alpha-inner"), 210 alphaSlider = container.find(".sp-alpha"), 211 alphaSlideHelper = container.find(".sp-alpha-handle"), 212 textInput = container.find(".sp-input"), 213 paletteContainer = container.find(".sp-palette"), 214 initialColorContainer = container.find(".sp-initial"), 215 cancelButton = container.find(".sp-cancel"), 216 clearButton = container.find(".sp-clear"), 217 chooseButton = container.find(".sp-choose"), 218 toggleButton = container.find(".sp-palette-toggle"), 219 isInput = boundElement.is("input"), 220 isInputTypeColor = isInput && inputTypeColorSupport && boundElement.attr("type") === "color", 221 shouldReplace = isInput && !flat, 222 replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]), 223 offsetElement = (shouldReplace) ? replacer : boundElement, 224 previewElement = replacer.find(".sp-preview-inner"), 225 initialColor = opts.color || (isInput && boundElement.val()), 226 colorOnShow = false, 227 preferredFormat = opts.preferredFormat, 228 currentPreferredFormat = preferredFormat, 229 clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange, 230 isEmpty = !initialColor, 231 allowEmpty = opts.allowEmpty && !isInputTypeColor; 232 233 function applyOptions() { 234 235 if (opts.showPaletteOnly) { 236 opts.showPalette = true; 237 } 238 239 toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText); 240 241 if (opts.palette) { 242 palette = opts.palette.slice(0); 243 paletteArray = $.isArray(palette[0]) ? palette : [palette]; 244 paletteLookup = {}; 245 for (var i = 0; i < paletteArray.length; i++) { 246 for (var j = 0; j < paletteArray[i].length; j++) { 247 var rgb = tinycolor(paletteArray[i][j]).toRgbString(); 248 paletteLookup[rgb] = true; 249 } 250 } 251 } 252 253 container.toggleClass("sp-flat", flat); 254 container.toggleClass("sp-input-disabled", !opts.showInput); 255 container.toggleClass("sp-alpha-enabled", opts.showAlpha); 256 container.toggleClass("sp-clear-enabled", allowEmpty); 257 container.toggleClass("sp-buttons-disabled", !opts.showButtons); 258 container.toggleClass("sp-palette-buttons-disabled", !opts.togglePaletteOnly); 259 container.toggleClass("sp-palette-disabled", !opts.showPalette); 260 container.toggleClass("sp-palette-only", opts.showPaletteOnly); 261 container.toggleClass("sp-initial-disabled", !opts.showInitial); 262 container.addClass(opts.className).addClass(opts.containerClassName); 263 264 reflow(); 265 } 266 267 function initialize() { 268 269 if (IE) { 270 container.find("*:not(input)").attr("unselectable", "on"); 271 } 272 273 applyOptions(); 274 275 if (shouldReplace) { 276 boundElement.after(replacer).hide(); 277 } 278 279 if (!allowEmpty) { 280 clearButton.hide(); 281 } 282 283 if (flat) { 284 boundElement.after(container).hide(); 285 } 286 else { 287 288 var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo); 289 if (appendTo.length !== 1) { 290 appendTo = $("body"); 291 } 292 293 appendTo.append(container); 294 } 295 296 updateSelectionPaletteFromStorage(); 297 298 offsetElement.bind("click.spectrum touchstart.spectrum", function (e) { 299 if (!disabled) { 300 toggle(); 301 } 302 303 e.stopPropagation(); 304 305 if (!$(e.target).is("input")) { 306 e.preventDefault(); 307 } 308 }); 309 310 if(boundElement.is(":disabled") || (opts.disabled === true)) { 311 disable(); 312 } 313 314 // Prevent clicks from bubbling up to document. This would cause it to be hidden. 315 container.click(stopPropagation); 316 317 // Handle user typed input 318 textInput.change(setFromTextInput); 319 textInput.bind("paste", function () { 320 setTimeout(setFromTextInput, 1); 321 }); 322 textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } }); 323 324 cancelButton.text(opts.cancelText); 325 cancelButton.bind("click.spectrum", function (e) { 326 e.stopPropagation(); 327 e.preventDefault(); 328 revert(); 329 hide(); 330 }); 331 332 clearButton.attr("title", opts.clearText); 333 clearButton.bind("click.spectrum", function (e) { 334 e.stopPropagation(); 335 e.preventDefault(); 336 isEmpty = true; 337 move(); 338 339 if(flat) { 340 //for the flat style, this is a change event 341 updateOriginalInput(true); 342 } 343 }); 344 345 chooseButton.text(opts.chooseText); 346 chooseButton.bind("click.spectrum", function (e) { 347 e.stopPropagation(); 348 e.preventDefault(); 349 350 if (isValid()) { 351 updateOriginalInput(true); 352 hide(); 353 } 354 }); 355 356 toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText); 357 toggleButton.bind("click.spectrum", function (e) { 358 e.stopPropagation(); 359 e.preventDefault(); 360 361 opts.showPaletteOnly = !opts.showPaletteOnly; 362 363 // To make sure the Picker area is drawn on the right, next to the 364 // Palette area (and not below the palette), first move the Palette 365 // to the left to make space for the picker, plus 5px extra. 366 // The 'applyOptions' function puts the whole container back into place 367 // and takes care of the button-text and the sp-palette-only CSS class. 368 if (!opts.showPaletteOnly && !flat) { 369 container.css('left', '-=' + (pickerContainer.outerWidth(true) + 5)); 370 } 371 applyOptions(); 372 }); 373 374 draggable(alphaSlider, function (dragX, dragY, e) { 375 currentAlpha = (dragX / alphaWidth); 376 isEmpty = false; 377 if (e.shiftKey) { 378 currentAlpha = Math.round(currentAlpha * 10) / 10; 379 } 380 381 move(); 382 }, dragStart, dragStop); 383 384 draggable(slider, function (dragX, dragY) { 385 currentHue = parseFloat(dragY / slideHeight); 386 isEmpty = false; 387 if (!opts.showAlpha) { 388 currentAlpha = 1; 389 } 390 move(); 391 }, dragStart, dragStop); 392 393 draggable(dragger, function (dragX, dragY, e) { 394 395 // shift+drag should snap the movement to either the x or y axis. 396 if (!e.shiftKey) { 397 shiftMovementDirection = null; 398 } 399 else if (!shiftMovementDirection) { 400 var oldDragX = currentSaturation * dragWidth; 401 var oldDragY = dragHeight - (currentValue * dragHeight); 402 var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY); 403 404 shiftMovementDirection = furtherFromX ? "x" : "y"; 405 } 406 407 var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x"; 408 var setValue = !shiftMovementDirection || shiftMovementDirection === "y"; 409 410 if (setSaturation) { 411 currentSaturation = parseFloat(dragX / dragWidth); 412 } 413 if (setValue) { 414 currentValue = parseFloat((dragHeight - dragY) / dragHeight); 415 } 416 417 isEmpty = false; 418 if (!opts.showAlpha) { 419 currentAlpha = 1; 420 } 421 422 move(); 423 424 }, dragStart, dragStop); 425 426 if (!!initialColor) { 427 set(initialColor); 428 429 // In case color was black - update the preview UI and set the format 430 // since the set function will not run (default color is black). 431 updateUI(); 432 currentPreferredFormat = preferredFormat || tinycolor(initialColor).format; 433 434 addColorToSelectionPalette(initialColor); 435 } 436 else { 437 updateUI(); 438 } 439 440 if (flat) { 441 show(); 442 } 443 444 function paletteElementClick(e) { 445 if (e.data && e.data.ignore) { 446 set($(e.target).closest(".sp-thumb-el").data("color")); 447 move(); 448 } 449 else { 450 set($(e.target).closest(".sp-thumb-el").data("color")); 451 move(); 452 updateOriginalInput(true); 453 if (opts.hideAfterPaletteSelect) { 454 hide(); 455 } 456 } 457 458 return false; 459 } 460 461 var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum"; 462 paletteContainer.delegate(".sp-thumb-el", paletteEvent, paletteElementClick); 463 initialColorContainer.delegate(".sp-thumb-el:nth-child(1)", paletteEvent, { ignore: true }, paletteElementClick); 464 } 465 466 function updateSelectionPaletteFromStorage() { 467 468 if (localStorageKey && window.localStorage) { 469 470 // Migrate old palettes over to new format. May want to remove this eventually. 471 try { 472 var oldPalette = window.localStorage[localStorageKey].split(",#"); 473 if (oldPalette.length > 1) { 474 delete window.localStorage[localStorageKey]; 475 $.each(oldPalette, function(i, c) { 476 addColorToSelectionPalette(c); 477 }); 478 } 479 } 480 catch(e) { } 481 482 try { 483 selectionPalette = window.localStorage[localStorageKey].split(";"); 484 } 485 catch (e) { } 486 } 487 } 488 489 function addColorToSelectionPalette(color) { 490 if (showSelectionPalette) { 491 var rgb = tinycolor(color).toRgbString(); 492 if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) { 493 selectionPalette.push(rgb); 494 while(selectionPalette.length > maxSelectionSize) { 495 selectionPalette.shift(); 496 } 497 } 498 499 if (localStorageKey && window.localStorage) { 500 try { 501 window.localStorage[localStorageKey] = selectionPalette.join(";"); 502 } 503 catch(e) { } 504 } 505 } 506 } 507 508 function getUniqueSelectionPalette() { 509 var unique = []; 510 if (opts.showPalette) { 511 for (var i = 0; i < selectionPalette.length; i++) { 512 var rgb = tinycolor(selectionPalette[i]).toRgbString(); 513 514 if (!paletteLookup[rgb]) { 515 unique.push(selectionPalette[i]); 516 } 517 } 518 } 519 520 return unique.reverse().slice(0, opts.maxSelectionSize); 521 } 522 523 function drawPalette() { 524 525 var currentColor = get(); 526 527 var html = $.map(paletteArray, function (palette, i) { 528 return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts); 529 }); 530 531 updateSelectionPaletteFromStorage(); 532 533 if (selectionPalette) { 534 html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection", opts)); 535 } 536 537 paletteContainer.html(html.join("")); 538 } 539 540 function drawInitial() { 541 if (opts.showInitial) { 542 var initial = colorOnShow; 543 var current = get(); 544 initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial", opts)); 545 } 546 } 547 548 function dragStart() { 549 if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) { 550 reflow(); 551 } 552 container.addClass(draggingClass); 553 shiftMovementDirection = null; 554 boundElement.trigger('dragstart.spectrum', [ get() ]); 555 } 556 557 function dragStop() { 558 container.removeClass(draggingClass); 559 boundElement.trigger('dragstop.spectrum', [ get() ]); 560 } 561 562 function setFromTextInput() { 563 564 var value = textInput.val(); 565 566 if ((value === null || value === "") && allowEmpty) { 567 set(null); 568 updateOriginalInput(true); 569 } 570 else { 571 var tiny = tinycolor(value); 572 if (tiny.isValid()) { 573 set(tiny); 574 updateOriginalInput(true); 575 } 576 else { 577 textInput.addClass("sp-validation-error"); 578 } 579 } 580 } 581 582 function toggle() { 583 if (visible) { 584 hide(); 585 } 586 else { 587 show(); 588 } 589 } 590 591 function show() { 592 var event = $.Event('beforeShow.spectrum'); 593 594 if (visible) { 595 reflow(); 596 return; 597 } 598 599 boundElement.trigger(event, [ get() ]); 600 601 if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) { 602 return; 603 } 604 605 hideAll(); 606 visible = true; 607 608 $(doc).bind("click.spectrum", clickout); 609 $(window).bind("resize.spectrum", resize); 610 replacer.addClass("sp-active"); 611 container.removeClass("sp-hidden"); 612 613 reflow(); 614 updateUI(); 615 616 colorOnShow = get(); 617 618 drawInitial(); 619 callbacks.show(colorOnShow); 620 boundElement.trigger('show.spectrum', [ colorOnShow ]); 621 } 622 623 function clickout(e) { 624 // Return on right click. 625 if (e && e.type == "click" && e.button == 2) { return; } 626 627 if (clickoutFiresChange) { 628 updateOriginalInput(true); 629 } 630 else { 631 revert(); 632 } 633 hide(); 634 } 635 636 function hide() { 637 // Return if hiding is unnecessary 638 if (!visible || flat) { return; } 639 visible = false; 640 641 $(doc).unbind("click.spectrum", clickout); 642 $(window).unbind("resize.spectrum", resize); 643 644 replacer.removeClass("sp-active"); 645 container.addClass("sp-hidden"); 646 647 callbacks.hide(get()); 648 boundElement.trigger('hide.spectrum', [ get() ]); 649 } 650 651 function revert() { 652 set(colorOnShow, true); 653 } 654 655 function set(color, ignoreFormatChange) { 656 if (tinycolor.equals(color, get())) { 657 // Update UI just in case a validation error needs 658 // to be cleared. 659 updateUI(); 660 return; 661 } 662 663 var newColor, newHsv; 664 if (!color && allowEmpty) { 665 isEmpty = true; 666 } else { 667 isEmpty = false; 668 newColor = tinycolor(color); 669 newHsv = newColor.toHsv(); 670 671 currentHue = (newHsv.h % 360) / 360; 672 currentSaturation = newHsv.s; 673 currentValue = newHsv.v; 674 currentAlpha = newHsv.a; 675 } 676 updateUI(); 677 678 if (newColor && newColor.isValid() && !ignoreFormatChange) { 679 currentPreferredFormat = preferredFormat || newColor.getFormat(); 680 } 681 } 682 683 function get(opts) { 684 opts = opts || { }; 685 686 if (allowEmpty && isEmpty) { 687 return null; 688 } 689 690 return tinycolor.fromRatio({ 691 h: currentHue, 692 s: currentSaturation, 693 v: currentValue, 694 a: Math.round(currentAlpha * 100) / 100 695 }, { format: opts.format || currentPreferredFormat }); 696 } 697 698 function isValid() { 699 return !textInput.hasClass("sp-validation-error"); 700 } 701 702 function move() { 703 updateUI(); 704 705 callbacks.move(get()); 706 boundElement.trigger('move.spectrum', [ get() ]); 707 } 708 709 function updateUI() { 710 711 textInput.removeClass("sp-validation-error"); 712 713 updateHelperLocations(); 714 715 // Update dragger background color (gradients take care of saturation and value). 716 var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 }); 717 dragger.css("background-color", flatColor.toHexString()); 718 719 // Get a format that alpha will be included in (hex and names ignore alpha) 720 var format = currentPreferredFormat; 721 if (currentAlpha < 1 && !(currentAlpha === 0 && format === "name")) { 722 if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") { 723 format = "rgb"; 724 } 725 } 726 727 var realColor = get({ format: format }), 728 displayColor = ''; 729 730 //reset background info for preview element 731 previewElement.removeClass("sp-clear-display"); 732 previewElement.css('background-color', 'transparent'); 733 734 if (!realColor && allowEmpty) { 735 // Update the replaced elements background with icon indicating no color selection 736 previewElement.addClass("sp-clear-display"); 737 } 738 else { 739 var realHex = realColor.toHexString(), 740 realRgb = realColor.toRgbString(); 741 742 // Update the replaced elements background color (with actual selected color) 743 if (rgbaSupport || realColor.alpha === 1) { 744 previewElement.css("background-color", realRgb); 745 } 746 else { 747 previewElement.css("background-color", "transparent"); 748 previewElement.css("filter", realColor.toFilter()); 749 } 750 751 if (opts.showAlpha) { 752 var rgb = realColor.toRgb(); 753 rgb.a = 0; 754 var realAlpha = tinycolor(rgb).toRgbString(); 755 var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")"; 756 757 if (IE) { 758 alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex)); 759 } 760 else { 761 alphaSliderInner.css("background", "-webkit-" + gradient); 762 alphaSliderInner.css("background", "-moz-" + gradient); 763 alphaSliderInner.css("background", "-ms-" + gradient); 764 // Use current syntax gradient on unprefixed property. 765 alphaSliderInner.css("background", 766 "linear-gradient(to right, " + realAlpha + ", " + realHex + ")"); 767 } 768 } 769 770 displayColor = realColor.toString(format); 771 } 772 773 // Update the text entry input as it changes happen 774 if (opts.showInput) { 775 textInput.val(displayColor); 776 } 777 778 if (opts.showPalette) { 779 drawPalette(); 780 } 781 782 drawInitial(); 783 } 784 785 function updateHelperLocations() { 786 var s = currentSaturation; 787 var v = currentValue; 788 789 if(allowEmpty && isEmpty) { 790 //if selected color is empty, hide the helpers 791 alphaSlideHelper.hide(); 792 slideHelper.hide(); 793 dragHelper.hide(); 794 } 795 else { 796 //make sure helpers are visible 797 alphaSlideHelper.show(); 798 slideHelper.show(); 799 dragHelper.show(); 800 801 // Where to show the little circle in that displays your current selected color 802 var dragX = s * dragWidth; 803 var dragY = dragHeight - (v * dragHeight); 804 dragX = Math.max( 805 -dragHelperHeight, 806 Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight) 807 ); 808 dragY = Math.max( 809 -dragHelperHeight, 810 Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight) 811 ); 812 dragHelper.css({ 813 "top": dragY + "px", 814 "left": dragX + "px" 815 }); 816 817 var alphaX = currentAlpha * alphaWidth; 818 alphaSlideHelper.css({ 819 "left": (alphaX - (alphaSlideHelperWidth / 2)) + "px" 820 }); 821 822 // Where to show the bar that displays your current selected hue 823 var slideY = (currentHue) * slideHeight; 824 slideHelper.css({ 825 "top": (slideY - slideHelperHeight) + "px" 826 }); 827 } 828 } 829 830 function updateOriginalInput(fireCallback) { 831 var color = get(), 832 displayColor = '', 833 hasChanged = !tinycolor.equals(color, colorOnShow); 834 835 if (color) { 836 displayColor = color.toString(currentPreferredFormat); 837 // Update the selection palette with the current color 838 addColorToSelectionPalette(color); 839 } 840 841 if (isInput) { 842 boundElement.val(displayColor); 843 } 844 845 if (fireCallback && hasChanged) { 846 callbacks.change(color); 847 boundElement.trigger('change', [ color ]); 848 } 849 } 850 851 function reflow() { 852 dragWidth = dragger.width(); 853 dragHeight = dragger.height(); 854 dragHelperHeight = dragHelper.height(); 855 slideWidth = slider.width(); 856 slideHeight = slider.height(); 857 slideHelperHeight = slideHelper.height(); 858 alphaWidth = alphaSlider.width(); 859 alphaSlideHelperWidth = alphaSlideHelper.width(); 860 861 if (!flat) { 862 container.css("position", "absolute"); 863 container.offset(getOffset(container, offsetElement)); 864 } 865 866 updateHelperLocations(); 867 868 if (opts.showPalette) { 869 drawPalette(); 870 } 871 872 boundElement.trigger('reflow.spectrum'); 873 } 874 875 function destroy() { 876 boundElement.show(); 877 offsetElement.unbind("click.spectrum touchstart.spectrum"); 878 container.remove(); 879 replacer.remove(); 880 spectrums[spect.id] = null; 881 } 882 883 function option(optionName, optionValue) { 884 if (optionName === undefined) { 885 return $.extend({}, opts); 886 } 887 if (optionValue === undefined) { 888 return opts[optionName]; 889 } 890 891 opts[optionName] = optionValue; 892 applyOptions(); 893 } 894 895 function enable() { 896 disabled = false; 897 boundElement.attr("disabled", false); 898 offsetElement.removeClass("sp-disabled"); 899 } 900 901 function disable() { 902 hide(); 903 disabled = true; 904 boundElement.attr("disabled", true); 905 offsetElement.addClass("sp-disabled"); 906 } 907 908 initialize(); 909 910 var spect = { 911 show: show, 912 hide: hide, 913 toggle: toggle, 914 reflow: reflow, 915 option: option, 916 enable: enable, 917 disable: disable, 918 set: function (c) { 919 set(c); 920 updateOriginalInput(); 921 }, 922 get: get, 923 destroy: destroy, 924 container: container 925 }; 926 927 spect.id = spectrums.push(spect) - 1; 928 929 return spect; 930 } 931 932 /** 933 * checkOffset - get the offset below/above and left/right element depending on screen position 934 * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js 935 */ 936 function getOffset(picker, input) { 937 var extraY = 0; 938 var dpWidth = picker.outerWidth(); 939 var dpHeight = picker.outerHeight(); 940 var inputHeight = input.outerHeight(); 941 var doc = picker[0].ownerDocument; 942 var docElem = doc.documentElement; 943 var viewWidth = docElem.clientWidth + $(doc).scrollLeft(); 944 var viewHeight = docElem.clientHeight + $(doc).scrollTop(); 945 var offset = input.offset(); 946 offset.top += inputHeight; 947 948 offset.left -= 949 Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 950 Math.abs(offset.left + dpWidth - viewWidth) : 0); 951 952 offset.top -= 953 Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 954 Math.abs(dpHeight + inputHeight - extraY) : extraY)); 955 956 return offset; 957 } 958 959 /** 960 * noop - do nothing 961 */ 962 function noop() { 963 964 } 965 966 /** 967 * stopPropagation - makes the code only doing this a little easier to read in line 968 */ 969 function stopPropagation(e) { 970 e.stopPropagation(); 971 } 972 973 /** 974 * Create a function bound to a given object 975 * Thanks to underscore.js 976 */ 977 function bind(func, obj) { 978 var slice = Array.prototype.slice; 979 var args = slice.call(arguments, 2); 980 return function () { 981 return func.apply(obj, args.concat(slice.call(arguments))); 982 }; 983 } 984 985 /** 986 * Lightweight drag helper. Handles containment within the element, so that 987 * when dragging, the x is within [0,element.width] and y is within [0,element.height] 988 */ 989 function draggable(element, onmove, onstart, onstop) { 990 onmove = onmove || function () { }; 991 onstart = onstart || function () { }; 992 onstop = onstop || function () { }; 993 var doc = document; 994 var dragging = false; 995 var offset = {}; 996 var maxHeight = 0; 997 var maxWidth = 0; 998 var hasTouch = ('ontouchstart' in window); 999 1000 var duringDragEvents = {}; 1001 duringDragEvents["selectstart"] = prevent; 1002 duringDragEvents["dragstart"] = prevent; 1003 duringDragEvents["touchmove mousemove"] = move; 1004 duringDragEvents["touchend mouseup"] = stop; 1005 1006 function prevent(e) { 1007 if (e.stopPropagation) { 1008 e.stopPropagation(); 1009 } 1010 if (e.preventDefault) { 1011 e.preventDefault(); 1012 } 1013 e.returnValue = false; 1014 } 1015 1016 function move(e) { 1017 if (dragging) { 1018 // Mouseup happened outside of window 1019 if (IE && doc.documentMode < 9 && !e.button) { 1020 return stop(); 1021 } 1022 1023 var touches = e.originalEvent.touches; 1024 var pageX = touches ? touches[0].pageX : e.pageX; 1025 var pageY = touches ? touches[0].pageY : e.pageY; 1026 1027 var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth)); 1028 var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight)); 1029 1030 if (hasTouch) { 1031 // Stop scrolling in iOS 1032 prevent(e); 1033 } 1034 1035 onmove.apply(element, [dragX, dragY, e]); 1036 } 1037 } 1038 1039 function start(e) { 1040 var rightclick = (e.which) ? (e.which == 3) : (e.button == 2); 1041 1042 if (!rightclick && !dragging) { 1043 if (onstart.apply(element, arguments) !== false) { 1044 dragging = true; 1045 maxHeight = $(element).height(); 1046 maxWidth = $(element).width(); 1047 offset = $(element).offset(); 1048 1049 $(doc).bind(duringDragEvents); 1050 $(doc.body).addClass("sp-dragging"); 1051 1052 if (!hasTouch) { 1053 move(e); 1054 } 1055 1056 prevent(e); 1057 } 1058 } 1059 } 1060 1061 function stop() { 1062 if (dragging) { 1063 $(doc).unbind(duringDragEvents); 1064 $(doc.body).removeClass("sp-dragging"); 1065 onstop.apply(element, arguments); 1066 } 1067 dragging = false; 1068 } 1069 1070 $(element).bind("touchstart mousedown", start); 1071 } 1072 1073 function throttle(func, wait, debounce) { 1074 var timeout; 1075 return function () { 1076 var context = this, args = arguments; 1077 var throttler = function () { 1078 timeout = null; 1079 func.apply(context, args); 1080 }; 1081 if (debounce) clearTimeout(timeout); 1082 if (debounce || !timeout) timeout = setTimeout(throttler, wait); 1083 }; 1084 } 1085 1086 /** 1087 * Define a jQuery plugin 1088 */ 1089 var dataID = "spectrum.id"; 1090 $.fn.spectrum = function (opts, extra) { 1091 1092 if (typeof opts == "string") { 1093 1094 var returnValue = this; 1095 var args = Array.prototype.slice.call( arguments, 1 ); 1096 1097 this.each(function () { 1098 var spect = spectrums[$(this).data(dataID)]; 1099 if (spect) { 1100 var method = spect[opts]; 1101 if (!method) { 1102 throw new Error( "Spectrum: no such method: '" + opts + "'" ); 1103 } 1104 1105 if (opts == "get") { 1106 returnValue = spect.get(); 1107 } 1108 else if (opts == "container") { 1109 returnValue = spect.container; 1110 } 1111 else if (opts == "option") { 1112 returnValue = spect.option.apply(spect, args); 1113 } 1114 else if (opts == "destroy") { 1115 spect.destroy(); 1116 $(this).removeData(dataID); 1117 } 1118 else { 1119 method.apply(spect, args); 1120 } 1121 } 1122 }); 1123 1124 return returnValue; 1125 } 1126 1127 // Initializing a new instance of spectrum 1128 return this.spectrum("destroy").each(function () { 1129 var options = $.extend({}, opts, $(this).data()); 1130 var spect = spectrum(this, options); 1131 $(this).data(dataID, spect.id); 1132 }); 1133 }; 1134 1135 $.fn.spectrum.load = true; 1136 $.fn.spectrum.loadOpts = {}; 1137 $.fn.spectrum.draggable = draggable; 1138 $.fn.spectrum.defaults = defaultOpts; 1139 1140 $.spectrum = { }; 1141 $.spectrum.localization = { }; 1142 $.spectrum.palettes = { }; 1143 1144 $.fn.spectrum.processNativeColorInputs = function () { 1145 if (!inputTypeColorSupport) { 1146 $("input[type=color]").spectrum({ 1147 preferredFormat: "hex6" 1148 }); 1149 } 1150 }; 1151 1152 // TinyColor v1.0.0 1153 // https://github.com/bgrins/TinyColor 1154 // Brian Grinstead, MIT License 1155 1156 (function() { 1157 1158 var trimLeft = /^[\s,#]+/, 1159 trimRight = /\s+$/, 1160 tinyCounter = 0, 1161 math = Math, 1162 mathRound = math.round, 1163 mathMin = math.min, 1164 mathMax = math.max, 1165 mathRandom = math.random; 1166 1167 var tinycolor = function tinycolor (color, opts) { 1168 1169 color = (color) ? color : ''; 1170 opts = opts || { }; 1171 1172 // If input is already a tinycolor, return itself 1173 if (color instanceof tinycolor) { 1174 return color; 1175 } 1176 // If we are called as a function, call using new instead 1177 if (!(this instanceof tinycolor)) { 1178 return new tinycolor(color, opts); 1179 } 1180 1181 var rgb = inputToRGB(color); 1182 this._r = rgb.r, 1183 this._g = rgb.g, 1184 this._b = rgb.b, 1185 this._a = rgb.a, 1186 this._roundA = mathRound(100*this._a) / 100, 1187 this._format = opts.format || rgb.format; 1188 this._gradientType = opts.gradientType; 1189 1190 // Don't let the range of [0,255] come back in [0,1]. 1191 // Potentially lose a little bit of precision here, but will fix issues where 1192 // .5 gets interpreted as half of the total, instead of half of 1 1193 // If it was supposed to be 128, this was already taken care of by `inputToRgb` 1194 if (this._r < 1) { this._r = mathRound(this._r); } 1195 if (this._g < 1) { this._g = mathRound(this._g); } 1196 if (this._b < 1) { this._b = mathRound(this._b); } 1197 1198 this._ok = rgb.ok; 1199 this._tc_id = tinyCounter++; 1200 }; 1201 1202 tinycolor.prototype = { 1203 isDark: function() { 1204 return this.getBrightness() < 128; 1205 }, 1206 isLight: function() { 1207 return !this.isDark(); 1208 }, 1209 isValid: function() { 1210 return this._ok; 1211 }, 1212 getFormat: function() { 1213 return this._format; 1214 }, 1215 getAlpha: function() { 1216 return this._a; 1217 }, 1218 getBrightness: function() { 1219 var rgb = this.toRgb(); 1220 return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000; 1221 }, 1222 setAlpha: function(value) { 1223 this._a = boundAlpha(value); 1224 this._roundA = mathRound(100*this._a) / 1
vendor: 14,953 bytes, lines 1224-1647
122400; 1225 return this; 1226 }, 1227 toHsv: function() { 1228 var hsv = rgbToHsv(this._r, this._g, this._b); 1229 return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a }; 1230 }, 1231 toHsvString: function() { 1232 var hsv = rgbToHsv(this._r, this._g, this._b); 1233 var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100); 1234 return (this._a == 1) ? 1235 "hsv(" + h + ", " + s + "%, " + v + "%)" : 1236 "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")"; 1237 }, 1238 toHsl: function() { 1239 var hsl = rgbToHsl(this._r, this._g, this._b); 1240 return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a }; 1241 }, 1242 toHslString: function() { 1243 var hsl = rgbToHsl(this._r, this._g, this._b); 1244 var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100); 1245 return (this._a == 1) ? 1246 "hsl(" + h + ", " + s + "%, " + l + "%)" : 1247 "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")"; 1248 }, 1249 toHex: function(allow3Char) { 1250 return rgbToHex(this._r, this._g, this._b, allow3Char); 1251 }, 1252 toHexString: function(allow3Char) { 1253 return '#' + this.toHex(allow3Char); 1254 }, 1255 toHex8: function() { 1256 return rgbaToHex(this._r, this._g, this._b, this._a); 1257 }, 1258 toHex8String: function() { 1259 return '#' + this.toHex8(); 1260 }, 1261 toRgb: function() { 1262 return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a }; 1263 }, 1264 toRgbString: function() { 1265 return (this._a == 1) ? 1266 "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" : 1267 "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")"; 1268 }, 1269 toPercentageRgb: function() { 1270 return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a }; 1271 }, 1272 toPercentageRgbString: function() { 1273 return (this._a == 1) ? 1274 "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" : 1275 "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")"; 1276 }, 1277 toName: function() { 1278 if (this._a === 0) { 1279 return "transparent"; 1280 } 1281 1282 if (this._a < 1) { 1283 return false; 1284 } 1285 1286 return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false; 1287 }, 1288 toFilter: function(secondColor) { 1289 var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a); 1290 var secondHex8String = hex8String; 1291 var gradientType = this._gradientType ? "GradientType = 1, " : ""; 1292 1293 if (secondColor) { 1294 var s = tinycolor(secondColor); 1295 secondHex8String = s.toHex8String(); 1296 } 1297 1298 return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"; 1299 }, 1300 toString: function(format) { 1301 var formatSet = !!format; 1302 format = format || this._format; 1303 1304 var formattedString = false; 1305 var hasAlpha = this._a < 1 && this._a >= 0; 1306 var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name"); 1307 1308 if (needsAlphaFormat) { 1309 // Special case for "transparent", all other non-alpha formats 1310 // will return rgba when there is transparency. 1311 if (format === "name" && this._a === 0) { 1312 return this.toName(); 1313 } 1314 return this.toRgbString(); 1315 } 1316 if (format === "rgb") { 1317 formattedString = this.toRgbString(); 1318 } 1319 if (format === "prgb") { 1320 formattedString = this.toPercentageRgbString(); 1321 } 1322 if (format === "hex" || format === "hex6") { 1323 formattedString = this.toHexString(); 1324 } 1325 if (format === "hex3") { 1326 formattedString = this.toHexString(true); 1327 } 1328 if (format === "hex8") { 1329 formattedString = this.toHex8String(); 1330 } 1331 if (format === "name") { 1332 formattedString = this.toName(); 1333 } 1334 if (format === "hsl") { 1335 formattedString = this.toHslString(); 1336 } 1337 if (format === "hsv") { 1338 formattedString = this.toHsvString(); 1339 } 1340 1341 return formattedString || this.toHexString(); 1342 }, 1343 1344 _applyModification: function(fn, args) { 1345 var color = fn.apply(null, [this].concat([].slice.call(args))); 1346 this._r = color._r; 1347 this._g = color._g; 1348 this._b = color._b; 1349 this.setAlpha(color._a); 1350 return this; 1351 }, 1352 lighten: function() { 1353 return this._applyModification(lighten, arguments); 1354 }, 1355 brighten: function() { 1356 return this._applyModification(brighten, arguments); 1357 }, 1358 darken: function() { 1359 return this._applyModification(darken, arguments); 1360 }, 1361 desaturate: function() { 1362 return this._applyModification(desaturate, arguments); 1363 }, 1364 saturate: function() { 1365 return this._applyModification(saturate, arguments); 1366 }, 1367 greyscale: function() { 1368 return this._applyModification(greyscale, arguments); 1369 }, 1370 spin: function() { 1371 return this._applyModification(spin, arguments); 1372 }, 1373 1374 _applyCombination: function(fn, args) { 1375 return fn.apply(null, [this].concat([].slice.call(args))); 1376 }, 1377 analogous: function() { 1378 return this._applyCombination(analogous, arguments); 1379 }, 1380 complement: function() { 1381 return this._applyCombination(complement, arguments); 1382 }, 1383 monochromatic: function() { 1384 return this._applyCombination(monochromatic, arguments); 1385 }, 1386 splitcomplement: function() { 1387 return this._applyCombination(splitcomplement, arguments); 1388 }, 1389 triad: function() { 1390 return this._applyCombination(triad, arguments); 1391 }, 1392 tetrad: function() { 1393 return this._applyCombination(tetrad, arguments); 1394 } 1395 }; 1396 1397 // If input is an object, force 1 into "1.0" to handle ratios properly 1398 // String input requires "1.0" as input, so 1 will be treated as 1 1399 tinycolor.fromRatio = function(color, opts) { 1400 if (typeof color == "object") { 1401 var newColor = {}; 1402 for (var i in color) { 1403 if (color.hasOwnProperty(i)) { 1404 if (i === "a") { 1405 newColor[i] = color[i]; 1406 } 1407 else { 1408 newColor[i] = convertToPercentage(color[i]); 1409 } 1410 } 1411 } 1412 color = newColor; 1413 } 1414 1415 return tinycolor(color, opts); 1416 }; 1417 1418 // Given a string or object, convert that input to RGB 1419 // Possible string inputs: 1420 // 1421 // "red" 1422 // "#f00" or "f00" 1423 // "#ff0000" or "ff0000" 1424 // "#ff000000" or "ff000000" 1425 // "rgb 255 0 0" or "rgb (255, 0, 0)" 1426 // "rgb 1.0 0 0" or "rgb (1, 0, 0)" 1427 // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" 1428 // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" 1429 // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" 1430 // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" 1431 // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" 1432 // 1433 function inputToRGB(color) { 1434 1435 var rgb = { r: 0, g: 0, b: 0 }; 1436 var a = 1; 1437 var ok = false; 1438 var format = false; 1439 1440 if (typeof color == "string") { 1441 color = stringInputToObject(color); 1442 } 1443 1444 if (typeof color == "object") { 1445 if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) { 1446 rgb = rgbToRgb(color.r, color.g, color.b); 1447 ok = true; 1448 format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; 1449 } 1450 else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) { 1451 color.s = convertToPercentage(color.s); 1452 color.v = convertToPercentage(color.v); 1453 rgb = hsvToRgb(color.h, color.s, color.v); 1454 ok = true; 1455 format = "hsv"; 1456 } 1457 else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) { 1458 color.s = convertToPercentage(color.s); 1459 color.l = convertToPercentage(color.l); 1460 rgb = hslToRgb(color.h, color.s, color.l); 1461 ok = true; 1462 format = "hsl"; 1463 } 1464 1465 if (color.hasOwnProperty("a")) { 1466 a = color.a; 1467 } 1468 } 1469 1470 a = boundAlpha(a); 1471 1472 return { 1473 ok: ok, 1474 format: color.format || format, 1475 r: mathMin(255, mathMax(rgb.r, 0)), 1476 g: mathMin(255, mathMax(rgb.g, 0)), 1477 b: mathMin(255, mathMax(rgb.b, 0)), 1478 a: a 1479 }; 1480 } 1481 1482 1483 // Conversion Functions 1484 // -------------------- 1485 1486 // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: 1487 // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript> 1488 1489 // `rgbToRgb` 1490 // Handle bounds / percentage checking to conform to CSS color spec 1491 // <http://www.w3.org/TR/css3-color/> 1492 // *Assumes:* r, g, b in [0, 255] or [0, 1] 1493 // *Returns:* { r, g, b } in [0, 255] 1494 function rgbToRgb(r, g, b){ 1495 return { 1496 r: bound01(r, 255) * 255, 1497 g: bound01(g, 255) * 255, 1498 b: bound01(b, 255) * 255 1499 }; 1500 } 1501 1502 // `rgbToHsl` 1503 // Converts an RGB color value to HSL. 1504 // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] 1505 // *Returns:* { h, s, l } in [0,1] 1506 function rgbToHsl(r, g, b) { 1507 1508 r = bound01(r, 255); 1509 g = bound01(g, 255); 1510 b = bound01(b, 255); 1511 1512 var max = mathMax(r, g, b), min = mathMin(r, g, b); 1513 var h, s, l = (max + min) / 2; 1514 1515 if(max == min) { 1516 h = s = 0; // achromatic 1517 } 1518 else { 1519 var d = max - min; 1520 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 1521 switch(max) { 1522 case r: h = (g - b) / d + (g < b ? 6 : 0); break; 1523 case g: h = (b - r) / d + 2; break; 1524 case b: h = (r - g) / d + 4; break; 1525 } 1526 1527 h /= 6; 1528 } 1529 1530 return { h: h, s: s, l: l }; 1531 } 1532 1533 // `hslToRgb` 1534 // Converts an HSL color value to RGB. 1535 // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] 1536 // *Returns:* { r, g, b } in the set [0, 255] 1537 function hslToRgb(h, s, l) { 1538 var r, g, b; 1539 1540 h = bound01(h, 360); 1541 s = bound01(s, 100); 1542 l = bound01(l, 100); 1543 1544 function hue2rgb(p, q, t) { 1545 if(t < 0) t += 1; 1546 if(t > 1) t -= 1; 1547 if(t < 1/6) return p + (q - p) * 6 * t; 1548 if(t < 1/2) return q; 1549 if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; 1550 return p; 1551 } 1552 1553 if(s === 0) { 1554 r = g = b = l; // achromatic 1555 } 1556 else { 1557 var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 1558 var p = 2 * l - q; 1559 r = hue2rgb(p, q, h + 1/3); 1560 g = hue2rgb(p, q, h); 1561 b = hue2rgb(p, q, h - 1/3); 1562 } 1563 1564 return { r: r * 255, g: g * 255, b: b * 255 }; 1565 } 1566 1567 // `rgbToHsv` 1568 // Converts an RGB color value to HSV 1569 // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] 1570 // *Returns:* { h, s, v } in [0,1] 1571 function rgbToHsv(r, g, b) { 1572 1573 r = bound01(r, 255); 1574 g = bound01(g, 255); 1575 b = bound01(b, 255); 1576 1577 var max = mathMax(r, g, b), min = mathMin(r, g, b); 1578 var h, s, v = max; 1579 1580 var d = max - min; 1581 s = max === 0 ? 0 : d / max; 1582 1583 if(max == min) { 1584 h = 0; // achromatic 1585 } 1586 else { 1587 switch(max) { 1588 case r: h = (g - b) / d + (g < b ? 6 : 0); break; 1589 case g: h = (b - r) / d + 2; break; 1590 case b: h = (r - g) / d + 4; break; 1591 } 1592 h /= 6; 1593 } 1594 return { h: h, s: s, v: v }; 1595 } 1596 1597 // `hsvToRgb` 1598 // Converts an HSV color value to RGB. 1599 // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] 1600 // *Returns:* { r, g, b } in the set [0, 255] 1601 function hsvToRgb(h, s, v) { 1602 1603 h = bound01(h, 360) * 6; 1604 s = bound01(s, 100); 1605 v = bound01(v, 100); 1606 1607 var i = math.floor(h), 1608 f = h - i, 1609 p = v * (1 - s), 1610 q = v * (1 - f * s), 1611 t = v * (1 - (1 - f) * s), 1612 mod = i % 6, 1613 r = [v, q, p, p, t, v][mod], 1614 g = [t, v, v, q, p, p][mod], 1615 b = [p, p, t, v, v, q][mod]; 1616 1617 return { r: r * 255, g: g * 255, b: b * 255 }; 1618 } 1619 1620 // `rgbToHex` 1621 // Converts an RGB color to hex 1622 // Assumes r, g, and b are contained in the set [0, 255] 1623 // Returns a 3 or 6 character hex 1624 function rgbToHex(r, g, b, allow3Char) { 1625 1626 var hex = [ 1627 pad2(mathRound(r).toString(16)), 1628 pad2(mathRound(g).toString(16)), 1629 pad2(mathRound(b).toString(16)) 1630 ]; 1631 1632 // Return a 3 character hex if possible 1633 if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { 1634 return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); 1635 } 1636 1637 return hex.join(""); 1638 } 1639 // `rgbaToHex` 1640 // Converts an RGBA color plus alpha transparency to hex 1641 // Assumes r, g, b and a are contained in the set [0, 255] 1642 // Returns an 8 character hex 1643 function rgbaToHex(r, g, b, a) { 1644 1645 var hex = [ 1646 pad2(convertDecimalToHex(a)), 1647
1647 pad2(mathRound(r).toString(16)), 1648 pad2(mathRound(g).toString(16)), 1649 pad2(mathRound(b).toString(16)) 1650 ]; 1651 1652 return hex.join(""); 1653
vendor: 11,675 bytes, lines 1653-2028
1653 } 1654 1655 // `equals` 1656 // Can be called with any tinycolor input 1657 tinycolor.equals = function (color1, color2) { 1658 if (!color1 || !color2) { return false; } 1659 return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); 1660 }; 1661 tinycolor.random = function() { 1662 return tinycolor.fromRatio({ 1663 r: mathRandom(), 1664 g: mathRandom(), 1665 b: mathRandom() 1666 }); 1667 }; 1668 1669 1670 // Modification Functions 1671 // ---------------------- 1672 // Thanks to less.js for some of the basics here 1673 // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js> 1674 1675 function desaturate(color, amount) { 1676 amount = (amount === 0) ? 0 : (amount || 10); 1677 var hsl = tinycolor(color).toHsl(); 1678 hsl.s -= amount / 100; 1679 hsl.s = clamp01(hsl.s); 1680 return tinycolor(hsl); 1681 } 1682 1683 function saturate(color, amount) { 1684 amount = (amount === 0) ? 0 : (amount || 10); 1685 var hsl = tinycolor(color).toHsl(); 1686 hsl.s += amount / 100; 1687 hsl.s = clamp01(hsl.s); 1688 return tinycolor(hsl); 1689 } 1690 1691 function greyscale(color) { 1692 return tinycolor(color).desaturate(100); 1693 } 1694 1695 function lighten (color, amount) { 1696 amount = (amount === 0) ? 0 : (amount || 10); 1697 var hsl = tinycolor(color).toHsl(); 1698 hsl.l += amount / 100; 1699 hsl.l = clamp01(hsl.l); 1700 return tinycolor(hsl); 1701 } 1702 1703 function brighten(color, amount) { 1704 amount = (amount === 0) ? 0 : (amount || 10); 1705 var rgb = tinycolor(color).toRgb(); 1706 rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100)))); 1707 rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100)))); 1708 rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100)))); 1709 return tinycolor(rgb); 1710 } 1711 1712 function darken (color, amount) { 1713 amount = (amount === 0) ? 0 : (amount || 10); 1714 var hsl = tinycolor(color).toHsl(); 1715 hsl.l -= amount / 100; 1716 hsl.l = clamp01(hsl.l); 1717 return tinycolor(hsl); 1718 } 1719 1720 // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. 1721 // Values outside of this range will be wrapped into this range. 1722 function spin(color, amount) { 1723 var hsl = tinycolor(color).toHsl(); 1724 var hue = (mathRound(hsl.h) + amount) % 360; 1725 hsl.h = hue < 0 ? 360 + hue : hue; 1726 return tinycolor(hsl); 1727 } 1728 1729 // Combination Functions 1730 // --------------------- 1731 // Thanks to jQuery xColor for some of the ideas behind these 1732 // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js> 1733 1734 function complement(color) { 1735 var hsl = tinycolor(color).toHsl(); 1736 hsl.h = (hsl.h + 180) % 360; 1737 return tinycolor(hsl); 1738 } 1739 1740 function triad(color) { 1741 var hsl = tinycolor(color).toHsl(); 1742 var h = hsl.h; 1743 return [ 1744 tinycolor(color), 1745 tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), 1746 tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) 1747 ]; 1748 } 1749 1750 function tetrad(color) { 1751 var hsl = tinycolor(color).toHsl(); 1752 var h = hsl.h; 1753 return [ 1754 tinycolor(color), 1755 tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), 1756 tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), 1757 tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) 1758 ]; 1759 } 1760 1761 function splitcomplement(color) { 1762 var hsl = tinycolor(color).toHsl(); 1763 var h = hsl.h; 1764 return [ 1765 tinycolor(color), 1766 tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), 1767 tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) 1768 ]; 1769 } 1770 1771 function analogous(color, results, slices) { 1772 results = results || 6; 1773 slices = slices || 30; 1774 1775 var hsl = tinycolor(color).toHsl(); 1776 var part = 360 / slices; 1777 var ret = [tinycolor(color)]; 1778 1779 for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { 1780 hsl.h = (hsl.h + part) % 360; 1781 ret.push(tinycolor(hsl)); 1782 } 1783 return ret; 1784 } 1785 1786 function monochromatic(color, results) { 1787 results = results || 6; 1788 var hsv = tinycolor(color).toHsv(); 1789 var h = hsv.h, s = hsv.s, v = hsv.v; 1790 var ret = []; 1791 var modification = 1 / results; 1792 1793 while (results--) { 1794 ret.push(tinycolor({ h: h, s: s, v: v})); 1795 v = (v + modification) % 1; 1796 } 1797 1798 return ret; 1799 } 1800 1801 // Utility Functions 1802 // --------------------- 1803 1804 tinycolor.mix = function(color1, color2, amount) { 1805 amount = (amount === 0) ? 0 : (amount || 50); 1806 1807 var rgb1 = tinycolor(color1).toRgb(); 1808 var rgb2 = tinycolor(color2).toRgb(); 1809 1810 var p = amount / 100; 1811 var w = p * 2 - 1; 1812 var a = rgb2.a - rgb1.a; 1813 1814 var w1; 1815 1816 if (w * a == -1) { 1817 w1 = w; 1818 } else { 1819 w1 = (w + a) / (1 + w * a); 1820 } 1821 1822 w1 = (w1 + 1) / 2; 1823 1824 var w2 = 1 - w1; 1825 1826 var rgba = { 1827 r: rgb2.r * w1 + rgb1.r * w2, 1828 g: rgb2.g * w1 + rgb1.g * w2, 1829 b: rgb2.b * w1 + rgb1.b * w2, 1830 a: rgb2.a * p + rgb1.a * (1 - p) 1831 }; 1832 1833 return tinycolor(rgba); 1834 }; 1835 1836 1837 // Readability Functions 1838 // --------------------- 1839 // <http://www.w3.org/TR/AERT#color-contrast> 1840 1841 // `readability` 1842 // Analyze the 2 colors and returns an object with the following properties: 1843 // `brightness`: difference in brightness between the two colors 1844 // `color`: difference in color/hue between the two colors 1845 tinycolor.readability = function(color1, color2) { 1846 var c1 = tinycolor(color1); 1847 var c2 = tinycolor(color2); 1848 var rgb1 = c1.toRgb(); 1849 var rgb2 = c2.toRgb(); 1850 var brightnessA = c1.getBrightness(); 1851 var brightnessB = c2.getBrightness(); 1852 var colorDiff = ( 1853 Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) + 1854 Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) + 1855 Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b) 1856 ); 1857 1858 return { 1859 brightness: Math.abs(brightnessA - brightnessB), 1860 color: colorDiff 1861 }; 1862 }; 1863 1864 // `readable` 1865 // http://www.w3.org/TR/AERT#color-contrast 1866 // Ensure that foreground and background color combinations provide sufficient contrast. 1867 // *Example* 1868 // tinycolor.isReadable("#000", "#111") => false 1869 tinycolor.isReadable = function(color1, color2) { 1870 var readability = tinycolor.readability(color1, color2); 1871 return readability.brightness > 125 && readability.color > 500; 1872 }; 1873 1874 // `mostReadable` 1875 // Given a base color and a list of possible foreground or background 1876 // colors for that base, returns the most readable color. 1877 // *Example* 1878 // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000" 1879 tinycolor.mostReadable = function(baseColor, colorList) { 1880 var bestColor = null; 1881 var bestScore = 0; 1882 var bestIsReadable = false; 1883 for (var i=0; i < colorList.length; i++) { 1884 1885 // We normalize both around the "acceptable" breaking point, 1886 // but rank brightness constrast higher than hue. 1887 1888 var readability = tinycolor.readability(baseColor, colorList[i]); 1889 var readable = readability.brightness > 125 && readability.color > 500; 1890 var score = 3 * (readability.brightness / 125) + (readability.color / 500); 1891 1892 if ((readable && ! bestIsReadable) || 1893 (readable && bestIsReadable && score > bestScore) || 1894 ((! readable) && (! bestIsReadable) && score > bestScore)) { 1895 bestIsReadable = readable; 1896 bestScore = score; 1897 bestColor = tinycolor(colorList[i]); 1898 } 1899 } 1900 return bestColor; 1901 }; 1902 1903 1904 // Big List of Colors 1905 // ------------------ 1906 // <http://www.w3.org/TR/css3-color/#svg-color> 1907 var names = tinycolor.names = { 1908 aliceblue: "f0f8ff", 1909 antiquewhite: "faebd7", 1910 aqua: "0ff", 1911 aquamarine: "7fffd4", 1912 azure: "f0ffff", 1913 beige: "f5f5dc", 1914 bisque: "ffe4c4", 1915 black: "000", 1916 blanchedalmond: "ffebcd", 1917 blue: "00f", 1918 blueviolet: "8a2be2", 1919 brown: "a52a2a", 1920 burlywood: "deb887", 1921 burntsienna: "ea7e5d", 1922 cadetblue: "5f9ea0", 1923 chartreuse: "7fff00", 1924 chocolate: "d2691e", 1925 coral: "ff7f50", 1926 cornflowerblue: "6495ed", 1927 cornsilk: "fff8dc", 1928 crimson: "dc143c", 1929 cyan: "0ff", 1930 darkblue: "00008b", 1931 darkcyan: "008b8b", 1932 darkgoldenrod: "b8860b", 1933 darkgray: "a9a9a9", 1934 darkgreen: "006400", 1935 darkgrey: "a9a9a9", 1936 darkkhaki: "bdb76b", 1937 darkmagenta: "8b008b", 1938 darkolivegreen: "556b2f", 1939 darkorange: "ff8c00", 1940 darkorchid: "9932cc", 1941 darkred: "8b0000", 1942 darksalmon: "e9967a", 1943 darkseagreen: "8fbc8f", 1944 darkslateblue: "483d8b", 1945 darkslategray: "2f4f4f", 1946 darkslategrey: "2f4f4f", 1947 darkturquoise: "00ced1", 1948 darkviolet: "9400d3", 1949 deeppink: "ff1493", 1950 deepskyblue: "00bfff", 1951 dimgray: "696969", 1952 dimgrey: "696969", 1953 dodgerblue: "1e90ff", 1954 firebrick: "b22222", 1955 floralwhite: "fffaf0", 1956 forestgreen: "228b22", 1957 fuchsia: "f0f", 1958 gainsboro: "dcdcdc", 1959 ghostwhite: "f8f8ff", 1960 gold: "ffd700", 1961 goldenrod: "daa520", 1962 gray: "808080", 1963 green: "008000", 1964 greenyellow: "adff2f", 1965 grey: "808080", 1966 honeydew: "f0fff0", 1967 hotpink: "ff69b4", 1968 indianred: "cd5c5c", 1969 indigo: "4b0082", 1970 ivory: "fffff0", 1971 khaki: "f0e68c", 1972 lavender: "e6e6fa", 1973 lavenderblush: "fff0f5", 1974 lawngreen: "7cfc00", 1975 lemonchiffon: "fffacd", 1976 lightblue: "add8e6", 1977 lightcoral: "f08080", 1978 lightcyan: "e0ffff", 1979 lightgoldenrodyellow: "fafad2", 1980 lightgray: "d3d3d3", 1981 lightgreen: "90ee90", 1982 lightgrey: "d3d3d3", 1983 lightpink: "ffb6c1", 1984 lightsalmon: "ffa07a", 1985 lightseagreen: "20b2aa", 1986 lightskyblue: "87cefa", 1987 lightslategray: "789", 1988 lightslategrey: "789", 1989 lightsteelblue: "b0c4de", 1990 lightyellow: "ffffe0", 1991 lime: "0f0", 1992 limegreen: "32cd32", 1993 linen: "faf0e6", 1994 magenta: "f0f", 1995 maroon: "800000", 1996 mediumaquamarine: "66cdaa", 1997 mediumblue: "0000cd", 1998 mediumorchid: "ba55d3", 1999 mediumpurple: "9370db", 2000 mediumseagreen: "3cb371", 2001 mediumslateblue: "7b68ee", 2002 mediumspringgreen: "00fa9a", 2003 mediumturquoise: "48d1cc", 2004 mediumvioletred: "c71585", 2005 midnightblue: "191970", 2006 mintcream: "f5fffa", 2007 mistyrose: "ffe4e1", 2008 moccasin: "ffe4b5", 2009 navajowhite: "ffdead", 2010 navy: "000080", 2011 oldlace: "fdf5e6", 2012 olive: "808000", 2013 olivedrab: "6b8e23", 2014 orange: "ffa500", 2015 orangered: "ff4500", 2016 orchid: "da70d6", 2017 palegoldenrod: "eee8aa", 2018 palegreen: "98fb98", 2019 paleturquoise: "afeeee", 2020 palevioletred: "db7093", 2021 papayawhip: "ffefd5", 2022 peachpuff: "ffdab9", 2023 peru: "cd853f", 2024 pink: "ffc0cb", 2025 plum: "dda0dd", 2026 powderblue: "b0e0e6", 2027 purple: "800080", 2028 re
vendor: 7,507 bytes, lines 2028-2255
2028d: "f00", 2029 rosybrown: "bc8f8f", 2030 royalblue: "4169e1", 2031 saddlebrown: "8b4513", 2032 salmon: "fa8072", 2033 sandybrown: "f4a460", 2034 seagreen: "2e8b57", 2035 seashell: "fff5ee", 2036 sienna: "a0522d", 2037 silver: "c0c0c0", 2038 skyblue: "87ceeb", 2039 slateblue: "6a5acd", 2040 slategray: "708090", 2041 slategrey: "708090", 2042 snow: "fffafa", 2043 springgreen: "00ff7f", 2044 steelblue: "4682b4", 2045 tan: "d2b48c", 2046 teal: "008080", 2047 thistle: "d8bfd8", 2048 tomato: "ff6347", 2049 turquoise: "40e0d0", 2050 violet: "ee82ee", 2051 wheat: "f5deb3", 2052 white: "fff", 2053 whitesmoke: "f5f5f5", 2054 yellow: "ff0", 2055 yellowgreen: "9acd32" 2056 }; 2057 2058 // Make it easy to access colors via `hexNames[hex]` 2059 var hexNames = tinycolor.hexNames = flip(names); 2060 2061 2062 // Utilities 2063 // --------- 2064 2065 // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` 2066 function flip(o) { 2067 var flipped = { }; 2068 for (var i in o) { 2069 if (o.hasOwnProperty(i)) { 2070 flipped[o[i]] = i; 2071 } 2072 } 2073 return flipped; 2074 } 2075 2076 // Return a valid alpha value [0,1] with all invalid values being set to 1 2077 function boundAlpha(a) { 2078 a = parseFloat(a); 2079 2080 if (isNaN(a) || a < 0 || a > 1) { 2081 a = 1; 2082 } 2083 2084 return a; 2085 } 2086 2087 // Take input from [0, n] and return it as [0, 1] 2088 function bound01(n, max) { 2089 if (isOnePointZero(n)) { n = "100%"; } 2090 2091 var processPercent = isPercentage(n); 2092 n = mathMin(max, mathMax(0, parseFloat(n))); 2093 2094 // Automatically convert percentage into number 2095 if (processPercent) { 2096 n = parseInt(n * max, 10) / 100; 2097 } 2098 2099 // Handle floating point rounding errors 2100 if ((math.abs(n - max) < 0.000001)) { 2101 return 1; 2102 } 2103 2104 // Convert into [0, 1] range if it isn't already 2105 return (n % max) / parseFloat(max); 2106 } 2107 2108 // Force a number between 0 and 1 2109 function clamp01(val) { 2110 return mathMin(1, mathMax(0, val)); 2111 } 2112 2113 // Parse a base-16 hex value into a base-10 integer 2114 function parseIntFromHex(val) { 2115 return parseInt(val, 16); 2116 } 2117 2118 // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 2119 // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0> 2120 function isOnePointZero(n) { 2121 return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; 2122 } 2123 2124 // Check to see if string passed in is a percentage 2125 function isPercentage(n) { 2126 return typeof n === "string" && n.indexOf('%') != -1; 2127 } 2128 2129 // Force a hex value to have 2 characters 2130 function pad2(c) { 2131 return c.length == 1 ? '0' + c : '' + c; 2132 } 2133 2134 // Replace a decimal with it's percentage value 2135 function convertToPercentage(n) { 2136 if (n <= 1) { 2137 n = (n * 100) + "%"; 2138 } 2139 2140 return n; 2141 } 2142 2143 // Converts a decimal to a hex value 2144 function convertDecimalToHex(d) { 2145 return Math.round(parseFloat(d) * 255).toString(16); 2146 } 2147 // Converts a hex value to a decimal 2148 function convertHexToDecimal(h) { 2149 return (parseIntFromHex(h) / 255); 2150 } 2151 2152 var matchers = (function() { 2153 2154 // <http://www.w3.org/TR/css3-values/#integers> 2155 var CSS_INTEGER = "[-\\+]?\\d+%?"; 2156 2157 // <http://www.w3.org/TR/css3-values/#number-value> 2158 var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; 2159 2160 // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. 2161 var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; 2162 2163 // Actual matching. 2164 // Parentheses and commas are optional, but not required. 2165 // Whitespace can take the place of commas or opening paren 2166 var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; 2167 var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; 2168 2169 return { 2170 rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), 2171 rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), 2172 hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), 2173 hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), 2174 hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), 2175 hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, 2176 hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, 2177 hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ 2178 }; 2179 })(); 2180 2181 // `stringInputToObject` 2182 // Permissive string parsing. Take in a number of formats, and output an object 2183 // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` 2184 function stringInputToObject(color) { 2185 2186 color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); 2187 var named = false; 2188 if (names[color]) { 2189 color = names[color]; 2190 named = true; 2191 } 2192 else if (color == 'transparent') { 2193 return { r: 0, g: 0, b: 0, a: 0, format: "name" }; 2194 } 2195 2196 // Try to match string input using regular expressions. 2197 // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] 2198 // Just return an object and let the conversion functions handle that. 2199 // This way the result will be the same whether the tinycolor is initialized with string or object. 2200 var match; 2201 if ((match = matchers.rgb.exec(color))) { 2202 return { r: match[1], g: match[2], b: match[3] }; 2203 } 2204 if ((match = matchers.rgba.exec(color))) { 2205 return { r: match[1], g: match[2], b: match[3], a: match[4] }; 2206 } 2207 if ((match = matchers.hsl.exec(color))) { 2208 return { h: match[1], s: match[2], l: match[3] }; 2209 } 2210 if ((match = matchers.hsla.exec(color))) { 2211 return { h: match[1], s: match[2], l: match[3], a: match[4] }; 2212 } 2213 if ((match = matchers.hsv.exec(color))) { 2214 return { h: match[1], s: match[2], v: match[3] }; 2215 } 2216 if ((match = matchers.hex8.exec(color))) { 2217 return { 2218 a: convertHexToDecimal(match[1]), 2219 r: parseIntFromHex(match[2]), 2220 g: parseIntFromHex(match[3]), 2221 b: parseIntFromHex(match[4]), 2222 format: named ? "name" : "hex8" 2223 }; 2224 } 2225 if ((match = matchers.hex6.exec(color))) { 2226 return { 2227 r: parseIntFromHex(match[1]), 2228 g: parseIntFromHex(match[2]), 2229 b: parseIntFromHex(match[3]), 2230 format: named ? "name" : "hex" 2231 }; 2232 } 2233 if ((match = matchers.hex3.exec(color))) { 2234 return { 2235 r: parseIntFromHex(match[1] + '' + match[1]), 2236 g: parseIntFromHex(match[2] + '' + match[2]), 2237 b: parseIntFromHex(match[3] + '' + match[3]), 2238 format: named ? "name" : "hex" 2239 }; 2240 } 2241 2242 return false; 2243 } 2244 2245 window.tinycolor = tinycolor; 2246 })(); 2247 2248 2249 $(function () { 2250 if ($.fn.spectrum.load) { 2251 $.fn.spectrum.processNativeColorInputs(); 2252 } 2253 }); 2254 2255})(window, 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.