Вход Регистрация
Файл: sys/static/js/spectrum.js
Строк: 2356
<?php
// Spectrum Colorpicker v1.8.0
// https://github.com/bgrins/spectrum
// Author: Brian Grinstead
// License: MIT

(function (factory) {
    
"use strict";

    if (
typeof define === 'function' && define.amd) { // AMD
        
define(['jquery'], factory);
    }
    else if (
typeof exports == "object" && typeof module == "object") { // CommonJS
        
module.exports factory(require('jquery'));
    }
    else { 
// Browser
        
factory(jQuery);
    }
})(function($, 
undefined) {
    
"use strict";

    var 
defaultOpts = {

        
// Callbacks
        
beforeShownoop,
        
movenoop,
        
changenoop,
        
shownoop,
        
hidenoop,

        
// Options
        
colorfalse,
        
flatfalse,
        
showInputfalse,
        
allowEmptyfalse,
        
showButtonstrue,
        
clickoutFiresChangetrue,
        
showInitialfalse,
        
showPalettefalse,
        
showPaletteOnlyfalse,
        
hideAfterPaletteSelectfalse,
        
togglePaletteOnlyfalse,
        
showSelectionPalettetrue,
        
localStorageKeyfalse,
        
appendTo"body",
        
maxSelectionSize7,
        
cancelText"cancel",
        
chooseText"choose",
        
togglePaletteMoreText"more",
        
togglePaletteLessText"less",
        
clearText"Clear Color Selection",
        
noColorSelectedText"No Color Selected",
        
preferredFormatfalse,
        
className""// Deprecated - use containerClassName and replacerClassName instead.
        
containerClassName"",
        
replacerClassName"",
        
showAlphafalse,
        
theme"sp-light",
        
palette: [["#ffffff""#000000""#ff0000""#ff8000""#ffff00""#008000""#0000ff""#4b0082""#9400d3"]],
        
selectionPalette: [],
        
disabledfalse,
        
offsetnull
    
},
    
spectrums = [],
    
IE = !!/msie/i.execwindow.navigator.userAgent ),
    
rgbaSupport = (function() {
        function 
containsstrsubstr ) {
            return !!~(
'' str).indexOf(substr);
        }

        var 
elem document.createElement('div');
        var 
style elem.style;
        
style.cssText 'background-color:rgba(0,0,0,.5)';
        return 
contains(style.backgroundColor'rgba') || contains(style.backgroundColor'hsla');
    })(),
    
replaceInput = [
        
"<div class='sp-replacer'>",
            
"<div class='sp-preview'><div class='sp-preview-inner'></div></div>",
            
"<div class='sp-dd'>&#9660;</div>",
        
"</div>"
    
].join(''),
    
markup = (function () {

        
// IE does not support gradients with multiple stops, so we need to simulate
        //  that for the rainbow slider with 8 divs that each have a single gradient
        
var gradientFix "";
        if (
IE) {
            for (var 
1<= 6i++) {
                
gradientFix += "<div class='sp-" "'></div>";
            }
        }

        return [
            
"<div class='sp-container sp-hidden'>",
                
"<div class='sp-palette-container'>",
                    
"<div class='sp-palette sp-thumb sp-cf'></div>",
                    
"<div class='sp-palette-button-container sp-cf'>",
                        
"<button type='button' class='sp-palette-toggle'></button>",
                    
"</div>",
                
"</div>",
                
"<div class='sp-picker-container'>",
                    
"<div class='sp-top sp-cf'>",
                        
"<div class='sp-fill'></div>",
                        
"<div class='sp-top-inner'>",
                            
"<div class='sp-color'>",
                                
"<div class='sp-sat'>",
                                    
"<div class='sp-val'>",
                                        
"<div class='sp-dragger'></div>",
                                    
"</div>",
                                
"</div>",
                            
"</div>",
                            
"<div class='sp-clear sp-clear-display'>",
                            
"</div>",
                            
"<div class='sp-hue'>",
                                
"<div class='sp-slider'></div>",
                                
gradientFix,
                            
"</div>",
                        
"</div>",

                        
"<div class='sp-right-inner'>",
                            
"<div class='sp-title'>Ваш цвет</div>"
                            
"<div class='sp-initial sp-thumb sp-cf'></div>",
                            
"<div class='sp-input-container sp-cf'>",
                                
"<input class='sp-input' type='text' spellcheck='false'  />",
                            
"</div>",
                            
"<div class='sp-button-container sp-cf'>",
                                
"<button type='button' class='sp-choose'></button>",
                                
"<a class='sp-cancel' href='#'></a>",
                            
"</div>",
                        
"</div>",
                        
"<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>",
                    
"</div>",
                
"</div>",
            
"</div>"
        
].join("");
    })();

    function 
paletteTemplate (pcolorclassNameopts) {
        var 
html = [];
        for (var 
0p.lengthi++) {
            var 
current p[i];
            if(
current) {
                var 
tiny tinycolor(current);
                var 
tiny.toHsl().0.5 "sp-thumb-el sp-thumb-dark" "sp-thumb-el sp-thumb-light";
                
+= (tinycolor.equals(colorcurrent)) ? " sp-thumb-active" "";
                var 
formattedString tiny.toString(opts.preferredFormat || "rgb");
                var 
swatchStyle rgbaSupport ? ("background-color:" tiny.toRgbString()) : "filter:" tiny.toFilter();
                
html.push('<span title="' formattedString '" data-color="' tiny.toRgbString() + '" class="' '"><span class="sp-thumb-inner" style="' swatchStyle ';" /></span>');
            } else {
                var 
cls 'sp-clear-display';
                
html.push($('<div />')
                    .
append($('<span data-color="" style="background-color:transparent;" class="' cls '"></span>')
                        .
attr('title'opts.noColorSelectedText)
                    )
                    .
html()
                );
            }
        }
        return 
"<div class='sp-cf " className "'>" html.join('') + "</div>";
    }

    function 
hideAll() {
        for (var 
0spectrums.lengthi++) {
            if (
spectrums[i]) {
                
spectrums[i].hide();
            }
        }
    }

    function 
instanceOptions(ocallbackContext) {
        var 
opts = $.extend({}, defaultOptso);
        
opts.callbacks = {
            
'move'bind(opts.movecallbackContext),
            
'change'bind(opts.changecallbackContext),
            
'show'bind(opts.showcallbackContext),
            
'hide'bind(opts.hidecallbackContext),
            
'beforeShow'bind(opts.beforeShowcallbackContext)
        };

        return 
opts;
    }

    function 
spectrum(elemento) {

        var 
opts instanceOptions(oelement),
            
flat opts.flat,
            
showSelectionPalette opts.showSelectionPalette,
            
localStorageKey opts.localStorageKey,
            
theme opts.theme,
            
callbacks opts.callbacks,
            
resize throttle(reflow10),
            
visible false,
            
isDragging false,
            
dragWidth 0,
            
dragHeight 0,
            
dragHelperHeight 0,
            
slideHeight 0,
            
slideWidth 0,
            
alphaWidth 0,
            
alphaSlideHelperWidth 0,
            
slideHelperHeight 0,
            
currentHue 0,
            
currentSaturation 0,
            
currentValue 0,
            
currentAlpha 1,
            
palette = [],
            
paletteArray = [],
            
paletteLookup = {},
            
selectionPalette opts.selectionPalette.slice(0),
            
maxSelectionSize opts.maxSelectionSize,
            
draggingClass "sp-dragging",
            
shiftMovementDirection null;

        var 
doc element.ownerDocument,
            
body doc.body,
            
boundElement = $(element),
            
disabled false,
            
container = $(markupdoc).addClass(theme),
            
pickerContainer container.find(".sp-picker-container"),
            
dragger container.find(".sp-color"),
            
dragHelper container.find(".sp-dragger"),
            
slider container.find(".sp-hue"),
            
slideHelper container.find(".sp-slider"),
            
alphaSliderInner container.find(".sp-alpha-inner"),
            
alphaSlider container.find(".sp-alpha"),
            
alphaSlideHelper container.find(".sp-alpha-handle"),
            
textInput container.find(".sp-input"),
            
paletteContainer container.find(".sp-palette"),
            
initialColorContainer container.find(".sp-initial"),
            
cancelButton container.find(".sp-cancel"),
            
clearButton container.find(".sp-clear"),
            
chooseButton container.find(".sp-choose"),
            
toggleButton container.find(".sp-palette-toggle"),
            
isInput boundElement.is("input"),
            
isInputTypeColor isInput && boundElement.attr("type") === "color" && inputTypeColorSupport(),
            
shouldReplace isInput && !flat,
            
replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),
            
offsetElement = (shouldReplace) ? replacer boundElement,
            
previewElement replacer.find(".sp-preview-inner"),
            
