"
+ ].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 i = 1; i <= 6; i++) {
+ gradientFix += "";
+ }
+ }
+
+ return [
+ "
",
+ "
",
+ "",
+ "
",
+ "",
+ "
",
+ "
",
+ "
",
+ "
",
+ "",
+ "
",
+ "
",
+ "
",
+ "
",
+ "",
+ "
",
+ "
",
+ "
",
+ "
",
+ "
",
+ "
",
+ "",
+ gradientFix,
+ "
",
+ "
",
+ "
",
+ "
",
+ "
",
+ "",
+ "
",
+ "",
+ "
",
+ "",
+ "",
+ "
",
+ "
",
+ "
"
+ ].join("");
+ })();
+
+ function paletteTemplate (p, color, className, opts) {
+ var html = [];
+ for (var i = 0; i < p.length; i++) {
+ var current = p[i];
+ if(current) {
+ var tiny = tinycolor(current);
+ var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
+ c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : "";
+ var formattedString = tiny.toString(opts.preferredFormat || "rgb");
+ var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
+ html.push('');
+ } else {
+ var cls = 'sp-clear-display';
+ html.push($('')
+ .append($('')
+ .attr('title', opts.noColorSelectedText)
+ )
+ .html()
+ );
+ }
+ }
+ return "
" + html.join('') + "
";
+ }
+
+ function hideAll() {
+ for (var i = 0; i < spectrums.length; i++) {
+ if (spectrums[i]) {
+ spectrums[i].hide();
+ }
+ }
+ }
+
+ function instanceOptions(o, callbackContext) {
+ var opts = $.extend({}, defaultOpts, o);
+ opts.callbacks = {
+ 'move': bind(opts.move, callbackContext),
+ 'change': bind(opts.change, callbackContext),
+ 'show': bind(opts.show, callbackContext),
+ 'hide': bind(opts.hide, callbackContext),
+ 'beforeShow': bind(opts.beforeShow, callbackContext)
+ };
+
+ return opts;
+ }
+
+ function spectrum(element, o) {
+
+ var opts = instanceOptions(o, element),
+ flat = opts.flat,
+ showSelectionPalette = opts.showSelectionPalette,
+ localStorageKey = opts.localStorageKey,
+ theme = opts.theme,
+ callbacks = opts.callbacks,
+ resize = throttle(reflow, 10),
+ 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 = $(markup, doc).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 = Array.isArray(palette[0]) ? palette : [palette];
+ paletteLookup = {};
+ for (var i = 0; i < paletteArray.length; i++) {
+ for (var j = 0; j < paletteArray[i].length; j++) {
+ 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.on("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.on("click", stopPropagation);
+
+ // Handle user typed input
+ textInput.on("change", setFromTextInput);
+ textInput.on("paste", function () {
+ setTimeout(setFromTextInput, 1);
+ });
+ textInput.on("keydown", function (e) { if (e.keyCode == 13) { setFromTextInput(); } });
+
+ cancelButton.text(opts.cancelText);
+ cancelButton.on("click.spectrum", function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ revert();
+ hide();
+ });
+
+ clearButton.attr("title", opts.clearText);
+ clearButton.on("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.on("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.on("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 (dragX, dragY, e) {
+ currentAlpha = (dragX / alphaWidth);
+ isEmpty = false;
+ if (e.shiftKey) {
+ currentAlpha = Math.round(currentAlpha * 10) / 10;
+ }
+
+ move();
+ }, dragStart, dragStop);
+
+ draggable(slider, function (dragX, dragY) {
+ currentHue = parseFloat(dragY / slideHeight);
+ isEmpty = false;
+ if (!opts.showAlpha) {
+ currentAlpha = 1;
+ }
+ move();
+ }, dragStart, dragStop);
+
+ draggable(dragger, function (dragX, dragY, e) {
+
+ // 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();
+
+ }, dragStart, dragStop);
+
+ 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();
+
+ // If the picker is going to close immediately, a palette selection
+ // is a change. Otherwise, it's a move only.
+ if (opts.hideAfterPaletteSelect) {
+ updateOriginalInput(true);
+ hide();
+ } else {
+ updateOriginalInput();
+ }
+ }
+
+ return false;
+ }
+
+ var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
+ paletteContainer.on(paletteEvent, ".sp-thumb-el", paletteElementClick);
+ initialColorContainer.on(paletteEvent, ".sp-thumb-el:nth-child(1)", { ignore: true }, 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(i, c) {
+ 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(rgb, selectionPalette) === -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 i = 0; i < selectionPalette.length; i++) {
+ var rgb = tinycolor(selectionPalette[i]).toRgbString();
+
+ if (!paletteLookup[rgb]) {
+ unique.push(selectionPalette[i]);
+ }
+ }
+ }
+
+ return unique.reverse().slice(0, opts.maxSelectionSize);
+ }
+
+ function drawPalette() {
+
+ var currentColor = get();
+
+ var html = $.map(paletteArray, function (palette, i) {
+ return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts);
+ });
+
+ 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([initial, current], current, "sp-palette-row-initial", opts));
+ }
+ }
+
+ function dragStart() {
+ if (dragHeight <= 0 || dragWidth <= 0 || 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);
+ move();
+ updateOriginalInput();
+ }
+ else {
+ var tiny = tinycolor(value);
+ if (tiny.isValid()) {
+ set(tiny);
+ move();
+ updateOriginalInput();
+ }
+ 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).on("keydown.spectrum", onkeydown);
+ $(doc).on("click.spectrum", clickout);
+ $(window).on("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).off("keydown.spectrum", onkeydown);
+ $(doc).off("click.spectrum", clickout);
+ $(window).off("resize.spectrum", resize);
+
+ replacer.removeClass("sp-active");
+ container.addClass("sp-hidden");
+
+ callbacks.hide(get());
+ boundElement.trigger('hide.spectrum', [ get() ]);
+ }
+
+ function revert() {
+ set(colorOnShow, true);
+ updateOriginalInput(true);
+ }
+
+ function set(color, ignoreFormatChange) {
+ if (tinycolor.equals(color, get())) {
+ // Update UI just in case a validation error needs
+ // to be cleared.
+ updateUI();
+ return;
+ }
+
+ var newColor, newHsv;
+ if (!color && allowEmpty) {
+ isEmpty = true;
+ } else {
+ isEmpty = false;
+ newColor = tinycolor(color);
+ newHsv = newColor.toHsv();
+
+ currentHue = (newHsv.h % 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({
+ h: currentHue,
+ s: currentSaturation,
+ v: currentValue,
+ a: Math.round(currentAlpha * 1000) / 1000
+ }, { format: opts.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({ h: currentHue, s: 1, v: 1 });
+ 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 < 1 && !(currentAlpha === 0 && format === "name")) {
+ if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
+ format = "rgb";
+ }
+ }
+
+ var realColor = get({ format: format }),
+ 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.a = 0;
+ var realAlpha = tinycolor(rgb).toRgbString();
+ var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")";
+
+ if (IE) {
+ alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, 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 s = currentSaturation;
+ var v = 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 = s * dragWidth;
+ var dragY = dragHeight - (v * dragHeight);
+ dragX = Math.max(
+ -dragHelperHeight,
+ Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)
+ );
+ dragY = Math.max(
+ -dragHelperHeight,
+ Math.min(dragHeight - dragHelperHeight, dragY - 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(color, colorOnShow);
+
+ 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(container, offsetElement));
+ }
+ }
+
+ updateHelperLocations();
+
+ if (opts.showPalette) {
+ drawPalette();
+ }
+
+ boundElement.trigger('reflow.spectrum');
+ }
+
+ function destroy() {
+ boundElement.show();
+ offsetElement.off("click.spectrum touchstart.spectrum");
+ container.remove();
+ replacer.remove();
+ spectrums[spect.id] = null;
+ }
+
+ function option(optionName, optionValue) {
+ 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 = {
+ show: show,
+ hide: hide,
+ toggle: toggle,
+ reflow: reflow,
+ option: option,
+ enable: enable,
+ disable: disable,
+ offset: setOffset,
+ set: function (c) {
+ set(c);
+ updateOriginalInput();
+ },
+ get: get,
+ destroy: destroy,
+ container: container
+ };
+
+ 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(picker, input) {
+ 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();
+ var offsetLeft = offset.left;
+ var offsetTop = offset.top;
+
+ offsetTop += inputHeight;
+
+ offsetLeft -=
+ Math.min(offsetLeft, (offsetLeft + dpWidth > viewWidth && viewWidth > dpWidth) ?
+ Math.abs(offsetLeft + dpWidth - viewWidth) : 0);
+
+ offsetTop -=
+ Math.min(offsetTop, ((offsetTop + dpHeight > viewHeight && viewHeight > dpHeight) ?
+ Math.abs(dpHeight + inputHeight - extraY) : extraY));
+
+ return {
+ top: offsetTop,
+ bottom: offset.bottom,
+ left: offsetLeft,
+ right: offset.right,
+ width: offset.width,
+ height: offset.height
+ };
+ }
+
+ /**
+ * 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(func, obj) {
+ var slice = Array.prototype.slice;
+ var args = slice.call(arguments, 2);
+ return function () {
+ return func.apply(obj, args.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(element, onmove, onstart, onstop) {
+ 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 < 9 && !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(0, Math.min(pageX - offset.left, maxWidth));
+ var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));
+
+ if (hasTouch) {
+ // Stop scrolling in iOS
+ prevent(e);
+ }
+
+ onmove.apply(element, [dragX, dragY, e]);
+ }
+ }
+
+ function start(e) {
+ var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);
+
+ if (!rightclick && !dragging) {
+ if (onstart.apply(element, arguments) !== false) {
+ dragging = true;
+ maxHeight = $(element).height();
+ maxWidth = $(element).width();
+ offset = $(element).offset();
+
+ $(doc).on(duringDragEvents);
+ $(doc.body).addClass("sp-dragging");
+
+ move(e);
+
+ prevent(e);
+ }
+ }
+ }
+
+ function stop() {
+ if (dragging) {
+ $(doc).off(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(element, arguments);
+ }, 0);
+ }
+ dragging = false;
+ }
+
+ $(element).on("touchstart mousedown", start);
+ }
+
+ function throttle(func, wait, debounce) {
+ var timeout;
+ return function () {
+ var context = this, args = arguments;
+ var throttler = function () {
+ timeout = null;
+ func.apply(context, args);
+ };
+ if (debounce) clearTimeout(timeout);
+ if (debounce || !timeout) timeout = setTimeout(throttler, wait);
+ };
+ }
+
+ function inputTypeColorSupport() {
+ return $.fn.spectrum.inputTypeColorSupport();
+ }
+
+ /**
+ * Define a jQuery plugin
+ */
+ var dataID = "spectrum.id";
+ $.fn.spectrum = function (opts, extra) {
+
+ if (typeof opts == "string") {
+
+ var returnValue = this;
+ var args = Array.prototype.slice.call( arguments, 1 );
+
+ 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(spect, args);
+ }
+ else if (opts == "destroy") {
+ spect.destroy();
+ $(this).removeData(dataID);
+ }
+ else {
+ method.apply(spect, args);
+ }
+ }
+ });
+
+ return returnValue;
+ }
+
+ // Initializing a new instance of spectrum
+ return this.spectrum("destroy").each(function () {
+ var options = $.extend({}, $(this).data(), opts);
+ var spect = spectrum(this, options);
+ $(this).data(dataID, spect.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 = $("")[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(color, opts) {
+
+ 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(color, opts);
+ }
+
+ 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(1000 * this._a) / 1000;
+ 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.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
+ },
+ setAlpha: function(value) {
+ this._a = boundAlpha(value);
+ this._roundA = mathRound(1000 * this._a) / 1000;
+ return this;
+ },
+ toHsv: function() {
+ var hsv = rgbToHsv(this._r, this._g, this._b);
+ return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
+ },
+ toHsvString: function() {
+ var hsv = rgbToHsv(this._r, this._g, this._b);
+ var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
+ return (this._a == 1) ?
+ "hsv(" + h + ", " + s + "%, " + v + "%)" :
+ "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
+ },
+ toHsl: function() {
+ var hsl = rgbToHsl(this._r, this._g, this._b);
+ return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
+ },
+ toHslString: function() {
+ var hsl = rgbToHsl(this._r, this._g, this._b);
+ var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
+ return (this._a == 1) ?
+ "hsl(" + h + ", " + s + "%, " + l + "%)" :
+ "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
+ },
+ toHex: function(allow3Char) {
+ return rgbToHex(this._r, this._g, this._b, allow3Char);
+ },
+ toHexString: function(allow3Char) {
+ return '#' + this.toHex(allow3Char);
+ },
+ toHex8: function() {
+ return rgbaToHex(this._r, this._g, this._b, this._a);
+ },
+ toHex8String: function() {
+ return '#' + this.toHex8();
+ },
+ toRgb: function() {
+ return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._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 { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
+ },
+ toPercentageRgbString: function() {
+ return (this._a == 1) ?
+ "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
+ "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
+ },
+ toName: function() {
+ if (this._a === 0) {
+ return "transparent";
+ }
+
+ if (this._a < 1) {
+ return false;
+ }
+
+ return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
+ },
+ toFilter: function(secondColor) {
+ var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
+ var secondHex8String = hex8String;
+ var gradientType = this._gradientType ? "GradientType = 1, " : "";
+
+ if (secondColor) {
+ var s = 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 < 1 && 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(lighten, arguments);
+ },
+ brighten: function() {
+ return this._applyModification(brighten, arguments);
+ },
+ darken: function() {
+ return this._applyModification(darken, arguments);
+ },
+ desaturate: function() {
+ return this._applyModification(desaturate, arguments);
+ },
+ saturate: function() {
+ return this._applyModification(saturate, arguments);
+ },
+ greyscale: function() {
+ return this._applyModification(greyscale, arguments);
+ },
+ spin: function() {
+ return this._applyModification(spin, arguments);
+ },
+
+ _applyCombination: function(fn, args) {
+ return fn.apply(null, [this].concat([].slice.call(args)));
+ },
+ analogous: function() {
+ return this._applyCombination(analogous, arguments);
+ },
+ complement: function() {
+ return this._applyCombination(complement, arguments);
+ },
+ monochromatic: function() {
+ return this._applyCombination(monochromatic, arguments);
+ },
+ splitcomplement: function() {
+ return this._applyCombination(splitcomplement, arguments);
+ },
+ triad: function() {
+ return this._applyCombination(triad, arguments);
+ },
+ tetrad: function() {
+ return this._applyCombination(tetrad, arguments);
+ }
+ };
+
+ // 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(color, opts) {
+ if (typeof color == "object") {
+ var newColor = {};
+ for (var i in color) {
+ if (color.hasOwnProperty(i)) {
+ if (i === "a") {
+ newColor[i] = color[i];
+ }
+ else {
+ newColor[i] = convertToPercentage(color[i]);
+ }
+ }
+ }
+ color = newColor;
+ }
+
+ return tinycolor(color, opts);
+ };
+
+ // 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 = { r: 0, g: 0, b: 0 };
+ var a = 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.r, color.g, color.b);
+ ok = true;
+ format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
+ }
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
+ color.s = convertToPercentage(color.s);
+ color.v = convertToPercentage(color.v);
+ rgb = hsvToRgb(color.h, color.s, color.v);
+ ok = true;
+ format = "hsv";
+ }
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
+ color.s = convertToPercentage(color.s);
+ color.l = convertToPercentage(color.l);
+ rgb = hslToRgb(color.h, color.s, color.l);
+ ok = true;
+ format = "hsl";
+ }
+
+ if (color.hasOwnProperty("a")) {
+ a = color.a;
+ }
+ }
+
+ a = boundAlpha(a);
+
+ return {
+ ok: ok,
+ format: color.format || format,
+ r: mathMin(255, mathMax(rgb.r, 0)),
+ g: mathMin(255, mathMax(rgb.g, 0)),
+ b: mathMin(255, mathMax(rgb.b, 0)),
+ a: a
+ };
+ }
+
+
+ // Conversion Functions
+ // --------------------
+
+ // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
+ //
+
+ // `rgbToRgb`
+ // Handle bounds / percentage checking to conform to CSS color spec
+ //
+ // *Assumes:* r, g, b in [0, 255] or [0, 1]
+ // *Returns:* { r, g, b } in [0, 255]
+ function rgbToRgb(r, g, b){
+ return {
+ r: bound01(r, 255) * 255,
+ g: bound01(g, 255) * 255,
+ b: bound01(b, 255) * 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(r, g, b) {
+
+ r = bound01(r, 255);
+ g = bound01(g, 255);
+ b = bound01(b, 255);
+
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
+ var h, s, l = (max + min) / 2;
+
+ if(max == min) {
+ h = s = 0; // achromatic
+ }
+ else {
+ var d = max - min;
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+ switch(max) {
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+ case g: h = (b - r) / d + 2; break;
+ case b: h = (r - g) / d + 4; break;
+ }
+
+ h /= 6;
+ }
+
+ return { h: h, s: s, l: l };
+ }
+
+ // `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(h, s, l) {
+ var r, g, b;
+
+ h = bound01(h, 360);
+ s = bound01(s, 100);
+ l = bound01(l, 100);
+
+ function hue2rgb(p, q, t) {
+ if(t < 0) t += 1;
+ if(t > 1) t -= 1;
+ if(t < 1/6) return p + (q - p) * 6 * t;
+ if(t < 1/2) return q;
+ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
+ return p;
+ }
+
+ if(s === 0) {
+ r = g = b = l; // achromatic
+ }
+ else {
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ var p = 2 * l - q;
+ r = hue2rgb(p, q, h + 1/3);
+ g = hue2rgb(p, q, h);
+ b = hue2rgb(p, q, h - 1/3);
+ }
+
+ return { r: r * 255, g: g * 255, b: b * 255 };
+ }
+
+ // `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(r, g, b) {
+
+ r = bound01(r, 255);
+ g = bound01(g, 255);
+ b = bound01(b, 255);
+
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
+ var h, s, v = max;
+
+ var d = max - min;
+ s = max === 0 ? 0 : d / max;
+
+ if(max == min) {
+ h = 0; // achromatic
+ }
+ else {
+ switch(max) {
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+ case g: h = (b - r) / d + 2; break;
+ case b: h = (r - g) / d + 4; break;
+ }
+ h /= 6;
+ }
+ return { h: h, s: s, v: v };
+ }
+
+ // `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(h, s, v) {
+
+ h = bound01(h, 360) * 6;
+ s = bound01(s, 100);
+ v = bound01(v, 100);
+
+ var i = math.floor(h),
+ f = h - i,
+ p = v * (1 - s),
+ q = v * (1 - f * s),
+ t = v * (1 - (1 - f) * s),
+ mod = i % 6,
+ r = [v, q, p, p, t, v][mod],
+ g = [t, v, v, q, p, p][mod],
+ b = [p, p, t, v, v, q][mod];
+
+ return { r: r * 255, g: g * 255, b: b * 255 };
+ }
+
+ // `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(r, g, b, allow3Char) {
+
+ 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(r, g, b, a) {
+
+ 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 (color1, color2) {
+ if (!color1 || !color2) { return false; }
+ return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
+ };
+ tinycolor.random = function() {
+ return tinycolor.fromRatio({
+ r: mathRandom(),
+ g: mathRandom(),
+ b: mathRandom()
+ });
+ };
+
+
+ // Modification Functions
+ // ----------------------
+ // Thanks to less.js for some of the basics here
+ //
+
+ function desaturate(color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var hsl = tinycolor(color).toHsl();
+ hsl.s -= amount / 100;
+ hsl.s = clamp01(hsl.s);
+ return tinycolor(hsl);
+ }
+
+ function saturate(color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var hsl = tinycolor(color).toHsl();
+ hsl.s += amount / 100;
+ hsl.s = clamp01(hsl.s);
+ return tinycolor(hsl);
+ }
+
+ function greyscale(color) {
+ return tinycolor(color).desaturate(100);
+ }
+
+ function lighten (color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var hsl = tinycolor(color).toHsl();
+ hsl.l += amount / 100;
+ hsl.l = clamp01(hsl.l);
+ return tinycolor(hsl);
+ }
+
+ function brighten(color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var rgb = tinycolor(color).toRgb();
+ rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
+ rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
+ rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
+ return tinycolor(rgb);
+ }
+
+ function darken (color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var hsl = tinycolor(color).toHsl();
+ hsl.l -= amount / 100;
+ hsl.l = 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(color, amount) {
+ var hsl = tinycolor(color).toHsl();
+ var hue = (mathRound(hsl.h) + amount) % 360;
+ hsl.h = hue < 0 ? 360 + hue : hue;
+ return tinycolor(hsl);
+ }
+
+ // Combination Functions
+ // ---------------------
+ // Thanks to jQuery xColor for some of the ideas behind these
+ //
+
+ function complement(color) {
+ var hsl = tinycolor(color).toHsl();
+ hsl.h = (hsl.h + 180) % 360;
+ return tinycolor(hsl);
+ }
+
+ function triad(color) {
+ var hsl = tinycolor(color).toHsl();
+ var h = hsl.h;
+ return [
+ tinycolor(color),
+ tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
+ tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
+ ];
+ }
+
+ function tetrad(color) {
+ var hsl = tinycolor(color).toHsl();
+ var h = hsl.h;
+ return [
+ tinycolor(color),
+ tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
+ tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
+ tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
+ ];
+ }
+
+ function splitcomplement(color) {
+ var hsl = tinycolor(color).toHsl();
+ var h = hsl.h;
+ return [
+ tinycolor(color),
+ tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
+ tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
+ ];
+ }
+
+ function analogous(color, results, slices) {
+ results = results || 6;
+ slices = slices || 30;
+
+ var hsl = tinycolor(color).toHsl();
+ var part = 360 / slices;
+ var ret = [tinycolor(color)];
+
+ for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
+ hsl.h = (hsl.h + part) % 360;
+ ret.push(tinycolor(hsl));
+ }
+ return ret;
+ }
+
+ function monochromatic(color, results) {
+ results = results || 6;
+ var hsv = tinycolor(color).toHsv();
+ var h = hsv.h, s = hsv.s, v = hsv.v;
+ var ret = [];
+ var modification = 1 / results;
+
+ while (results--) {
+ ret.push(tinycolor({ h: h, s: s, v: v}));
+ v = (v + modification) % 1;
+ }
+
+ return ret;
+ }
+
+ // Utility Functions
+ // ---------------------
+
+ tinycolor.mix = function(color1, color2, amount) {
+ amount = (amount === 0) ? 0 : (amount || 50);
+
+ var rgb1 = tinycolor(color1).toRgb();
+ var rgb2 = tinycolor(color2).toRgb();
+
+ var p = amount / 100;
+ var w = p * 2 - 1;
+ var a = rgb2.a - rgb1.a;
+
+ var w1;
+
+ if (w * a == -1) {
+ w1 = w;
+ } else {
+ w1 = (w + a) / (1 + w * a);
+ }
+
+ w1 = (w1 + 1) / 2;
+
+ var w2 = 1 - w1;
+
+ var rgba = {
+ r: rgb2.r * w1 + rgb1.r * w2,
+ g: rgb2.g * w1 + rgb1.g * w2,
+ b: rgb2.b * w1 + rgb1.b * w2,
+ a: rgb2.a * p + rgb1.a * (1 - p)
+ };
+
+ return tinycolor(rgba);
+ };
+
+
+ // Readability Functions
+ // ---------------------
+ //
+
+ // `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(color1, color2) {
+ 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.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +
+ Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +
+ Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)
+ );
+
+ return {
+ brightness: Math.abs(brightnessA - brightnessB),
+ color: colorDiff
+ };
+ };
+
+ // `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(color1, color2) {
+ var readability = tinycolor.readability(color1, color2);
+ 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(baseColor, colorList) {
+ var bestColor = null;
+ var bestScore = 0;
+ var bestIsReadable = false;
+ for (var i=0; i < colorList.length; i++) {
+
+ // We normalize both around the "acceptable" breaking point,
+ // but rank brightness constrast higher than hue.
+
+ var readability = tinycolor.readability(baseColor, colorList[i]);
+ var readable = readability.brightness > 125 && readability.color > 500;
+ var score = 3 * (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
+ // ------------------
+ //
+ 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) {
+ a = parseFloat(a);
+
+ if (isNaN(a) || a < 0 || a > 1) {
+ a = 1;
+ }
+
+ return a;
+ }
+
+ // Take input from [0, n] and return it as [0, 1]
+ function bound01(n, max) {
+ if (isOnePointZero(n)) { n = "100%"; }
+
+ var processPercent = isPercentage(n);
+ n = mathMin(max, mathMax(0, parseFloat(n)));
+
+ // Automatically convert percentage into number
+ if (processPercent) {
+ n = parseInt(n * max, 10) / 100;
+ }
+
+ // Handle floating point rounding errors
+ if ((math.abs(n - max) < 0.000001)) {
+ return 1;
+ }
+
+ // Convert into [0, 1] range if it isn't already
+ return (n % max) / parseFloat(max);
+ }
+
+ // Force a number between 0 and 1
+ function clamp01(val) {
+ return mathMin(1, mathMax(0, val));
+ }
+
+ // Parse a base-16 hex value into a base-10 integer
+ function parseIntFromHex(val) {
+ return parseInt(val, 16);
+ }
+
+ // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
+ //
+ function isOnePointZero(n) {
+ return typeof n == "string" && n.indexOf('.') != -1 && 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 == 1 ? '0' + c : '' + c;
+ }
+
+ // Replace a decimal with it's percentage value
+ function convertToPercentage(n) {
+ if (n <= 1) {
+ n = (n * 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() {
+
+ //
+ var CSS_INTEGER = "[-\\+]?\\d+%?";
+
+ //
+ 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 { r: 0, g: 0, b: 0, a: 0, format: "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 { r: match[1], g: match[2], b: match[3] };
+ }
+ if ((match = matchers.rgba.exec(color))) {
+ return { r: match[1], g: match[2], b: match[3], a: match[4] };
+ }
+ if ((match = matchers.hsl.exec(color))) {
+ return { h: match[1], s: match[2], l: match[3] };
+ }
+ if ((match = matchers.hsla.exec(color))) {
+ return { h: match[1], s: match[2], l: match[3], a: match[4] };
+ }
+ if ((match = matchers.hsv.exec(color))) {
+ return { h: match[1], s: match[2], v: match[3] };
+ }
+ if ((match = matchers.hsva.exec(color))) {
+ return { h: match[1], s: match[2], v: match[3], a: match[4] };
+ }
+ if ((match = matchers.hex8.exec(color))) {
+ return {
+ a: convertHexToDecimal(match[1]),
+ r: parseIntFromHex(match[2]),
+ g: parseIntFromHex(match[3]),
+ b: parseIntFromHex(match[4]),
+ format: named ? "name" : "hex8"
+ };
+ }
+ if ((match = matchers.hex6.exec(color))) {
+ return {
+ r: parseIntFromHex(match[1]),
+ g: parseIntFromHex(match[2]),
+ b: parseIntFromHex(match[3]),
+ format: named ? "name" : "hex"
+ };
+ }
+ if ((match = matchers.hex3.exec(color))) {
+ return {
+ r: parseIntFromHex(match[1] + '' + match[1]),
+ g: parseIntFromHex(match[2] + '' + match[2]),
+ b: parseIntFromHex(match[3] + '' + match[3]),
+ format: named ? "name" : "hex"
+ };
+ }
+
+ return false;
+ }
+
+ window.tinycolor = tinycolor;
+ })();
+
+ $(function () {
+ if ($.fn.spectrum.load) {
+ $.fn.spectrum.processNativeColorInputs();
+ }
+ });
+
+});
diff --git a/site/modules/.FieldtypeColor/x11color.txt b/site/modules/.FieldtypeColor/x11color.txt
new file mode 100644
index 0000000..cb6df03
--- /dev/null
+++ b/site/modules/.FieldtypeColor/x11color.txt
@@ -0,0 +1,143 @@
+indianred #CD5C5C 205,92,92
+lightcoral #F08080 240,128,128
+salmon #FA8072 250,128,114
+darksalmon #E9967A 233,150,122
+lightsalmon #FFA07A 255,160,122
+crimson #DC143C 220,20,60
+red #FF0000 255,0,0
+firebrick #B22222 178,34,34
+darkred #8B0000 139,0,0
+pink #FFC0CB 255,192,203
+lightpink #FFB6C1 255,182,193
+hotpink #FF69B4 255,105,180
+deeppink #FF1493 255,20,147
+mediumvioletred #C71585 199,21,133
+palevioletred #DB7093 219,112,147
+lightsalmon #FFA07A 255,160,122
+coral #FF7F50 255,127,80
+tomato #FF6347 255,99,71
+orangered #FF4500 255,69,0
+darkorange #FF8C00 255,140,0
+orange #FFA500 255,165,0
+gold #FFD700 255,215,0
+yellow #FFFF00 255,255,0
+lightyellow #FFFFE0 255,255,224
+lemonchiffon #FFFACD 255,250,205
+lightgoldenrodyellow #FAFAD2 250,250,210
+papayawhip #FFEFD5 255,239,213
+moccasin #FFE4B5 255,228,181
+peachpuff #FFDAB9 255,218,185
+palegoldenrod #EEE8AA 238,232,170
+khaki #F0E68C 240,230,140
+darkkhaki #BDB76B 189,183,107
+lavender #E6E6FA 230,230,250
+thistle #D8BFD8 216,191,216
+plum #DDA0DD 221,160,221
+violet #EE82EE 238,130,238
+orchid #DA70D6 218,112,214
+fuchsia #FF00FF 255,0,255
+magenta #FF00FF 255,0,255
+mediumorchid #BA55D3 186,85,211
+mediumpurple #9370DB 147,112,219
+blueviolet #8A2BE2 138,43,226
+darkviolet #9400D3 148,0,211
+darkorchid #9932CC 153,50,204
+darkmagenta #8B008B 139,0,139
+purple #800080 128,0,128
+indigo #4B0082 75,0,130
+slateblue #6A5ACD 106,90,205
+darkslateblue #483D8B 72,61,139
+mediumslateblue #7B68EE 123,104,238
+greenyellow #ADFF2F 173,255,47
+chartreuse #7FFF00 127,255,0
+lawngreen #7CFC00 124,252,0
+lime #00FF00 0,255,0
+limegreen #32CD32 50,205,50
+palegreen #98FB98 152,251,152
+lightgreen #90EE90 144,238,144
+mediumspringgreen #00FA9A 0,250,154
+springgreen #00FF7F 0,255,127
+mediumseagreen #3CB371 60,179,113
+seagreen #2E8B57 46,139,87
+forestgreen #228B22 34,139,34
+green #008000 0,128,0
+darkgreen #006400 0,100,0
+yellowgreen #9ACD32 154,205,50
+olivedrab #6B8E23 107,142,35
+olive #808000 128,128,0
+darkolivegreen #556B2F 85,107,47
+mediumaquamarine #66CDAA 102,205,170
+darkseagreen #8FBC8F 143,188,143
+lightseagreen #20B2AA 32,178,170
+darkcyan #008B8B 0,139,139
+teal #008080 0,128,128
+aqua #00FFFF 0,255,255
+cyan #00FFFF 0,255,255
+lightcyan #E0FFFF 224,255,255
+paleturquoise #AFEEEE 175,238,238
+aquamarine #7FFFD4 127,255,212
+turquoise #40E0D0 64,224,208
+mediumturquoise #48D1CC 72,209,204
+darkturquoise #00CED1 0,206,209
+cadetblue #5F9EA0 95,158,160
+steelblue #4682B4 70,130,180
+lightsteelblue #B0C4DE 176,196,222
+powderblue #B0E0E6 176,224,230
+lightblue #ADD8E6 173,216,230
+skyblue #87CEEB 135,206,235
+lightskyblue #87CEFA 135,206,250
+deepskyblue #00BFFF 0,191,255
+dodgerblue #1E90FF 30,144,255
+cornflowerblue #6495ED 100,149,237
+mediumslateblue #7B68EE 123,104,238
+royalblue #4169E1 65,105,225
+blue #0000FF 0,0,255
+mediumblue #0000CD 0,0,205
+darkblue #00008B 0,0,139
+navy #000080 0,0,128
+midnightblue #191970 25,25,112
+cornsilk #FFF8DC 255,248,220
+blanchedalmond #FFEBCD 255,235,205
+bisque #FFE4C4 255,228,196
+navajowhite #FFDEAD 255,222,173
+wheat #F5DEB3 245,222,179
+burlywood #DEB887 222,184,135
+tan #D2B48C 210,180,140
+rosybrown #BC8F8F 188,143,143
+sandybrown #F4A460 244,164,96
+goldenrod #DAA520 218,165,32
+darkgoldenrod #B8860B 184,134,11
+peru #CD853F 205,133,63
+chocolate #D2691E 210,105,30
+saddlebrown #8B4513 139,69,19
+sienna #A0522D 160,82,45
+brown #A52A2A 165,42,42
+maroon #800000 128,0,0
+white #FFFFFF 255,255,255
+snow #FFFAFA 255,250,250
+honeydew #F0FFF0 240,255,240
+mintcream #F5FFFA 245,255,250
+azure #F0FFFF 240,255,255
+aliceblue #F0F8FF 240,248,255
+ghostwhite #F8F8FF 248,248,255
+whitesmoke #F5F5F5 245,245,245
+seashell #FFF5EE 255,245,238
+beige #F5F5DC 245,245,220
+oldlace #FDF5E6 253,245,230
+floralwhite #FFFAF0 255,250,240
+ivory #FFFFF0 255,255,240
+antiquewhite #FAEBD7 250,235,215
+linen #FAF0E6 250,240,230
+lavenderblush #FFF0F5 255,240,245
+mistyrose #FFE4E1 255,228,225
+gainsboro #DCDCDC 220,220,220
+lightgrey #D3D3D3 211,211,211
+silver #C0C0C0 192,192,192
+darkgray #A9A9A9 169,169,169
+gray #808080 128,128,128
+dimgray #696969 105,105,105
+lightslategray #778899 119,136,153
+slategray #708090 112,128,144
+darkslategray #2F4F4F 47,79,79
+black #000000 0,0,0
+rebeccapurple #663399 102,51,153
\ No newline at end of file
diff --git a/site/modules/ColorPicker/FieldtypeColorPicker.module b/site/modules/ColorPicker/FieldtypeColorPicker.module
deleted file mode 100644
index 25bc4c4..0000000
--- a/site/modules/ColorPicker/FieldtypeColorPicker.module
+++ /dev/null
@@ -1,135 +0,0 @@
- 'ColorPicker',
- 'version' => 203,
- 'summary' => 'Fieldtype that stores a HEX color or the value transp. Color can be picked using a jQuery ColorPicker Plugin by http://www.eyecon.ro/colorpicker/ or from a configurable color swatch.',
- 'href' => 'http://processwire.com/talk/topic/865-module-colorpicker/page__gopid__7340#entry7340',
- 'installs' => 'InputfieldColorPicker'
- );
- }
-
- /**
- * Return the default or if not set a blank value
- *
- */
- public function getBlankValue(Page $page, Field $field) {
- if($field->default == "0") $field->default = "000000";
- return $field->default ? $field->default : '';
- }
-
-
- /**
- * Return the associated InputfieldColorPicker
- *
- */
- public function getInputfield(Page $page, Field $field) {
- $inputField = $this->modules->get('InputfieldColorPicker');
- $inputField->set('default', $field->default);
- $inputField->set('swatch', $field->swatch);
- return $inputField;
- }
-
- /**
- * Format the value for output
- * @param Page $page
- * @param Field $field
- * @param mixed $value
- * @return string
- */
- public function ___formatValue(Page $page, Field $field, $value){
-
- if(!$value) $value = trim($field->default);
- if(!strlen($value)) return $value;
- if(!$field->formatting) return $value;
-
- if("transp" == strtolower($value)) return self::TRANSPARENT;
- if($value == "0") $value = "000000";
-
- return self::HEX_PREFIX . $value;
- }
-
- /**
- * Render formatted markup for use in Admin ie. Lister
- */
- public function ___markupValue(Page $page, Field $field, $value = null, $property = '') {
- $m = "";
- if($value) {
- $m = "";
- }
- return $m;
- }
-
- /**
- * sanitize the HEX value and cut off characters if longer than 6
- */
- public function sanitizeValue(Page $page, Field $field, $value) {
- $value = $value == "transp" ? $value : strtoupper(substr($value, 0, 6));
- return $value;
- }
-
- /**
- * Return the database schema in specified format
- *
- */
- public function getDatabaseSchema(Field $field) {
- $schema = parent::getDatabaseSchema($field);
- $schema['data'] = 'CHAR(6) NOT NULL'; // i.e. FFFFFF or 333333 (hex color codes) or transp
- return $schema;
- }
-
- /**
- * set the config option fields for this field
- *
- */
- public function ___getConfigInputfields(Field $field) {
- $inputfields = parent::___getConfigInputfields($field);
-
- $f = $this->modules->get("InputfieldText");
- $f->attr('name', 'default');
- $f->attr('size', 6);
- $f->attr('value', $field->default);
- $f->label = $this->_('Default Value');
- $f->description = $this->_('Set the default HEX value or "transp" (transparent) for the field.');
- $f->notes = $this->_('For example "EAEAEA". To have a blank value leave this field empty.');
- $inputfields->append($f);
-
- /* additions (swatches) by @Rayden */
- $f = $this->modules->get("InputfieldTextarea");
- $f->attr('name', 'swatch');
- $f->attr('value', $field->swatch);
- $f->label = $this->_('Color Swatch');
- $f->description = $this->_('Comma seperated HEX values or "transp" (transparent) to add color swatches for each.');
- $f->notes = $this->_('For example "transp,FFFFFF,000000". Leave this field empty if you do not want to use the color swatch.');
- $inputfields->append($f);
-
- $f = $this->modules->get("InputfieldCheckbox");
- $f->attr('name', 'formatting');
- $f->attr('value', $field->formatting);
- $f->attr('checked', $field->formatting ? 'checked' : '');
- $f->label = $this->_('Turn on output formatting');
- $f->description = $this->_('Enabling this turns on output formatting for this field. This will return the HEX value of the field already prefixed with "#" for convenience i.e "#FFAADD" and "transp" will be output as "transparent".');;
- $inputfields->append($f);
-
- return $inputfields;
- }
-
-}
diff --git a/site/modules/ColorPicker/InputfieldColorPicker.js b/site/modules/ColorPicker/InputfieldColorPicker.js
deleted file mode 100644
index 0c40a2f..0000000
--- a/site/modules/ColorPicker/InputfieldColorPicker.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * An Inputfieldtype for handling Colors
- * used by the FieldtypeColorPicker/InputfieldColorPicker
- *
- * created by Philipp "Soma" Urlich
- * ColorPicker jQuery Plugin by http://www.eyecon.ro/colorpicker/
- *
- * Licensed under LGPL3 http://www.gnu.org/licenses/lgpl-3.0.txt
- *
- */
-
-;
-
-(function(document, $){
-
- var InputfieldColorPicker = {
-
- init: function() {
-
- $('div[id^=ColorPicker_]:not(.colorpicker_loaded)').each(function(){
- var $colorpicker = $(this);
- console.log("init colorpicker" + $colorpicker);
-
- $colorpicker.ColorPicker({
- color: $(this).data('color').toString(),
- onShow: function (colpkr) {
- $(colpkr).fadeIn(500);
- return false;
- },
- onHide: function (colpkr) {
- $(colpkr).fadeOut(500);
- return false;
- },
- onChange: function (hsb, hex, rgb) {
- $colorpicker.css('backgroundColor', '#' + hex);
- $colorpicker.css('background-image', 'none');
- $colorpicker.next('input').val(hex).trigger('change');
- }
- });
-
- $colorpicker.addClass("colorpicker_loaded");
-
- });
-
- },
-
- attachEvents: function() {
- $(document).on('click', 'a.ColorPickerReset', function(e){
- e.preventDefault();
- var color = $(this).data('default') && $(this).data('default') != 'transp' ? '#' + $(this).data('default').toString() : 'transparent';
- $(this).parent().find('input').val($(this).data('default')).trigger('change');
- $(this).parent().find('div[id^=ColorPicker_]').ColorPickerSetColor($(this).data('default').toString());
- $(this).parent().find('div[id^=ColorPicker_]')
- .css('backgroundColor', color)
- .css('background-image', 'none')
- .attr('data-color', $(this).data('default').toString());
- if(color == 'transparent') {
- var modurl = $(this).data('modurl');
- $(this).parent().find('div[id^=ColorPicker_]')
- .css('background-image', 'url(' + modurl + 'transparent.gif)');
- }
- });
-
- /* additions (swatches) by @Rayden */
- $(document).on('click', 'div.ColorPickerSwatch',function(e){
- e.preventDefault();
- var color = $(this).data('color') && $(this).data('color') != 'transp' ? '#' + $(this).data('color').toString() : 'transparent';
- $(this).closest('.ui-widget-content, .InputfieldContent').find('input').val($(this).data('color')).trigger('change');
- $(this).closest('.ui-widget-content, .InputfieldContent').find('div[id^=ColorPicker_]').ColorPickerSetColor($(this).data('color').toString());
- $(this).closest('.ui-widget-content, .InputfieldContent').find('div[id^=ColorPicker_]')
- .css('backgroundColor', color)
- .css('background-image', 'none')
- .attr('data-color', $(this).data('color').toString());
- if(color == 'transparent') {
- var modurl = $(this).closest('.ui-widget-content, .InputfieldContent').find('.ColorPickerReset').data('modurl');
- $(this).closest('.ui-widget-content, .InputfieldContent').find('div[id^=ColorPicker_]')
- .css('background-image', 'url(' + modurl + 'transparent.gif)');
- }
- });
- }
-
- };
-
- // document ready
- $(function(){
- InputfieldColorPicker.init();
- InputfieldColorPicker.attachEvents();
- $(".Inputfield").on("repeateradd", ".InputfieldRepeater", InputfieldColorPicker.init);
- $(".Inputfield").on("reloaded", ".InputfieldRepeater", function(){
- InputfieldColorPicker.init();
- });
-
- });
-
-}(document, jQuery));
-
diff --git a/site/modules/ColorPicker/InputfieldColorPicker.module b/site/modules/ColorPicker/InputfieldColorPicker.module
deleted file mode 100644
index 3fa5a30..0000000
--- a/site/modules/ColorPicker/InputfieldColorPicker.module
+++ /dev/null
@@ -1,93 +0,0 @@
- 'ColorPicker',
- 'version' => 203,
- 'summary' => 'Choose your colors the easy way.',
- 'href' => 'http://processwire.com/talk/topic/865-module-colorpicker/page__gopid__7340#entry7340',
- 'requires' => array("FieldtypeColorPicker")
- );
- }
-
- public function __construct() {
- parent::__construct();
- $this->setAttribute('type', 'hidden');
- }
-
- /**
- * inputfield is loaded
- */
- public function init() {
- parent::init();
- $conf = $this->getModuleInfo();
- $version = (int) $conf['version'];
- // append script needed for the inputfield
- $this->config->styles->add($this->config->urls->InputfieldColorPicker . "colorpicker/css/colorpicker.css?v={$version}");
- $this->config->scripts->add($this->config->urls->InputfieldColorPicker . "colorpicker/js/colorpicker.min.js?v={$version}");
- }
-
- /**
- * render the markup for this iputfield
- * @return string html markup
- */
- public function ___render() {
-
- $out = "\n";
- $out .= "getAttributesString() . " />";
- if($this->default == "0") $this->default = "000000";
- $out .= "_('reset color') . "";
-
- /**
- * add swatches for predefined color values | @Rayden
- */
- $swatch = trim($this->swatch);
-
- if(strlen($swatch)) {
-
- $csvalues = explode(",", trim($swatch));
-
- if(count($csvalues)) {
-
- $out .= "
";
- }
- }
-
- return $out;
- }
-
-
-}
diff --git a/site/modules/ColorPicker/README.md b/site/modules/ColorPicker/README.md
deleted file mode 100644
index 654214e..0000000
--- a/site/modules/ColorPicker/README.md
+++ /dev/null
@@ -1,101 +0,0 @@
-ColorPicker
-=====================
-
-**Custom Fieldtype/Inputfield for ProcessWire 2.+/3.+**
-
-This module gives you a new custom Fieldtype. Let's you select a color using a Colorpicker jQuery Plugin. The color selected will be stored in HEX format uppercase: "EAEAEA";
-
-When creating a new field in the admin, you can set a default value. The default value will be set when creating a new page, and it will also be used for empty fields.
-
-The field supports a transparent value. In the field setting you can use the name "transp" to define it. When output formatting (2.0.0) of the field is enabled, the field will return "transparent" in template code.
-
-The field supports a "reset" button to be able to set it back to the default value.
-
-### How to use it
-
-To use it in your template as a background HEX color, you'd simple output the value and prefix it with a #:
-
-```
-echo "background-color: #" . $page->color;
-```
-
-Since of 2.0.0 you can enable output formatting of the field in the details settings. When enabled it will format value directly from AADDEE to "#AADDEE" and "transp" to "transparent".
-
-```
-echo "background-color: " . $page->color;
-```
-
-The colorpicker used:
-[ColorPicker jQuery Plugin by Eyecon](http://www.eyecon.ro/colorpicker/)
-
-### Changelog
-
-**2.0.2**
-
-- fixed issue when field is in a Repeater or RepeaterMatrix
-- added support for ___markupValue() used in Lister
-
-
-**2.0.1**
-
-- Fixed default "000000" value issue in Fieldtype
-
-**2.0.0**
-
-- Added output formatting option to format values with prefix "#" when output in template code.
-- Added checks for "0" values and returning them as "000000", just in case ProcessWire converts them to 0.
-
-**1.0.8**
-
-- some maintenance, remove
not needed
-- remove overflow: auto
-_ colorpicker css fix input with box sizing coming from new admin theme
-
-**1.0.7**
-
-- fixed typecasting bug: when a color value is numeric it should be
-typecasted to string. This prevents the color picker window from not
-being launched. @Rayden
-- fixed small visualisation issue with the color swatch preventing a
-box collapse with css. @Rayden
-
-**1.0.6**
-
-- added support for color swatches for easy predefining and selecting color values @Rayden
-- added "transp" support for a transparent value (empty)
-
-**1.0.5**
-
-- fix bug with default value
-
-**1.0.4**
-
-- fix bug when used in repeaters
-
-**1.0.3**
-
-- added support for default value
-- added reset link to set back to default color
-
-**1.0.2**
-
-- Fixed issue with colorpicker not working when used in tabs
-
-**1.0.1**
-
-- Remove lots of code not needed. Cleanup.
-
-**1.0.0**
-
-- Initial Stable Release.
-
-
-### How to install:
-
-- Download the contents of this repository and put the folder renamed as "ColorPicker" into your site/modules/ folder
-- Login to processwire and got to Modules page and click "Check for new modules". You should see a note that two new modules were found. Install the FieldtypeColorPicker module under "Field" section. This will also install the required InputfieldColorPicker at the same time.
-- Done
-- You can now create a new field with the "ColorPicker" Fieldtype.
-
-
-
diff --git a/site/modules/ColorPicker/colorpicker/.DS_Store b/site/modules/ColorPicker/colorpicker/.DS_Store
deleted file mode 100644
index c0893ad..0000000
Binary files a/site/modules/ColorPicker/colorpicker/.DS_Store and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/css/colorpicker.css b/site/modules/ColorPicker/colorpicker/css/colorpicker.css
deleted file mode 100644
index bf08d25..0000000
--- a/site/modules/ColorPicker/colorpicker/css/colorpicker.css
+++ /dev/null
@@ -1,164 +0,0 @@
-
-.colorpicker {
- width: 356px;
- height: 176px;
- overflow: hidden;
- position: absolute;
- background: url(../images/colorpicker_background.png);
- font-family: Arial, Helvetica, sans-serif;
- display: none;
- z-index:1;
-}
-.colorpicker_color {
- width: 150px;
- height: 150px;
- left: 14px;
- top: 13px;
- position: absolute;
- background: #f00;
- overflow: hidden;
- cursor: crosshair;
-}
-.colorpicker_color div {
- position: absolute;
- top: 0;
- left: 0;
- width: 150px;
- height: 150px;
- background: url(../images/colorpicker_overlay.png);
-}
-.colorpicker_color div div {
- position: absolute;
- top: 0;
- left: 0;
- width: 11px;
- height: 11px;
- overflow: hidden;
- background: url(../images/colorpicker_select.gif);
- margin: -5px 0 0 -5px;
-}
-.colorpicker_hue {
- position: absolute;
- top: 13px;
- left: 171px;
- width: 35px;
- height: 150px;
- cursor: n-resize;
-}
-.colorpicker_hue div {
- position: absolute;
- width: 35px;
- height: 9px;
- overflow: hidden;
- background: url(../images/colorpicker_indic.gif) left top;
- margin: -4px 0 0 0;
- left: 0px;
-}
-.colorpicker_new_color {
- position: absolute;
- width: 60px;
- height: 30px;
- left: 213px;
- top: 13px;
- background: #f00;
-}
-.colorpicker_current_color {
- position: absolute;
- width: 60px;
- height: 30px;
- left: 283px;
- top: 13px;
- background: #f00;
-}
-.colorpicker input {
- background-color: transparent;
- border: 1px solid transparent;
- position: absolute;
- font-size: 10px;
- font-family: Arial, Helvetica, sans-serif;
- color: #898989;
- top: 4px;
- right: 11px;
- text-align: right;
- margin: 0;
- padding: 0;
- height: 15px;
-
-}
-.colorpicker_hex {
- position: absolute;
- width: 72px;
- height: 22px;
- background: url(../images/colorpicker_hex.png) top;
- left: 212px;
- top: 142px;
-}
-.colorpicker_hex input {
- right: 6px;
-}
-.colorpicker_field {
- height: 22px;
- width: 62px;
- background-position: top;
- position: absolute;
-}
-.colorpicker_field span {
- position: absolute;
- width: 12px;
- height: 22px;
- overflow: hidden;
- top: 0;
- right: 0;
- cursor: n-resize;
-}
-.colorpicker_rgb_r {
- background-image: url(../images/colorpicker_rgb_r.png);
- top: 52px;
- left: 212px;
-}
-.colorpicker_rgb_g {
- background-image: url(../images/colorpicker_rgb_g.png);
- top: 82px;
- left: 212px;
-}
-.colorpicker_rgb_b {
- background-image: url(../images/colorpicker_rgb_b.png);
- top: 112px;
- left: 212px;
-}
-.colorpicker_hsb_h {
- background-image: url(../images/colorpicker_hsb_h.png);
- top: 52px;
- left: 282px;
-}
-.colorpicker_hsb_s {
- background-image: url(../images/colorpicker_hsb_s.png);
- top: 82px;
- left: 282px;
-}
-.colorpicker_hsb_b {
- background-image: url(../images/colorpicker_hsb_b.png);
- top: 112px;
- left: 282px;
-}
-.colorpicker_submit {
- position: absolute;
- width: 22px;
- height: 22px;
- background: url(../images/colorpicker_submit.png) top;
- left: 322px;
- top: 142px;
- overflow: hidden;
-}
-.colorpicker_focus {
- background-position: center;
-}
-.colorpicker_hex.colorpicker_focus {
- background-position: bottom;
-}
-.colorpicker_submit.colorpicker_focus {
- background-position: bottom;
-}
-.colorpicker_slider {
- background-position: bottom;
-}
diff --git a/site/modules/ColorPicker/colorpicker/images/Thumbs.db b/site/modules/ColorPicker/colorpicker/images/Thumbs.db
deleted file mode 100644
index d396c36..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/Thumbs.db and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/blank.gif b/site/modules/ColorPicker/colorpicker/images/blank.gif
deleted file mode 100644
index 75b945d..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/blank.gif and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_background.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_background.png
deleted file mode 100644
index 8401572..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_background.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_hex.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_hex.png
deleted file mode 100644
index 4e532d7..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_hex.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_b.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_b.png
deleted file mode 100644
index dfac595..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_b.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_h.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_h.png
deleted file mode 100644
index 3977ed9..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_h.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_s.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_s.png
deleted file mode 100644
index a2a6997..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_s.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_indic.gif b/site/modules/ColorPicker/colorpicker/images/colorpicker_indic.gif
deleted file mode 100644
index f9fa95e..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_indic.gif and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_overlay.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_overlay.png
deleted file mode 100644
index 561cdd9..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_overlay.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_b.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_b.png
deleted file mode 100644
index dfac595..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_b.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_g.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_g.png
deleted file mode 100644
index 72b3276..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_g.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_r.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_r.png
deleted file mode 100644
index 4855fe0..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_r.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_select.gif b/site/modules/ColorPicker/colorpicker/images/colorpicker_select.gif
deleted file mode 100644
index 599f7f1..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_select.gif and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_submit.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_submit.png
deleted file mode 100644
index 7f4c082..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_submit.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_background.png b/site/modules/ColorPicker/colorpicker/images/custom_background.png
deleted file mode 100644
index cf55ffd..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_background.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_hex.png b/site/modules/ColorPicker/colorpicker/images/custom_hex.png
deleted file mode 100644
index 888f444..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_hex.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_hsb_b.png b/site/modules/ColorPicker/colorpicker/images/custom_hsb_b.png
deleted file mode 100644
index 2f99dae..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_hsb_b.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_hsb_h.png b/site/modules/ColorPicker/colorpicker/images/custom_hsb_h.png
deleted file mode 100644
index a217e92..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_hsb_h.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_hsb_s.png b/site/modules/ColorPicker/colorpicker/images/custom_hsb_s.png
deleted file mode 100644
index 7826b41..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_hsb_s.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_indic.gif b/site/modules/ColorPicker/colorpicker/images/custom_indic.gif
deleted file mode 100644
index 222fb94..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_indic.gif and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_rgb_b.png b/site/modules/ColorPicker/colorpicker/images/custom_rgb_b.png
deleted file mode 100644
index 80764e5..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_rgb_b.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_rgb_g.png b/site/modules/ColorPicker/colorpicker/images/custom_rgb_g.png
deleted file mode 100644
index fc9778b..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_rgb_g.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_rgb_r.png b/site/modules/ColorPicker/colorpicker/images/custom_rgb_r.png
deleted file mode 100644
index 91b0cd4..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_rgb_r.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/custom_submit.png b/site/modules/ColorPicker/colorpicker/images/custom_submit.png
deleted file mode 100644
index cd202cd..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/custom_submit.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/select.png b/site/modules/ColorPicker/colorpicker/images/select.png
deleted file mode 100644
index 21213bf..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/select.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/select2.png b/site/modules/ColorPicker/colorpicker/images/select2.png
deleted file mode 100644
index 2cd2cab..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/select2.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/images/slider.png b/site/modules/ColorPicker/colorpicker/images/slider.png
deleted file mode 100644
index 8b03da9..0000000
Binary files a/site/modules/ColorPicker/colorpicker/images/slider.png and /dev/null differ
diff --git a/site/modules/ColorPicker/colorpicker/js/colorpicker.js b/site/modules/ColorPicker/colorpicker/js/colorpicker.js
deleted file mode 100644
index 10a2b22..0000000
--- a/site/modules/ColorPicker/colorpicker/js/colorpicker.js
+++ /dev/null
@@ -1,484 +0,0 @@
-/**
- *
- * Color picker
- * Author: Stefan Petre www.eyecon.ro
- *
- * Dual licensed under the MIT and GPL licenses
- *
- */
-(function ($) {
- var ColorPicker = function () {
- var
- ids = {},
- inAction,
- charMin = 65,
- visible,
- tpl = '
"
+ ].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 i = 1; i <= 6; i++) {
+ gradientFix += "";
+ }
+ }
+
+ return [
+ "
",
+ "
",
+ "",
+ "
",
+ "",
+ "
",
+ "
",
+ "
",
+ "
",
+ "",
+ "
",
+ "
",
+ "
",
+ "
",
+ "",
+ "
",
+ "
",
+ "
",
+ "
",
+ "
",
+ "
",
+ "",
+ gradientFix,
+ "
",
+ "
",
+ "
",
+ "
",
+ "
",
+ "",
+ "
",
+ "",
+ "
",
+ "",
+ "",
+ "
",
+ "
",
+ "
"
+ ].join("");
+ })();
+
+ function paletteTemplate (p, color, className, opts) {
+ var html = [];
+ for (var i = 0; i < p.length; i++) {
+ var current = p[i];
+ if(current) {
+ var tiny = tinycolor(current);
+ var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
+ c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : "";
+ var formattedString = tiny.toString(opts.preferredFormat || "rgb");
+ var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
+ html.push('');
+ } else {
+ var cls = 'sp-clear-display';
+ html.push($('')
+ .append($('')
+ .attr('title', opts.noColorSelectedText)
+ )
+ .html()
+ );
+ }
+ }
+ return "
" + html.join('') + "
";
+ }
+
+ function hideAll() {
+ for (var i = 0; i < spectrums.length; i++) {
+ if (spectrums[i]) {
+ spectrums[i].hide();
+ }
+ }
+ }
+
+ function instanceOptions(o, callbackContext) {
+ var opts = $.extend({}, defaultOpts, o);
+ opts.callbacks = {
+ 'move': bind(opts.move, callbackContext),
+ 'change': bind(opts.change, callbackContext),
+ 'show': bind(opts.show, callbackContext),
+ 'hide': bind(opts.hide, callbackContext),
+ 'beforeShow': bind(opts.beforeShow, callbackContext)
+ };
+
+ return opts;
+ }
+
+ function spectrum(element, o) {
+
+ var opts = instanceOptions(o, element),
+ flat = opts.flat,
+ showSelectionPalette = opts.showSelectionPalette,
+ localStorageKey = opts.localStorageKey,
+ theme = opts.theme,
+ callbacks = opts.callbacks,
+ resize = throttle(reflow, 10),
+ 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 = $(markup, doc).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 = Array.isArray(palette[0]) ? palette : [palette];
+ paletteLookup = {};
+ for (var i = 0; i < paletteArray.length; i++) {
+ for (var j = 0; j < paletteArray[i].length; j++) {
+ 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.on("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.on("click", stopPropagation);
+
+ // Handle user typed input
+ textInput.on("change", setFromTextInput);
+ textInput.on("paste", function () {
+ setTimeout(setFromTextInput, 1);
+ });
+ textInput.on("keydown", function (e) { if (e.keyCode == 13) { setFromTextInput(); } });
+
+ cancelButton.text(opts.cancelText);
+ cancelButton.on("click.spectrum", function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ revert();
+ hide();
+ });
+
+ clearButton.attr("title", opts.clearText);
+ clearButton.on("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.on("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.on("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 (dragX, dragY, e) {
+ currentAlpha = (dragX / alphaWidth);
+ isEmpty = false;
+ if (e.shiftKey) {
+ currentAlpha = Math.round(currentAlpha * 10) / 10;
+ }
+
+ move();
+ }, dragStart, dragStop);
+
+ draggable(slider, function (dragX, dragY) {
+ currentHue = parseFloat(dragY / slideHeight);
+ isEmpty = false;
+ if (!opts.showAlpha) {
+ currentAlpha = 1;
+ }
+ move();
+ }, dragStart, dragStop);
+
+ draggable(dragger, function (dragX, dragY, e) {
+
+ // 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();
+
+ }, dragStart, dragStop);
+
+ 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();
+
+ // If the picker is going to close immediately, a palette selection
+ // is a change. Otherwise, it's a move only.
+ if (opts.hideAfterPaletteSelect) {
+ updateOriginalInput(true);
+ hide();
+ } else {
+ updateOriginalInput();
+ }
+ }
+
+ return false;
+ }
+
+ var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
+ paletteContainer.on(paletteEvent, ".sp-thumb-el", paletteElementClick);
+ initialColorContainer.on(paletteEvent, ".sp-thumb-el:nth-child(1)", { ignore: true }, 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(i, c) {
+ 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(rgb, selectionPalette) === -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 i = 0; i < selectionPalette.length; i++) {
+ var rgb = tinycolor(selectionPalette[i]).toRgbString();
+
+ if (!paletteLookup[rgb]) {
+ unique.push(selectionPalette[i]);
+ }
+ }
+ }
+
+ return unique.reverse().slice(0, opts.maxSelectionSize);
+ }
+
+ function drawPalette() {
+
+ var currentColor = get();
+
+ var html = $.map(paletteArray, function (palette, i) {
+ return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts);
+ });
+
+ 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([initial, current], current, "sp-palette-row-initial", opts));
+ }
+ }
+
+ function dragStart() {
+ if (dragHeight <= 0 || dragWidth <= 0 || 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);
+ move();
+ updateOriginalInput();
+ }
+ else {
+ var tiny = tinycolor(value);
+ if (tiny.isValid()) {
+ set(tiny);
+ move();
+ updateOriginalInput();
+ }
+ 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).on("keydown.spectrum", onkeydown);
+ $(doc).on("click.spectrum", clickout);
+ $(window).on("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).off("keydown.spectrum", onkeydown);
+ $(doc).off("click.spectrum", clickout);
+ $(window).off("resize.spectrum", resize);
+
+ replacer.removeClass("sp-active");
+ container.addClass("sp-hidden");
+
+ callbacks.hide(get());
+ boundElement.trigger('hide.spectrum', [ get() ]);
+ }
+
+ function revert() {
+ set(colorOnShow, true);
+ updateOriginalInput(true);
+ }
+
+ function set(color, ignoreFormatChange) {
+ if (tinycolor.equals(color, get())) {
+ // Update UI just in case a validation error needs
+ // to be cleared.
+ updateUI();
+ return;
+ }
+
+ var newColor, newHsv;
+ if (!color && allowEmpty) {
+ isEmpty = true;
+ } else {
+ isEmpty = false;
+ newColor = tinycolor(color);
+ newHsv = newColor.toHsv();
+
+ currentHue = (newHsv.h % 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({
+ h: currentHue,
+ s: currentSaturation,
+ v: currentValue,
+ a: Math.round(currentAlpha * 1000) / 1000
+ }, { format: opts.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({ h: currentHue, s: 1, v: 1 });
+ 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 < 1 && !(currentAlpha === 0 && format === "name")) {
+ if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
+ format = "rgb";
+ }
+ }
+
+ var realColor = get({ format: format }),
+ 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.a = 0;
+ var realAlpha = tinycolor(rgb).toRgbString();
+ var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")";
+
+ if (IE) {
+ alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, 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 s = currentSaturation;
+ var v = 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 = s * dragWidth;
+ var dragY = dragHeight - (v * dragHeight);
+ dragX = Math.max(
+ -dragHelperHeight,
+ Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)
+ );
+ dragY = Math.max(
+ -dragHelperHeight,
+ Math.min(dragHeight - dragHelperHeight, dragY - 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(color, colorOnShow);
+
+ 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(container, offsetElement));
+ }
+ }
+
+ updateHelperLocations();
+
+ if (opts.showPalette) {
+ drawPalette();
+ }
+
+ boundElement.trigger('reflow.spectrum');
+ }
+
+ function destroy() {
+ boundElement.show();
+ offsetElement.off("click.spectrum touchstart.spectrum");
+ container.remove();
+ replacer.remove();
+ spectrums[spect.id] = null;
+ }
+
+ function option(optionName, optionValue) {
+ 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 = {
+ show: show,
+ hide: hide,
+ toggle: toggle,
+ reflow: reflow,
+ option: option,
+ enable: enable,
+ disable: disable,
+ offset: setOffset,
+ set: function (c) {
+ set(c);
+ updateOriginalInput();
+ },
+ get: get,
+ destroy: destroy,
+ container: container
+ };
+
+ 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(picker, input) {
+ 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();
+ var offsetLeft = offset.left;
+ var offsetTop = offset.top;
+
+ offsetTop += inputHeight;
+
+ offsetLeft -=
+ Math.min(offsetLeft, (offsetLeft + dpWidth > viewWidth && viewWidth > dpWidth) ?
+ Math.abs(offsetLeft + dpWidth - viewWidth) : 0);
+
+ offsetTop -=
+ Math.min(offsetTop, ((offsetTop + dpHeight > viewHeight && viewHeight > dpHeight) ?
+ Math.abs(dpHeight + inputHeight - extraY) : extraY));
+
+ return {
+ top: offsetTop,
+ bottom: offset.bottom,
+ left: offsetLeft,
+ right: offset.right,
+ width: offset.width,
+ height: offset.height
+ };
+ }
+
+ /**
+ * 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(func, obj) {
+ var slice = Array.prototype.slice;
+ var args = slice.call(arguments, 2);
+ return function () {
+ return func.apply(obj, args.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(element, onmove, onstart, onstop) {
+ 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 < 9 && !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(0, Math.min(pageX - offset.left, maxWidth));
+ var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));
+
+ if (hasTouch) {
+ // Stop scrolling in iOS
+ prevent(e);
+ }
+
+ onmove.apply(element, [dragX, dragY, e]);
+ }
+ }
+
+ function start(e) {
+ var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);
+
+ if (!rightclick && !dragging) {
+ if (onstart.apply(element, arguments) !== false) {
+ dragging = true;
+ maxHeight = $(element).height();
+ maxWidth = $(element).width();
+ offset = $(element).offset();
+
+ $(doc).on(duringDragEvents);
+ $(doc.body).addClass("sp-dragging");
+
+ move(e);
+
+ prevent(e);
+ }
+ }
+ }
+
+ function stop() {
+ if (dragging) {
+ $(doc).off(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(element, arguments);
+ }, 0);
+ }
+ dragging = false;
+ }
+
+ $(element).on("touchstart mousedown", start);
+ }
+
+ function throttle(func, wait, debounce) {
+ var timeout;
+ return function () {
+ var context = this, args = arguments;
+ var throttler = function () {
+ timeout = null;
+ func.apply(context, args);
+ };
+ if (debounce) clearTimeout(timeout);
+ if (debounce || !timeout) timeout = setTimeout(throttler, wait);
+ };
+ }
+
+ function inputTypeColorSupport() {
+ return $.fn.spectrum.inputTypeColorSupport();
+ }
+
+ /**
+ * Define a jQuery plugin
+ */
+ var dataID = "spectrum.id";
+ $.fn.spectrum = function (opts, extra) {
+
+ if (typeof opts == "string") {
+
+ var returnValue = this;
+ var args = Array.prototype.slice.call( arguments, 1 );
+
+ 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(spect, args);
+ }
+ else if (opts == "destroy") {
+ spect.destroy();
+ $(this).removeData(dataID);
+ }
+ else {
+ method.apply(spect, args);
+ }
+ }
+ });
+
+ return returnValue;
+ }
+
+ // Initializing a new instance of spectrum
+ return this.spectrum("destroy").each(function () {
+ var options = $.extend({}, $(this).data(), opts);
+ var spect = spectrum(this, options);
+ $(this).data(dataID, spect.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 = $("")[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(color, opts) {
+
+ 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(color, opts);
+ }
+
+ 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(1000 * this._a) / 1000;
+ 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.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
+ },
+ setAlpha: function(value) {
+ this._a = boundAlpha(value);
+ this._roundA = mathRound(1000 * this._a) / 1000;
+ return this;
+ },
+ toHsv: function() {
+ var hsv = rgbToHsv(this._r, this._g, this._b);
+ return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
+ },
+ toHsvString: function() {
+ var hsv = rgbToHsv(this._r, this._g, this._b);
+ var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
+ return (this._a == 1) ?
+ "hsv(" + h + ", " + s + "%, " + v + "%)" :
+ "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
+ },
+ toHsl: function() {
+ var hsl = rgbToHsl(this._r, this._g, this._b);
+ return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
+ },
+ toHslString: function() {
+ var hsl = rgbToHsl(this._r, this._g, this._b);
+ var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
+ return (this._a == 1) ?
+ "hsl(" + h + ", " + s + "%, " + l + "%)" :
+ "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
+ },
+ toHex: function(allow3Char) {
+ return rgbToHex(this._r, this._g, this._b, allow3Char);
+ },
+ toHexString: function(allow3Char) {
+ return '#' + this.toHex(allow3Char);
+ },
+ toHex8: function() {
+ return rgbaToHex(this._r, this._g, this._b, this._a);
+ },
+ toHex8String: function() {
+ return '#' + this.toHex8();
+ },
+ toRgb: function() {
+ return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._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 { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
+ },
+ toPercentageRgbString: function() {
+ return (this._a == 1) ?
+ "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
+ "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
+ },
+ toName: function() {
+ if (this._a === 0) {
+ return "transparent";
+ }
+
+ if (this._a < 1) {
+ return false;
+ }
+
+ return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
+ },
+ toFilter: function(secondColor) {
+ var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
+ var secondHex8String = hex8String;
+ var gradientType = this._gradientType ? "GradientType = 1, " : "";
+
+ if (secondColor) {
+ var s = 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 < 1 && 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(lighten, arguments);
+ },
+ brighten: function() {
+ return this._applyModification(brighten, arguments);
+ },
+ darken: function() {
+ return this._applyModification(darken, arguments);
+ },
+ desaturate: function() {
+ return this._applyModification(desaturate, arguments);
+ },
+ saturate: function() {
+ return this._applyModification(saturate, arguments);
+ },
+ greyscale: function() {
+ return this._applyModification(greyscale, arguments);
+ },
+ spin: function() {
+ return this._applyModification(spin, arguments);
+ },
+
+ _applyCombination: function(fn, args) {
+ return fn.apply(null, [this].concat([].slice.call(args)));
+ },
+ analogous: function() {
+ return this._applyCombination(analogous, arguments);
+ },
+ complement: function() {
+ return this._applyCombination(complement, arguments);
+ },
+ monochromatic: function() {
+ return this._applyCombination(monochromatic, arguments);
+ },
+ splitcomplement: function() {
+ return this._applyCombination(splitcomplement, arguments);
+ },
+ triad: function() {
+ return this._applyCombination(triad, arguments);
+ },
+ tetrad: function() {
+ return this._applyCombination(tetrad, arguments);
+ }
+ };
+
+ // 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(color, opts) {
+ if (typeof color == "object") {
+ var newColor = {};
+ for (var i in color) {
+ if (color.hasOwnProperty(i)) {
+ if (i === "a") {
+ newColor[i] = color[i];
+ }
+ else {
+ newColor[i] = convertToPercentage(color[i]);
+ }
+ }
+ }
+ color = newColor;
+ }
+
+ return tinycolor(color, opts);
+ };
+
+ // 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 = { r: 0, g: 0, b: 0 };
+ var a = 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.r, color.g, color.b);
+ ok = true;
+ format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
+ }
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
+ color.s = convertToPercentage(color.s);
+ color.v = convertToPercentage(color.v);
+ rgb = hsvToRgb(color.h, color.s, color.v);
+ ok = true;
+ format = "hsv";
+ }
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
+ color.s = convertToPercentage(color.s);
+ color.l = convertToPercentage(color.l);
+ rgb = hslToRgb(color.h, color.s, color.l);
+ ok = true;
+ format = "hsl";
+ }
+
+ if (color.hasOwnProperty("a")) {
+ a = color.a;
+ }
+ }
+
+ a = boundAlpha(a);
+
+ return {
+ ok: ok,
+ format: color.format || format,
+ r: mathMin(255, mathMax(rgb.r, 0)),
+ g: mathMin(255, mathMax(rgb.g, 0)),
+ b: mathMin(255, mathMax(rgb.b, 0)),
+ a: a
+ };
+ }
+
+
+ // Conversion Functions
+ // --------------------
+
+ // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
+ //
+
+ // `rgbToRgb`
+ // Handle bounds / percentage checking to conform to CSS color spec
+ //
+ // *Assumes:* r, g, b in [0, 255] or [0, 1]
+ // *Returns:* { r, g, b } in [0, 255]
+ function rgbToRgb(r, g, b){
+ return {
+ r: bound01(r, 255) * 255,
+ g: bound01(g, 255) * 255,
+ b: bound01(b, 255) * 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(r, g, b) {
+
+ r = bound01(r, 255);
+ g = bound01(g, 255);
+ b = bound01(b, 255);
+
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
+ var h, s, l = (max + min) / 2;
+
+ if(max == min) {
+ h = s = 0; // achromatic
+ }
+ else {
+ var d = max - min;
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+ switch(max) {
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+ case g: h = (b - r) / d + 2; break;
+ case b: h = (r - g) / d + 4; break;
+ }
+
+ h /= 6;
+ }
+
+ return { h: h, s: s, l: l };
+ }
+
+ // `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(h, s, l) {
+ var r, g, b;
+
+ h = bound01(h, 360);
+ s = bound01(s, 100);
+ l = bound01(l, 100);
+
+ function hue2rgb(p, q, t) {
+ if(t < 0) t += 1;
+ if(t > 1) t -= 1;
+ if(t < 1/6) return p + (q - p) * 6 * t;
+ if(t < 1/2) return q;
+ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
+ return p;
+ }
+
+ if(s === 0) {
+ r = g = b = l; // achromatic
+ }
+ else {
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ var p = 2 * l - q;
+ r = hue2rgb(p, q, h + 1/3);
+ g = hue2rgb(p, q, h);
+ b = hue2rgb(p, q, h - 1/3);
+ }
+
+ return { r: r * 255, g: g * 255, b: b * 255 };
+ }
+
+ // `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(r, g, b) {
+
+ r = bound01(r, 255);
+ g = bound01(g, 255);
+ b = bound01(b, 255);
+
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
+ var h, s, v = max;
+
+ var d = max - min;
+ s = max === 0 ? 0 : d / max;
+
+ if(max == min) {
+ h = 0; // achromatic
+ }
+ else {
+ switch(max) {
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+ case g: h = (b - r) / d + 2; break;
+ case b: h = (r - g) / d + 4; break;
+ }
+ h /= 6;
+ }
+ return { h: h, s: s, v: v };
+ }
+
+ // `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(h, s, v) {
+
+ h = bound01(h, 360) * 6;
+ s = bound01(s, 100);
+ v = bound01(v, 100);
+
+ var i = math.floor(h),
+ f = h - i,
+ p = v * (1 - s),
+ q = v * (1 - f * s),
+ t = v * (1 - (1 - f) * s),
+ mod = i % 6,
+ r = [v, q, p, p, t, v][mod],
+ g = [t, v, v, q, p, p][mod],
+ b = [p, p, t, v, v, q][mod];
+
+ return { r: r * 255, g: g * 255, b: b * 255 };
+ }
+
+ // `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(r, g, b, allow3Char) {
+
+ 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(r, g, b, a) {
+
+ 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 (color1, color2) {
+ if (!color1 || !color2) { return false; }
+ return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
+ };
+ tinycolor.random = function() {
+ return tinycolor.fromRatio({
+ r: mathRandom(),
+ g: mathRandom(),
+ b: mathRandom()
+ });
+ };
+
+
+ // Modification Functions
+ // ----------------------
+ // Thanks to less.js for some of the basics here
+ //
+
+ function desaturate(color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var hsl = tinycolor(color).toHsl();
+ hsl.s -= amount / 100;
+ hsl.s = clamp01(hsl.s);
+ return tinycolor(hsl);
+ }
+
+ function saturate(color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var hsl = tinycolor(color).toHsl();
+ hsl.s += amount / 100;
+ hsl.s = clamp01(hsl.s);
+ return tinycolor(hsl);
+ }
+
+ function greyscale(color) {
+ return tinycolor(color).desaturate(100);
+ }
+
+ function lighten (color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var hsl = tinycolor(color).toHsl();
+ hsl.l += amount / 100;
+ hsl.l = clamp01(hsl.l);
+ return tinycolor(hsl);
+ }
+
+ function brighten(color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var rgb = tinycolor(color).toRgb();
+ rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
+ rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
+ rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
+ return tinycolor(rgb);
+ }
+
+ function darken (color, amount) {
+ amount = (amount === 0) ? 0 : (amount || 10);
+ var hsl = tinycolor(color).toHsl();
+ hsl.l -= amount / 100;
+ hsl.l = 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(color, amount) {
+ var hsl = tinycolor(color).toHsl();
+ var hue = (mathRound(hsl.h) + amount) % 360;
+ hsl.h = hue < 0 ? 360 + hue : hue;
+ return tinycolor(hsl);
+ }
+
+ // Combination Functions
+ // ---------------------
+ // Thanks to jQuery xColor for some of the ideas behind these
+ //
+
+ function complement(color) {
+ var hsl = tinycolor(color).toHsl();
+ hsl.h = (hsl.h + 180) % 360;
+ return tinycolor(hsl);
+ }
+
+ function triad(color) {
+ var hsl = tinycolor(color).toHsl();
+ var h = hsl.h;
+ return [
+ tinycolor(color),
+ tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
+ tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
+ ];
+ }
+
+ function tetrad(color) {
+ var hsl = tinycolor(color).toHsl();
+ var h = hsl.h;
+ return [
+ tinycolor(color),
+ tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
+ tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
+ tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
+ ];
+ }
+
+ function splitcomplement(color) {
+ var hsl = tinycolor(color).toHsl();
+ var h = hsl.h;
+ return [
+ tinycolor(color),
+ tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
+ tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
+ ];
+ }
+
+ function analogous(color, results, slices) {
+ results = results || 6;
+ slices = slices || 30;
+
+ var hsl = tinycolor(color).toHsl();
+ var part = 360 / slices;
+ var ret = [tinycolor(color)];
+
+ for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
+ hsl.h = (hsl.h + part) % 360;
+ ret.push(tinycolor(hsl));
+ }
+ return ret;
+ }
+
+ function monochromatic(color, results) {
+ results = results || 6;
+ var hsv = tinycolor(color).toHsv();
+ var h = hsv.h, s = hsv.s, v = hsv.v;
+ var ret = [];
+ var modification = 1 / results;
+
+ while (results--) {
+ ret.push(tinycolor({ h: h, s: s, v: v}));
+ v = (v + modification) % 1;
+ }
+
+ return ret;
+ }
+
+ // Utility Functions
+ // ---------------------
+
+ tinycolor.mix = function(color1, color2, amount) {
+ amount = (amount === 0) ? 0 : (amount || 50);
+
+ var rgb1 = tinycolor(color1).toRgb();
+ var rgb2 = tinycolor(color2).toRgb();
+
+ var p = amount / 100;
+ var w = p * 2 - 1;
+ var a = rgb2.a - rgb1.a;
+
+ var w1;
+
+ if (w * a == -1) {
+ w1 = w;
+ } else {
+ w1 = (w + a) / (1 + w * a);
+ }
+
+ w1 = (w1 + 1) / 2;
+
+ var w2 = 1 - w1;
+
+ var rgba = {
+ r: rgb2.r * w1 + rgb1.r * w2,
+ g: rgb2.g * w1 + rgb1.g * w2,
+ b: rgb2.b * w1 + rgb1.b * w2,
+ a: rgb2.a * p + rgb1.a * (1 - p)
+ };
+
+ return tinycolor(rgba);
+ };
+
+
+ // Readability Functions
+ // ---------------------
+ //
+
+ // `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(color1, color2) {
+ 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.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +
+ Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +
+ Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)
+ );
+
+ return {
+ brightness: Math.abs(brightnessA - brightnessB),
+ color: colorDiff
+ };
+ };
+
+ // `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(color1, color2) {
+ var readability = tinycolor.readability(color1, color2);
+ 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(baseColor, colorList) {
+ var bestColor = null;
+ var bestScore = 0;
+ var bestIsReadable = false;
+ for (var i=0; i < colorList.length; i++) {
+
+ // We normalize both around the "acceptable" breaking point,
+ // but rank brightness constrast higher than hue.
+
+ var readability = tinycolor.readability(baseColor, colorList[i]);
+ var readable = readability.brightness > 125 && readability.color > 500;
+ var score = 3 * (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
+ // ------------------
+ //
+ 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) {
+ a = parseFloat(a);
+
+ if (isNaN(a) || a < 0 || a > 1) {
+ a = 1;
+ }
+
+ return a;
+ }
+
+ // Take input from [0, n] and return it as [0, 1]
+ function bound01(n, max) {
+ if (isOnePointZero(n)) { n = "100%"; }
+
+ var processPercent = isPercentage(n);
+ n = mathMin(max, mathMax(0, parseFloat(n)));
+
+ // Automatically convert percentage into number
+ if (processPercent) {
+ n = parseInt(n * max, 10) / 100;
+ }
+
+ // Handle floating point rounding errors
+ if ((math.abs(n - max) < 0.000001)) {
+ return 1;
+ }
+
+ // Convert into [0, 1] range if it isn't already
+ return (n % max) / parseFloat(max);
+ }
+
+ // Force a number between 0 and 1
+ function clamp01(val) {
+ return mathMin(1, mathMax(0, val));
+ }
+
+ // Parse a base-16 hex value into a base-10 integer
+ function parseIntFromHex(val) {
+ return parseInt(val, 16);
+ }
+
+ // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
+ //
+ function isOnePointZero(n) {
+ return typeof n == "string" && n.indexOf('.') != -1 && 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 == 1 ? '0' + c : '' + c;
+ }
+
+ // Replace a decimal with it's percentage value
+ function convertToPercentage(n) {
+ if (n <= 1) {
+ n = (n * 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() {
+
+ //
+ var CSS_INTEGER = "[-\\+]?\\d+%?";
+
+ //
+ 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 { r: 0, g: 0, b: 0, a: 0, format: "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 { r: match[1], g: match[2], b: match[3] };
+ }
+ if ((match = matchers.rgba.exec(color))) {
+ return { r: match[1], g: match[2], b: match[3], a: match[4] };
+ }
+ if ((match = matchers.hsl.exec(color))) {
+ return { h: match[1], s: match[2], l: match[3] };
+ }
+ if ((match = matchers.hsla.exec(color))) {
+ return { h: match[1], s: match[2], l: match[3], a: match[4] };
+ }
+ if ((match = matchers.hsv.exec(color))) {
+ return { h: match[1], s: match[2], v: match[3] };
+ }
+ if ((match = matchers.hsva.exec(color))) {
+ return { h: match[1], s: match[2], v: match[3], a: match[4] };
+ }
+ if ((match = matchers.hex8.exec(color))) {
+ return {
+ a: convertHexToDecimal(match[1]),
+ r: parseIntFromHex(match[2]),
+ g: parseIntFromHex(match[3]),
+ b: parseIntFromHex(match[4]),
+ format: named ? "name" : "hex8"
+ };
+ }
+ if ((match = matchers.hex6.exec(color))) {
+ return {
+ r: parseIntFromHex(match[1]),
+ g: parseIntFromHex(match[2]),
+ b: parseIntFromHex(match[3]),
+ format: named ? "name" : "hex"
+ };
+ }
+ if ((match = matchers.hex3.exec(color))) {
+ return {
+ r: parseIntFromHex(match[1] + '' + match[1]),
+ g: parseIntFromHex(match[2] + '' + match[2]),
+ b: parseIntFromHex(match[3] + '' + match[3]),
+ format: named ? "name" : "hex"
+ };
+ }
+
+ return false;
+ }
+
+ window.tinycolor = tinycolor;
+ })();
+
+ $(function () {
+ if ($.fn.spectrum.load) {
+ $.fn.spectrum.processNativeColorInputs();
+ }
+ });
+
+});
diff --git a/site/modules/FieldtypeColor/x11color.txt b/site/modules/FieldtypeColor/x11color.txt
new file mode 100644
index 0000000..cb6df03
--- /dev/null
+++ b/site/modules/FieldtypeColor/x11color.txt
@@ -0,0 +1,143 @@
+indianred #CD5C5C 205,92,92
+lightcoral #F08080 240,128,128
+salmon #FA8072 250,128,114
+darksalmon #E9967A 233,150,122
+lightsalmon #FFA07A 255,160,122
+crimson #DC143C 220,20,60
+red #FF0000 255,0,0
+firebrick #B22222 178,34,34
+darkred #8B0000 139,0,0
+pink #FFC0CB 255,192,203
+lightpink #FFB6C1 255,182,193
+hotpink #FF69B4 255,105,180
+deeppink #FF1493 255,20,147
+mediumvioletred #C71585 199,21,133
+palevioletred #DB7093 219,112,147
+lightsalmon #FFA07A 255,160,122
+coral #FF7F50 255,127,80
+tomato #FF6347 255,99,71
+orangered #FF4500 255,69,0
+darkorange #FF8C00 255,140,0
+orange #FFA500 255,165,0
+gold #FFD700 255,215,0
+yellow #FFFF00 255,255,0
+lightyellow #FFFFE0 255,255,224
+lemonchiffon #FFFACD 255,250,205
+lightgoldenrodyellow #FAFAD2 250,250,210
+papayawhip #FFEFD5 255,239,213
+moccasin #FFE4B5 255,228,181
+peachpuff #FFDAB9 255,218,185
+palegoldenrod #EEE8AA 238,232,170
+khaki #F0E68C 240,230,140
+darkkhaki #BDB76B 189,183,107
+lavender #E6E6FA 230,230,250
+thistle #D8BFD8 216,191,216
+plum #DDA0DD 221,160,221
+violet #EE82EE 238,130,238
+orchid #DA70D6 218,112,214
+fuchsia #FF00FF 255,0,255
+magenta #FF00FF 255,0,255
+mediumorchid #BA55D3 186,85,211
+mediumpurple #9370DB 147,112,219
+blueviolet #8A2BE2 138,43,226
+darkviolet #9400D3 148,0,211
+darkorchid #9932CC 153,50,204
+darkmagenta #8B008B 139,0,139
+purple #800080 128,0,128
+indigo #4B0082 75,0,130
+slateblue #6A5ACD 106,90,205
+darkslateblue #483D8B 72,61,139
+mediumslateblue #7B68EE 123,104,238
+greenyellow #ADFF2F 173,255,47
+chartreuse #7FFF00 127,255,0
+lawngreen #7CFC00 124,252,0
+lime #00FF00 0,255,0
+limegreen #32CD32 50,205,50
+palegreen #98FB98 152,251,152
+lightgreen #90EE90 144,238,144
+mediumspringgreen #00FA9A 0,250,154
+springgreen #00FF7F 0,255,127
+mediumseagreen #3CB371 60,179,113
+seagreen #2E8B57 46,139,87
+forestgreen #228B22 34,139,34
+green #008000 0,128,0
+darkgreen #006400 0,100,0
+yellowgreen #9ACD32 154,205,50
+olivedrab #6B8E23 107,142,35
+olive #808000 128,128,0
+darkolivegreen #556B2F 85,107,47
+mediumaquamarine #66CDAA 102,205,170
+darkseagreen #8FBC8F 143,188,143
+lightseagreen #20B2AA 32,178,170
+darkcyan #008B8B 0,139,139
+teal #008080 0,128,128
+aqua #00FFFF 0,255,255
+cyan #00FFFF 0,255,255
+lightcyan #E0FFFF 224,255,255
+paleturquoise #AFEEEE 175,238,238
+aquamarine #7FFFD4 127,255,212
+turquoise #40E0D0 64,224,208
+mediumturquoise #48D1CC 72,209,204
+darkturquoise #00CED1 0,206,209
+cadetblue #5F9EA0 95,158,160
+steelblue #4682B4 70,130,180
+lightsteelblue #B0C4DE 176,196,222
+powderblue #B0E0E6 176,224,230
+lightblue #ADD8E6 173,216,230
+skyblue #87CEEB 135,206,235
+lightskyblue #87CEFA 135,206,250
+deepskyblue #00BFFF 0,191,255
+dodgerblue #1E90FF 30,144,255
+cornflowerblue #6495ED 100,149,237
+mediumslateblue #7B68EE 123,104,238
+royalblue #4169E1 65,105,225
+blue #0000FF 0,0,255
+mediumblue #0000CD 0,0,205
+darkblue #00008B 0,0,139
+navy #000080 0,0,128
+midnightblue #191970 25,25,112
+cornsilk #FFF8DC 255,248,220
+blanchedalmond #FFEBCD 255,235,205
+bisque #FFE4C4 255,228,196
+navajowhite #FFDEAD 255,222,173
+wheat #F5DEB3 245,222,179
+burlywood #DEB887 222,184,135
+tan #D2B48C 210,180,140
+rosybrown #BC8F8F 188,143,143
+sandybrown #F4A460 244,164,96
+goldenrod #DAA520 218,165,32
+darkgoldenrod #B8860B 184,134,11
+peru #CD853F 205,133,63
+chocolate #D2691E 210,105,30
+saddlebrown #8B4513 139,69,19
+sienna #A0522D 160,82,45
+brown #A52A2A 165,42,42
+maroon #800000 128,0,0
+white #FFFFFF 255,255,255
+snow #FFFAFA 255,250,250
+honeydew #F0FFF0 240,255,240
+mintcream #F5FFFA 245,255,250
+azure #F0FFFF 240,255,255
+aliceblue #F0F8FF 240,248,255
+ghostwhite #F8F8FF 248,248,255
+whitesmoke #F5F5F5 245,245,245
+seashell #FFF5EE 255,245,238
+beige #F5F5DC 245,245,220
+oldlace #FDF5E6 253,245,230
+floralwhite #FFFAF0 255,250,240
+ivory #FFFFF0 255,255,240
+antiquewhite #FAEBD7 250,235,215
+linen #FAF0E6 250,240,230
+lavenderblush #FFF0F5 255,240,245
+mistyrose #FFE4E1 255,228,225
+gainsboro #DCDCDC 220,220,220
+lightgrey #D3D3D3 211,211,211
+silver #C0C0C0 192,192,192
+darkgray #A9A9A9 169,169,169
+gray #808080 128,128,128
+dimgray #696969 105,105,105
+lightslategray #778899 119,136,153
+slategray #708090 112,128,144
+darkslategray #2F4F4F 47,79,79
+black #000000 0,0,0
+rebeccapurple #663399 102,51,153
\ No newline at end of file
diff --git a/site/templates/contacto.php b/site/templates/contacto.php
index e9bf2d8..a4b1aa6 100644
--- a/site/templates/contacto.php
+++ b/site/templates/contacto.php
@@ -15,7 +15,7 @@ else
$menu = renderMenu($inicio->children);
}
-if(isset($_POST['enviar']))
+if($input->post('enviar'))
{
$correo = wireMail();
$correo->to($configuracion['contacto_correo']);
@@ -49,6 +49,10 @@ if(isset($_POST['enviar']))
}
+else
+{
+ $contido .= 'No Enviado';
+}
$contido .= renderMigasPan($page) . "\n";
$contido .= '' . "\n";
diff --git a/site/templates/layout/func.php b/site/templates/layout/func.php
index 8c457ea..4c31ace 100644
--- a/site/templates/layout/func.php
+++ b/site/templates/layout/func.php
@@ -9,25 +9,24 @@ function getConfig($paxina)
{
$configuracion = array();
- foreach($paxina->configuracion as $config)
+ foreach($paxina->configuracion as $cfg)
{
- switch ($config->parametro_tipo->value)
+ switch ($cfg->parametro_tipo->value)
{
case 'texto':
- $configuracion[$config->parametro_nome] = $config->parametro_valor;
+ $configuracion[$cfg->parametro_nome] = $cfg->parametro_valor;
break;
case 'cor':
- list($r, $g, $b) = sscanf($config->parametro_cor, "%02x%02x%02x");
- $configuracion[$config->parametro_nome] = $r . ', ' . $g . ', ' . $b;
+ $configuracion[$cfg->parametro_nome] = $cfg->parametro_cor[0] . ", " . $cfg->parametro_cor[1] . ", " . $cfg->parametro_cor[2];
break;
case 'mantemento':
- if($config->parametro_mantemento==1)
+ if($cfg->parametro_mantemento==1)
{
$configuracion['mantemento'] = array(
'activo' => true,
- 'titular' => $config->titular,
- 'artigo' => $config->artigo,
- 'imaxe' => $config->imaxe
+ 'titular' => $cfg->titular,
+ 'artigo' => $cfg->artigo,
+ 'imaxe' => $cfg->imaxe
);
}
else
@@ -36,7 +35,7 @@ function getConfig($paxina)
}
break;
case 'logo':
- foreach($config->imaxes as $logo)
+ foreach($cfg->imaxes as $logo)
{
$configuracion['logo'][$logo->tags] = array(
'url' => $logo->url,