initialColor opts.color || (isInput && boundElement.val()),
            
colorOnShow false,
            
currentPreferredFormat opts.preferredFormat,
            
clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,
            
isEmpty = !initialColor,
            
allowEmpty opts.allowEmpty && !isInputTypeColor;

        function 
applyOptions() {

            if (
opts.showPaletteOnly) {
                
opts.showPalette true;
            }

            
toggleButton.text(opts.showPaletteOnly opts.togglePaletteMoreText opts.togglePaletteLessText);

            if (
opts.palette) {
                
palette opts.palette.slice(0);
                
paletteArray = $.isArray(palette[0]) ? palette : [palette];
                
paletteLookup = {};
                for (var 
0paletteArray.lengthi++) {
                    for (var 
0paletteArray[i].lengthj++) {
                        var 
rgb tinycolor(paletteArray[i][j]).toRgbString();
                        
paletteLookup[rgb] = true;
                    }
                }
            }

            
container.toggleClass("sp-flat"flat);
            
container.toggleClass("sp-input-disabled", !opts.showInput);
            
container.toggleClass("sp-alpha-enabled"opts.showAlpha);
            
container.toggleClass("sp-clear-enabled"allowEmpty);
            
container.toggleClass("sp-buttons-disabled", !opts.showButtons);
            
container.toggleClass("sp-palette-buttons-disabled", !opts.togglePaletteOnly);
            
container.toggleClass("sp-palette-disabled", !opts.showPalette);
            
container.toggleClass("sp-palette-only"opts.showPaletteOnly);
            
container.toggleClass("sp-initial-disabled", !opts.showInitial);
            
container.addClass(opts.className).addClass(opts.containerClassName);

            
reflow();
        }

        function 
initialize() {

            if (
IE) {
                
container.find("*:not(input)").attr("unselectable""on");
            }

            
applyOptions();

            if (
shouldReplace) {
                
boundElement.after(replacer).hide();
            }

            if (!
allowEmpty) {
                
clearButton.hide();
            }

            if (
flat) {
                
boundElement.after(container).hide();
            }
            else {

                var 
appendTo opts.appendTo === "parent" boundElement.parent() : $(opts.appendTo);
                if (
appendTo.length !== 1) {
                    
appendTo = $("body");
                }

                
appendTo.append(container);
            }

            
updateSelectionPaletteFromStorage();

            
offsetElement.bind("click.spectrum touchstart.spectrum", function (e) {
                if (!
disabled) {
                    
toggle();
                }

                
e.stopPropagation();

                if (!$(
e.target).is("input")) {
                    
e.preventDefault();
                }
            });

            if(
boundElement.is(":disabled") || (opts.disabled === true)) {
                
disable();
            }

            
// Prevent clicks from bubbling up to document.  This would cause it to be hidden.
            
container.click(stopPropagation);

            
// Handle user typed input
            
textInput.change(setFromTextInput);
            
textInput.bind("paste", function () {
                
setTimeout(setFromTextInput1);
            });
            
textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });

            
cancelButton.text(opts.cancelText);
            
cancelButton.bind("click.spectrum", function (e) {
                
e.stopPropagation();
                
e.preventDefault();
                
revert();
                
hide();
            });

            
clearButton.attr("title"opts.clearText);
            
clearButton.bind("click.spectrum", function (e) {
                
e.stopPropagation();
                
e.preventDefault();
                
isEmpty true;
                
move();

                if(
flat) {
                    
//for the flat style, this is a change event
                    
updateOriginalInput(true);
                }
            });

            
chooseButton.text(opts.chooseText);
            
chooseButton.bind("click.spectrum", function (e) {
                
e.stopPropagation();
                
e.preventDefault();

                if (
IE && textInput.is(":focus")) {
                    
textInput.trigger('change');
                }

                if (
isValid()) {
                    
updateOriginalInput(true);
                    
hide();
                }
            });

            
toggleButton.text(opts.showPaletteOnly opts.togglePaletteMoreText opts.togglePaletteLessText);
            
toggleButton.bind("click.spectrum", function (e) {
                
e.stopPropagation();
                
e.preventDefault();

                
opts.showPaletteOnly = !opts.showPaletteOnly;

                
// To make sure the Picker area is drawn on the right, next to the
                // Palette area (and not below the palette), first move the Palette
                // to the left to make space for the picker, plus 5px extra.
                // The 'applyOptions' function puts the whole container back into place
                // and takes care of the button-text and the sp-palette-only CSS class.
                
if (!opts.showPaletteOnly && !flat) {
                    
container.css('left''-=' + (pickerContainer.outerWidth(true) + 5));
                }
                
applyOptions();
            });

            
draggable(alphaSlider, function (dragXdragYe) {
                
currentAlpha = (dragX alphaWidth);
                
isEmpty false;
                if (
e.shiftKey) {
                    
currentAlpha Math.round(currentAlpha 10) / 10;
                }

                
move();
            }, 
dragStartdragStop);

            
draggable(slider, function (dragXdragY) {
                
currentHue parseFloat(dragY slideHeight);
                
isEmpty false;
                if (!
opts.showAlpha) {
                    
currentAlpha 1;
                }
                
move();
            }, 
dragStartdragStop);

            
draggable(dragger, function (dragXdragYe) {

                
// shift+drag should snap the movement to either the x or y axis.
                
if (!e.shiftKey) {
                    
shiftMovementDirection null;
                }
                else if (!
shiftMovementDirection) {
                    var 
oldDragX currentSaturation dragWidth;
                    var 
oldDragY dragHeight - (currentValue dragHeight);
                    var 
furtherFromX Math.abs(dragX oldDragX) > Math.abs(dragY oldDragY);

                    
shiftMovementDirection furtherFromX "x" "y";
                }

                var 
setSaturation = !shiftMovementDirection || shiftMovementDirection === "x";
                var 
setValue = !shiftMovementDirection || shiftMovementDirection === "y";

                if (
setSaturation) {
                    
currentSaturation parseFloat(dragX dragWidth);
                }
                if (
setValue) {
                    
currentValue parseFloat((dragHeight dragY) / dragHeight);
                }

                
isEmpty false;
                if (!
opts.showAlpha) {
                    
currentAlpha 1;
                }

                
move();

            }, 
dragStartdragStop);

            if (!!
initialColor) {
                
set(initialColor);

                
// In case color was black - update the preview UI and set the format
                // since the set function will not run (default color is black).
                
updateUI();
                
currentPreferredFormat opts.preferredFormat || tinycolor(initialColor).format;

                
addColorToSelectionPalette(initialColor);
            }
            else {
                
updateUI();
            }

            if (
flat) {
                
show();
            }

            function 
paletteElementClick(e) {
                if (
e.data && e.data.ignore) {
                    
set($(e.target).closest(".sp-thumb-el").data("color"));
                    
move();
                }
                else {
                    
set($(e.target).closest(".sp-thumb-el").data("color"));
                    
move();
                    
updateOriginalInput(true);
                    if (
opts.hideAfterPaletteSelect) {
                      
hide();
                    }
                }

                return 
false;
            }

            var 
paletteEvent IE "mousedown.spectrum" "click.spectrum touchstart.spectrum";
            
paletteContainer.delegate(".sp-thumb-el"paletteEventpaletteElementClick);
            
initialColorContainer.delegate(".sp-thumb-el:nth-child(1)"paletteEvent, { ignoretrue }, paletteElementClick);
        }

        function 
updateSelectionPaletteFromStorage() {

            if (
localStorageKey && window.localStorage) {

                
// Migrate old palettes over to new format.  May want to remove this eventually.
                
try {
                    var 
oldPalette window.localStorage[localStorageKey].split(",#");
                    if (
oldPalette.length 1) {
                        
delete window.localStorage[localStorageKey];
                        $.
each(oldPalette, function(ic) {
                             
addColorToSelectionPalette(c);
                        });
                    }
                }
                catch(
e) { }

                try {
                    
selectionPalette window.localStorage[localStorageKey].split(";");
                }
                catch (
e) { }
            }
        }

        function 
addColorToSelectionPalette(color) {
            if (
showSelectionPalette) {
                var 
rgb tinycolor(color).toRgbString();
                if (!
paletteLookup[rgb] && $.inArray(rgbselectionPalette) === -1) {
                    
selectionPalette.push(rgb);
                    while(
selectionPalette.length maxSelectionSize) {
                        
selectionPalette.shift();
                    }
                }

                if (
localStorageKey && window.localStorage) {
                    try {
                        
window.localStorage[localStorageKey] = selectionPalette.join(";");
                    }
                    catch(
e) { }
                }
            }
        }

        function 
getUniqueSelectionPalette() {
            var 
unique = [];
            if (
opts.showPalette) {
                for (var 
0selectionPalette.lengthi++) {
                    var 
rgb tinycolor(selectionPalette[i]).toRgbString();

                    if (!
paletteLookup[rgb]) {
                        
unique.push(selectionPalette[i]);
                    }
                }
            }

            return 
unique.reverse().slice(0opts.maxSelectionSize);
        }

        function 
drawPalette() {

            var 
currentColor get();

            var 
html = $.map(paletteArray, function (palettei) {
                return 
paletteTemplate(palettecurrentColor"sp-palette-row sp-palette-row-" iopts);
            });

            
updateSelectionPaletteFromStorage();

            if (
selectionPalette) {
                
html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor"sp-palette-row sp-palette-row-selection"opts));
            }

            
paletteContainer.html(html.join(""));
        }

        function 
drawInitial() {
            if (
opts.showInitial) {
                var 
initial colorOnShow;
                var 
current get();
                
initialColorContainer.html(paletteTemplate([initialcurrent], current"sp-palette-row-initial"opts));
            }
        }

        function 
dragStart() {
            if (
dragHeight <= || dragWidth <= || slideHeight <= 0) {
                
reflow();
            }
            
isDragging true;
            
container.addClass(draggingClass);
            
shiftMovementDirection null;
            
boundElement.trigger('dragstart.spectrum', [ get() ]);
        }

        function 
dragStop() {
            
isDragging false;
            
container.removeClass(draggingClass);
            
boundElement.trigger('dragstop.spectrum', [ get() ]);
        }

        function 
setFromTextInput() {

            var 
value textInput.val();

            if ((
value === null || value === "") && allowEmpty) {
                
set(null);
                
updateOriginalInput(true);
            }
            else {
                var 
tiny tinycolor(value);
                if (
tiny.isValid()) {
                    
set(tiny);
                    
updateOriginalInput(true);
                }
                else {
                    
textInput.addClass("sp-validation-error");
                }
            }
        }

        function 
toggle() {
            if (
visible) {
                
hide();
            }
            else {
                
show();
            }
        }

        function 
show() {
            var 
event = $.Event('beforeShow.spectrum');

            if (
visible) {
                
reflow();
                return;
            }

            
boundElement.trigger(event, [ get() ]);

            if (
callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {
                return;
            }

            
hideAll();
            
visible true;

            $(
doc).bind("keydown.spectrum"onkeydown);
            $(
doc).bind("click.spectrum"clickout);
            $(
window).bind("resize.spectrum"resize);
            
replacer.addClass("sp-active");
            
container.removeClass("sp-hidden");

            
reflow();
            
updateUI();

            
colorOnShow get();

            
drawInitial();
            
callbacks.show(colorOnShow);
            
boundElement.trigger('show.spectrum', [ colorOnShow ]);
        }

        function 
onkeydown(e) {
            
// Close on ESC
            
if (e.keyCode === 27) {
                
hide();
            }
        }

        function 
clickout(e) {
            
// Return on right click.
            
if (e.button == 2) { return; }

            
// If a drag event was happening during the mouseup, don't hide
            // on click.
            
if (isDragging) { return; }

            if (
clickoutFiresChange) {
                
updateOriginalInput(true);
            }
            else {
                
revert();
            }
            
hide();
        }

        function 
hide() {
            
// Return if hiding is unnecessary
            
if (!visible || flat) { return; }
            
visible false;

            $(
doc).unbind("keydown.spectrum"onkeydown);
            $(
doc).unbind("click.spectrum"clickout);
            $(
window).unbind("resize.spectrum"resize);

            
replacer.removeClass("sp-active");
            
container.addClass("sp-hidden");

            
callbacks.hide(get());
            
boundElement.trigger('hide.spectrum', [ get() ]);
        }

        function 
revert() {
            
set(colorOnShowtrue);
        }

        function 
set(colorignoreFormatChange) {
            if (
tinycolor.equals(colorget())) {
                
// Update UI just in case a validation error needs
                // to be cleared.
                
updateUI();
                return;
            }

            var 
newColornewHsv;
            if (!
color && allowEmpty) {
                
isEmpty true;
            } else {
                
isEmpty false;
                
newColor tinycolor(color);
                
newHsv newColor.toHsv();

                
currentHue = (newHsv.360) / 360;
                
currentSaturation newHsv.s;
                
currentValue newHsv.v;
                
currentAlpha newHsv.a;
            }
            
updateUI();

            if (
newColor && newColor.isValid() && !ignoreFormatChange) {
                
currentPreferredFormat opts.preferredFormat || newColor.getFormat();
            }
        }

        function 
get(opts) {
            
opts opts || { };

            if (
allowEmpty && isEmpty) {
                return 
null;
            }

            return 
tinycolor.fromRatio({
                
hcurrentHue,
                
scurrentSaturation,
                
vcurrentValue,
                
aMath.round(currentAlpha 100) / 100
            
}, { formatopts.format || currentPreferredFormat });
        }

        function 
isValid() {
            return !
textInput.hasClass("sp-validation-error");
        }

        function 
move() {
            
updateUI();

            
callbacks.move(get());
            
boundElement.trigger('move.spectrum', [ get() ]);
        }

        function 
updateUI() {

            
textInput.removeClass("sp-validation-error");

            
updateHelperLocations();

            
// Update dragger background color (gradients take care of saturation and value).
            
var flatColor tinycolor.fromRatio({ hcurrentHues1v});
            
dragger.css("background-color"flatColor.toHexString());

            
// Get a format that alpha will be included in (hex and names ignore alpha)
            
var format currentPreferredFormat;
            if (
currentAlpha && !(currentAlpha === && format === "name")) {
                if (
format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
                    
format "rgb";
                }
            }

            var 
realColor get({ formatformat }),
                
displayColor '';

             
//reset background info for preview element
            
previewElement.removeClass("sp-clear-display");
            
previewElement.css('background-color''transparent');

            if (!
realColor && allowEmpty) {
                
// Update the replaced elements background with icon indicating no color selection
                
previewElement.addClass("sp-clear-display");
            }
            else {
                var 
realHex realColor.toHexString(),
                    
realRgb realColor.toRgbString();

                
// Update the replaced elements background color (with actual selected color)
                
if (rgbaSupport || realColor.alpha === 1) {
                    
previewElement.css("background-color"realRgb);
                }
                else {
                    
previewElement.css("background-color""transparent");
                    
previewElement.css("filter"realColor.toFilter());
                }

                if (
opts.showAlpha) {
                    var 
rgb realColor.toRgb();
                    
rgb.0;
                    var 
realAlpha tinycolor(rgb).toRgbString();
                    var 
gradient "linear-gradient(left, " realAlpha ", " realHex ")";

                    if (
IE) {
                        
alphaSliderInner.css("filter"tinycolor(realAlpha).toFilter({ gradientType}, realHex));
                    }
                    else {
                        
alphaSliderInner.css("background""-webkit-" gradient);
                        
alphaSliderInner.css("background""-moz-" gradient);
                        
alphaSliderInner.css("background""-ms-" gradient);
                        
// Use current syntax gradient on unprefixed property.
                        
alphaSliderInner.css("background",
                            
"linear-gradient(to right, " realAlpha ", " realHex ")");
                    }
                }

                
displayColor realColor.toString(format);
            }

            
// Update the text entry input as it changes happen
            
if (opts.showInput) {
                
textInput.val(displayColor);
            }

            if (
opts.showPalette) {
                
drawPalette();
            }

            
drawInitial();
        }

        function 
updateHelperLocations() {
            var 
currentSaturation;
            var 
currentValue;

            if(
allowEmpty && isEmpty) {
                
//if selected color is empty, hide the helpers
                
alphaSlideHelper.hide();
                
slideHelper.hide();
                
dragHelper.hide();
            }
            else {
                
//make sure helpers are visible
                
alphaSlideHelper.show();
                
slideHelper.show();
                
dragHelper.show();

                
// Where to show the little circle in that displays your current selected color
                
var dragX dragWidth;
                var 
dragY dragHeight - (dragHeight);
                
dragX Math.max(
                    -
dragHelperHeight,
                    
Math.min(dragWidth dragHelperHeightdragX dragHelperHeight)
                );
                
dragY Math.max(
                    -
dragHelperHeight,
                    
Math.min(dragHeight dragHelperHeightdragY dragHelperHeight)
                );
                
dragHelper.css({
                    
"top"dragY "px",
                    
"left"dragX "px"
                
});

                var 
alphaX currentAlpha alphaWidth;
                
alphaSlideHelper.css({
                    
"left": (alphaX - (alphaSlideHelperWidth 2)) + "px"
                
});

                
// Where to show the bar that displays your current selected hue
                
var slideY = (currentHue) * slideHeight;
                
slideHelper.css({
                    
"top": (slideY slideHelperHeight) + "px"
                
});
            }
        }

        function 
updateOriginalInput(fireCallback) {
            var 
color get(),
                
displayColor '',
                
hasChanged = !tinycolor.equals(colorcolorOnShow);

            if (
color) {
                
displayColor color.toString(currentPreferredFormat);
                
// Update the selection palette with the current color
                
addColorToSelectionPalette(color);
            }

            if (
isInput) {
                
boundElement.val(displayColor);
            }

            if (
fireCallback && hasChanged) {
                
callbacks.change(color);
                
boundElement.trigger('change', [ color ]);
            }
        }

        function 
reflow() {
            if (!
visible) {
                return; 
// Calculations would be useless and wouldn't be reliable anyways
            
}
            
dragWidth dragger.width();
            
dragHeight dragger.height();
            
dragHelperHeight dragHelper.height();
            
slideWidth slider.width();
            
slideHeight slider.height();
            
slideHelperHeight slideHelper.height();
            
alphaWidth alphaSlider.width();
            
alphaSlideHelperWidth alphaSlideHelper.width();

            if (!
flat) {
                
container.css("position""absolute");
                if (
opts.offset) {
                    
container.offset(opts.offset);
                } else {
                    
container.offset(getOffset(containeroffsetElement));
                }
            }

            
updateHelperLocations();

            if (
opts.showPalette) {
                
drawPalette();
            }

            
boundElement.trigger('reflow.spectrum');
        }

        function 
destroy() {
            
boundElement.show();
            
offsetElement.unbind("click.spectrum touchstart.spectrum");
            
container.remove();
            
replacer.remove();
            
spectrums[spect.id] = null;
        }

        function 
option(optionNameoptionValue) {
            if (
optionName === undefined) {
                return $.
extend({}, opts);
            }
            if (
optionValue === undefined) {
                return 
opts[optionName];
            }

            
opts[optionName] = optionValue;

            if (
optionName === "preferredFormat") {
                
currentPreferredFormat opts.preferredFormat;
            }
            
applyOptions();
        }

        function 
enable() {
            
disabled false;
            
boundElement.attr("disabled"false);
            
offsetElement.removeClass("sp-disabled");
        }

        function 
disable() {
            
hide();
            
disabled true;
            
boundElement.attr("disabled"true);
            
offsetElement.addClass("sp-disabled");
        }

        function 
setOffset(coord) {
            
opts.offset coord;
            
reflow();
        }

        
initialize();

        var 
spect = {
            
showshow,
            
hidehide,
            
toggletoggle,
            
reflowreflow,
            
optionoption,
            
enableenable,
            
disabledisable,
            
offsetsetOffset,
            
set: function (c) {
                
set(c);
                
updateOriginalInput();
            },
            
getget,
            
destroydestroy,
            
containercontainer
        
};

        
spect.id spectrums.push(spect) - 1;

        return 
spect;
    }

    
/**
    * checkOffset - get the offset below/above and left/right element depending on screen position
    * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
    */
    
function getOffset(pickerinput) {
        var 
extraY 0;
        var 
dpWidth picker.outerWidth();
        var 
dpHeight picker.outerHeight();
        var 
inputHeight input.outerHeight();
        var 
doc picker[0].ownerDocument;
        var 
docElem doc.documentElement;
        var 
viewWidth docElem.clientWidth + $(doc).scrollLeft();
        var 
viewHeight docElem.clientHeight + $(doc).scrollTop();
        var 
offset input.offset();
        
offset.top += inputHeight;

        
offset.left -=
            
Math.min(offset.left, (offset.left dpWidth viewWidth && viewWidth dpWidth) ?
            
Math.abs(offset.left dpWidth viewWidth) : 0);

        
offset.top -=
            
Math.min(offset.top, ((offset.top dpHeight viewHeight && viewHeight dpHeight) ?
            
Math.abs(dpHeight inputHeight extraY) : extraY));

        return 
offset;
    }

    
/**
    * noop - do nothing
    */
    
function noop() {

    }

    
/**
    * stopPropagation - makes the code only doing this a little easier to read in line
    */
    
function stopPropagation(e) {
        
e.stopPropagation();
    }

    
/**
    * Create a function bound to a given object
    * Thanks to underscore.js
    */
    
function bind(funcobj) {
        var 
slice = Array.prototype.slice;
        var 
args slice.call(arguments2);
        return function () {
            return 
func.apply(objargs.concat(slice.call(arguments)));
        };
    }

    
/**
    * Lightweight drag helper.  Handles containment within the element, so that
    * when dragging, the x is within [0,element.width] and y is within [0,element.height]
    */
    
function draggable(elementonmoveonstartonstop) {
        
onmove onmove || function () { };
        
onstart onstart || function () { };
        
onstop onstop || function () { };
        var 
doc document;
        var 
dragging false;
        var 
offset = {};
        var 
maxHeight 0;
        var 
maxWidth 0;
        var 
hasTouch = ('ontouchstart' in window);

        var 
duringDragEvents = {};
        
duringDragEvents["selectstart"] = prevent;
        
duringDragEvents["dragstart"] = prevent;
        
duringDragEvents["touchmove mousemove"] = move;
        
duringDragEvents["touchend mouseup"] = stop;

        function 
prevent(e) {
            if (
e.stopPropagation) {
                
e.stopPropagation();
            }
            if (
e.preventDefault) {
                
e.preventDefault();
            }
            
e.returnValue false;
        }

        function 
move(e) {
            if (
dragging) {
                
// Mouseup happened outside of window
                
if (IE && doc.documentMode && !e.button) {
                    return 
stop();
                }

                var 
t0 e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0];
                var 
pageX t0 && t0.pageX || e.pageX;
                var 
pageY t0 && t0.pageY || e.pageY;

                var 
dragX Math.max(0Math.min(pageX offset.leftmaxWidth));
                var 
dragY Math.max(0Math.min(pageY offset.topmaxHeight));

                if (
hasTouch) {
                    
// Stop scrolling in iOS
                    
prevent(e);
                }

                
onmove.apply(element, [dragXdragYe]);
            }
        }

        function 
start(e) {
            var 
rightclick = (e.which) ? (e.which == 3) : (e.button == 2);

            if (!
rightclick && !dragging) {
                if (
onstart.apply(elementarguments) !== false) {
                    
dragging true;
                    
maxHeight = $(element).height();
                    
maxWidth = $(element).width();
                    
offset = $(element).offset();

                    $(
doc).bind(duringDragEvents);
                    $(
doc.body).addClass("sp-dragging");

                    
move(e);

                    
prevent(e);
                }
            }
        }

        function 
stop() {
            if (
dragging) {
                $(
doc).unbind(duringDragEvents);
                $(
doc.body).removeClass("sp-dragging");

                
// Wait a tick before notifying observers to allow the click event
                // to fire in Chrome.
                
setTimeout(function() {
                    
onstop.apply(elementarguments);
                }, 
0);
            }
            
dragging false;
        }

        $(
element).bind("touchstart mousedown"start);
    }

    function 
throttle(funcwaitdebounce) {
        var 
timeout;
        return function () {
            var 
context thisargs arguments;
            var 
throttler = function () {
                
timeout null;
                
func.apply(contextargs);
            };
            if (
debounceclearTimeout(timeout);
            if (
debounce || !timeouttimeout setTimeout(throttlerwait);
        };
    }

    function 
inputTypeColorSupport() {
        return $.fn.
spectrum.inputTypeColorSupport();
    }

    
/**
    * Define a jQuery plugin
    */
    
var dataID "spectrum.id";
    $.fn.
spectrum = function (optsextra) {

        if (
typeof opts == "string") {

            var 
returnValue this;
            var 
args = Array.prototype.slice.callarguments);

            
this.each(function () {
                var 
spect spectrums[$(this).data(dataID)];
                if (
spect) {
                    var 
method spect[opts];
                    if (!
method) {
                        throw new 
Error"Spectrum: no such method: '" opts "'" );
                    }

                    if (
opts == "get") {
                        
returnValue spect.get();
                    }
                    else if (
opts == "container") {
                        
returnValue spect.container;
                    }
                    else if (
opts == "option") {
                        
returnValue spect.option.apply(spectargs);
                    }
                    else if (
opts == "destroy") {
                        
spect.destroy();
                        $(
this).removeData(dataID);
                    }
                    else {
                        
method.apply(spectargs);
                    }
                }
            });

            return 
returnValue;
        }

        
// Initializing a new instance of spectrum
        
return this.spectrum("destroy").each(function () {
            var 
options = $.extend({}, opts, $(this).data());
            var 
spect spectrum(thisoptions);
            $(
this).data(dataIDspect.id);
        });
    };

    $.fn.
spectrum.load true;
    $.fn.
spectrum.loadOpts = {};
    $.fn.
spectrum.draggable draggable;
    $.fn.
spectrum.defaults defaultOpts;
    $.fn.
spectrum.inputTypeColorSupport = function inputTypeColorSupport() {
        if (
typeof inputTypeColorSupport._cachedResult === "undefined") {
            var 
colorInput = $("<input type='color'/>")[0]; // if color element is supported, value will default to not null
            
inputTypeColorSupport._cachedResult colorInput.type === "color" && colorInput.value !== "";
        }
        return 
inputTypeColorSupport._cachedResult;
    };

    $.
spectrum = { };
    $.
spectrum.localization = { };
    $.
spectrum.palettes = { };

    $.fn.
spectrum.processNativeColorInputs = function () {
        var 
colorInputs = $("input[type=color]");
        if (
colorInputs.length && !inputTypeColorSupport()) {
            
colorInputs.spectrum({
                
preferredFormat"hex6"
            
});
        }
    };

    
// TinyColor v1.1.2
    // https://github.com/bgrins/TinyColor
    // Brian Grinstead, MIT License

    
(function() {

    var 
trimLeft = /^[s,#]+/,
        
trimRight = /s+$/,
        
tinyCounter 0,
        
math Math,
        
mathRound math.round,
        
mathMin math.min,
        
mathMax math.max,
        
mathRandom math.random;

    var 
tinycolor = function(coloropts) {

        
color = (color) ? color '';
        
opts opts || { };

        
// If input is already a tinycolor, return itself
        
if (color instanceof tinycolor) {
           return 
color;
        }
        
// If we are called as a function, call using new instead
        
if (!(this instanceof tinycolor)) {
            return new 
tinycolor(coloropts);
        }

        var 
rgb inputToRGB(color);
        
this._originalInput color,
        
this._r rgb.r,
        
this._g rgb.g,
        
this._b rgb.b,
        
this._a rgb.a,
        
this._roundA mathRound(100*this._a) / 100,
        
this._format opts.format || rgb.format;
        
this._gradientType opts.gradientType;

        
// Don't let the range of [0,255] come back in [0,1].
        // Potentially lose a little bit of precision here, but will fix issues where
        // .5 gets interpreted as half of the total, instead of half of 1
        // If it was supposed to be 128, this was already taken care of by `inputToRgb`
        
if (this._r 1) { this._r mathRound(this._r); }
        if (
this._g 1) { this._g mathRound(this._g); }
        if (
this._b 1) { this._b mathRound(this._b); }

        
this._ok rgb.ok;
        
this._tc_id tinyCounter++;
    };

    
tinycolor.prototype = {
        
isDark: function() {
            return 
this.getBrightness() < 128;
        },
        
isLight: function() {
            return !
this.isDark();
        },
        
isValid: function() {
            return 
this._ok;
        },
        
getOriginalInput: function() {
          return 
this._originalInput;
        },
        
getFormat: function() {
            return 
this._format;
        },
        
getAlpha: function() {
            return 
this._a;
        },
        
getBrightness: function() {
            var 
rgb this.toRgb();
            return (
rgb.299 rgb.587 rgb.114) / 1000;
        },
        
setAlpha: function(value) {
            
this._a boundAlpha(value);
            
this._roundA mathRound(100*this._a) / 100;
            return 
this;
        },
        
toHsv: function() {
            var 
hsv rgbToHsv(this._rthis._gthis._b);
            return { 
hhsv.360shsv.svhsv.vathis._a };
        },
        
toHsvString: function() {
            var 
hsv rgbToHsv(this._rthis._gthis._b);
            var 
mathRound(hsv.360), mathRound(hsv.100), mathRound(hsv.100);
            return (
this._a == 1) ?
              
"hsv("  ", " "%, " "%)" :
              
"hsva(" ", " "%, " "%, "this._roundA ")";
        },
        
toHsl: function() {
            var 
hsl rgbToHsl(this._rthis._gthis._b);
            return { 
hhsl.360shsl.slhsl.lathis._a };
        },
        
toHslString: function() {
            var 
hsl rgbToHsl(this._rthis._gthis._b);
            var 
mathRound(hsl.360), mathRound(hsl.100), mathRound(hsl.100);
            return (
this._a == 1) ?
              
"hsl("  ", " "%, " "%)" :
              
"hsla(" ", " "%, " "%, "this._roundA ")";
        },
        
toHex: function(allow3Char) {
            return 
rgbToHex(this._rthis._gthis._ballow3Char);
        },
        
toHexString: function(allow3Char) {
            return 
'#' this.toHex(allow3Char);
        },
        
toHex8: function() {
            return 
rgbaToHex(this._rthis._gthis._bthis._a);
        },
        
toHex8String: function() {
            return 
'#' this.toHex8();
        },
        
toRgb: function() {
            return { 
rmathRound(this._r), gmathRound(this._g), bmathRound(this._b), athis._a };
        },
        
toRgbString: function() {
            return (
this._a == 1) ?
              
"rgb("  mathRound(this._r) + ", " mathRound(this._g) + ", " mathRound(this._b) + ")" :
              
"rgba(" mathRound(this._r) + ", " mathRound(this._g) + ", " mathRound(this._b) + ", " this._roundA ")";
        },
        
toPercentageRgb: function() {
            return { 
rmathRound(bound01(this._r255) * 100) + "%"gmathRound(bound01(this._g255) * 100) + "%"bmathRound(bound01(this._b255) * 100) + "%"athis._a };
        },
        
toPercentageRgbString: function() {
            return (
this._a == 1) ?
              
"rgb("  mathRound(bound01(this._r255) * 100) + "%, " mathRound(bound01(this._g255) * 100) + "%, " mathRound(bound01(this._b255) * 100) + "%)" :
              
"rgba(" mathRound(bound01(this._r255) * 100) + "%, " mathRound(bound01(this._g255) * 100) + "%, " mathRound(bound01(this._b255) * 100) + "%, " this._roundA ")";
        },
        
toName: function() {
            if (
this._a === 0) {
                return 
"transparent";
            }

            if (
this._a 1) {
                return 
false;
            }

            return 
hexNames[rgbToHex(this._rthis._gthis._btrue)] || false;
        },
        
toFilter: function(secondColor) {
            var 
hex8String '#' rgbaToHex(this._rthis._gthis._bthis._a);
            var 
secondHex8String hex8String;
            var 
gradientType this._gradientType "GradientType = 1, " "";

            if (
secondColor) {
                var 
tinycolor(secondColor);
                
secondHex8String s.toHex8String();
            }

            return 
"progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
        },
        
toString: function(format) {
            var 
formatSet = !!format;
            
format format || this._format;

            var 
formattedString false;
            var 
hasAlpha this._a && this._a >= 0;
            var 
needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");

            if (
needsAlphaFormat) {
                
// Special case for "transparent", all other non-alpha formats
                // will return rgba when there is transparency.
                
if (format === "name" && this._a === 0) {
                    return 
this.toName();
                }
                return 
this.toRgbString();
            }
            if (
format === "rgb") {
                
formattedString this.toRgbString();
            }
            if (
format === "prgb") {
                
formattedString this.toPercentageRgbString();
            }
            if (
format === "hex" || format === "hex6") {
                
formattedString this.toHexString();
            }
            if (
format === "hex3") {
                
formattedString this.toHexString(true);
            }
            if (
format === "hex8") {
                
formattedString this.toHex8String();
            }
            if (
format === "name") {
                
formattedString this.toName();
            }
            if (
format === "hsl") {
                
formattedString this.toHslString();
            }
            if (
format === "hsv") {
                
formattedString this.toHsvString();
            }

            return 
formattedString || this.toHexString();
        },

        
_applyModification: function(fn, args) {
            var 
color = fn.apply(null, [this].concat([].slice.call(args)));
            
this._r color._r;
            
this._g color._g;
            
this._b color._b;
            
this.setAlpha(color._a);
            return 
this;
        },
        
lighten: function() {
            return 
this._applyModification(lightenarguments);
        },
        
brighten: function() {
            return 
this._applyModification(brightenarguments);
        },
        
darken: function() {
            return 
this._applyModification(darkenarguments);
        },
        
desaturate: function() {
            return 
this._applyModification(desaturatearguments);
        },
        
saturate: function() {
            return 
this._applyModification(saturatearguments);
        },
        
greyscale: function() {
            return 
this._applyModification(greyscalearguments);
        },
        
spin: function() {
            return 
this._applyModification(spinarguments);
        },

        
_applyCombination: function(fn, args) {
            return fn.
apply(null, [this].concat([].slice.call(args)));
        },
        
analogous: function() {
            return 
this._applyCombination(analogousarguments);
        },
        
complement: function() {
            return 
this._applyCombination(complementarguments);
        },
        
monochromatic: function() {
            return 
this._applyCombination(monochromaticarguments);
        },
        
splitcomplement: function() {
            return 
this._applyCombination(splitcomplementarguments);
        },
        
triad: function() {
            return 
this._applyCombination(triadarguments);
        },
        
tetrad: function() {
            return 
this._applyCombination(tetradarguments);
        }
    };

    
// If input is an object, force 1 into "1.0" to handle ratios properly
    // String input requires "1.0" as input, so 1 will be treated as 1
    
tinycolor.fromRatio = function(coloropts) {
        if (
typeof color == "object") {
            var 
newColor = {};
            for (var 
i in color) {
                if (
color.hasOwnProperty(i)) {
                    if (
=== "a") {
                        
newColor[i] = color[i];
                    }
                    else {
                        
newColor[i] = convertToPercentage(color[i]);
                    }
                }
            }
            
color newColor;
        }

        return 
tinycolor(coloropts);
    };

    
// Given a string or object, convert that input to RGB
    // Possible string inputs:
    //
    //     "red"
    //     "#f00" or "f00"
    //     "#ff0000" or "ff0000"
    //     "#ff000000" or "ff000000"
    //     "rgb 255 0 0" or "rgb (255, 0, 0)"
    //     "rgb 1.0 0 0" or "rgb (1, 0, 0)"
    //     "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
    //     "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
    //     "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
    //     "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
    //     "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
    //
    
function inputToRGB(color) {

        var 
rgb = { r0g0b};
        var 
1;
        var 
ok false;
        var 
format false;

        if (
typeof color == "string") {
            
color stringInputToObject(color);
        }

        if (
typeof color == "object") {
            if (
color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
                
rgb rgbToRgb(color.rcolor.gcolor.b);
                
ok true;
                
format String(color.r).substr(-1) === "%" "prgb" "rgb";
            }
            else if (
color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
                
color.convertToPercentage(color.s);
                
color.convertToPercentage(color.v);
                
rgb hsvToRgb(color.hcolor.scolor.v);
                
ok true;
                
format "hsv";
            }
            else if (
color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
                
color.convertToPercentage(color.s);
                
color.convertToPercentage(color.l);
                
rgb hslToRgb(color.hcolor.scolor.l);
                
ok true;
                
format "hsl";
            }

            if (
color.hasOwnProperty("a")) {
                
color.a;
            }
        }

        
boundAlpha(a);

        return {
            
okok,
            
formatcolor.format || format,
            
rmathMin(255mathMax(rgb.r0)),
            
gmathMin(255mathMax(rgb.g0)),
            
bmathMin(255mathMax(rgb.b0)),
            
aa
        
};
    }


    
// Conversion Functions
    // --------------------

    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>

    // `rgbToRgb`
    // Handle bounds / percentage checking to conform to CSS color spec
    // <http://www.w3.org/TR/css3-color/>
    // *Assumes:* r, g, b in [0, 255] or [0, 1]
    // *Returns:* { r, g, b } in [0, 255]
    
function rgbToRgb(rgb){
        return {
            
rbound01(r255) * 255,
            
gbound01(g255) * 255,
            
bbound01(b255) * 255
        
};
    }

    
// `rgbToHsl`
    // Converts an RGB color value to HSL.
    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
    // *Returns:* { h, s, l } in [0,1]
    
function rgbToHsl(rgb) {

        
bound01(r255);
        
bound01(g255);
        
bound01(b255);

        var 
max mathMax(rgb), min mathMin(rgb);
        var 
hs= (max min) / 2;

        if(
max == min) {
            
0// achromatic
        
}
        else {
            var 
max min;
            
0.5 / (max min) : / (max min);
            switch(
max) {
                case 
r= (b) / + (0); break;
                case 
g= (r) / 2; break;
                case 
b= (g) / 4; break;
            }

            
/= 6;
        }

        return { 
hhssl};
    }

    
// `hslToRgb`
    // Converts an HSL color value to RGB.
    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
    // *Returns:* { r, g, b } in the set [0, 255]
    
function hslToRgb(hsl) {
        var 
rgb;

        
bound01(h360);
        
bound01(s100);
        
bound01(l100);

        function 
hue2rgb(pqt) {
            if(
0+= 1;
            if(
1-= 1;
            if(
1/6) return + (p) * t;
            if(
1/2) return q;
            if(
2/3) return + (p) * (2/t) * 6;
            return 
p;
        }

        if(
=== 0) {
            
l// achromatic
        
}
        else {
            var 
0.5 * (s) : s;
            var 
q;
            
hue2rgb(pq1/3);
            
hue2rgb(pqh);
            
hue2rgb(pq1/3);
        }

        return { 
r255g255b255 };
    }

    
// `rgbToHsv`
    // Converts an RGB color value to HSV
    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
    // *Returns:* { h, s, v } in [0,1]
    
function rgbToHsv(rgb) {

        
bound01(r255);
        
bound01(g255);
        
bound01(b255);

        var 
max mathMax(rgb), min mathMin(rgb);
        var 
hsmax;

        var 
max min;
        
max === max;

        if(
max == min) {
            
0// achromatic
        
}
        else {
            switch(
max) {
                case 
r= (b) / + (0); break;
                case 
g= (r) / 2; break;
                case 
b= (g) / 4; break;
            }
            
/= 6;
        }
        return { 
hhssv};
    }

    
// `hsvToRgb`
    // Converts an HSV color value to RGB.
    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
    // *Returns:* { r, g, b } in the set [0, 255]
     
function hsvToRgb(hsv) {

        
bound01(h360) * 6;
        
bound01(s100);
        
bound01(v100);

        var 
math.floor(h),
            
i,
            
* (s),
            
* (s),
            
* (- (f) * s),
            
mod 6,
            
= [vqpptv][mod],
            
= [tvvqpp][mod],
            
= [pptvvq][mod];

        return { 
r255g255b255 };
    }

    
// `rgbToHex`
    // Converts an RGB color to hex
    // Assumes r, g, and b are contained in the set [0, 255]
    // Returns a 3 or 6 character hex
    
function rgbToHex(rgballow3Char) {

        var 
hex = [
            
pad2(mathRound(r).toString(16)),
            
pad2(mathRound(g).toString(16)),
            
pad2(mathRound(b).toString(16))
        ];

        
// Return a 3 character hex if possible
        
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)) {
            return 
hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
        }

        return 
hex.join("");
    }
        
// `rgbaToHex`
        // Converts an RGBA color plus alpha transparency to hex
        // Assumes r, g, b and a are contained in the set [0, 255]
        // Returns an 8 character hex
        
function rgbaToHex(rgba) {

            var 
hex = [
                
pad2(convertDecimalToHex(a)),
                
pad2(mathRound(r).toString(16)),
                
pad2(mathRound(g).toString(16)),
                
pad2(mathRound(b).toString(16))
            ];

            return 
hex.join("");
        }

    
// `equals`
    // Can be called with any tinycolor input
    
tinycolor.equals = function (color1color2) {
        if (!
color1 || !color2) { return false; }
        return 
tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
    };
    
tinycolor.random = function() {
        return 
tinycolor.fromRatio({
            
rmathRandom(),
            
gmathRandom(),
            
bmathRandom()
        });
    };


    
// Modification Functions
    // ----------------------
    // Thanks to less.js for some of the basics here
    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>

    
function desaturate(coloramount) {
        
amount = (amount === 0) ? : (amount || 10);
        var 
hsl tinycolor(color).toHsl();
        
hsl.-= amount 100;
        
hsl.clamp01(hsl.s);
        return 
tinycolor(hsl);
    }

    function 
saturate(coloramount) {
        
amount = (amount === 0) ? : (amount || 10);
        var 
hsl tinycolor(color).toHsl();
        
hsl.+= amount 100;
        
hsl.clamp01(hsl.s);
        return 
tinycolor(hsl);
    }

    function 
greyscale(color) {
        return 
tinycolor(color).desaturate(100);
    }

    function 
lighten (coloramount) {
        
amount = (amount === 0) ? : (amount || 10);
        var 
hsl tinycolor(color).toHsl();
        
hsl.+= amount 100;
        
hsl.clamp01(hsl.l);
        return 
tinycolor(hsl);
    }

    function 
brighten(coloramount) {
        
amount = (amount === 0) ? : (amount || 10);
        var 
rgb tinycolor(color).toRgb();
        
rgb.mathMax(0mathMin(255rgb.mathRound(255 * - (amount 100))));
        
rgb.mathMax(0mathMin(255rgb.mathRound(255 * - (amount 100))));
        
rgb.mathMax(0mathMin(255rgb.mathRound(255 * - (amount 100))));
        return 
tinycolor(rgb);
    }

    function 
darken (coloramount) {
        
amount = (amount === 0) ? : (amount || 10);
        var 
hsl tinycolor(color).toHsl();
        
hsl.-= amount 100;
        
hsl.clamp01(hsl.l);
        return 
tinycolor(hsl);
    }

    
// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
    // Values outside of this range will be wrapped into this range.
    
function spin(coloramount) {
        var 
hsl tinycolor(color).toHsl();
        var 
hue = (mathRound(hsl.h) + amount) % 360;
        
hsl.hue 360 hue hue;
        return 
tinycolor(hsl);
    }

    
// Combination Functions
    // ---------------------
    // Thanks to jQuery xColor for some of the ideas behind these
    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>

    
function complement(color) {
        var 
hsl tinycolor(color).toHsl();
        
hsl.= (hsl.180) % 360;
        return 
tinycolor(hsl);
    }

    function 
triad(color) {
        var 
hsl tinycolor(color).toHsl();
        var 
hsl.h;
        return [
            
tinycolor(color),
            
tinycolor({ h: (120) % 360shsl.slhsl.}),
            
tinycolor({ h: (240) % 360shsl.slhsl.})
        ];
    }

    function 
tetrad(color) {
        var 
hsl tinycolor(color).toHsl();
        var 
hsl.h;
        return [
            
tinycolor(color),
            
tinycolor({ h: (90) % 360shsl.slhsl.}),
            
tinycolor({ h: (180) % 360shsl.slhsl.}),
            
tinycolor({ h: (270) % 360shsl.slhsl.})
        ];
    }

    function 
splitcomplement(color) {
        var 
hsl tinycolor(color).toHsl();
        var 
hsl.h;
        return [
            
tinycolor(color),
            
tinycolor({ h: (72) % 360shsl.slhsl.l}),
            
tinycolor({ h: (216) % 360shsl.slhsl.l})
        ];
    }

    function 
analogous(colorresultsslices) {
        
results results || 6;
        
slices slices || 30;

        var 
hsl tinycolor(color).toHsl();
        var 
part 360 slices;
        var 
ret = [tinycolor(color)];

        for (
hsl.= ((hsl.- (part results >> 1)) + 720) % 360; --results; ) {
            
hsl.= (hsl.part) % 360;
            
ret.push(tinycolor(hsl));
        }
        return 
ret;
    }

    function 
monochromatic(colorresults) {
        
results results || 6;
        var 
hsv tinycolor(color).toHsv();
        var 
hsv.hhsv.shsv.v;
        var 
ret = [];
        var 
modification results;

        while (
results--) {
            
ret.push(tinycolor({ hhssvv}));
            
= (modification) % 1;
        }

        return 
ret;
    }

    
// Utility Functions
    // ---------------------

    
tinycolor.mix = function(color1color2amount) {
        
amount = (amount === 0) ? : (amount || 50);

        var 
rgb1 tinycolor(color1).toRgb();
        var 
rgb2 tinycolor(color2).toRgb();

        var 
amount 100;
        var 
1;
        var 
rgb2.rgb1.a;

        var 
w1;

        if (
== -1) {
            
w1 w;
        } else {
            
w1 = (a) / (a);
        }

        
w1 = (w1 1) / 2;

        var 
w2 w1;

        var 
rgba = {
            
rrgb2.w1 rgb1.w2,
            
grgb2.w1 rgb1.w2,
            
brgb2.w1 rgb1.w2,
            
argb2.p  rgb1.* (p)
        };

        return 
tinycolor(rgba);
    };


    
// Readability Functions
    // ---------------------
    // <http://www.w3.org/TR/AERT#color-contrast>

    // `readability`
    // Analyze the 2 colors and returns an object with the following properties:
    //    `brightness`: difference in brightness between the two colors
    //    `color`: difference in color/hue between the two colors
    
tinycolor.readability = function(color1color2) {
        var 
c1 tinycolor(color1);
        var 
c2 tinycolor(color2);
        var 
rgb1 c1.toRgb();
        var 
rgb2 c2.toRgb();
        var 
brightnessA c1.getBrightness();
        var 
brightnessB c2.getBrightness();
        var 
colorDiff = (
            
Math.max(rgb1.rrgb2.r) - Math.min(rgb1.rrgb2.r) +
            
Math.max(rgb1.grgb2.g) - Math.min(rgb1.grgb2.g) +
            
Math.max(rgb1.brgb2.b) - Math.min(rgb1.brgb2.b)
        );

        return {
            
brightnessMath.abs(brightnessA brightnessB),
            
colorcolorDiff
        
};
    };

    
// `readable`
    // http://www.w3.org/TR/AERT#color-contrast
    // Ensure that foreground and background color combinations provide sufficient contrast.
    // *Example*
    //    tinycolor.isReadable("#000", "#111") => false
    
tinycolor.isReadable = function(color1color2) {
        var 
readability tinycolor.readability(color1color2);
        return 
readability.brightness 125 && readability.color 500;
    };

    
// `mostReadable`
    // Given a base color and a list of possible foreground or background
    // colors for that base, returns the most readable color.
    // *Example*
    //    tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
    
tinycolor.mostReadable = function(baseColorcolorList) {
        var 
bestColor null;
        var 
bestScore 0;
        var 
bestIsReadable false;
        for (var 
i=0colorList.lengthi++) {

            
// We normalize both around the "acceptable" breaking point,
            // but rank brightness constrast higher than hue.

            
var readability tinycolor.readability(baseColorcolorList[i]);
            var 
readable readability.brightness 125 && readability.color 500;
            var 
score * (readability.brightness 125) + (readability.color 500);

            if ((
readable && ! bestIsReadable) ||
                (
readable && bestIsReadable && score bestScore) ||
                ((! 
readable) && (! bestIsReadable) && score bestScore)) {
                
bestIsReadable readable;
                
bestScore score;
                
bestColor tinycolor(colorList[i]);
            }
        }
        return 
bestColor;
    };


    
// Big List of Colors
    // ------------------
    // <http://www.w3.org/TR/css3-color/#svg-color>
    
var names tinycolor.names = {
        
aliceblue"f0f8ff",
        
antiquewhite"faebd7",
        
aqua"0ff",
        
aquamarine"7fffd4",
        
azure"f0ffff",
        
beige"f5f5dc",
        
bisque"ffe4c4",
        
black"000",
        
blanchedalmond"ffebcd",
        
blue"00f",
        
blueviolet"8a2be2",
        
brown"a52a2a",
        
burlywood"deb887",
        
burntsienna"ea7e5d",
        
cadetblue"5f9ea0",
        
chartreuse"7fff00",
        
chocolate"d2691e",
        
coral"ff7f50",
        
cornflowerblue"6495ed",
        
cornsilk"fff8dc",
        
crimson"dc143c",
        
cyan"0ff",
        
darkblue"00008b",
        
darkcyan"008b8b",
        
darkgoldenrod"b8860b",
        
darkgray"a9a9a9",
        
darkgreen"006400",
        
darkgrey"a9a9a9",
        
darkkhaki"bdb76b",
        
darkmagenta"8b008b",
        
darkolivegreen"556b2f",
        
darkorange"ff8c00",
        
darkorchid"9932cc",
        
darkred"8b0000",
        
darksalmon"e9967a",
        
darkseagreen"8fbc8f",
        
darkslateblue"483d8b",
        
darkslategray"2f4f4f",
        
darkslategrey"2f4f4f",
        
darkturquoise"00ced1",
        
darkviolet"9400d3",
        
deeppink"ff1493",
        
deepskyblue"00bfff",
        
dimgray"696969",
        
dimgrey"696969",
        
dodgerblue"1e90ff",
        
firebrick"b22222",
        
floralwhite"fffaf0",
        
forestgreen"228b22",
        
fuchsia"f0f",
        
gainsboro"dcdcdc",
        
ghostwhite"f8f8ff",
        
gold"ffd700",
        
goldenrod"daa520",
        
gray"808080",
        
green"008000",
        
greenyellow"adff2f",
        
grey"808080",
        
honeydew"f0fff0",
        
hotpink"ff69b4",
        
indianred"cd5c5c",
        
indigo"4b0082",
        
ivory"fffff0",
        
khaki"f0e68c",
        
lavender"e6e6fa",
        
lavenderblush"fff0f5",
        
lawngreen"7cfc00",
        
lemonchiffon"fffacd",
        
lightblue"add8e6",
        
lightcoral"f08080",
        
lightcyan"e0ffff",
        
lightgoldenrodyellow"fafad2",
        
lightgray"d3d3d3",
        
lightgreen"90ee90",
        
lightgrey"d3d3d3",
        
lightpink"ffb6c1",
        
lightsalmon"ffa07a",
        
lightseagreen"20b2aa",
        
lightskyblue"87cefa",
        
lightslategray"789",
        
lightslategrey"789",
        
lightsteelblue"b0c4de",
        
lightyellow"ffffe0",
        
lime"0f0",
        
limegreen"32cd32",
        
linen"faf0e6",
        
magenta"f0f",
        
maroon"800000",
        
mediumaquamarine"66cdaa",
        
mediumblue"0000cd",
        
mediumorchid"ba55d3",
        
mediumpurple"9370db",
        
mediumseagreen"3cb371",
        
mediumslateblue"7b68ee",
        
mediumspringgreen"00fa9a",
        
mediumturquoise"48d1cc",
        
mediumvioletred"c71585",
        
midnightblue"191970",
        
mintcream"f5fffa",
        
mistyrose"ffe4e1",
        
moccasin"ffe4b5",
        
navajowhite"ffdead",
        
navy"000080",
        
oldlace"fdf5e6",
        
olive"808000",
        
olivedrab"6b8e23",
        
orange"ffa500",
        
orangered"ff4500",
        
orchid"da70d6",
        
palegoldenrod"eee8aa",
        
palegreen"98fb98",
        
paleturquoise"afeeee",
        
palevioletred"db7093",
        
papayawhip"ffefd5",
        
peachpuff"ffdab9",
        
peru"cd853f",
        
pink"ffc0cb",
        
plum"dda0dd",
        
powderblue"b0e0e6",
        
purple"800080",
        
rebeccapurple"663399",
        
red"f00",
        
rosybrown"bc8f8f",
        
royalblue"4169e1",
        
saddlebrown"8b4513",
        
salmon"fa8072",
        
sandybrown"f4a460",
        
seagreen"2e8b57",
        
seashell"fff5ee",
        
sienna"a0522d",
        
silver"c0c0c0",
        
skyblue"87ceeb",
        
slateblue"6a5acd",
        
slategray"708090",
        
slategrey"708090",
        
snow"fffafa",
        
springgreen"00ff7f",
        
steelblue"4682b4",
        
tan"d2b48c",
        
teal"008080",
        
thistle"d8bfd8",
        
tomato"ff6347",
        
turquoise"40e0d0",
        
violet"ee82ee",
        
wheat"f5deb3",
        
white"fff",
        
whitesmoke"f5f5f5",
        
yellow"ff0",
        
yellowgreen"9acd32"
    
};

    
// Make it easy to access colors via `hexNames[hex]`
    
var hexNames tinycolor.hexNames flip(names);


    
// Utilities
    // ---------

    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
    
function flip(o) {
        var 
flipped = { };
        for (var 
i in o) {
            if (
o.hasOwnProperty(i)) {
                
flipped[o[i]] = i;
            }
        }
        return 
flipped;
    }

    
// Return a valid alpha value [0,1] with all invalid values being set to 1
    
function boundAlpha(a) {
        
parseFloat(a);

        if (
isNaN(a) || || 1) {
            
1;
        }

        return 
a;
    }

    
// Take input from [0, n] and return it as [0, 1]
    
function bound01(nmax) {
        if (
isOnePointZero(n)) { "100%"; }

        var 
processPercent isPercentage(n);
        
mathMin(maxmathMax(0parseFloat(n)));

        
// Automatically convert percentage into number
        
if (processPercent) {
            
parseInt(max10) / 100;
        }

        
// Handle floating point rounding errors
        
if ((math.abs(max) < 0.000001)) {
            return 
1;
        }

        
// Convert into [0, 1] range if it isn't already
        
return (max) / parseFloat(max);
    }

    
// Force a number between 0 and 1
    
function clamp01(val) {
        return 
mathMin(1mathMax(0val));
    }

    
// Parse a base-16 hex value into a base-10 integer
    
function parseIntFromHex(val) {
        return 
parseInt(val16);
    }

    
// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
    
function isOnePointZero(n) {
        return 
typeof n == "string" && n.indexOf('.') != -&& parseFloat(n) === 1;
    }

    
// Check to see if string passed in is a percentage
    
function isPercentage(n) {
        return 
typeof n === "string" && n.indexOf('%') != -1;
    }

    
// Force a hex value to have 2 characters
    
function pad2(c) {
        return 
c.length == '0' '' c;
    }

    
// Replace a decimal with it's percentage value
    
function convertToPercentage(n) {
        if (
<= 1) {
            
= (100) + "%";
        }

        return 
n;
    }

    
// Converts a decimal to a hex value
    
function convertDecimalToHex(d) {
        return 
Math.round(parseFloat(d) * 255).toString(16);
    }
    
// Converts a hex value to a decimal
    
function convertHexToDecimal(h) {
        return (
parseIntFromHex(h) / 255);
    }

    var 
matchers = (function() {

        
// <http://www.w3.org/TR/css3-values/#integers>
        
var CSS_INTEGER "[-\+]?\d+%?";

        
// <http://www.w3.org/TR/css3-values/#number-value>
        
var CSS_NUMBER "[-\+]?\d*\.\d+%?";

        
// Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
        
var CSS_UNIT "(?:" CSS_NUMBER ")|(?:" CSS_INTEGER ")";

        
// Actual matching.
        // Parentheses and commas are optional, but not required.
        // Whitespace can take the place of commas or opening paren
        
var PERMISSIVE_MATCH3 "[\s|\(]+(" CSS_UNIT ")[,|\s]+(" CSS_UNIT ")[,|\s]+(" CSS_UNIT ")\s*\)?";
        var 
PERMISSIVE_MATCH4 "[\s|\(]+(" CSS_UNIT ")[,|\s]+(" CSS_UNIT ")[,|\s]+(" CSS_UNIT ")[,|\s]+(" CSS_UNIT ")\s*\)?";

        return {
            
rgb: new RegExp("rgb" PERMISSIVE_MATCH3),
            
rgba: new RegExp("rgba" PERMISSIVE_MATCH4),
            
hsl: new RegExp("hsl" PERMISSIVE_MATCH3),
            
hsla: new RegExp("hsla" PERMISSIVE_MATCH4),
            
hsv: new RegExp("hsv" PERMISSIVE_MATCH3),
            
hsva: new RegExp("hsva" PERMISSIVE_MATCH4),
            
hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
            
hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
            
hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
        };
    })();

    
// `stringInputToObject`
    // Permissive string parsing.  Take in a number of formats, and output an object
    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
    
function stringInputToObject(color) {

        
color color.replace(trimLeft,'').replace(trimRight'').toLowerCase();
        var 
named false;
        if (
names[color]) {
            
color names[color];
            
named true;
        }
        else if (
color == 'transparent') {
            return { 
r0g0b0a0format"name" };
        }

        
// Try to match string input using regular expressions.
        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
        // Just return an object and let the conversion functions handle that.
        // This way the result will be the same whether the tinycolor is initialized with string or object.
        
var match;
        if ((
match matchers.rgb.exec(color))) {
            return { 
rmatch[1], gmatch[2], bmatch[3] };
        }
        if ((
match matchers.rgba.exec(color))) {
            return { 
rmatch[1], gmatch[2], bmatch[3], amatch[4] };
        }
        if ((
match matchers.hsl.exec(color))) {
            return { 
hmatch[1], smatch[2], lmatch[3] };
        }
        if ((
match matchers.hsla.exec(color))) {
            return { 
hmatch[1], smatch[2], lmatch[3], amatch[4] };
        }
        if ((
match matchers.hsv.exec(color))) {
            return { 
hmatch[1], smatch[2], vmatch[3] };
        }
        if ((
match matchers.hsva.exec(color))) {
            return { 
hmatch[1], smatch[2], vmatch[3], amatch[4] };
        }
        if ((
match matchers.hex8.exec(color))) {
            return {
                
aconvertHexToDecimal(match[1]),
                
rparseIntFromHex(match[2]),
                
gparseIntFromHex(match[3]),
                
bparseIntFromHex(match[4]),
                
formatnamed "name" "hex8"
            
};
        }
        if ((
match matchers.hex6.exec(color))) {
            return {
                
rparseIntFromHex(match[1]),
                
gparseIntFromHex(match[2]),
                
bparseIntFromHex(match[3]),
                
formatnamed "name" "hex"
            
};
        }
        if ((
match matchers.hex3.exec(color))) {
            return {
                
rparseIntFromHex(match[1] + '' match[1]),
                
gparseIntFromHex(match[2] + '' match[2]),
                
bparseIntFromHex(match[3] + '' match[3]),
                
formatnamed "name" "hex"
            
};
        }

        return 
false;
    }

    
window.tinycolor tinycolor;
    })();

    $(function () {
        if ($.fn.
spectrum.load) {
            $.fn.
spectrum.processNativeColorInputs();
        }
    });

});
?>
Онлайн: 1
Реклама