From 0b9c73d8f36057252b8d051747b882c73d6d3c8b Mon Sep 17 00:00:00 2001 From: Laegnur Date: Thu, 4 Apr 2024 14:38:16 +0200 Subject: [PATCH] Cambio do modulo de seleccion de cores. --- site/modules/.FieldtypeColor/.gitattributes | 4 + site/modules/.FieldtypeColor/.gitignore | 5 + .../.FieldtypeColor/FieldtypeColor.module | 336 +++ .../.FieldtypeColor/InputfieldColor.css | 9 + .../.FieldtypeColor/InputfieldColor.module | 354 +++ site/modules/.FieldtypeColor/README.md | 107 + site/modules/.FieldtypeColor/colornames.json | 143 + .../.FieldtypeColor/spectrum/spectrum.css | 507 ++++ .../.FieldtypeColor/spectrum/spectrum.js | 2341 +++++++++++++++++ site/modules/.FieldtypeColor/x11color.txt | 143 + .../ColorPicker/FieldtypeColorPicker.module | 135 - .../ColorPicker/InputfieldColorPicker.js | 96 - .../ColorPicker/InputfieldColorPicker.module | 93 - site/modules/ColorPicker/README.md | 101 - .../modules/ColorPicker/colorpicker/.DS_Store | Bin 6148 -> 0 bytes .../colorpicker/css/colorpicker.css | 164 -- .../ColorPicker/colorpicker/images/Thumbs.db | Bin 19968 -> 0 bytes .../ColorPicker/colorpicker/images/blank.gif | Bin 49 -> 0 bytes .../images/colorpicker_background.png | Bin 1897 -> 0 bytes .../colorpicker/images/colorpicker_hex.png | Bin 532 -> 0 bytes .../colorpicker/images/colorpicker_hsb_b.png | Bin 970 -> 0 bytes .../colorpicker/images/colorpicker_hsb_h.png | Bin 1012 -> 0 bytes .../colorpicker/images/colorpicker_hsb_s.png | Bin 1171 -> 0 bytes .../colorpicker/images/colorpicker_indic.gif | Bin 86 -> 0 bytes .../images/colorpicker_overlay.png | Bin 10355 -> 0 bytes .../colorpicker/images/colorpicker_rgb_b.png | Bin 970 -> 0 bytes .../colorpicker/images/colorpicker_rgb_g.png | Bin 1069 -> 0 bytes .../colorpicker/images/colorpicker_rgb_r.png | Bin 1066 -> 0 bytes .../colorpicker/images/colorpicker_select.gif | Bin 78 -> 0 bytes .../colorpicker/images/colorpicker_submit.png | Bin 984 -> 0 bytes .../colorpicker/images/custom_background.png | Bin 1916 -> 0 bytes .../colorpicker/images/custom_hex.png | Bin 562 -> 0 bytes .../colorpicker/images/custom_hsb_b.png | Bin 1097 -> 0 bytes .../colorpicker/images/custom_hsb_h.png | Bin 970 -> 0 bytes .../colorpicker/images/custom_hsb_s.png | Bin 1168 -> 0 bytes .../colorpicker/images/custom_indic.gif | Bin 86 -> 0 bytes .../colorpicker/images/custom_rgb_b.png | Bin 1008 -> 0 bytes .../colorpicker/images/custom_rgb_g.png | Bin 1069 -> 0 bytes .../colorpicker/images/custom_rgb_r.png | Bin 1018 -> 0 bytes .../colorpicker/images/custom_submit.png | Bin 997 -> 0 bytes .../ColorPicker/colorpicker/images/select.png | Bin 506 -> 0 bytes .../colorpicker/images/select2.png | Bin 518 -> 0 bytes .../ColorPicker/colorpicker/images/slider.png | Bin 315 -> 0 bytes .../ColorPicker/colorpicker/js/colorpicker.js | 484 ---- .../colorpicker/js/colorpicker.min.js | 24 - .../modules/ColorPicker/colorpicker/js/eye.js | 34 - .../ColorPicker/colorpicker/js/layout.js | 67 - .../ColorPicker/colorpicker/js/utils.js | 252 -- site/modules/ColorPicker/pw-colorpicker.jpg | Bin 94759 -> 0 bytes site/modules/ColorPicker/transparent.gif | Bin 72 -> 0 bytes site/modules/FieldtypeColor/.gitattributes | 4 + site/modules/FieldtypeColor/.gitignore | 5 + .../FieldtypeColor/FieldtypeColor.module | 342 +++ .../FieldtypeColor/InputfieldColor.css | 9 + .../FieldtypeColor/InputfieldColor.module | 355 +++ site/modules/FieldtypeColor/README.md | 107 + site/modules/FieldtypeColor/colornames.json | 143 + .../FieldtypeColor/spectrum/spectrum.css | 507 ++++ .../FieldtypeColor/spectrum/spectrum.js | 2341 +++++++++++++++++ site/modules/FieldtypeColor/x11color.txt | 143 + site/templates/contacto.php | 6 +- site/templates/layout/func.php | 19 +- 62 files changed, 7919 insertions(+), 1461 deletions(-) create mode 100644 site/modules/.FieldtypeColor/.gitattributes create mode 100644 site/modules/.FieldtypeColor/.gitignore create mode 100644 site/modules/.FieldtypeColor/FieldtypeColor.module create mode 100644 site/modules/.FieldtypeColor/InputfieldColor.css create mode 100644 site/modules/.FieldtypeColor/InputfieldColor.module create mode 100644 site/modules/.FieldtypeColor/README.md create mode 100644 site/modules/.FieldtypeColor/colornames.json create mode 100644 site/modules/.FieldtypeColor/spectrum/spectrum.css create mode 100644 site/modules/.FieldtypeColor/spectrum/spectrum.js create mode 100644 site/modules/.FieldtypeColor/x11color.txt delete mode 100644 site/modules/ColorPicker/FieldtypeColorPicker.module delete mode 100644 site/modules/ColorPicker/InputfieldColorPicker.js delete mode 100644 site/modules/ColorPicker/InputfieldColorPicker.module delete mode 100644 site/modules/ColorPicker/README.md delete mode 100644 site/modules/ColorPicker/colorpicker/.DS_Store delete mode 100644 site/modules/ColorPicker/colorpicker/css/colorpicker.css delete mode 100644 site/modules/ColorPicker/colorpicker/images/Thumbs.db delete mode 100644 site/modules/ColorPicker/colorpicker/images/blank.gif delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_background.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_hex.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_b.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_h.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_s.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_indic.gif delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_overlay.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_b.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_g.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_r.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_select.gif delete mode 100644 site/modules/ColorPicker/colorpicker/images/colorpicker_submit.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_background.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_hex.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_hsb_b.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_hsb_h.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_hsb_s.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_indic.gif delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_rgb_b.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_rgb_g.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_rgb_r.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/custom_submit.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/select.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/select2.png delete mode 100644 site/modules/ColorPicker/colorpicker/images/slider.png delete mode 100644 site/modules/ColorPicker/colorpicker/js/colorpicker.js delete mode 100644 site/modules/ColorPicker/colorpicker/js/colorpicker.min.js delete mode 100644 site/modules/ColorPicker/colorpicker/js/eye.js delete mode 100644 site/modules/ColorPicker/colorpicker/js/layout.js delete mode 100644 site/modules/ColorPicker/colorpicker/js/utils.js delete mode 100644 site/modules/ColorPicker/pw-colorpicker.jpg delete mode 100644 site/modules/ColorPicker/transparent.gif create mode 100644 site/modules/FieldtypeColor/.gitattributes create mode 100644 site/modules/FieldtypeColor/.gitignore create mode 100644 site/modules/FieldtypeColor/FieldtypeColor.module create mode 100644 site/modules/FieldtypeColor/InputfieldColor.css create mode 100644 site/modules/FieldtypeColor/InputfieldColor.module create mode 100644 site/modules/FieldtypeColor/README.md create mode 100644 site/modules/FieldtypeColor/colornames.json create mode 100644 site/modules/FieldtypeColor/spectrum/spectrum.css create mode 100644 site/modules/FieldtypeColor/spectrum/spectrum.js create mode 100644 site/modules/FieldtypeColor/x11color.txt diff --git a/site/modules/.FieldtypeColor/.gitattributes b/site/modules/.FieldtypeColor/.gitattributes new file mode 100644 index 0000000..ab85459 --- /dev/null +++ b/site/modules/.FieldtypeColor/.gitattributes @@ -0,0 +1,4 @@ +# Auto detect text files and perform LF normalization +* text=auto +# Show correct language for ProcessWire .module +*.module linguist-language=PHP diff --git a/site/modules/.FieldtypeColor/.gitignore b/site/modules/.FieldtypeColor/.gitignore new file mode 100644 index 0000000..a866f03 --- /dev/null +++ b/site/modules/.FieldtypeColor/.gitignore @@ -0,0 +1,5 @@ +dematte/* +jscolor-2.0.4/* +colorpicker/* +InputfieldColor.js +.DS_Store diff --git a/site/modules/.FieldtypeColor/FieldtypeColor.module b/site/modules/.FieldtypeColor/FieldtypeColor.module new file mode 100644 index 0000000..4102c45 --- /dev/null +++ b/site/modules/.FieldtypeColor/FieldtypeColor.module @@ -0,0 +1,336 @@ + 'Color', + 'version' => 118, + 'summary' => 'Field that stores a color value as 32bit integer reflecting a RGBA value. Many options for Input (HTML5 Inputfield Color, Textfield with changing background, various jQuery/JS ColorPickers, custom jQuery/JS/CSS) and Output (RGB, RGBA, HSL, HSLA, HEX, Array).', + 'installs' => 'InputfieldColor', + 'href' => 'https://processwire.com/talk/topic/16679-fieldtypecolor/' + ); + } + + public function ___getCompatibleFieldtypes(Field $field) { + $fieldtypes = $this->wire(new Fieldtypes()); + foreach($this->wire('fieldtypes') as $fieldtype) { + if(!$fieldtype instanceof FieldtypeInteger && + !$fieldtype instanceof FieldtypeColor && + $fieldtype != 'FieldtypeText') { + $fieldtypes->remove($fieldtype); + } + } + return $fieldtypes; + } + + public function getInputfield(Page $page, Field $field) { + $inputfield = $this->modules->get('InputfieldColor'); + $inputfield->initValue = $this->sanitizeValue($page, $field, $field->defaultValue); + $inputfield->class = $this->className(); + return $inputfield; + } + + public function sanitizeValue(Page $page, Field $field, $value) { + if (!$value) return $value; + $value = ltrim($value, '#'); + if (strlen($value) == 8) return $value; + else if (strlen($value) == 6) return 'ff'.$value; // add alpha channel + else throw New WireException('Expecting Hex color string (length 6 or 8 digits) with optional leading \'#\''); + + } + + public function sleepValue(Page $page, Field $field, $value) { + return hexdec($value); + } + + public function wakeupValue(Page $page, Field $field, $value) { + if (!$value) return $value; + if (function_exists("bcmod")) return str_pad(self::bcdechex($value), 8, '0', STR_PAD_LEFT); // BCMath extension required + return str_pad(dechex($value), 8, '0', STR_PAD_LEFT); // 64-bit system required + } + + /** + * Converts a number from decimal to hex (BCMath extension required) + * returns precice result even if number is bigger than PHP_INT_MAX (safe for 32bit systems) + * + * @param int/string/float number + * @return string + * + * @see http://php.net/manual/en/ref.bc.php#99130 + */ + public static function bcdechex($dec) { + $last = bcmod("$dec", 16); + $remain = bcdiv(bcsub("$dec", $last), 16); + if($remain == 0) return dechex($last); + else return self::bcdechex($remain).dechex($last); + } + + /** + * Converts a RGB color value to HSL. Conversion formula + * @param array of 3 color values R, G, and B [0, 255] + * @return array The HSL representation + * + * @see https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion/9493060#9493060 + * @see http://en.wikipedia.org/wiki/HSL_color_space + */ + public function RGB2HSL(array $rgb) { + $rgb = array_map(function($v) { return $v/ 255; }, $rgb); + $max = max($rgb); + $min = min($rgb); + $hue = $sat = $light = ($max + $min) / 2; + + if($max == $min) { + $hue = $sat = 0; // achromatic + } else { + $d = $max - $min; + $sat = $light > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min); + switch($max) { + case $rgb[0]: + $hue = ($rgb[1] - $rgb[2]) / $d + ($rgb[1] < $rgb[1] ? 6 : 0); + break; + case $rgb[1]: + $hue = ($rgb[2] - $rgb[0]) / $d + 2; + break; + case $rgb[2]: + $hue = ($rgb[0] - $rgb[1]) / $d + 4; + break; + } + $hue = $hue / 6; + } + // round and convert float to string with dot as decimal separator in any language + $hue = str_replace(',', '.', round($hue * 360)); + $sat = str_replace(',', '.', round($sat * 100, 1)); + $light = str_replace(',', '.', round($light * 100, 1)); + + return [$hue, $sat, $light]; + } + + /** + * Find the "naive" difference between two colors. + * @see https://php.tutorialink.com/finding-nearest-match-rgb-color-from-array-of-colors/ + * @param int[] $color_a Three-element array with R,G,B color values 0-255. + * @param int[] $color_b Three-element array with R,G,B color values 0-255. + * @return int + */ + public function getColorDistance(array $color_a, array $color_b): int { + return + abs($color_a[0] - $color_b[0]) + + abs($color_a[1] - $color_b[1]) + + abs($color_a[2] - $color_b[2]); + } + + /** + * Find the difference between two colors' luminance values. + * @see https://php.tutorialink.com/finding-nearest-match-rgb-color-from-array-of-colors/ + * @param int[] $color_a Three-element array with R,G,B color values 0-255. + * @param int[] $color_b Three-element array with R,G,B color values 0-255. + * @return int + */ + public function getLuminanceDistance(array $color_a, array $color_b): int { + $luminance_f = function ($red, $green, $blue): int { + // Source: https://en.wikipedia.org/wiki/Relative_luminance + $luminance = (int) (0.2126 * $red + 0.7152 * $green + 0.0722 * $blue); + return $luminance; + }; + + return abs( + $luminance_f($color_a[0], $color_a[1], $color_a[2]) - + $luminance_f($color_b[0], $color_b[1], $color_b[2]) + ); + } + + /** + * Find the closest named color + * @param hexcolor + * @return string + */ + public function getClosestColorName(string $color) { + $color = ltrim($color, '#'); + if (strlen($color) == 6) $color = "ff$color"; + if (strlen($color) != 8) throw new WireException("Invalid parameter. Expected hex string of 6 or 8 digits length with or without leading '#'."); + $color = $this->formatColorString($color, 9); + $palette = json_decode(file_get_contents(__DIR__ . '/colornames.json'), true); + $min = 765; + $match = null; + foreach ($palette as $name => $pcolor) { + $pcolor = $this->formatColorString("ff$pcolor", 9); + if ($pcolor === $color) return $name; // quick exit if full match + $distance = $this->getColorDistance($pcolor, $color); + if ($distance >= $min) continue; + $min = $distance; + $match = $name; + } + return $match; + } + + /** + * Format value for output + * + */ + public function ___formatValue(Page $page, Field $field, $value) { + if (!$value) return null; + if ($field->outputFormat === 7) return $this->sleepValue($page, $field, $value); + return $this->formatColorString($value, $field->outputFormat); + } + + /** + * Format color string + * + * @param $value string - hex string of 8 chiffres, first 2 is the alpha channel + * @param $of int - output format + * @return string formatted color string + * @throws object WireException - if input doesn't match (check for length, detailed check in debug mode) + * + */ + public function formatColorString($value, $of = 0) { + + // simple length check or preg_match in debug mode + if (strlen($value) != 8 || ($this->wire('config')->debug && !preg_match('/[A-Fa-f0-9]{8}/', $value))) { + throw new WireException("Invalid input: $value. Expected hex string of 8 digits length."); + } + + if ($of === 6) return $value; + if ($of === 0) return "#".substr($value,2); + if ($of === 1) return "#".$value; + + $hexVals = str_split($value, 2); + $value = array_map('hexdec', $hexVals); + + // opacity + $opacity = '0'; + if ($value[0] > 1 && in_array($of ,array(3,5,8,10,12))) { + $opacity = round($value[0] / 255, 2); // float + $opacity = rtrim(number_format($opacity, 2, '.', ''),'.0'); // convert float to string with dot as decimal separator + } + + if ($of === 9) return [$value[1], $value[2], $value[3]]; + if ($of === 10) return [$value[1], $value[2], $value[3], $opacity]; + + if ($of === 8) { + $assocArray = array( + 'o' => $opacity, + 'r' => $value[1], + 'g' => $value[2], + 'b' => $value[3], + 'ox' => $hexVals[0], + 'rx' => $hexVals[1], + 'gx' => $hexVals[2], + 'bx' => $hexVals[3], + ); + return array_merge($value, $assocArray); + } + + if ($of === 2) return "rgb($value[1], $value[2], $value[3])"; + if ($of === 3) return "rgba($value[1], $value[2], $value[3], $opacity)"; + + $hsl = $this->RGB2HSL(array_slice($value,1,3)); + + if ($of === 11) return $hsl; + + if ($of === 12) { + $hsla = $hsl; + $hsla[] = $opacity; + return $hsla; + } + + if ($of === 4) return "hsl($hsl[0], $hsl[1]%, $hsl[2]%)"; + if ($of === 5) return "hsla($hsl[0], $hsl[1]%, $hsl[2]%, $opacity)"; + } + + public function getDatabaseSchema(Field $field) { + $schema = parent::getDatabaseSchema($field); + $schema['data'] = "int UNSIGNED NOT NULL"; + return $schema; + } + + public function ___getConfigInputfields(Field $field) { + + $inputfields = $this->wire(new InputfieldWrapper()); + + $f = $this->wire('modules')->get('InputfieldRadios'); + $f->attr('name', 'outputFormat'); + $f->label = $this->_('Output Format'); + $f->description = $this->_('Choose your preferred output format.'); + + $f->addOption(0, $this->_('string 6-digit hex color *#4496dd*')); + $f->addOption(1, $this->_('string 8-digit hex color *#fa4496dd* (limited browser support)')); + $f->addOption(2, $this->_('string *rgb(68, 100, 221)*')); + $f->addOption(3, $this->_('string *rgba(68, 100, 221, 0.98)*')); + $f->addOption(4, $this->_('string *hsl(227, 69.2%, 56.7%)*')); + $f->addOption(5, $this->_('string *hsla(227, 69.2%, 56.7%, 0.98)*')); + $f->addOption(6, $this->_('string 8-digit raw hex *fa4496dd* (unformatted)')); + $f->addOption(7, $this->_('int 32bit (storage)')); + $f->addOption(8, $this->_('array(r[0,255], g[0,255], b[0,255], o[0,1], rx[00,ff], gx[00,ff], bx[00,ff], ox[00,ff])')); + $f->addOption(9, $this->_('array([0,255], [0,255], [0,255]) indexed array: R,G,B')); + $f->addOption(10, $this->_('array([0,255], [0,255], [0,255], [0,1]) indexed array: R,G,B,Alpha')); + $f->addOption(11, $this->_('array([0,360], [69.2%], [56.7%]) indexed array: H,S,L')); + $f->addOption(12, $this->_('array([0,360], [69.2%], [56.7%], [0,1]) indexed array: H,S,L,Alpha')); + + $f->attr('value', (int) $field->outputFormat); + $inputfields->add($f); + + $f = $this->wire('modules')->get('InputfieldColor'); + $f->attr('name', 'defaultValue'); + $f->label = $this->_('Default value'); + + $f->inputType = $field->inputType; + $f->spectrum = $field->spectrum; + $f->initJS = $field->initJS; + $f->fileJS = $field->fileJS; + $f->fileCSS = $field->fileCSS; + $f->jqueryCore = $field->jqueryCore; + $f->jqueryUI = $field->jqueryUI; + $f->alpha = $field->alpha; + + $f->description = $this->_('This value is assigned as the default for blank fields and on newly created pages.'); + $f->collapsed = Inputfield::collapsedBlank; + $f->attr('value', strlen($field->defaultValue) ? $this->sanitizeValue($this->wire('page'), $field, $field->defaultValue) : null); + + $inputfields->add($f); + + return $inputfields; + } + + public function ___install() { + if (function_exists("bcmod") === false && PHP_INT_SIZE < 8) { + throw new WireException($this->_('The BCMath extension is required if your system can not handle 64-bit integer values.')); + } + parent::___install(); + } +} \ No newline at end of file diff --git a/site/modules/.FieldtypeColor/InputfieldColor.css b/site/modules/.FieldtypeColor/InputfieldColor.css new file mode 100644 index 0000000..b0e7da5 --- /dev/null +++ b/site/modules/.FieldtypeColor/InputfieldColor.css @@ -0,0 +1,9 @@ +.InputfieldColor input[type=color], input[type=color].FieldtypeColor, input[type=color]#Inputfield_defaultValue { + height:2em; + padding:0; +} + +.AdminThemeUikit .InputfieldColor input[type=color], .AdminThemeUikit input[type=color].FieldtypeColor, .AdminThemeUikit input[type=color]#Inputfield_defaultValue { + height:40px; + width: 100% !important; +} \ No newline at end of file diff --git a/site/modules/.FieldtypeColor/InputfieldColor.module b/site/modules/.FieldtypeColor/InputfieldColor.module new file mode 100644 index 0000000..3e3efc1 --- /dev/null +++ b/site/modules/.FieldtypeColor/InputfieldColor.module @@ -0,0 +1,354 @@ + __('Color', __FILE__), // Module Title + 'summary' => __('Inputfield for colors', __FILE__), // Module Summary + 'version' => 116, + 'href' => 'https://processwire.com/talk/topic/16679-fieldtypecolor/' + ); + } + + /** + * Construct + * + * @throws WireException + * + */ + public function __construct() { + parent::__construct(); + $this->set('icon', 'paint-brush'); + $this->setAttribute('type', 'text'); + $this->setAttribute('size', 10); + $this->setAttribute('placeholder', '#000000'); + $this->setAttribute('pattern', '(#?[a-fA-F\d]{6})?'); + } + + public function init() { + $this->inputType = 0; + $this->spectrum = ''; + $this->initJS = ''; + $this->fileJS = ''; + $this->fileCSS = ''; + $this->jqueryCore = 0; + $this->jqueryUI = 0; + $this->alpha = 0; // int 0, 1 will be set dependend on inputType. To disable explicitly for inputType = 3 (spectrum color picker) set bool false + parent::init(); + } + + /** + * Called before the render method + * checking for SpectrumColorPicker + * + * @param Inputfield $parent + * @param bool $renderValueMode + * @return $this + * + */ + public function renderReady(Inputfield $parent = null, $renderValueMode = false) { + $url = $this->config->urls->get('InputfieldColor'); + switch ($this->inputType) { + case 3: + $this->wire('modules')->get('JqueryCore'); + $this->config->scripts->add($url . 'spectrum/spectrum.js'); + $this->config->styles->add($url . 'spectrum/spectrum.css'); + break; + case 4: + if ($this->jqueryCore) $this->wire('modules')->get('JqueryCore'); + if ($this->jqueryUI) $this->wire('modules')->get('JqueryUI'); + if ($this->fileJS) $this->config->scripts->add($url . $this->fileJS); + if ($this->fileCSS) $this->config->styles->add($url . $this->fileCSS); + break; + } + parent::renderReady($parent, $renderValueMode); + } + + /** + * get textcolor (light or dark) corresponding to the background for better contrast + * + * @param int/string $bgColor expecting string or int with 6 (24bit) or 8 (32bit) digits with or without leading '#' + * @param int/string $textColorLight default: '#fff' (white) + * @param int/string $textColorDark default: '#000' (black) + * @return string $color light or dark + * + */ + public function getTextColor($bgColor, $textColorLight = '#fff', $textColorDark = '#000') { + if (!is_string($bgColor)) return $textColorDark; + else if (!ctype_xdigit(ltrim($bgColor, '#'))) { + $bgColor = $this->convertColorName($bgColor); + if (false === $bgColor) return $textColorDark; + } + $bgColor = ltrim($bgColor, '#'); + $bgColor = str_pad($bgColor,8,'f',STR_PAD_LEFT); + $ARGB = array_map('hexdec', str_split($bgColor, 2)); + $opacity = round($ARGB[0] / 255, 2); + if ($opacity < 0.45) return $textColorDark; + return ($ARGB[1]+6*$ARGB[2]+$ARGB[3])*3/8 > 460? $textColorDark : $textColorLight; + } + + /** + * convert color name (hex -> html, html -> hex) + * + * @param $color + * @param $to convert to 'hex' or 'html' + * @return bool/ string + * + */ + public function convertColorName($color, $to = 'hex') { + $colorArray = $this->getX11ColorArray(); + if ($to = 'hex') { + $key = array_search($color, array_column($colorArray, 0)); + return empty($colorArray[$key][1])? false : $colorArray[$key][1]; + } + else if ($to = 'html') { + $key = array_search($color, array_column($colorArray, 1)); + return empty($colorArray[$key][0])? false : $colorArray[$key][0]; + } + return false; + } + + /** + * get multiple array with html color names and corresponding hex codes and rgb values + * + * @param $domain + * @param $path file path + * @return boolean + * + */ + protected function getX11ColorArray() { + $path = __DIR__ .'/x11color.txt'; + if (!file_exists($path)) throw new WireException("Missing file " . $path); + $array = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + if ($array === false) throw new WireException("Failed to open file: $path"); + return array_map(function($e) { + return explode("\t", $e); + }, $array); + } + + public function ___render() { + if ($this->value === "" && strlen($this->initValue)) $this->value = $this->initValue; + if (!$this->value) $this->value = null; + + if ($this->value) { + $this->value = str_pad(ltrim($this->value, '#'),8,'f',STR_PAD_LEFT); + $color32 = "#".$this->value; + $color24 = $bgColor = "#".substr($this->value,2,6); + $value = array_map('hexdec', str_split($this->value, 2)); + } else { + $color32 = $color24 = null; + $value = array(255,255,255,255); + $bgColor = '#fff'; + } + + $opacity = round($value[0] / 255, 2); + $opacity = $opacity? rtrim(number_format($opacity, 2, '.', ''),'.0') : '0'; + + $textColor = $this->getTextColor($this->value); + $rgba = "rgba($value[1], $value[2], $value[3], $opacity)"; + $this->attr('value', $color24); + $this->attr('data-input-type', $this->inputType); + + switch ($this->inputType) { + case 0: + $this->attr('type', 'color'); + break; + case 1: + $this->attr('style', "color: $textColor; background: $bgColor;"); + break; + case 2: + $this->alpha = 1; + $this->attr('value', $color32); + $this->attr('style', "color: $textColor; background: $bgColor; background-image: linear-gradient($rgba, $rgba), url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==');"); + $this->attr('placeholder', '#ff000000'); + $this->attr('pattern', '(#?[a-fA-F\d]{8})?'); + break; + case 3: + if ($this->alpha !== false) $this->alpha = 1; + if (!$color32) $color32 = '#00000000'; + $this->attr('value', $color32); + $this->attr('placeholder', '#ff000000'); + $this->removeAttr('pattern'); + break; + case 4: + if ($this->alpha) $this->attr('value', $color32); + else $this->attr('value', $color24); + } + + $attrs = $this->getAttributes(); + + $out = "getAttributesString($attrs) . " />"; + if( $this->inputType == 3) { + $options = $this->spectrum? str_replace(array(",\n","\n"),", ", trim($this->spectrum,",\t\n\r\0\x0B")).',' : ''; + $value = $color32? $color32 : null; + $format = $this->alpha? 'toHex8String' : 'toHexString'; + $out .= " + "; + } + if( $this->inputType == 4) { + $value = $color32? $color32 : null; + if ($this->initJS) { + $initJS = str_replace(array("{value}","{id}"), array($color24, $this->id), $this->initJS); + $out .= " + "; + } + } + return $out; + } + + public function ___processInput(WireInputData $input) { + parent::___processInput($input); + $value = $this->attr('value'); + if (!$value) return $this; + // bugfix (workaround): something went wrong in javascript spectrum + if (is_string($value) && in_array($value, ['hsva(0, 0%, 0%, 0)','hsla(0, 0%, 0%, 0)','rgba(0, 0, 0, 0)'])) { + $this->attr('value', '00000000'); + return $this; + } + $pattern = $this->alpha? '/#?[a-fA-F\d]{8}/' : '/#?[a-fA-F\d]{6}/'; + if(!preg_match($pattern, $value)) $this->error("Submitted value: $value does not match required pattern: $pattern."); + return $this; + + } + + public function getConfigInputfields() { + $inputfields = parent::getConfigInputfields(); + + $f = $this->wire('modules')->get('InputfieldRadios'); + $f->attr('name', 'inputType'); + $f->label = $this->_('Inputfieldtype'); + $f->addOption(0, $this->_('Inputfield type=\'color\' (HTML5 - limited browser support)')); + $f->addOption(1, $this->_('Inputfield type=\'text\' expects 24bit hexcode strings')); + $f->addOption(2, $this->_('Inputfield type=\'text\' expects 32bit hexcode strings (alpha channel)')); + $f->addOption(3, $this->_('Inputfield with Spectrum Color Picker (JavaScript)')); + $f->addOption(4, $this->_('Inputfield type=\'text\' with custom JavaScript and/or CSS')); + $f->attr('value', $this->inputType); + $f->description = $this->_(''); + $f->columnWidth = 50; + $inputfields->add($f); + + $f = $this->wire('modules')->get('InputfieldTextarea'); + $f->attr('name', 'spectrum'); + $f->attr('rows', 10); + $f->label = $this->_('Color Picker Options'); + $f->attr('value', $this->spectrum); + $f->description = $this->_('Set or modify options for the **Spectrum Color Picker**. [Read more ...](https://bgrins.github.io/spectrum/#options)'); + $f->notes = $this->_("One option per line in the format: 'option: value'. The options: 'color' and 'change' are used by the system and not modifiable."); + $f->columnWidth = 50; + $f->showIf = "inputType=3"; + $inputfields->add($f); + + $f = $this->wire('modules')->get('InputfieldTextarea'); + $f->attr('name', 'initJS'); + $f->attr('rows', 3); + $f->label = $this->_('Initial JS'); + $f->attr('value', $this->initJS); + $f->description = $this->_('JavaScript code initiating your custom JS color picker. Use {id} and {value} as placeholders for the related field attributes in your selector'); + $f->notes = sprintf($this->_('{id} will be replaced by the string "%s"'), $this->id); + $f->columnWidth = 33; + $f->showIf = "inputType=4"; + $f->requiredIf = "inputType=4"; + $inputfields->add($f); + + $rootUrl = $this->config->urls->get('InputfieldColor'); + + $f = $this->wire('modules')->get('InputfieldURL'); + $f->attr('name', 'fileJS'); + $f->label = $this->_('Include JS File'); + $f->attr('value', $this->fileJS); + $f->description = $this->_('Set the path to your custom JavaScript file.'); + $f->notes = sprintf($this->_('URL string relative to "%s"'), $rootUrl); + $f->columnWidth = 34; + $f->showIf = "inputType=4"; + $f->requiredIf = "inputType=4"; + $inputfields->add($f); + + $f = $this->wire('modules')->get('InputfieldURL'); + $f->attr('name', 'fileCSS'); + $f->label = $this->_('Include CSS File'); + $f->attr('value', $this->fileCSS); + $f->description = $this->_('Set the path to your custom stylesheet file.'); + $f->notes = sprintf($this->_('URL string relative to "%s"'), $rootUrl); + $f->columnWidth = 33; + $f->showIf = "inputType=4"; + $f->requiredIf = "inputType=4"; + $inputfields->add($f); + + $f = $this->modules->get('InputfieldCheckbox'); + $f->attr('name', 'jqueryCore'); + $f->label = __('Enable JqueryCore'); + $f->attr('checked', $this->jqueryCore ? 'checked' : '' ); + $f->columnWidth = 33; + $f->showIf = "inputType=4"; + $inputfields->append($f); + + $f = $this->modules->get('InputfieldCheckbox'); + $f->attr('name', 'jqueryUI'); + $f->label = __('Enable JqueryUI'); + $f->attr('checked', $this->jqueryUI ? 'checked' : '' ); + $f->columnWidth = 34; + $f->showIf = "inputType=4"; + $inputfields->append($f); + + $f = $this->modules->get('InputfieldRadios'); + $f->attr('name', 'alpha'); + $f->addOption(0, $this->_('6 digits "#ff0000"')); + $f->addOption(1, $this->_('8 digits "#ffff0000" (leading alpha channel)')); + $f->label = __('Select value type'); + $f->attr('value', $this->alpha); + $f->columnWidth = 33; + $f->showIf = "inputType=4"; + $inputfields->append($f); + + return $inputfields; + } +} diff --git a/site/modules/.FieldtypeColor/README.md b/site/modules/.FieldtypeColor/README.md new file mode 100644 index 0000000..42f438a --- /dev/null +++ b/site/modules/.FieldtypeColor/README.md @@ -0,0 +1,107 @@ +FieldtypeColor +============== + +## Fieldtype/Inputfield for ProcessWire 3.0 + +Field that stores colors. Many options for Input (HTML5 Inputfield Color, Textfield with changing background, various jQuery/JS ColorPickers, custom jQuery/JS/CSS) and Output (RGB, RGBA, HSL, HSLA, HEX). Package includes Fieldtype Color Select. + +## Inputfield +Select between **5 types of Inputfields** + ++ Html5 Inputfield of type='color' (if supported by browser) ++ Inputfield type='text' expecting a 24bit hexcode string (RGB). Input format: *'#4496dd'* +The background color of the input fields shows selected color ++ Inputfield of type='text' expecting 32bit hexcode strings (RGB + alpha channel) Input format: *'#fa4496dd'* ++ Inputfield with **Spectrum Color Picker** (JavaScript) +Options modifiable ++ Inputfield type='text' with **custom JavaScript** and/or CSS + + +## Output + +Define output format under **Details** - Tab in field settings. Select from the following options: + ++ *string* 6-digit hex color. Example: **'#4496dd'** ++ *string* 8-digit hex color with leading Alpha channel (limited browser support). Example: **'#fa4496dd'** ++ *string* CSS color value **RGB**. Example: **'rgb(68, 100, 221)'** ++ *string* CSS color value **RGBA**. Example: **'rgba(68, 100, 221, 0.98)'** ++ *string* CSS color value **HSL**. Example: **'hsl(227, 69.2%, 56.7%)'** ++ *string* CSS color value **HSLA**. Example: **'hsla(227, 69.2%, 56.7%, 0.98)'** ++ *string* 32bit raw hex value. Example: **'fa4496dd'** (unformatted output value) ++ *int 32bit*. Example: **'4198799069'** (storage value) ++ *array(R,G,B)* ++ *array(R,G,B,Alpha)* ++ *array(H,S,L)* ++ *array(H,S,L,Alpha)* + + +``` + array( + [0] => 0-255, // opacity + [1],['r'] => 0-255, + [2],['g'] => 0-255, + [3],['b'] => 0-255, + ['rx'] => 00-ff, + ['gx'] => 00-ff, + ['bx'] => 00-ff, + ['ox'] => 00-ff, // opacity + ['o'] => 0-1 // opacity + ) +``` + + +## Templates & API +You can always modify values or output format via ProcessWire API. + +**Modify output format** + +``` +$f = $page->fields->get('myColorField'); +$f->outputFormat = 8; +echo $page->color['rx']; +``` + +**Modify values** + ++ Delete the page field value by setting empty string or *NULL*. ++ The values (int) 0, (string) '0', '00000000' and '#00000000' are similar and stored as (int) 0 (black, full transparent). + +``` +$page->of(false); +$page->myColorField = 'ff0000'; // red +$page->save('myColorField'); +``` + +## Notes +**Deleting values** is only possible with inputfields of type='text' and via API. + +If a **default value** is set, the field is filled with it if the field is empty (for example on newly created pages). +If Inputfield of type='text' 32bit is selected you can set the value to '#00000000' and the default value will be ignored. + +The Fieldtype includes +[**Spectrum Color Picker** by Brian Grinstead](https://github.com/bgrins/spectrum) + +Any custom Javascript based Inputfield can be used. + +If the **Inputfield** is **used as is** e.g. for Module Settings, the following properties are provided: + +``` +$f->wire('modules')->get('InputfieldColor); +$f->inputType = 0; // int 0 - 4 +$f->alpha = 0; // int 0 or 1, will be set automatically dependend on inputType. To disable explicitly for inputType = 3 (spectrum color picker) set to bool false +$f->spectrum = ''; // options for spectrum Color Picker if inputType = 3 @see https://bgrins.github.io/spectrum/ + +// properties for inputType = 4 only +$f->initJS = ''; // initial JS +$f->fileJS = ''; // path to JS file +$f->fileCSS = ''; // path to CSS file +$f->jqueryCore = 0; // enable jqueryCore +$f->jqueryUI = 0; // enable jqueryUI +``` + +--- + +Fieldtype Select Color Options +============================== + +This fieldtype is included in the package. The module is an extension of the Core **FieldtypeOptions** module and offers colors as predefined selectable options via 4 different input field types (Select, SelectMultiple, Checkboxes and Radios). diff --git a/site/modules/.FieldtypeColor/colornames.json b/site/modules/.FieldtypeColor/colornames.json new file mode 100644 index 0000000..5df7793 --- /dev/null +++ b/site/modules/.FieldtypeColor/colornames.json @@ -0,0 +1,143 @@ +{ + "AliceBlue": "f0f8ff", + "AntiqueWhite": "faebd7", + "Aqua": "00ffff", + "AquaMarine": "7fffd4", + "Azure": "f0ffff", + "Beige": "f5f5dc", + "Bisque": "ffe4c4", + "Black": "000000", + "BlanchedAlmond": "ffebcd", + "Blue": "0000ff", + "BlueViolet": "8a2be2", + "Brown": "a52a2a", + "BurlyWood": "deb887", + "CadetBlue": "5f9ea0", + "Chartreuse": "7fff00", + "Chocolate": "d2691e", + "Coral": "ff7f50", + "CornFlowerBlue": "6495ed", + "Cornsilk": "fff8dc", + "Crimson": "dc143c", + "Cyan": "00ffff", + "DarkBlue": "00008b", + "DarkCyan": "008b8b", + "DarkGoldenRod": "b8860b", + "DarkGray": "a9a9a9", + "DarkGreen": "006400", + "DarkKhaki": "bdb76b", + "DarkMagenta": "8b008b", + "DarkOliveGreen": "556b2f", + "DarkOrange": "ff8c00", + "DarkOrchid": "9932cc", + "DarkRed": "8b0000", + "DarkSalmon": "e9967a", + "DarkSeaGreen": "8fbc8f", + "DarkSlateBlue": "483d8b", + "DarkSlateGray": "2f4f4f", + "DarkTurquoise": "00ced1", + "DarkViolet": "9400d3", + "DeepPink": "ff1493", + "DeepSkyBlue": "00bfff", + "DimGray": "696969", + "DodgerBlue": "1e90ff", + "FireBrick": "b22222", + "FloralWhite": "fffaf0", + "ForestGreen": "228b22", + "Fuchsia": "ff00ff", + "Gainsboro": "dcdcdc", + "GhostWhite": "f8f8ff", + "Gold": "ffd700", + "GoldenRod": "daa520", + "Gray": "808080", + "Green": "008000", + "GreenYellow": "adff2f", + "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", + "LightPink": "ffb6c1", + "LightSalmon": "ffa07a", + "LightSeaGreen": "20b2aa", + "LightSkyBlue": "87cefa", + "LightSlateGray": "778899", + "LightSteelBlue": "b0c4de", + "LightYellow": "ffffe0", + "Lime": "00ff00", + "LimeGreen": "32cd32", + "Linen": "faf0e6", + "Magenta": "ff00ff", + "Maroon": "800000", + "MediumAquaMarine": "66cdaa", + "MediumBlue": "0000cd", + "MediumOrchid": "ba55d3", + "MediumPurple": "9370d8", + "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": "ff0000", + "RosyBrown": "bc8f8f", + "RoyalBlue": "4169e1", + "SaddleBrown": "8b4513", + "Salmon": "fa8072", + "SandyBrown": "f4a460", + "SeaGreen": "2e8b57", + "SeaShell": "fff5ee", + "Sienna": "a0522d", + "Silver": "c0c0c0", + "SkyBlue": "87ceeb", + "SlateBlue": "6a5acd", + "SlateGray": "708090", + "Snow": "fffafa", + "SpringGreen": "00ff7f", + "SteelBlue": "4682b4", + "Tan": "d2b48c", + "Teal": "008080", + "Thistle": "d8bfd8", + "Tomato": "ff6347", + "Turquoise": "40e0d0", + "Violet": "ee82ee", + "Wheat": "f5deb3", + "White": "ffffff", + "WhiteSmoke": "f5f5f5", + "Yellow": "ffff00", + "YellowGreen": "9acd32" +} \ No newline at end of file diff --git a/site/modules/.FieldtypeColor/spectrum/spectrum.css b/site/modules/.FieldtypeColor/spectrum/spectrum.css new file mode 100644 index 0000000..e68f492 --- /dev/null +++ b/site/modules/.FieldtypeColor/spectrum/spectrum.css @@ -0,0 +1,507 @@ +/*** +Spectrum Colorpicker v1.8.1 +https://github.com/bgrins/spectrum +Author: Brian Grinstead +License: MIT +***/ + +.sp-container { + position:absolute; + top:0; + left:0; + display:inline-block; + *display: inline; + *zoom: 1; + /* https://github.com/bgrins/spectrum/issues/40 */ + z-index: 9999994; + overflow: hidden; +} +.sp-container.sp-flat { + position: relative; +} + +/* Fix for * { box-sizing: border-box; } */ +.sp-container, +.sp-container * { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */ +.sp-top { + position:relative; + width: 100%; + display:inline-block; +} +.sp-top-inner { + position:absolute; + top:0; + left:0; + bottom:0; + right:0; +} +.sp-color { + position: absolute; + top:0; + left:0; + bottom:0; + right:20%; +} +.sp-hue { + position: absolute; + top:0; + right:0; + bottom:0; + left:84%; + height: 100%; +} + +.sp-clear-enabled .sp-hue { + top:33px; + height: 77.5%; +} + +.sp-fill { + padding-top: 80%; +} +.sp-sat, .sp-val { + position: absolute; + top:0; + left:0; + right:0; + bottom:0; +} + +.sp-alpha-enabled .sp-top { + margin-bottom: 18px; +} +.sp-alpha-enabled .sp-alpha { + display: block; +} +.sp-alpha-handle { + position:absolute; + top:-4px; + bottom: -4px; + width: 6px; + left: 50%; + cursor: pointer; + border: 1px solid black; + background: white; + opacity: .8; +} +.sp-alpha { + display: none; + position: absolute; + bottom: -14px; + right: 0; + left: 0; + height: 8px; +} +.sp-alpha-inner { + border: solid 1px #333; +} + +.sp-clear { + display: none; +} + +.sp-clear.sp-clear-display { + background-position: center; +} + +.sp-clear-enabled .sp-clear { + display: block; + position:absolute; + top:0px; + right:0; + bottom:0; + left:84%; + height: 28px; +} + +/* Don't allow text selection */ +.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button { + -webkit-user-select:none; + -moz-user-select: -moz-none; + -o-user-select:none; + user-select: none; +} + +.sp-container.sp-input-disabled .sp-input-container { + display: none; +} +.sp-container.sp-buttons-disabled .sp-button-container { + display: none; +} +.sp-container.sp-palette-buttons-disabled .sp-palette-button-container { + display: none; +} +.sp-palette-only .sp-picker-container { + display: none; +} +.sp-palette-disabled .sp-palette-container { + display: none; +} + +.sp-initial-disabled .sp-initial { + display: none; +} + + +/* Gradients for hue, saturation and value instead of images. Not pretty... but it works */ +.sp-sat { + background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0))); + background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0)); + background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); + background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); + background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); + background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0)); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)"; + filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81'); +} +.sp-val { + background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0))); + background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0)); + background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); + background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); + background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); + background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0)); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)"; + filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000'); +} + +.sp-hue { + background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000)); + background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); +} + +/* IE filters do not support multiple color stops. + Generate 6 divs, line them up, and do two color gradients for each. + Yes, really. + */ +.sp-1 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00'); +} +.sp-2 { + height:16%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00'); +} +.sp-3 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff'); +} +.sp-4 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff'); +} +.sp-5 { + height:16%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff'); +} +.sp-6 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000'); +} + +.sp-hidden { + display: none !important; +} + +/* Clearfix hack */ +.sp-cf:before, .sp-cf:after { content: ""; display: table; } +.sp-cf:after { clear: both; } +.sp-cf { *zoom: 1; } + +/* Mobile devices, make hue slider bigger so it is easier to slide */ +@media (max-device-width: 480px) { + .sp-color { right: 40%; } + .sp-hue { left: 63%; } + .sp-fill { padding-top: 60%; } +} +.sp-dragger { + border-radius: 5px; + height: 5px; + width: 5px; + border: 1px solid #fff; + background: #000; + cursor: pointer; + position:absolute; + top:0; + left: 0; +} +.sp-slider { + position: absolute; + top:0; + cursor:pointer; + height: 3px; + left: -1px; + right: -1px; + border: 1px solid #000; + background: white; + opacity: .8; +} + +/* +Theme authors: +Here are the basic themeable display options (colors, fonts, global widths). +See http://bgrins.github.io/spectrum/themes/ for instructions. +*/ + +.sp-container { + border-radius: 0; + background-color: #ECECEC; + border: solid 1px #f0c49B; + padding: 0; +} +.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear { + font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} +.sp-top { + margin-bottom: 3px; +} +.sp-color, .sp-hue, .sp-clear { + border: solid 1px #666; +} + +/* Input */ +.sp-input-container { + float:right; + width: 100px; + margin-bottom: 4px; +} +.sp-initial-disabled .sp-input-container { + width: 100%; +} +.sp-input { + font-size: 12px !important; + border: 1px inset; + padding: 4px 5px; + margin: 0; + width: 100%; + background:transparent; + border-radius: 3px; + color: #222; +} +.sp-input:focus { + border: 1px solid orange; +} +.sp-input.sp-validation-error { + border: 1px solid red; + background: #fdd; +} +.sp-picker-container , .sp-palette-container { + float:left; + position: relative; + padding: 10px; + padding-bottom: 300px; + margin-bottom: -290px; +} +.sp-picker-container { + width: 172px; + border-left: solid 1px #fff; +} + +/* Palettes */ +.sp-palette-container { + border-right: solid 1px #ccc; +} + +.sp-palette-only .sp-palette-container { + border: 0; +} + +.sp-palette .sp-thumb-el { + display: block; + position:relative; + float:left; + width: 24px; + height: 15px; + margin: 3px; + cursor: pointer; + border:solid 2px transparent; +} +.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active { + border-color: orange; +} +.sp-thumb-el { + position:relative; +} + +/* Initial */ +.sp-initial { + float: left; + border: solid 1px #333; +} +.sp-initial span { + width: 30px; + height: 25px; + border:none; + display:block; + float:left; + margin:0; +} + +.sp-initial .sp-clear-display { + background-position: center; +} + +/* Buttons */ +.sp-palette-button-container, +.sp-button-container { + float: right; +} + +/* Replacer (the little preview div that shows up instead of the ) */ +.sp-replacer { + margin:0; + overflow:hidden; + cursor:pointer; + padding: 4px; + display:inline-block; + *zoom: 1; + *display: inline; + border: solid 1px #91765d; + background: #eee; + color: #333; + vertical-align: middle; +} +.sp-replacer:hover, .sp-replacer.sp-active { + border-color: #F0C49B; + color: #111; +} +.sp-replacer.sp-disabled { + cursor:default; + border-color: silver; + color: silver; +} +.sp-dd { + padding: 2px 0; + height: 16px; + line-height: 16px; + float:left; + font-size:10px; +} +.sp-preview { + position:relative; + width:25px; + height: 20px; + border: solid 1px #222; + margin-right: 5px; + float:left; + z-index: 0; +} + +.sp-palette { + *width: 220px; + max-width: 220px; +} +.sp-palette .sp-thumb-el { + width:16px; + height: 16px; + margin:2px 1px; + border: solid 1px #d0d0d0; +} + +.sp-container { + padding-bottom:0; +} + + +/* Buttons: http://hellohappy.org/css3-buttons/ */ +.sp-container button { + background-color: #eeeeee; + background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc); + background-image: -moz-linear-gradient(top, #eeeeee, #cccccc); + background-image: -ms-linear-gradient(top, #eeeeee, #cccccc); + background-image: -o-linear-gradient(top, #eeeeee, #cccccc); + background-image: linear-gradient(to bottom, #eeeeee, #cccccc); + border: 1px solid #ccc; + border-bottom: 1px solid #bbb; + border-radius: 3px; + color: #333; + font-size: 14px; + line-height: 1; + padding: 5px 4px; + text-align: center; + text-shadow: 0 1px 0 #eee; + vertical-align: middle; +} +.sp-container button:hover { + background-color: #dddddd; + background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb); + background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb); + background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb); + background-image: -o-linear-gradient(top, #dddddd, #bbbbbb); + background-image: linear-gradient(to bottom, #dddddd, #bbbbbb); + border: 1px solid #bbb; + border-bottom: 1px solid #999; + cursor: pointer; + text-shadow: 0 1px 0 #ddd; +} +.sp-container button:active { + border: 1px solid #aaa; + border-bottom: 1px solid #888; + -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; +} +.sp-cancel { + font-size: 11px; + color: #d93f3f !important; + margin:0; + padding:2px; + margin-right: 5px; + vertical-align: middle; + text-decoration:none; + +} +.sp-cancel:hover { + color: #d93f3f !important; + text-decoration: underline; +} + + +.sp-palette span:hover, .sp-palette span.sp-thumb-active { + border-color: #000; +} + +.sp-preview, .sp-alpha, .sp-thumb-el { + position:relative; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==); +} +.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner { + display:block; + position:absolute; + top:0;left:0;bottom:0;right:0; +} + +.sp-palette .sp-thumb-inner { + background-position: 50% 50%; + background-repeat: no-repeat; +} + +.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=); +} + +.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=); +} + +.sp-clear-display { + background-repeat:no-repeat; + background-position: center; + background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==); +} diff --git a/site/modules/.FieldtypeColor/spectrum/spectrum.js b/site/modules/.FieldtypeColor/spectrum/spectrum.js new file mode 100644 index 0000000..6c48c12 --- /dev/null +++ b/site/modules/.FieldtypeColor/spectrum/spectrum.js @@ -0,0 +1,2341 @@ +// Spectrum Colorpicker v1.8.1 +// https://github.com/bgrins/spectrum +// Author: Brian Grinstead +// License: MIT + +(function (factory) { + "use strict"; + + if (typeof define === 'function' && define.amd) { // AMD + define(['jquery'], factory); + } + else if (typeof exports == "object" && typeof module == "object") { // CommonJS + module.exports = factory(require('jquery')); + } + else { // Browser + factory(jQuery); + } +})(function($, undefined) { + "use strict"; + + var defaultOpts = { + + // Callbacks + beforeShow: noop, + move: noop, + change: noop, + show: noop, + hide: noop, + + // Options + color: false, + flat: false, + showInput: false, + allowEmpty: false, + showButtons: true, + clickoutFiresChange: true, + showInitial: false, + showPalette: false, + showPaletteOnly: false, + hideAfterPaletteSelect: false, + togglePaletteOnly: false, + showSelectionPalette: true, + localStorageKey: false, + appendTo: "body", + maxSelectionSize: 7, + cancelText: "cancel", + chooseText: "choose", + togglePaletteMoreText: "more", + togglePaletteLessText: "less", + clearText: "Clear Color Selection", + noColorSelectedText: "No Color Selected", + preferredFormat: false, + className: "", // Deprecated - use containerClassName and replacerClassName instead. + containerClassName: "", + replacerClassName: "", + showAlpha: false, + theme: "sp-light", + palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]], + selectionPalette: [], + disabled: false, + offset: null + }, + spectrums = [], + IE = !!/msie/i.exec( window.navigator.userAgent ), + rgbaSupport = (function() { + function contains( str, substr ) { + return !!~('' + str).indexOf(substr); + } + + var elem = document.createElement('div'); + var style = elem.style; + style.cssText = 'background-color:rgba(0,0,0,.5)'; + return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla'); + })(), + replaceInput = [ + "
", + "
", + "
", + "
" + ].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 .= "
    "; - - foreach($csvalues as $csvalue) { - $csvalue = trim($csvalue); - if($csvalue == "0") $csvalue = "000000"; - $out .= "
  • "; - } - - $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 c0893ad02a3de9255faaa2f8f8836954ac0463cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 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 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 8401572f1939a1a24c1963513573b0194ad36ee0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1897 zcmY*a3pATo9RCoHhLk=v9+hya?P*IB^(tbYgf7-$bhEY|(I?UtUPi9vs#R ziy#P&{yr@fLG&2ly2iu^RFBrRRp1Ms>i=nK7%MiF8HO#xOG2 z_n6)YVr)vMq5IN*f2sWccT3)gRvu2oXh6my%^v}*O;ra5-< zrfBywZT3aSz8bWP1#@=ep&&&2r%2Xx zddEiY1@l}|b6YxdaO6Q`RJq3)wtKZi&2z5yNzot36|pnd_gApH!?MH9gq?hIkpDQ? zoi#k4#OM3Qvsl*nW+NM0+h-~TfAN~J`Np!FYfHA<4F{vc3Gd`y^@%F1#Ljo6xgBMf z>q*?e(2(gjbtEPC06P3(T2t>_N`opfT&(A|#nr9ubq;Roe8EGc50&a+@Ca&D8N&V5 zfWzVZ*wTW^c5k?}vCRiBX+63NTRRx9IULPb=kLtbG7G2PR9LSNtF=j!&s8JxkH+I- zofPjPqCAy{x*V^kY%4z8I+~=}5Ut2+RB9hQnF-=Yy8f)_*S6oz?C#RkmvpMq7QP(o zbZ!bUKi!a-F8i&JTjM>>TAUAmd?)cz-HnW2PWdWk#$QRa^0SMsE*Ei8-<`C&zPP^R zdHWR`(Q|r$)T?{(gtteqpleg1llyjZ0ZVLw8leHw(a;G~vcN1Y>6s-e44f7NN&vzO zSzky!K z<_U2aPpuI;9PaSb&;Ej+#b@gJvw)$&8ZCQ!O0HDG-5Ryk0-~ziB-tPWKJK=>?ocx|gRt#KYNSCK| zmrMW=4om~tMIU%ONCY$t9RcY(kaUNR#1=v%^?pW-QzJnZCkAr|iCQDD687K8FZ`q_ zi57h%KMX!lwtAe@@x)l}04zNB(A4Qum^BC!^1cdZ=xa=ei3OvQ+5@W08>NszykE}f zv?z;H%6*$BjvuB;iP6rpc{~#`#C$juv62eaJ-(#wzbS@&`|x8xR0#<2lFZ9l84oq~ z)RtYb1_uH_On@$HmKKWl$={|vFVC?D2S?ere)+Ii3ZCYJc1u{wg0CgRowk%p6z-vm z25al~YDe{K&MKf#`#$i4g$_`C3_gpv%r}IrbhdU7n7ws`iL~u?7mnTC+5f*Z3oqn> z!F~y5)zR3`!AmrFCO)o-qINJDjGjk AumAu6 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 4e532d7c65393fe56d7463e1da3faa591f03de84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 532 zcmV+v0_**WP)h+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA2nn^@KRCwC#n6YcZKorKmBnM{5VnN~}9ReD%Nhj%)e@2UckI?wn+*F*3;85I( zxENdy>|*I~AlHjh(Li4w_e~$k1>TSMlH7e>k|a?SftQq0B8sB@e$Nc7)9DBRzVCyb z1b`q2c!CKbZg`U5o2itl0Sv%)yQM?b>-9{KyTHhep8?|QckHZYvzcW~5d<@9^YvHp ztN^T5E7MqasmZKO0Qfo_tQD_Cp^cRCbkSPY3PWmOrwUtP=mYq!XfhrH$n!kUb8V{2 z2zJb@O#p!BU0T}j_bo$O28aMq#VY1=a}K4HFOx|FxU3(vcdlc4{G^oH07wS|@(ugl zu}h2#{EpG-rzyuU{=%QDL_0lRX0#t`gyJhJT=_461{Fr^gFFz2D& z?#3}Quw7Y-ZXCZam(0MPhC`Q9H4*H#%p;?>f&5sn>j`t-77IF5&!dq`sa#4$MD?Up z1Z7s}QYx2H{U_Ho#}=1TQ65E?QgHyga(l)Q>~phW+cE0rF`i(%vV0^K=++YE{0sm& WpVhv@?^YTB0000h+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA4P)S5VRCwC#nn6n&K^TU=-E6Jmny{kAgHdYMnDn-IF?jG$4BqP9gMtMis0Dw8 zAV{dW=nt@ez?%dVDIU_2gRqI_5Em~-k8ZNXWV1btZa3MO4c19#+Wqh_Zf2N=;hoLQ zLzrMN$n!kVR;sFUJkQ_V-BE`=I5@}w0L!vKVQ~Q9@px!O=Q!>KBXRE#RaJ4J1Hkq5 zH74#rAmB*#N9cI-&+9?5X8Zj7{P_5|^XQH{u=yKC6vb33b$ff;+uIw9#SFtZ zJw0vcV;BZjbSqURlaVB;VRjAxerlS1&~!NI`5fVIQh?ryB; zCRH|X*Y~znJyFxHP3oeqGU3e&1O9;`*C3*9*=)dr#lP& zn<{s4fg0h-$-2z|0F15BXa1p~(a}*s5CEWXbyYJAdmo&O{#YpD48vSpURq~=HZW^z zYn4ic=lPM5k&}~?zi?i#P(>mU00>*Q=~G~A=!rx^QIxK(E{0+5@9$+<_W68FXS3cg z9in$e&*$@{Qpx;xe0;nc^Q+Ji{h4jrtW!Iut3V(?BD!Pgx=!e-({Wy>6NMqMNDj~M~n z)!GO=qQA@t;I7t2;1S(50Ji7R-H^E z;Fxt5y+yKp{*YWFP<>kUy}douSY2JE!wBfrD*F4hvVtJ@ z_xH_*L>mEXHkOx{0bprq$rczQjer>#REvv?4Nu550(w0tO-7)tlOusf;N935Ms)0f sary=%7ro}V>f{=MmOlY4Yuc{?08g~^-7;vm)Bpeg07*qoM6N<$g2&OnRsaA1 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 3977ed9f21e3186eefd37b198a7cc3f8de6c69cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1012 zcmVh+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA4dPzh1Z?xtc9W|d^8%pySrl!Jsywq01yZSfWhDafa5q;(RrSK!_25Mnz_o6R-Q8VL6wU6+%F4pRf-Q$MI@dS4=mAHh)9FT|@$~eByOWcX z!Cq-b_?cFRh?(5s;V}d2mk4K?&4-6bIBX^iheAZrO{%IS z0YIfv$z`+F(Rl#Sb=`U9^73-C*$nbL0E`QQVHk#CxMmUxbFA4+=9etvc4lVg#bpWz zInPX|)2gcCza|_G>$(mIxn`0I%UGFA#{CZCigR#qP_0(EKmY)WdwYgq^vWbf{@jo* zE^s3|JL^F2F_(#niAW>@0HNVwp65~TOfr++9V?g3RwW5{t@J$$rn?^>GJgkDFu7a~ z0J4_L6actnGO6o2dKt1Tm&@fyBr-HKgb=#EzCJrUYqeSQ+^ z@p#6tJ$H`nQONIahe-%W5W9r2sHGI!dV# zn9t`wEiLs)_< zqd%&uZ8MDk?wUrxmh*4WOQjM3lu9KVI=x0fd;SdeWoPH>w{N(;v%SrL5$IU%>swn} z&Ykoc0rTVI;o%`}Y;JDa?=Z*_rV$WDQ4~e15wPVDEf~Cg-q^s9M@L8IPO6Q7wKmq* z*8yN{ZOu_IR2l)>*Xq^PRofnVjezF$`JY}R@TxaQ3XQ;rsVRc!#0$pj@kcMZ?m6r9 i8Ue%TbFitZe+B@uIz19ZnQ%P-0000P)h+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA58A(JzRCwC#nn6h0U=+t+YIIeCZ8N0REt9otS9j@(Ajt5v?W7gKqX!Ee2!alT z*{jEbDCoQ>c=RY9Hf%t4)YgLZFxlE#lxYuB4{FKmYLj+{XqP4>>D<09+4?7kkiL)i zCw=+8yx$khX0s6l0a_EoFgQUFr>Ccyv)*xTdJ9d`TAin3TNEXx9h36D@HluRbgX0xZi|M`m->2&(y;zATt zUtgb2rxE!!7z{#JcW)%jt^)w9^msr~9*-v;i!CfHcs!of)m5L*$Fi&_47G}h;x`gy z*8u=lD!{P5zCN4HW;7V?-@EsXVF2Ld*VWaPbRbERt*xy_qcI!~ z@9yrBBxyFAg#ir>4MLasI!M{&seDmP)0v*(}F#R;yKycq%MgFbV-Kmy2at z6btolO5PRDr@!4Z$8p@>z3aEPu8Q|{ty*UoMyqW#X);+#XFW~m>+vyeF`IXyQO#NJ zbh~RrKwCuMN$DHKAJ?Z?3}IWn844lt{j9sYMg;ybB7j=*MBv)`?T7$s$rFKV>l!5j zc-gjXW@g6ebar)h4ST%+u)Mq+iA1Vh>;hK~hoekI)rdfi2>c2WDBo(VtgHlsL7oWA z&(HHjpvo(k$QAFtqAp4OL_n^=BM3sifqK^6t;x3f;LDd95%>>@z}MsBc8bzsTdm2i z6abo=n^j5#I^FK)FJH<8eAw7fFA-2=n(8G26ji+};bGxL%+uSO z+~1duRQyKZk=2THHElK;WdhRY=jtT_oYMBcdWk?qZ;mP?0uS5U5n4xHFiI<+dadUb l@49-4fb1urmzm6u0RTq3k6f>52*3aU002ovPDHLkV1hB)7U=*0 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 f9fa95e2825eadd2d779ad270a71eddb94f94748..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 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 RdwKu>002ovPDHLkV1myV#+d*B 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 dfac595d017e279ff670df2c816e02d922660d9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 970 zcmV;*12z1KP)h+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA4P)S5VRCwC#nn6n&K^TU=-E6Jmny{kAgHdYMnDn-IF?jG$4BqP9gMtMis0Dw8 zAV{dW=nt@ez?%dVDIU_2gRqI_5Em~-k8ZNXWV1btZa3MO4c19#+Wqh_Zf2N=;hoLQ zLzrMN$n!kVR;sFUJkQ_V-BE`=I5@}w0L!vKVQ~Q9@px!O=Q!>KBXRE#RaJ4J1Hkq5 zH74#rAmB*#N9cI-&+9?5X8Zj7{P_5|^XQH{u=yKC6vb33b$ff;+uIw9#SFtZ zJw0vcV;BZjbSqURlaVB;VRjAxerlS1&~!NI`5fVIQh?ryB; zCRH|X*Y~znJyFxHP3oeqGU3e&1O9;`*C3*9*=)dr#lP& zn<{s4fg0h-$-2z|0F15BXa1p~(a}*s5CEWXbyYJAdmo&O{#YpD48vSpURq~=HZW^z zYn4ic=lPM5k&}~?zi?i#P(>mU00>*Q=~G~A=!rx^QIxK(E{0+5@9$+<_W68FXS3cg z9in$e&*$@{Qpx;xe0;nc^Q+Ji{h4jrtW!Iut3V(?BD!Pgx=!e-({Wy>6NMqMNDj~M~n z)!GO=qQA@t;I7t2;1S(50Ji7R-H^E z;Fxt5y+yKp{*YWFP<>kUy}douSY2JE!wBfrD*F4hvVtJ@ z_xH_*L>mEXHkOx{0bprq$rczQjer>#REvv?4Nu550(w0tO-7)tlOusf;N935Ms)0f sary=%7ro}V>f{=MmOlY4Yuc{?08g~^-7;vm)Bpeg07*qoM6N<$g2&OnRsaA1 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 72b32760a5c40b7ab834d176ac588750a06f13f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1069 zcmV+|1k(G7P)h+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA4vq?ljRCwC#na@w+KorMcp|EVXQK$+YM6*gzHqnN7BF59kyLV$Gkwjyn8-M%_ zE{RbNUKIZauO4)ds|T|oT-ef(s1a0_$f>a^t?r@HEtF8AJM1*eOAln2$@}v7PN(lv zVqjo^rfD!+2!cS;G+ihZOeejotBV8xi^T#a3=#mWR;yX1lO*|ym8f@!APA_W1Hk3w zB_iEkuh&r3o1~-lLnG2_dVP3!cw}V6=kpbd#Y`r1aB$FM>4rPdqTFGsf@RrABvLAs z_V)IUj*iC1$ET;KtLC7VuFaK9CiU4#0Js;$s%4Xtll%Mo+uPgi?d>#8=kxjb`T6VX zYnRih&Uxo>AeFAF`pIzskVqr~Lqpo^765pv442ErFwDvEaR>5>mzrVKEiOMUN%>sbW=d;^vxor09`ug(nG5}<=S@G^porYX_`AU~VE3z!TGDK12 zc|IHtTS-zB#k2Esx7%GV#GgQ4^p{X9P7p+z=e5~u7zO}#c6JsQ7vu3b&+`;T_4M>` z9GA&t7={6YXue?rfdBvuX|^c<5G>0+K0fLf%ChWqI(vJ2Z8lpnnM|cp%5P9_w|2W7 z>1kS1l^S-tomBpdnunPn2&bo~4-XFj(BI$hKzujU8^&M)%d(Orp*X1D81+?=O8VFB zIa!wfZPi~d9gF96vq~2P!K`gH<8pO-Jf@R=lh2dg9?y?N!gSI{gTWRNFc%T{RQW{l z*CWMo2;1uKCntz>kA*@lBG4iNxDWx@ z)`lq&7!3wLPfXOA@a^yrUm{@0H1Q<@4N1q72$V`Cvl4;&Z#A$c0u5CiPaZTH69Gx%^@W86{U8at z_Fg3dSGk-*1b!6?u~UR@?manP6sovBm$~8BD1qf>UcbEU>Hn@ zfYuw~a2Nn)W@dDT!IB76y{(>_nyMPXmk7v4umABS0u4PmVn_r&_Vpo@j@&Rtryjo2 npA4&xFA;ctuJh%cDE=M*G)vtq^hrv*00000NkvXXu0mjffA{0B 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 4855fe03f8ea8d88b4f8ae625c7958eea65208ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1066 zcmV+_1l9YAP)h+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA4ut`KgRCwC#nL$e%K@`W|#$^*@2)1ijA*P`i*Vs!8o}|Yj_z@}|6buN87D4dl zS;)b(p0whp5G)M=FI7^gQ8aB#6dSZ+h!%w1Y;?1+hmFg+nRFn+=R+9LJG1n=PBo8cw>y;UEFPWHNyPjRb(ErY56GCrR=VBT=6aj^j{C z2Y}PlQ$)I5E>~4mPm+!{9%_-UkM*gkDWxt5LNprP-`}sZ^r|P&B!6Kv=J9woH#gVT z*4Ee8bGcj~5O6x38Xwfs)pPCb?dfMH0U$33`jPQ?{QUg<*V)k*x3{;YrDbbti|2U@V!3Kl zRCTj#GL@3+Y**KVSOqeE%ahy@p z>gUg%wKI(2q+et*WIMxri^U8lz0dD&5CLNmfmf=FKMMPvNFYqBzie+K(*3%>zd-~V zL;x2efZ8e(fs*tF5oi#B1`)uT2$WAXLZQ&n(GgA41VQBU`NhRWQ51QeZ*Fd`W2iq+ zC9AKVB^iPU{58STq)rq?Q52=WX&5rCK1rt=MBqOp0vDN#+vPH1T5ZUz6aegYJElaS z&+mUTFi^oE5)R`_1gbJke2G9!((xn$q9_`b2vmO6z?uluwCZ>gfvT~NFA}u zJ+zYaydY?bOazXPk7GMK??WM;=NX3ieRZYrsgLwvFbDv_U{E6+Um_sgKZCuSp8l}3 zB-f`^k&G`9D5zq6Vq!wyh%XUP9v_#Nm*vX%__#5MfK({RB``K7i(FY*Q5vx(0tHD@ z%IN4Q0E~=`C@okM0nKam@bIvv1z#c{ReS!&mk88!bHtDcymY$}N=F_r<$jdLkY231 k>i80YySoaVIYIa{0Hu_2rW%yutN;K207*qoM6N<$f_Z=6i~s-t 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 599f7f13a6854d198f501588948ffcf97bf9f365..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmZ?wbhEHbij|08)1sO8@`> 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 7f4c0825f53cc4faba8fc9e043502276765da1f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 984 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 P00000NkvXXu0mjfA`AaT 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 a217e9218e6a512b507a35e8a6141f0e56193439..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 970 zcmV;*12z1KP)h+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA4P)S5VRCwC#m|aK|K^(yUyEA+4?d5?fXd;=M7I&7CAQ1#X&_j>CL_YN-gn@+F zgHSIeAw>3IK|;|7L=oge5IzJ#A^0E&>G?(8=|!HGo*#L7AKu<>4|8pMd)HkZt+#{w zXC7weW^aBB|Jj-SF*9F$o1tx>E$qcMycycAC@-ZBJ@9=M1Art+Kw)425XHpaLf3nT z*o$qs(c_|+-@n%!JfIWz{MV(NRK`u1oK!3sq$xeUk30*0rTO&r;Lz}xX3Q?2XDLZ^ zNtQLm=b0`ovGcrzGy{tZJ8^M;iCsNLZ*=us&BvV@!eqi&`J(hE1%Vf=JRxLR*23X^ zHtTjcstkxmW4fX%R1Gc%0Gw!YjZb;hvts~YStk9-f%l(m0w0fy0I;#P!Y~ZOFd0Yc z6v|xg8E^fO8d9H}oln`OnfJJ7mbVJzw2DT;EXx*f%c_Y}(B({td#$~-(d7^m2>@v8 zyhBz%)<4CSQ06-3bdbu#v?m=s^TUgQAW80>SVT-DWO+Bqe^ZT5c^X^}GWW!^H|6DM z{2&`t&HcxOX}{XxtgBuQu9KfyE}VDPRTnB@)bzR0U55`X2iGIf82PEXs$7=k;M$J@ zqW{A-4Q++h&2S`|@upE=bVXp?Ee;`O5dSyi! z_6LF|n~ze5J~HYyjR0NfpC{*ZC2Op&)zJu?In|^S_t5Z|X#`9oU=$;ucVssLNp#Z) zm`1=f0;Ul#jllmj0z<=NR2qTWnkv%>>_H8 zN}^l&B27_@0BI^lKr=??RZm8DS1SN?ceNr_7}^MstN?&p_nzJCxJ2r=d!JKa1US_; z?df}&-f3JTfPWoH*RQmY%H4;rv~L($))vJGczsJ=-;&x0XvXM>ju9#M``?gN>ukHI zbY@GK!e7T#7lFRVZvo)JlL2+7ag6|%dL;F~c&F(xt`Sh)F!UJ#{5Lm80~&$3`EU8J sdf~SzMzo^mJOqtv1hQW_1cCoK0IhW09jn*o82|tP07*qoM6N<$g4YtalK=n! 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 7826b415077be23ed1b1bf05b2da62d4aa5b1c67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1168 zcmV;B1aJF^P)h+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA57D+@wRCwC#nQcf@Q5eUc-Fr6Onu3&AF^rild$UyX1q~x8l(L`*3O@uvFO(o; z_5wxr@*$1tgY{vMl7$6QeMqAy6e1xqkX2R|TUIxmtGu(iIrnyNAC8Ud=Dmt?_1xOS z`EYjbGoJs>o;~L|ziI4tJI8S#VLo05L|S~@48(C$eTIg-ib~hV#^6c%;`soO zlezfi8;3YL0sx8%PiTw9QdL!zm6bIwEpOSPl&u?AQj2Q*-QCgA(fXtl0Cw!$vnn?|%wceFNYM&oFvQ9@3=R%a03eJUpBbjP zxp`q)T3K1y!+W<%Hg9jJw`vg*Mw-&Q9tyNHEd`IT=#UEpqjD~4E z^RfC@Z$F3^H8z_~ryHfSWm(qgbTa*XVcv?&bj$btfnHa?*um@dDVpmsF>?L3*Xu+0 zyNG<2kdR<9neuc7gy{DU#-ng495vU+K24>ZIF9oRKKZ>NR5}3gyyPRArjJ2 zf+9GneqF87jYgx)wVGJz@o_T{>vs3KTv8sMfSye0b7#*&eJ)p4MuzH$z|-elQ6iu& zBJkq1T~TGrm!v941lAN}Dx|xuy)#M#qC|icBA~R%6M*&npp9OT#pigC=nPp5g7fdQCeDBTwIKaKxO%EOa#U(w2IzM!^(@?E$JU80&VS` zsw4ubW>b_1{D(wfc2d$OhEe0SngVs&z)y})BJlKi*ZoJ2WgLpv7LrQ@Xd0=N2vB3; zSaOMgR;yDh5zy*l)Jg<&+6m=42}FRVDYX&-MAM;h_SjzWOGMK|6M@hlJ|_?D1b{O~ zcb%xIR|gRYCCsVwSC1dqf#;_$G^l_GXhlEMv$c(piwF||u`vwu!e-l0Qj(pWefUUx zZQbpLdh413tIzMB(#G&_!c^|xjwk0X-;976L=pjnXgn@jo3O}(`?iG^i6#O_)CkmG zxeWl9>h6da$t42Xkw=pC+TE}fa*4p0M-sV20F9?}B#;Q$d%jF+*QfVdjmwBCrAMCe isv!dMU5CLC`)2?-k0%YdqHBTx0000b%7 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 80764e5d6dd8aac3c5ef87d83b45d29780af1fe9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1008 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 T=Ar9_QX-DN@01`G*?mYE;P(j>ieaLJ zp1@KmP7DbnxHd5epSMZF>_Ios1X7kEzM%)`8u}mxVv)EwgAVwi+aL%gVHgVE_pQ>@ zbuG%W6jfCb)Fr3i6gRMr(1H#Un@BbTwH6Q2xnfI1$74|x z`a$b3REt~>BR!+Rjm(B~!)%yB$32-1&(IZ{4HWmQa;H~;maQBTMsJ;5 wu=L25Ib=s<$1=nh_wOs&FkN?ph+v*8l*BQUCyPMF0TmW&i*=2LJ#e`2#0~ zRsaA2j7da6RCwC#n88ZJKomvKOQ$N-q%EcB2MDDFapS&Ut2tcoJKO0Z5XR@gxT5=E@BPRC5JM(-{EmRs+wi z*>P|@#ScQvT9QAwUwvX=#Ku^(QHKpv2~+}=KqXKKR03@~kh1h#z3lU2-9S7%K9wHY zZlHd@zd1k|%qmdMx=&^ql(G#p7!3Z$L#9{gzl=qFW|hX6M^<+t`|yc1Y?-gyyEotInm#MOm!f^^y*-dYoVJ8o0wy4TmX zR?7dfn;bc9{iI8VpES5yofZaYh;TjCpK_UhilywQPp{V&o!)zNr-EuAP#7%xRC{Am z6GR!1|0e8}W%vqnuQi`zyC%VuOt~~QLec?j5=hH8t&PuqF6Zm0mDYFhgqkAab@NoR n(3#>M@3IhYo&TccjBE_r(UXjnZhw#mdW^x-)z4*}Q$iB}AxU+4 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 = '

', - defaults = { - eventName: 'click', - onShow: function () {}, - onBeforeShow: function(){}, - onHide: function () {}, - onChange: function () {}, - onSubmit: function () {}, - color: 'ff0000', - livePreview: true, - flat: false - }, - fillRGBFields = function (hsb, cal) { - var rgb = HSBToRGB(hsb); - $(cal).data('colorpicker').fields - .eq(1).val(rgb.r).end() - .eq(2).val(rgb.g).end() - .eq(3).val(rgb.b).end(); - }, - fillHSBFields = function (hsb, cal) { - $(cal).data('colorpicker').fields - .eq(4).val(hsb.h).end() - .eq(5).val(hsb.s).end() - .eq(6).val(hsb.b).end(); - }, - fillHexFields = function (hsb, cal) { - $(cal).data('colorpicker').fields - .eq(0).val(HSBToHex(hsb)).end(); - }, - setSelector = function (hsb, cal) { - $(cal).data('colorpicker').selector.css('backgroundColor', '#' + HSBToHex({h: hsb.h, s: 100, b: 100})); - $(cal).data('colorpicker').selectorIndic.css({ - left: parseInt(150 * hsb.s/100, 10), - top: parseInt(150 * (100-hsb.b)/100, 10) - }); - }, - setHue = function (hsb, cal) { - $(cal).data('colorpicker').hue.css('top', parseInt(150 - 150 * hsb.h/360, 10)); - }, - setCurrentColor = function (hsb, cal) { - $(cal).data('colorpicker').currentColor.css('backgroundColor', '#' + HSBToHex(hsb)); - }, - setNewColor = function (hsb, cal) { - $(cal).data('colorpicker').newColor.css('backgroundColor', '#' + HSBToHex(hsb)); - }, - keyDown = function (ev) { - var pressedKey = ev.charCode || ev.keyCode || -1; - if ((pressedKey > charMin && pressedKey <= 90) || pressedKey == 32) { - return false; - } - var cal = $(this).parent().parent(); - if (cal.data('colorpicker').livePreview === true) { - change.apply(this); - } - }, - change = function (ev) { - var cal = $(this).parent().parent(), col; - if (this.parentNode.className.indexOf('_hex') > 0) { - cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value)); - } else if (this.parentNode.className.indexOf('_hsb') > 0) { - cal.data('colorpicker').color = col = fixHSB({ - h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10), - s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10), - b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10) - }); - } else { - cal.data('colorpicker').color = col = RGBToHSB(fixRGB({ - r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10), - g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10), - b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10) - })); - } - if (ev) { - fillRGBFields(col, cal.get(0)); - fillHexFields(col, cal.get(0)); - fillHSBFields(col, cal.get(0)); - } - setSelector(col, cal.get(0)); - setHue(col, cal.get(0)); - setNewColor(col, cal.get(0)); - cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]); - }, - blur = function (ev) { - var cal = $(this).parent().parent(); - cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus'); - }, - focus = function () { - charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65; - $(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus'); - $(this).parent().addClass('colorpicker_focus'); - }, - downIncrement = function (ev) { - var field = $(this).parent().find('input').focus(); - var current = { - el: $(this).parent().addClass('colorpicker_slider'), - max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255), - y: ev.pageY, - field: field, - val: parseInt(field.val(), 10), - preview: $(this).parent().parent().data('colorpicker').livePreview - }; - $(document).bind('mouseup', current, upIncrement); - $(document).bind('mousemove', current, moveIncrement); - }, - moveIncrement = function (ev) { - ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10)))); - if (ev.data.preview) { - change.apply(ev.data.field.get(0), [true]); - } - return false; - }, - upIncrement = function (ev) { - change.apply(ev.data.field.get(0), [true]); - ev.data.el.removeClass('colorpicker_slider').find('input').focus(); - $(document).unbind('mouseup', upIncrement); - $(document).unbind('mousemove', moveIncrement); - return false; - }, - downHue = function (ev) { - var current = { - cal: $(this).parent(), - y: $(this).offset().top - }; - current.preview = current.cal.data('colorpicker').livePreview; - $(document).bind('mouseup', current, upHue); - $(document).bind('mousemove', current, moveHue); - }, - moveHue = function (ev) { - change.apply( - ev.data.cal.data('colorpicker') - .fields - .eq(4) - .val(parseInt(360*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.y))))/150, 10)) - .get(0), - [ev.data.preview] - ); - return false; - }, - upHue = function (ev) { - fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0)); - fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0)); - $(document).unbind('mouseup', upHue); - $(document).unbind('mousemove', moveHue); - return false; - }, - downSelector = function (ev) { - var current = { - cal: $(this).parent(), - pos: $(this).offset() - }; - current.preview = current.cal.data('colorpicker').livePreview; - $(document).bind('mouseup', current, upSelector); - $(document).bind('mousemove', current, moveSelector); - }, - moveSelector = function (ev) { - change.apply( - ev.data.cal.data('colorpicker') - .fields - .eq(6) - .val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.pos.top))))/150, 10)) - .end() - .eq(5) - .val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - ev.data.pos.left))))/150, 10)) - .get(0), - [ev.data.preview] - ); - return false; - }, - upSelector = function (ev) { - fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0)); - fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0)); - $(document).unbind('mouseup', upSelector); - $(document).unbind('mousemove', moveSelector); - return false; - }, - enterSubmit = function (ev) { - $(this).addClass('colorpicker_focus'); - }, - leaveSubmit = function (ev) { - $(this).removeClass('colorpicker_focus'); - }, - clickSubmit = function (ev) { - var cal = $(this).parent(); - var col = cal.data('colorpicker').color; - cal.data('colorpicker').origColor = col; - setCurrentColor(col, cal.get(0)); - cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col), cal.data('colorpicker').el); - }, - show = function (ev) { - var cal = $('#' + $(this).data('colorpickerId')); - cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]); - var pos = $(this).offset(); - var viewPort = getViewport(); - var top = pos.top + this.offsetHeight; - var left = pos.left; - if (top + 176 > viewPort.t + viewPort.h) { - top -= this.offsetHeight + 176; - } - if (left + 356 > viewPort.l + viewPort.w) { - left -= 356; - } - cal.css({left: left + 'px', top: top + 'px'}); - if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) { - cal.show(); - } - $(document).bind('mousedown', {cal: cal}, hide); - return false; - }, - hide = function (ev) { - if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) { - if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) { - ev.data.cal.hide(); - } - $(document).unbind('mousedown', hide); - } - }, - isChildOf = function(parentEl, el, container) { - if (parentEl == el) { - return true; - } - if (parentEl.contains) { - return parentEl.contains(el); - } - if ( parentEl.compareDocumentPosition ) { - return !!(parentEl.compareDocumentPosition(el) & 16); - } - var prEl = el.parentNode; - while(prEl && prEl != container) { - if (prEl == parentEl) - return true; - prEl = prEl.parentNode; - } - return false; - }, - getViewport = function () { - var m = document.compatMode == 'CSS1Compat'; - return { - l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft), - t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop), - w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth), - h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight) - }; - }, - fixHSB = function (hsb) { - return { - h: Math.min(360, Math.max(0, hsb.h)), - s: Math.min(100, Math.max(0, hsb.s)), - b: Math.min(100, Math.max(0, hsb.b)) - }; - }, - fixRGB = function (rgb) { - return { - r: Math.min(255, Math.max(0, rgb.r)), - g: Math.min(255, Math.max(0, rgb.g)), - b: Math.min(255, Math.max(0, rgb.b)) - }; - }, - fixHex = function (hex) { - var len = 6 - hex.length; - if (len > 0) { - var o = []; - for (var i=0; i -1) ? hex.substring(1) : hex), 16); - return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)}; - }, - HexToHSB = function (hex) { - return RGBToHSB(HexToRGB(hex)); - }, - RGBToHSB = function (rgb) { - var hsb = { - h: 0, - s: 0, - b: 0 - }; - var min = Math.min(rgb.r, rgb.g, rgb.b); - var max = Math.max(rgb.r, rgb.g, rgb.b); - var delta = max - min; - hsb.b = max; - if (max != 0) { - - } - hsb.s = max != 0 ? 255 * delta / max : 0; - if (hsb.s != 0) { - if (rgb.r == max) { - hsb.h = (rgb.g - rgb.b) / delta; - } else if (rgb.g == max) { - hsb.h = 2 + (rgb.b - rgb.r) / delta; - } else { - hsb.h = 4 + (rgb.r - rgb.g) / delta; - } - } else { - hsb.h = -1; - } - hsb.h *= 60; - if (hsb.h < 0) { - hsb.h += 360; - } - hsb.s *= 100/255; - hsb.b *= 100/255; - return hsb; - }, - HSBToRGB = function (hsb) { - var rgb = {}; - var h = Math.round(hsb.h); - var s = Math.round(hsb.s*255/100); - var v = Math.round(hsb.b*255/100); - if(s == 0) { - rgb.r = rgb.g = rgb.b = v; - } else { - var t1 = v; - var t2 = (255-s)*v/255; - var t3 = (t1-t2)*(h%60)/60; - if(h==360) h = 0; - if(h<60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3} - else if(h<120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3} - else if(h<180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3} - else if(h<240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3} - else if(h<300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3} - else if(h<360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3} - else {rgb.r=0; rgb.g=0; rgb.b=0} - } - return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)}; - }, - RGBToHex = function (rgb) { - var hex = [ - rgb.r.toString(16), - rgb.g.toString(16), - rgb.b.toString(16) - ]; - $.each(hex, function (nr, val) { - if (val.length == 1) { - hex[nr] = '0' + val; - } - }); - return hex.join(''); - }, - HSBToHex = function (hsb) { - return RGBToHex(HSBToRGB(hsb)); - }, - restoreOriginal = function () { - var cal = $(this).parent(); - var col = cal.data('colorpicker').origColor; - cal.data('colorpicker').color = col; - fillRGBFields(col, cal.get(0)); - fillHexFields(col, cal.get(0)); - fillHSBFields(col, cal.get(0)); - setSelector(col, cal.get(0)); - setHue(col, cal.get(0)); - setNewColor(col, cal.get(0)); - }; - return { - init: function (opt) { - opt = $.extend({}, defaults, opt||{}); - if (typeof opt.color == 'string') { - opt.color = HexToHSB(opt.color); - } else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) { - opt.color = RGBToHSB(opt.color); - } else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) { - opt.color = fixHSB(opt.color); - } else { - return this; - } - return this.each(function () { - if (!$(this).data('colorpickerId')) { - var options = $.extend({}, opt); - options.origColor = opt.color; - var id = 'collorpicker_' + parseInt(Math.random() * 1000); - $(this).data('colorpickerId', id); - var cal = $(tpl).attr('id', id); - if (options.flat) { - cal.appendTo(this).show(); - } else { - cal.appendTo(document.body); - } - options.fields = cal - .find('input') - .bind('keyup', keyDown) - .bind('change', change) - .bind('blur', blur) - .bind('focus', focus); - cal - .find('span').bind('mousedown', downIncrement).end() - .find('>div.colorpicker_current_color').bind('click', restoreOriginal); - options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector); - options.selectorIndic = options.selector.find('div div'); - options.el = this; - options.hue = cal.find('div.colorpicker_hue div'); - cal.find('div.colorpicker_hue').bind('mousedown', downHue); - options.newColor = cal.find('div.colorpicker_new_color'); - options.currentColor = cal.find('div.colorpicker_current_color'); - cal.data('colorpicker', options); - cal.find('div.colorpicker_submit') - .bind('mouseenter', enterSubmit) - .bind('mouseleave', leaveSubmit) - .bind('click', clickSubmit); - fillRGBFields(options.color, cal.get(0)); - fillHSBFields(options.color, cal.get(0)); - fillHexFields(options.color, cal.get(0)); - setHue(options.color, cal.get(0)); - setSelector(options.color, cal.get(0)); - setCurrentColor(options.color, cal.get(0)); - setNewColor(options.color, cal.get(0)); - if (options.flat) { - cal.css({ - position: 'relative', - display: 'block' - }); - } else { - $(this).bind(options.eventName, show); - } - } - }); - }, - showPicker: function() { - return this.each( function () { - if ($(this).data('colorpickerId')) { - show.apply(this); - } - }); - }, - hidePicker: function() { - return this.each( function () { - if ($(this).data('colorpickerId')) { - $('#' + $(this).data('colorpickerId')).hide(); - } - }); - }, - setColor: function(col) { - if (typeof col == 'string') { - col = HexToHSB(col); - } else if (col.r != undefined && col.g != undefined && col.b != undefined) { - col = RGBToHSB(col); - } else if (col.h != undefined && col.s != undefined && col.b != undefined) { - col = fixHSB(col); - } else { - return this; - } - return this.each(function(){ - if ($(this).data('colorpickerId')) { - var cal = $('#' + $(this).data('colorpickerId')); - cal.data('colorpicker').color = col; - cal.data('colorpicker').origColor = col; - fillRGBFields(col, cal.get(0)); - fillHSBFields(col, cal.get(0)); - fillHexFields(col, cal.get(0)); - setHue(col, cal.get(0)); - setSelector(col, cal.get(0)); - setCurrentColor(col, cal.get(0)); - setNewColor(col, cal.get(0)); - } - }); - } - }; - }(); - $.fn.extend({ - ColorPicker: ColorPicker.init, - ColorPickerHide: ColorPicker.hidePicker, - ColorPickerShow: ColorPicker.showPicker, - ColorPickerSetColor: ColorPicker.setColor - }); -})(jQuery) \ No newline at end of file diff --git a/site/modules/ColorPicker/colorpicker/js/colorpicker.min.js b/site/modules/ColorPicker/colorpicker/js/colorpicker.min.js deleted file mode 100644 index f0bfb30..0000000 --- a/site/modules/ColorPicker/colorpicker/js/colorpicker.min.js +++ /dev/null @@ -1,24 +0,0 @@ -(function($){var ColorPicker=function(){var ids={},inAction,charMin=65,visible,tpl='
', -defaults={eventName:"click",onShow:function(){},onBeforeShow:function(){},onHide:function(){},onChange:function(){},onSubmit:function(){},color:"ff0000",livePreview:true,flat:false},fillRGBFields=function(hsb,cal){var rgb=HSBToRGB(hsb);$(cal).data("colorpicker").fields.eq(1).val(rgb.r).end().eq(2).val(rgb.g).end().eq(3).val(rgb.b).end()},fillHSBFields=function(hsb,cal){$(cal).data("colorpicker").fields.eq(4).val(hsb.h).end().eq(5).val(hsb.s).end().eq(6).val(hsb.b).end()},fillHexFields=function(hsb, -cal){$(cal).data("colorpicker").fields.eq(0).val(HSBToHex(hsb)).end()},setSelector=function(hsb,cal){$(cal).data("colorpicker").selector.css("backgroundColor","#"+HSBToHex({h:hsb.h,s:100,b:100}));$(cal).data("colorpicker").selectorIndic.css({left:parseInt(150*hsb.s/100,10),top:parseInt(150*(100-hsb.b)/100,10)})},setHue=function(hsb,cal){$(cal).data("colorpicker").hue.css("top",parseInt(150-150*hsb.h/360,10))},setCurrentColor=function(hsb,cal){$(cal).data("colorpicker").currentColor.css("backgroundColor", -"#"+HSBToHex(hsb))},setNewColor=function(hsb,cal){$(cal).data("colorpicker").newColor.css("backgroundColor","#"+HSBToHex(hsb))},keyDown=function(ev){var pressedKey=ev.charCode||ev.keyCode||-1;if(pressedKey>charMin&&pressedKey<=90||pressedKey==32)return false;var cal=$(this).parent().parent();if(cal.data("colorpicker").livePreview===true)change.apply(this)},change=function(ev){var cal=$(this).parent().parent(),col;if(this.parentNode.className.indexOf("_hex")>0)cal.data("colorpicker").color=col=HexToHSB(fixHex(this.value)); -else if(this.parentNode.className.indexOf("_hsb")>0)cal.data("colorpicker").color=col=fixHSB({h:parseInt(cal.data("colorpicker").fields.eq(4).val(),10),s:parseInt(cal.data("colorpicker").fields.eq(5).val(),10),b:parseInt(cal.data("colorpicker").fields.eq(6).val(),10)});else cal.data("colorpicker").color=col=RGBToHSB(fixRGB({r:parseInt(cal.data("colorpicker").fields.eq(1).val(),10),g:parseInt(cal.data("colorpicker").fields.eq(2).val(),10),b:parseInt(cal.data("colorpicker").fields.eq(3).val(),10)})); -if(ev){fillRGBFields(col,cal.get(0));fillHexFields(col,cal.get(0));fillHSBFields(col,cal.get(0))}setSelector(col,cal.get(0));setHue(col,cal.get(0));setNewColor(col,cal.get(0));cal.data("colorpicker").onChange.apply(cal,[col,HSBToHex(col),HSBToRGB(col)])},blur=function(ev){var cal=$(this).parent().parent();cal.data("colorpicker").fields.parent().removeClass("colorpicker_focus")},focus=function(){charMin=this.parentNode.className.indexOf("_hex")>0?70:65;$(this).parent().parent().data("colorpicker").fields.parent().removeClass("colorpicker_focus"); -$(this).parent().addClass("colorpicker_focus")},downIncrement=function(ev){var field=$(this).parent().find("input").focus();var current={el:$(this).parent().addClass("colorpicker_slider"),max:this.parentNode.className.indexOf("_hsb_h")>0?360:this.parentNode.className.indexOf("_hsb")>0?100:255,y:ev.pageY,field:field,val:parseInt(field.val(),10),preview:$(this).parent().parent().data("colorpicker").livePreview};$(document).bind("mouseup",current,upIncrement);$(document).bind("mousemove",current,moveIncrement)}, -moveIncrement=function(ev){ev.data.field.val(Math.max(0,Math.min(ev.data.max,parseInt(ev.data.val+ev.pageY-ev.data.y,10))));if(ev.data.preview)change.apply(ev.data.field.get(0),[true]);return false},upIncrement=function(ev){change.apply(ev.data.field.get(0),[true]);ev.data.el.removeClass("colorpicker_slider").find("input").focus();$(document).unbind("mouseup",upIncrement);$(document).unbind("mousemove",moveIncrement);return false},downHue=function(ev){var current={cal:$(this).parent(),y:$(this).offset().top}; -current.preview=current.cal.data("colorpicker").livePreview;$(document).bind("mouseup",current,upHue);$(document).bind("mousemove",current,moveHue)},moveHue=function(ev){change.apply(ev.data.cal.data("colorpicker").fields.eq(4).val(parseInt(360*(150-Math.max(0,Math.min(150,ev.pageY-ev.data.y)))/150,10)).get(0),[ev.data.preview]);return false},upHue=function(ev){fillRGBFields(ev.data.cal.data("colorpicker").color,ev.data.cal.get(0));fillHexFields(ev.data.cal.data("colorpicker").color,ev.data.cal.get(0)); -$(document).unbind("mouseup",upHue);$(document).unbind("mousemove",moveHue);return false},downSelector=function(ev){var current={cal:$(this).parent(),pos:$(this).offset()};current.preview=current.cal.data("colorpicker").livePreview;$(document).bind("mouseup",current,upSelector);$(document).bind("mousemove",current,moveSelector)},moveSelector=function(ev){change.apply(ev.data.cal.data("colorpicker").fields.eq(6).val(parseInt(100*(150-Math.max(0,Math.min(150,ev.pageY-ev.data.pos.top)))/150,10)).end().eq(5).val(parseInt(100* -Math.max(0,Math.min(150,ev.pageX-ev.data.pos.left))/150,10)).get(0),[ev.data.preview]);return false},upSelector=function(ev){fillRGBFields(ev.data.cal.data("colorpicker").color,ev.data.cal.get(0));fillHexFields(ev.data.cal.data("colorpicker").color,ev.data.cal.get(0));$(document).unbind("mouseup",upSelector);$(document).unbind("mousemove",moveSelector);return false},enterSubmit=function(ev){$(this).addClass("colorpicker_focus")},leaveSubmit=function(ev){$(this).removeClass("colorpicker_focus")},clickSubmit= -function(ev){var cal=$(this).parent();var col=cal.data("colorpicker").color;cal.data("colorpicker").origColor=col;setCurrentColor(col,cal.get(0));cal.data("colorpicker").onSubmit(col,HSBToHex(col),HSBToRGB(col),cal.data("colorpicker").el)},show=function(ev){var cal=$("#"+$(this).data("colorpickerId"));cal.data("colorpicker").onBeforeShow.apply(this,[cal.get(0)]);var pos=$(this).offset();var viewPort=getViewport();var top=pos.top+this.offsetHeight;var left=pos.left;if(top+176>viewPort.t+viewPort.h)top-= -this.offsetHeight+176;if(left+356>viewPort.l+viewPort.w)left-=356;cal.css({left:left+"px",top:top+"px"});if(cal.data("colorpicker").onShow.apply(this,[cal.get(0)])!=false)cal.show();$(document).bind("mousedown",{cal:cal},hide);return false},hide=function(ev){if(!isChildOf(ev.data.cal.get(0),ev.target,ev.data.cal.get(0))){if(ev.data.cal.data("colorpicker").onHide.apply(this,[ev.data.cal.get(0)])!=false)ev.data.cal.hide();$(document).unbind("mousedown",hide)}},isChildOf=function(parentEl,el,container){if(parentEl== -el)return true;if(parentEl.contains)return parentEl.contains(el);if(parentEl.compareDocumentPosition)return!!(parentEl.compareDocumentPosition(el)&16);var prEl=el.parentNode;while(prEl&&prEl!=container){if(prEl==parentEl)return true;prEl=prEl.parentNode}return false},getViewport=function(){var m=document.compatMode=="CSS1Compat";return{l:window.pageXOffset||(m?document.documentElement.scrollLeft:document.body.scrollLeft),t:window.pageYOffset||(m?document.documentElement.scrollTop:document.body.scrollTop), -w:window.innerWidth||(m?document.documentElement.clientWidth:document.body.clientWidth),h:window.innerHeight||(m?document.documentElement.clientHeight:document.body.clientHeight)}},fixHSB=function(hsb){return{h:Math.min(360,Math.max(0,hsb.h)),s:Math.min(100,Math.max(0,hsb.s)),b:Math.min(100,Math.max(0,hsb.b))}},fixRGB=function(rgb){return{r:Math.min(255,Math.max(0,rgb.r)),g:Math.min(255,Math.max(0,rgb.g)),b:Math.min(255,Math.max(0,rgb.b))}},fixHex=function(hex){var len=6-hex.length;if(len>0){var o= -[];for(var i=0;i-1?hex.substring(1):hex,16);return{r:hex>>16,g:(hex&65280)>>8,b:hex&255}},HexToHSB=function(hex){return RGBToHSB(HexToRGB(hex))},RGBToHSB=function(rgb){var hsb={h:0,s:0,b:0};var min=Math.min(rgb.r,rgb.g,rgb.b);var max=Math.max(rgb.r,rgb.g,rgb.b);var delta=max-min;hsb.b=max;if(max!=0);hsb.s=max!=0?255*delta/max:0;if(hsb.s!=0)if(rgb.r==max)hsb.h=(rgb.g-rgb.b)/delta;else if(rgb.g== -max)hsb.h=2+(rgb.b-rgb.r)/delta;else hsb.h=4+(rgb.r-rgb.g)/delta;else hsb.h=-1;hsb.h*=60;if(hsb.h<0)hsb.h+=360;hsb.s*=100/255;hsb.b*=100/255;return hsb},HSBToRGB=function(hsb){var rgb={};var h=Math.round(hsb.h);var s=Math.round(hsb.s*255/100);var v=Math.round(hsb.b*255/100);if(s==0)rgb.r=rgb.g=rgb.b=v;else{var t1=v;var t2=(255-s)*v/255;var t3=(t1-t2)*(h%60)/60;if(h==360)h=0;if(h<60){rgb.r=t1;rgb.b=t2;rgb.g=t2+t3}else if(h<120){rgb.g=t1;rgb.b=t2;rgb.r=t1-t3}else if(h<180){rgb.g=t1;rgb.r=t2;rgb.b=t2+ -t3}else if(h<240){rgb.b=t1;rgb.r=t2;rgb.g=t1-t3}else if(h<300){rgb.b=t1;rgb.g=t2;rgb.r=t2+t3}else if(h<360){rgb.r=t1;rgb.g=t2;rgb.b=t1-t3}else{rgb.r=0;rgb.g=0;rgb.b=0}}return{r:Math.round(rgb.r),g:Math.round(rgb.g),b:Math.round(rgb.b)}},RGBToHex=function(rgb){var hex=[rgb.r.toString(16),rgb.g.toString(16),rgb.b.toString(16)];$.each(hex,function(nr,val){if(val.length==1)hex[nr]="0"+val});return hex.join("")},HSBToHex=function(hsb){return RGBToHex(HSBToRGB(hsb))},restoreOriginal=function(){var cal= -$(this).parent();var col=cal.data("colorpicker").origColor;cal.data("colorpicker").color=col;fillRGBFields(col,cal.get(0));fillHexFields(col,cal.get(0));fillHSBFields(col,cal.get(0));setSelector(col,cal.get(0));setHue(col,cal.get(0));setNewColor(col,cal.get(0))};return{init:function(opt){opt=$.extend({},defaults,opt||{});if(typeof opt.color=="string")opt.color=HexToHSB(opt.color);else if(opt.color.r!=undefined&&opt.color.g!=undefined&&opt.color.b!=undefined)opt.color=RGBToHSB(opt.color);else if(opt.color.h!= -undefined&&opt.color.s!=undefined&&opt.color.b!=undefined)opt.color=fixHSB(opt.color);else return this;return this.each(function(){if(!$(this).data("colorpickerId")){var options=$.extend({},opt);options.origColor=opt.color;var id="collorpicker_"+parseInt(Math.random()*1E3);$(this).data("colorpickerId",id);var cal=$(tpl).attr("id",id);if(options.flat)cal.appendTo(this).show();else cal.appendTo(document.body);options.fields=cal.find("input").bind("keyup",keyDown).bind("change",change).bind("blur",blur).bind("focus", -focus);cal.find("span").bind("mousedown",downIncrement).end().find(">div.colorpicker_current_color").bind("click",restoreOriginal);options.selector=cal.find("div.colorpicker_color").bind("mousedown",downSelector);options.selectorIndic=options.selector.find("div div");options.el=this;options.hue=cal.find("div.colorpicker_hue div");cal.find("div.colorpicker_hue").bind("mousedown",downHue);options.newColor=cal.find("div.colorpicker_new_color");options.currentColor=cal.find("div.colorpicker_current_color"); -cal.data("colorpicker",options);cal.find("div.colorpicker_submit").bind("mouseenter",enterSubmit).bind("mouseleave",leaveSubmit).bind("click",clickSubmit);fillRGBFields(options.color,cal.get(0));fillHSBFields(options.color,cal.get(0));fillHexFields(options.color,cal.get(0));setHue(options.color,cal.get(0));setSelector(options.color,cal.get(0));setCurrentColor(options.color,cal.get(0));setNewColor(options.color,cal.get(0));if(options.flat)cal.css({position:"relative",display:"block"});else $(this).bind(options.eventName, -show)}})},showPicker:function(){return this.each(function(){if($(this).data("colorpickerId"))show.apply(this)})},hidePicker:function(){return this.each(function(){if($(this).data("colorpickerId"))$("#"+$(this).data("colorpickerId")).hide()})},setColor:function(col){if(typeof col=="string")col=HexToHSB(col);else if(col.r!=undefined&&col.g!=undefined&&col.b!=undefined)col=RGBToHSB(col);else if(col.h!=undefined&&col.s!=undefined&&col.b!=undefined)col=fixHSB(col);else return this;return this.each(function(){if($(this).data("colorpickerId")){var cal= -$("#"+$(this).data("colorpickerId"));cal.data("colorpicker").color=col;cal.data("colorpicker").origColor=col;fillRGBFields(col,cal.get(0));fillHSBFields(col,cal.get(0));fillHexFields(col,cal.get(0));setHue(col,cal.get(0));setSelector(col,cal.get(0));setCurrentColor(col,cal.get(0));setNewColor(col,cal.get(0))}})}}}();$.fn.extend({ColorPicker:ColorPicker.init,ColorPickerHide:ColorPicker.hidePicker,ColorPickerShow:ColorPicker.showPicker,ColorPickerSetColor:ColorPicker.setColor})})(jQuery); \ No newline at end of file diff --git a/site/modules/ColorPicker/colorpicker/js/eye.js b/site/modules/ColorPicker/colorpicker/js/eye.js deleted file mode 100644 index ea70e64..0000000 --- a/site/modules/ColorPicker/colorpicker/js/eye.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * - * Zoomimage - * Author: Stefan Petre www.eyecon.ro - * - */ -(function($){ - var EYE = window.EYE = function() { - var _registered = { - init: [] - }; - return { - init: function() { - $.each(_registered.init, function(nr, fn){ - fn.call(); - }); - }, - extend: function(prop) { - for (var i in prop) { - if (prop[i] != undefined) { - this[i] = prop[i]; - } - } - }, - register: function(fn, type) { - if (!_registered[type]) { - _registered[type] = []; - } - _registered[type].push(fn); - } - }; - }(); - $(EYE.init); -})(jQuery); diff --git a/site/modules/ColorPicker/colorpicker/js/layout.js b/site/modules/ColorPicker/colorpicker/js/layout.js deleted file mode 100644 index e0dfb8f..0000000 --- a/site/modules/ColorPicker/colorpicker/js/layout.js +++ /dev/null @@ -1,67 +0,0 @@ -(function($){ - var initLayout = function() { - var hash = window.location.hash.replace('#', ''); - var currentTab = $('ul.navigationTabs a') - .bind('click', showTab) - .filter('a[rel=' + hash + ']'); - if (currentTab.size() == 0) { - currentTab = $('ul.navigationTabs a:first'); - } - showTab.apply(currentTab.get(0)); - $('#colorpickerHolder').ColorPicker({flat: true}); - $('#colorpickerHolder2').ColorPicker({ - flat: true, - color: '#00ff00', - onSubmit: function(hsb, hex, rgb) { - $('#colorSelector2 div').css('backgroundColor', '#' + hex); - } - }); - $('#colorpickerHolder2>div').css('position', 'absolute'); - var widt = false; - $('#colorSelector2').bind('click', function() { - $('#colorpickerHolder2').stop().animate({height: widt ? 0 : 173}, 500); - widt = !widt; - }); - $('#colorpickerField1, #colorpickerField2, #colorpickerField3').ColorPicker({ - onSubmit: function(hsb, hex, rgb, el) { - $(el).val(hex); - $(el).ColorPickerHide(); - }, - onBeforeShow: function () { - $(this).ColorPickerSetColor(this.value); - } - }) - .bind('keyup', function(){ - $(this).ColorPickerSetColor(this.value); - }); - $('#colorSelector').ColorPicker({ - color: '#0000ff', - onShow: function (colpkr) { - $(colpkr).fadeIn(500); - return false; - }, - onHide: function (colpkr) { - $(colpkr).fadeOut(500); - return false; - }, - onChange: function (hsb, hex, rgb) { - $('#colorSelector div').css('backgroundColor', '#' + hex); - } - }); - }; - - var showTab = function(e) { - var tabIndex = $('ul.navigationTabs a') - .removeClass('active') - .index(this); - $(this) - .addClass('active') - .blur(); - $('div.tab') - .hide() - .eq(tabIndex) - .show(); - }; - - EYE.register(initLayout, 'init'); -})(jQuery) \ No newline at end of file diff --git a/site/modules/ColorPicker/colorpicker/js/utils.js b/site/modules/ColorPicker/colorpicker/js/utils.js deleted file mode 100644 index cc7ce14..0000000 --- a/site/modules/ColorPicker/colorpicker/js/utils.js +++ /dev/null @@ -1,252 +0,0 @@ -/** - * - * Utilities - * Author: Stefan Petre www.eyecon.ro - * - */ -(function($) { -EYE.extend({ - getPosition : function(e, forceIt) - { - var x = 0; - var y = 0; - var es = e.style; - var restoreStyles = false; - if (forceIt && jQuery.curCSS(e,'display') == 'none') { - var oldVisibility = es.visibility; - var oldPosition = es.position; - restoreStyles = true; - es.visibility = 'hidden'; - es.display = 'block'; - es.position = 'absolute'; - } - var el = e; - if (el.getBoundingClientRect) { // IE - var box = el.getBoundingClientRect(); - x = box.left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) - 2; - y = box.top + Math.max(document.documentElement.scrollTop, document.body.scrollTop) - 2; - } else { - x = el.offsetLeft; - y = el.offsetTop; - el = el.offsetParent; - if (e != el) { - while (el) { - x += el.offsetLeft; - y += el.offsetTop; - el = el.offsetParent; - } - } - if (jQuery.browser.safari && jQuery.curCSS(e, 'position') == 'absolute' ) { - x -= document.body.offsetLeft; - y -= document.body.offsetTop; - } - el = e.parentNode; - while (el && el.tagName.toUpperCase() != 'BODY' && el.tagName.toUpperCase() != 'HTML') - { - if (jQuery.curCSS(el, 'display') != 'inline') { - x -= el.scrollLeft; - y -= el.scrollTop; - } - el = el.parentNode; - } - } - if (restoreStyles == true) { - es.display = 'none'; - es.position = oldPosition; - es.visibility = oldVisibility; - } - return {x:x, y:y}; - }, - getSize : function(e) - { - var w = parseInt(jQuery.curCSS(e,'width'), 10); - var h = parseInt(jQuery.curCSS(e,'height'), 10); - var wb = 0; - var hb = 0; - if (jQuery.curCSS(e, 'display') != 'none') { - wb = e.offsetWidth; - hb = e.offsetHeight; - } else { - var es = e.style; - var oldVisibility = es.visibility; - var oldPosition = es.position; - es.visibility = 'hidden'; - es.display = 'block'; - es.position = 'absolute'; - wb = e.offsetWidth; - hb = e.offsetHeight; - es.display = 'none'; - es.position = oldPosition; - es.visibility = oldVisibility; - } - return {w:w, h:h, wb:wb, hb:hb}; - }, - getClient : function(e) - { - var h, w; - if (e) { - w = e.clientWidth; - h = e.clientHeight; - } else { - var de = document.documentElement; - w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth; - h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight; - } - return {w:w,h:h}; - }, - getScroll : function (e) - { - var t=0, l=0, w=0, h=0, iw=0, ih=0; - if (e && e.nodeName.toLowerCase() != 'body') { - t = e.scrollTop; - l = e.scrollLeft; - w = e.scrollWidth; - h = e.scrollHeight; - } else { - if (document.documentElement) { - t = document.documentElement.scrollTop; - l = document.documentElement.scrollLeft; - w = document.documentElement.scrollWidth; - h = document.documentElement.scrollHeight; - } else if (document.body) { - t = document.body.scrollTop; - l = document.body.scrollLeft; - w = document.body.scrollWidth; - h = document.body.scrollHeight; - } - if (typeof pageYOffset != 'undefined') { - t = pageYOffset; - l = pageXOffset; - } - iw = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0; - ih = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0; - } - return { t: t, l: l, w: w, h: h, iw: iw, ih: ih }; - }, - getMargins : function(e, toInteger) - { - var t = jQuery.curCSS(e,'marginTop') || ''; - var r = jQuery.curCSS(e,'marginRight') || ''; - var b = jQuery.curCSS(e,'marginBottom') || ''; - var l = jQuery.curCSS(e,'marginLeft') || ''; - if (toInteger) - return { - t: parseInt(t, 10)||0, - r: parseInt(r, 10)||0, - b: parseInt(b, 10)||0, - l: parseInt(l, 10) - }; - else - return {t: t, r: r, b: b, l: l}; - }, - getPadding : function(e, toInteger) - { - var t = jQuery.curCSS(e,'paddingTop') || ''; - var r = jQuery.curCSS(e,'paddingRight') || ''; - var b = jQuery.curCSS(e,'paddingBottom') || ''; - var l = jQuery.curCSS(e,'paddingLeft') || ''; - if (toInteger) - return { - t: parseInt(t, 10)||0, - r: parseInt(r, 10)||0, - b: parseInt(b, 10)||0, - l: parseInt(l, 10) - }; - else - return {t: t, r: r, b: b, l: l}; - }, - getBorder : function(e, toInteger) - { - var t = jQuery.curCSS(e,'borderTopWidth') || ''; - var r = jQuery.curCSS(e,'borderRightWidth') || ''; - var b = jQuery.curCSS(e,'borderBottomWidth') || ''; - var l = jQuery.curCSS(e,'borderLeftWidth') || ''; - if (toInteger) - return { - t: parseInt(t, 10)||0, - r: parseInt(r, 10)||0, - b: parseInt(b, 10)||0, - l: parseInt(l, 10)||0 - }; - else - return {t: t, r: r, b: b, l: l}; - }, - traverseDOM : function(nodeEl, func) - { - func(nodeEl); - nodeEl = nodeEl.firstChild; - while(nodeEl){ - EYE.traverseDOM(nodeEl, func); - nodeEl = nodeEl.nextSibling; - } - }, - getInnerWidth : function(el, scroll) { - var offsetW = el.offsetWidth; - return scroll ? Math.max(el.scrollWidth,offsetW) - offsetW + el.clientWidth:el.clientWidth; - }, - getInnerHeight : function(el, scroll) { - var offsetH = el.offsetHeight; - return scroll ? Math.max(el.scrollHeight,offsetH) - offsetH + el.clientHeight:el.clientHeight; - }, - getExtraWidth : function(el) { - if($.boxModel) - return (parseInt($.curCSS(el, 'paddingLeft'))||0) - + (parseInt($.curCSS(el, 'paddingRight'))||0) - + (parseInt($.curCSS(el, 'borderLeftWidth'))||0) - + (parseInt($.curCSS(el, 'borderRightWidth'))||0); - return 0; - }, - getExtraHeight : function(el) { - if($.boxModel) - return (parseInt($.curCSS(el, 'paddingTop'))||0) - + (parseInt($.curCSS(el, 'paddingBottom'))||0) - + (parseInt($.curCSS(el, 'borderTopWidth'))||0) - + (parseInt($.curCSS(el, 'borderBottomWidth'))||0); - return 0; - }, - isChildOf: function(parentEl, el, container) { - if (parentEl == el) { - return true; - } - if (!el || !el.nodeType || el.nodeType != 1) { - return false; - } - if (parentEl.contains && !$.browser.safari) { - return parentEl.contains(el); - } - if ( parentEl.compareDocumentPosition ) { - return !!(parentEl.compareDocumentPosition(el) & 16); - } - var prEl = el.parentNode; - while(prEl && prEl != container) { - if (prEl == parentEl) - return true; - prEl = prEl.parentNode; - } - return false; - }, - centerEl : function(el, axis) - { - var clientScroll = EYE.getScroll(); - var size = EYE.getSize(el); - if (!axis || axis == 'vertically') - $(el).css( - { - top: clientScroll.t + ((Math.min(clientScroll.h,clientScroll.ih) - size.hb)/2) + 'px' - } - ); - if (!axis || axis == 'horizontally') - $(el).css( - { - left: clientScroll.l + ((Math.min(clientScroll.w,clientScroll.iw) - size.wb)/2) + 'px' - } - ); - } -}); -if (!$.easing.easeout) { - $.easing.easeout = function(p, n, firstNum, delta, duration) { - return -delta * ((n=n/duration-1)*n*n*n - 1) + firstNum; - }; -} - -})(jQuery); \ No newline at end of file diff --git a/site/modules/ColorPicker/pw-colorpicker.jpg b/site/modules/ColorPicker/pw-colorpicker.jpg deleted file mode 100644 index 87241ae752bbb62330b61f32848144774f326fcf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94759 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 gKK$6NbT?{FPIQt(b diff --git a/site/modules/FieldtypeColor/.gitattributes b/site/modules/FieldtypeColor/.gitattributes new file mode 100644 index 0000000..ab85459 --- /dev/null +++ b/site/modules/FieldtypeColor/.gitattributes @@ -0,0 +1,4 @@ +# Auto detect text files and perform LF normalization +* text=auto +# Show correct language for ProcessWire .module +*.module linguist-language=PHP diff --git a/site/modules/FieldtypeColor/.gitignore b/site/modules/FieldtypeColor/.gitignore new file mode 100644 index 0000000..a866f03 --- /dev/null +++ b/site/modules/FieldtypeColor/.gitignore @@ -0,0 +1,5 @@ +dematte/* +jscolor-2.0.4/* +colorpicker/* +InputfieldColor.js +.DS_Store diff --git a/site/modules/FieldtypeColor/FieldtypeColor.module b/site/modules/FieldtypeColor/FieldtypeColor.module new file mode 100644 index 0000000..fcc3903 --- /dev/null +++ b/site/modules/FieldtypeColor/FieldtypeColor.module @@ -0,0 +1,342 @@ + 'Color', + 'version' => 120, + 'summary' => 'Field that stores a color value as 32bit integer reflecting a RGBA value. Many options for Input (HTML5 Inputfield Color, Textfield with changing background, various jQuery/JS ColorPickers, custom jQuery/JS/CSS) and Output (RGB, RGBA, HSL, HSLA, HEX, Array).', + 'installs' => 'InputfieldColor', + 'href' => 'https://processwire.com/talk/topic/16679-fieldtypecolor/' + ); + } + + public function ___getCompatibleFieldtypes(Field $field) { + $fieldtypes = $this->wire(new Fieldtypes()); + foreach($this->wire('fieldtypes') as $fieldtype) { + if(!$fieldtype instanceof FieldtypeInteger && + !$fieldtype instanceof FieldtypeColor && + $fieldtype != 'FieldtypeText') { + $fieldtypes->remove($fieldtype); + } + } + return $fieldtypes; + } + + public function getInputfield(Page $page, Field $field) { + $inputfield = $this->modules->get('InputfieldColor'); + $inputfield->initValue = $this->sanitizeValue($page, $field, $field->defaultValue); + $inputfield->class = $this->className(); + return $inputfield; + } + + public function sanitizeValue(Page $page, Field $field, $value) { + return $this->_sanitizeValue($value); + } + + protected function _sanitizeValue($value) { + if (!$value) return $value; + $value = ltrim($value, '#'); + if (strlen($value) == 8) return $value; + else if (strlen($value) == 6) return 'ff'.$value; // add alpha channel + else throw New WireException('Expecting Hex color string (length 6 or 8 digits) with optional leading \'#\''); + } + + public function sleepValue(Page $page, Field $field, $value) { + return hexdec($value); + } + + public function wakeupValue(Page $page, Field $field, $value) { + if (!$value) return $value; + if (function_exists("bcmod")) return str_pad(self::bcdechex($value), 8, '0', STR_PAD_LEFT); // BCMath extension required + return str_pad(dechex($value), 8, '0', STR_PAD_LEFT); // 64-bit system required + } + + /** + * Converts a number from decimal to hex (BCMath extension required) + * returns precice result even if number is bigger than PHP_INT_MAX (safe for 32bit systems) + * + * @param int/string/float number + * @return string + * + * @see http://php.net/manual/en/ref.bc.php#99130 + */ + public static function bcdechex($dec) { + $last = bcmod("$dec", 16); + $remain = bcdiv(bcsub("$dec", $last), 16); + if($remain == 0) return dechex($last); + else return self::bcdechex($remain).dechex($last); + } + + /** + * Converts a RGB color value to HSL. Conversion formula + * @param array of 3 color values R, G, and B [0, 255] + * @return array The HSL representation + * + * @see https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion/9493060#9493060 + * @see http://en.wikipedia.org/wiki/HSL_color_space + */ + public function RGB2HSL(array $rgb) { + $rgb = array_map(function($v) { return $v/ 255; }, $rgb); + $max = max($rgb); + $min = min($rgb); + $hue = $sat = $light = ($max + $min) / 2; + + if($max == $min) { + $hue = $sat = 0; // achromatic + } else { + $d = $max - $min; + $sat = $light > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min); + switch($max) { + case $rgb[0]: + $hue = ($rgb[1] - $rgb[2]) / $d + ($rgb[1] < $rgb[1] ? 6 : 0); + break; + case $rgb[1]: + $hue = ($rgb[2] - $rgb[0]) / $d + 2; + break; + case $rgb[2]: + $hue = ($rgb[0] - $rgb[1]) / $d + 4; + break; + } + $hue = $hue / 6; + } + // round and convert float to string with dot as decimal separator in any language + $hue = str_replace(',', '.', round($hue * 360)); + $sat = str_replace(',', '.', round($sat * 100, 1)); + $light = str_replace(',', '.', round($light * 100, 1)); + + return [$hue, $sat, $light]; + } + + /** + * Find the "naive" difference between two colors. + * @see https://php.tutorialink.com/finding-nearest-match-rgb-color-from-array-of-colors/ + * @param int[] $color_a Three-element array with R,G,B color values 0-255. + * @param int[] $color_b Three-element array with R,G,B color values 0-255. + * @return int + */ + public function getColorDistance(array $color_a, array $color_b): int { + return + abs($color_a[0] - $color_b[0]) + + abs($color_a[1] - $color_b[1]) + + abs($color_a[2] - $color_b[2]); + } + + /** + * Find the difference between two colors' luminance values. + * @see https://php.tutorialink.com/finding-nearest-match-rgb-color-from-array-of-colors/ + * @param int[] $color_a Three-element array with R,G,B color values 0-255. + * @param int[] $color_b Three-element array with R,G,B color values 0-255. + * @return int + */ + public function getLuminanceDistance(array $color_a, array $color_b): int { + $luminance_f = function ($red, $green, $blue): int { + // Source: https://en.wikipedia.org/wiki/Relative_luminance + $luminance = (int) (0.2126 * $red + 0.7152 * $green + 0.0722 * $blue); + return $luminance; + }; + + return abs( + $luminance_f($color_a[0], $color_a[1], $color_a[2]) - + $luminance_f($color_b[0], $color_b[1], $color_b[2]) + ); + } + + /** + * Find the closest named color + * @param hexcolor + * @return string + */ + public function getClosestColorName(string $color) { + $color = ltrim($color, '#'); + if (strlen($color) == 6) $color = "ff$color"; + if (strlen($color) != 8) throw new WireException("Invalid parameter. Expected hex string of 6 or 8 digits length with or without leading '#'."); + $color = $this->formatColorString($color, 9); + $palette = json_decode(file_get_contents(__DIR__ . '/colornames.json'), true); + $min = 765; + $match = null; + foreach ($palette as $name => $pcolor) { + $pcolor = $this->formatColorString("ff$pcolor", 9); + if ($pcolor === $color) return $name; // quick exit if full match + $distance = $this->getColorDistance($pcolor, $color); + if ($distance >= $min) continue; + $min = $distance; + $match = $name; + } + return $match; + } + + /** + * Format value for output + * + */ + public function ___formatValue(Page $page, Field $field, $value) { + if (!$value) return null; + if ($field->outputFormat === 7) return $this->sleepValue($page, $field, $value); + return $this->formatColorString($value, $field->outputFormat); + } + + /** + * Format color string + * + * @param $value string - hex string of 8 chiffres, first 2 is the alpha channel + * @param $of int - output format + * @return string formatted color string + * @throws object WireException - if input doesn't match (check for length, detailed check in debug mode) + * + */ + public function formatColorString($value, $of = 0) { + $value = $this->_sanitizeValue($value); + // simple length check or preg_match in debug mode + if (strlen($value) != 8 || ($this->wire('config')->debug && !preg_match('/[A-Fa-f0-9]{8}/', $value))) { + throw new WireException("Invalid input: $value. Expected hex string of 8 digits length."); + } + + if ($of === 6) return $value; + if ($of === 0) return "#".substr($value,2); + if ($of === 1) return "#".$value; + + $hexVals = str_split($value, 2); + $value = array_map('hexdec', $hexVals); + + // opacity + $opacity = '0'; + if ($value[0] > 1 && in_array($of ,array(3,5,8,10,12))) { + $opacity = round($value[0] / 255, 2); // float + $opacity = rtrim(number_format($opacity, 2, '.', ''),'.0'); // convert float to string with dot as decimal separator + } + + if ($of === 9) return [$value[1], $value[2], $value[3]]; + if ($of === 10) return [$value[1], $value[2], $value[3], $opacity]; + + if ($of === 8) { + $assocArray = array( + 'o' => $opacity, + 'r' => $value[1], + 'g' => $value[2], + 'b' => $value[3], + 'ox' => $hexVals[0], + 'rx' => $hexVals[1], + 'gx' => $hexVals[2], + 'bx' => $hexVals[3], + ); + return array_merge($value, $assocArray); + } + + if ($of === 2) return "rgb($value[1], $value[2], $value[3])"; + if ($of === 3) return "rgba($value[1], $value[2], $value[3], $opacity)"; + + $hsl = $this->RGB2HSL(array_slice($value,1,3)); + + if ($of === 11) return $hsl; + + if ($of === 12) { + $hsla = $hsl; + $hsla[] = $opacity; + return $hsla; + } + + if ($of === 4) return "hsl($hsl[0], $hsl[1]%, $hsl[2]%)"; + if ($of === 5) return "hsla($hsl[0], $hsl[1]%, $hsl[2]%, $opacity)"; + } + + public function getDatabaseSchema(Field $field) { + $schema = parent::getDatabaseSchema($field); + $schema['data'] = "int UNSIGNED NOT NULL"; + return $schema; + } + + public function ___getConfigInputfields(Field $field) { + + $inputfields = $this->wire(new InputfieldWrapper()); + + $f = $this->wire('modules')->get('InputfieldRadios'); + $f->attr('name', 'outputFormat'); + $f->label = $this->_('Output Format'); + $f->description = $this->_('Choose your preferred output format.'); + + $f->addOption(0, $this->_('string 6-digit hex color *#4496dd*')); + $f->addOption(1, $this->_('string 8-digit hex color *#fa4496dd* (limited browser support)')); + $f->addOption(2, $this->_('string *rgb(68, 100, 221)*')); + $f->addOption(3, $this->_('string *rgba(68, 100, 221, 0.98)*')); + $f->addOption(4, $this->_('string *hsl(227, 69.2%, 56.7%)*')); + $f->addOption(5, $this->_('string *hsla(227, 69.2%, 56.7%, 0.98)*')); + $f->addOption(6, $this->_('string 8-digit raw hex *fa4496dd* (unformatted)')); + $f->addOption(7, $this->_('int 32bit (storage)')); + $f->addOption(8, $this->_('array(r[0,255], g[0,255], b[0,255], o[0,1], rx[00,ff], gx[00,ff], bx[00,ff], ox[00,ff])')); + $f->addOption(9, $this->_('array([0,255], [0,255], [0,255]) indexed array: R,G,B')); + $f->addOption(10, $this->_('array([0,255], [0,255], [0,255], [0,1]) indexed array: R,G,B,Alpha')); + $f->addOption(11, $this->_('array([0,360], [69.2%], [56.7%]) indexed array: H,S,L')); + $f->addOption(12, $this->_('array([0,360], [69.2%], [56.7%], [0,1]) indexed array: H,S,L,Alpha')); + + $f->attr('value', (int) $field->outputFormat); + $inputfields->add($f); + + $f = $this->wire('modules')->get('InputfieldColor'); + $f->attr('name', 'defaultValue'); + $f->label = $this->_('Default value'); + + $f->inputType = $field->inputType; + $f->spectrum = $field->spectrum; + $f->initJS = $field->initJS; + $f->fileJS = $field->fileJS; + $f->fileCSS = $field->fileCSS; + $f->jqueryCore = $field->jqueryCore; + $f->jqueryUI = $field->jqueryUI; + $f->alpha = $field->alpha; + + $f->description = $this->_('This value is assigned as the default for blank fields and on newly created pages.'); + $f->collapsed = Inputfield::collapsedBlank; + $f->attr('value', strlen($field->defaultValue ?? '') ? $this->sanitizeValue($this->wire('page'), $field, $field->defaultValue) : null); + + $inputfields->add($f); + + return $inputfields; + } + + public function ___install() { + if (function_exists("bcmod") === false && PHP_INT_SIZE < 8) { + throw new WireException($this->_('The BCMath extension is required if your system can not handle 64-bit integer values.')); + } + parent::___install(); + } +} \ No newline at end of file diff --git a/site/modules/FieldtypeColor/InputfieldColor.css b/site/modules/FieldtypeColor/InputfieldColor.css new file mode 100644 index 0000000..b0e7da5 --- /dev/null +++ b/site/modules/FieldtypeColor/InputfieldColor.css @@ -0,0 +1,9 @@ +.InputfieldColor input[type=color], input[type=color].FieldtypeColor, input[type=color]#Inputfield_defaultValue { + height:2em; + padding:0; +} + +.AdminThemeUikit .InputfieldColor input[type=color], .AdminThemeUikit input[type=color].FieldtypeColor, .AdminThemeUikit input[type=color]#Inputfield_defaultValue { + height:40px; + width: 100% !important; +} \ No newline at end of file diff --git a/site/modules/FieldtypeColor/InputfieldColor.module b/site/modules/FieldtypeColor/InputfieldColor.module new file mode 100644 index 0000000..24a7ec8 --- /dev/null +++ b/site/modules/FieldtypeColor/InputfieldColor.module @@ -0,0 +1,355 @@ + __('Color', __FILE__), // Module Title + 'summary' => __('Inputfield for colors', __FILE__), // Module Summary + 'version' => 117, + 'href' => 'https://processwire.com/talk/topic/16679-fieldtypecolor/' + ); + } + + /** + * Construct + * + * @throws WireException + * + */ + public function __construct() { + parent::__construct(); + $this->set('icon', 'paint-brush'); + $this->setAttribute('type', 'text'); + $this->setAttribute('size', 10); + $this->setAttribute('placeholder', '#000000'); + $this->setAttribute('pattern', '(#?[a-fA-F\d]{6})?'); + } + + public function init() { + $this->inputType = 0; + $this->spectrum = ''; + $this->initJS = ''; + $this->fileJS = ''; + $this->fileCSS = ''; + $this->jqueryCore = 0; + $this->jqueryUI = 0; + $this->alpha = 0; // int 0, 1 will be set dependend on inputType. To disable explicitly for inputType = 3 (spectrum color picker) set bool false + parent::init(); + } + + /** + * Called before the render method + * checking for SpectrumColorPicker + * + * @param Inputfield $parent + * @param bool $renderValueMode + * @return $this + * + */ + public function renderReady(Inputfield $parent = null, $renderValueMode = false) { + $url = $this->config->urls->get('InputfieldColor'); + switch ($this->inputType) { + case 3: + $this->wire('modules')->get('JqueryCore'); + $this->config->scripts->add($url . 'spectrum/spectrum.js'); + $this->config->styles->add($url . 'spectrum/spectrum.css'); + break; + case 4: + if ($this->jqueryCore) $this->wire('modules')->get('JqueryCore'); + if ($this->jqueryUI) $this->wire('modules')->get('JqueryUI'); + if ($this->fileJS) $this->config->scripts->add($url . $this->fileJS); + if ($this->fileCSS) $this->config->styles->add($url . $this->fileCSS); + break; + } + parent::renderReady($parent, $renderValueMode); + } + + /** + * get textcolor (light or dark) corresponding to the background for better contrast + * + * @param int/string $bgColor expecting string or int with 6 (24bit) or 8 (32bit) digits with or without leading '#' + * @param int/string $textColorLight default: '#fff' (white) + * @param int/string $textColorDark default: '#000' (black) + * @return string $color light or dark + * + */ + public function getTextColor($bgColor, $textColorLight = '#fff', $textColorDark = '#000') { + if (!is_string($bgColor)) return $textColorDark; + else if (!ctype_xdigit(ltrim($bgColor, '#'))) { + $bgColor = $this->convertColorName($bgColor); + if (false === $bgColor) return $textColorDark; + } + $bgColor = ltrim($bgColor, '#'); + $bgColor = str_pad($bgColor,8,'f',STR_PAD_LEFT); + $ARGB = array_map('hexdec', str_split($bgColor, 2)); + $opacity = round($ARGB[0] / 255, 2); + if ($opacity < 0.45) return $textColorDark; + return ($ARGB[1]+6*$ARGB[2]+$ARGB[3])*3/8 > 460? $textColorDark : $textColorLight; + } + + /** + * convert color name (hex -> html, html -> hex) + * + * @param $color + * @param $to convert to 'hex' or 'html' + * @return bool/ string + * + */ + public function convertColorName($color, $to = 'hex') { + $colorArray = $this->getX11ColorArray(); + if ($to = 'hex') { + $key = array_search($color, array_column($colorArray, 0)); + return empty($colorArray[$key][1])? false : $colorArray[$key][1]; + } + else if ($to = 'html') { + $key = array_search($color, array_column($colorArray, 1)); + return empty($colorArray[$key][0])? false : $colorArray[$key][0]; + } + return false; + } + + /** + * get multiple array with html color names and corresponding hex codes and rgb values + * + * @param $domain + * @param $path file path + * @return boolean + * + */ + protected function getX11ColorArray() { + $path = __DIR__ .'/x11color.txt'; + if (!file_exists($path)) throw new WireException("Missing file " . $path); + $array = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + if ($array === false) throw new WireException("Failed to open file: $path"); + return array_map(function($e) { + return explode("\t", $e); + }, $array); + } + + public function ___render() { + if ($this->value === "" && strlen($this->initValue ?? '')) $this->value = $this->initValue; + if (!$this->value) $this->value = null; + + if ($this->value) { + $this->value = str_pad(ltrim($this->value, '#'),8,'f',STR_PAD_LEFT); + $color32 = "#".$this->value; + $color24 = $bgColor = "#".substr($this->value,2,6); + $value = array_map('hexdec', str_split($this->value, 2)); + } else { + $color32 = $color24 = null; + $value = array(255,255,255,255); + $bgColor = '#fff'; + } + + $opacity = round($value[0] / 255, 2); + $opacity = $opacity? rtrim(number_format($opacity, 2, '.', ''),'.0') : '0'; + + $textColor = $this->getTextColor($this->value); + $rgba = "rgba($value[1], $value[2], $value[3], $opacity)"; + $this->attr('value', $color24); + $this->attr('data-input-type', $this->inputType); + + switch ($this->inputType) { + case 0: + $this->attr('type', 'color'); + break; + case 1: + $this->attr('style', "color: $textColor; background: $bgColor;"); + break; + case 2: + $this->alpha = 1; + $this->attr('value', $color32); + $this->attr('style', "color: $textColor; background: $bgColor; background-image: linear-gradient($rgba, $rgba), url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==');"); + $this->attr('placeholder', '#ff000000'); + $this->attr('pattern', '(#?[a-fA-F\d]{8})?'); + break; + case 3: + if ($this->alpha !== false) $this->alpha = 1; + if (!$color32) $color32 = '#00000000'; + $this->attr('value', $color32); + $this->attr('placeholder', '#ff000000'); + $this->removeAttr('pattern'); + break; + case 4: + if ($this->alpha) $this->attr('value', $color32); + else $this->attr('value', $color24); + } + + $attrs = $this->getAttributes(); + + $out = "getAttributesString($attrs) . " />"; + if( $this->inputType == 3) { + $options = $this->spectrum? str_replace(array(",\n","\n"),", ", trim($this->spectrum,",\t\n\r\0\x0B")).',' : ''; + $value = $color32? $color32 : null; + $format = $this->alpha? 'toHex8String' : 'toHexString'; + $out .= " + "; + } + if( $this->inputType == 4) { + $value = $color32? $color32 : null; + if ($this->initJS) { + $initJS = str_replace(array("{value}","{id}"), array($color24, $this->id), $this->initJS); + $out .= " + "; + } + } + return $out; + } + + public function ___processInput(WireInputData $input) { + parent::___processInput($input); + $value = $this->attr('value'); + if (!$value) return $this; + // bugfix (workaround): something went wrong in javascript spectrum + if (is_string($value) && in_array($value, ['hsva(0, 0%, 0%, 0)','hsla(0, 0%, 0%, 0)','rgba(0, 0, 0, 0)'])) { + $this->attr('value', '00000000'); + return $this; + } + $pattern = $this->alpha? '/#?[a-fA-F\d]{8}/' : '/#?[a-fA-F\d]{6}/'; + if(!preg_match($pattern, $value)) $this->error("Submitted value: $value does not match required pattern: $pattern."); + return $this; + + } + + public function getConfigInputfields() { + $inputfields = parent::getConfigInputfields(); + + $f = $this->wire('modules')->get('InputfieldRadios'); + $f->attr('name', 'inputType'); + $f->label = $this->_('Inputfieldtype'); + $f->addOption(0, $this->_('Inputfield type=\'color\' (HTML5 - limited browser support)')); + $f->addOption(1, $this->_('Inputfield type=\'text\' expects 24bit hexcode strings')); + $f->addOption(2, $this->_('Inputfield type=\'text\' expects 32bit hexcode strings (alpha channel)')); + $f->addOption(3, $this->_('Inputfield with Spectrum Color Picker (JavaScript)')); + $f->addOption(4, $this->_('Inputfield type=\'text\' with custom JavaScript and/or CSS')); + $f->attr('value', $this->inputType); + $f->description = $this->_(''); + $f->columnWidth = 50; + $inputfields->add($f); + + $f = $this->wire('modules')->get('InputfieldTextarea'); + $f->attr('name', 'spectrum'); + $f->attr('rows', 10); + $f->label = $this->_('Color Picker Options'); + $f->attr('value', $this->spectrum); + $f->description = $this->_('Set or modify options for the **Spectrum Color Picker**. [Read more ...](https://bgrins.github.io/spectrum/#options)'); + $f->notes = $this->_("One option per line in the format: 'option: value'. The options: 'color' and 'change' are used by the system and not modifiable."); + $f->columnWidth = 50; + $f->showIf = "inputType=3"; + $inputfields->add($f); + + $f = $this->wire('modules')->get('InputfieldTextarea'); + $f->attr('name', 'initJS'); + $f->attr('rows', 3); + $f->label = $this->_('Initial JS'); + $f->attr('value', $this->initJS); + $f->description = $this->_('JavaScript code initiating your custom JS color picker. Use {id} and {value} as placeholders for the related field attributes in your selector'); + $f->notes = sprintf($this->_('{id} will be replaced by the string "%s"'), $this->id); + $f->columnWidth = 33; + $f->showIf = "inputType=4"; + $f->requiredIf = "inputType=4"; + $inputfields->add($f); + + $rootUrl = $this->config->urls->get('InputfieldColor'); + + $f = $this->wire('modules')->get('InputfieldURL'); + $f->attr('name', 'fileJS'); + $f->label = $this->_('Include JS File'); + $f->attr('value', $this->fileJS); + $f->description = $this->_('Set the path to your custom JavaScript file.'); + $f->notes = sprintf($this->_('URL string relative to "%s"'), $rootUrl); + $f->columnWidth = 34; + $f->showIf = "inputType=4"; + $f->requiredIf = "inputType=4"; + $inputfields->add($f); + + $f = $this->wire('modules')->get('InputfieldURL'); + $f->attr('name', 'fileCSS'); + $f->label = $this->_('Include CSS File'); + $f->attr('value', $this->fileCSS); + $f->description = $this->_('Set the path to your custom stylesheet file.'); + $f->notes = sprintf($this->_('URL string relative to "%s"'), $rootUrl); + $f->columnWidth = 33; + $f->showIf = "inputType=4"; + $f->requiredIf = "inputType=4"; + $inputfields->add($f); + + $f = $this->modules->get('InputfieldCheckbox'); + $f->attr('name', 'jqueryCore'); + $f->label = __('Enable JqueryCore'); + $f->attr('checked', $this->jqueryCore ? 'checked' : '' ); + $f->columnWidth = 33; + $f->showIf = "inputType=4"; + $inputfields->append($f); + + $f = $this->modules->get('InputfieldCheckbox'); + $f->attr('name', 'jqueryUI'); + $f->label = __('Enable JqueryUI'); + $f->attr('checked', $this->jqueryUI ? 'checked' : '' ); + $f->columnWidth = 34; + $f->showIf = "inputType=4"; + $inputfields->append($f); + + $f = $this->modules->get('InputfieldRadios'); + $f->attr('name', 'alpha'); + $f->addOption(0, $this->_('6 digits "#ff0000"')); + $f->addOption(1, $this->_('8 digits "#ffff0000" (leading alpha channel)')); + $f->label = __('Select value type'); + $f->attr('value', $this->alpha); + $f->columnWidth = 33; + $f->showIf = "inputType=4"; + $inputfields->append($f); + + return $inputfields; + } +} diff --git a/site/modules/FieldtypeColor/README.md b/site/modules/FieldtypeColor/README.md new file mode 100644 index 0000000..42f438a --- /dev/null +++ b/site/modules/FieldtypeColor/README.md @@ -0,0 +1,107 @@ +FieldtypeColor +============== + +## Fieldtype/Inputfield for ProcessWire 3.0 + +Field that stores colors. Many options for Input (HTML5 Inputfield Color, Textfield with changing background, various jQuery/JS ColorPickers, custom jQuery/JS/CSS) and Output (RGB, RGBA, HSL, HSLA, HEX). Package includes Fieldtype Color Select. + +## Inputfield +Select between **5 types of Inputfields** + ++ Html5 Inputfield of type='color' (if supported by browser) ++ Inputfield type='text' expecting a 24bit hexcode string (RGB). Input format: *'#4496dd'* +The background color of the input fields shows selected color ++ Inputfield of type='text' expecting 32bit hexcode strings (RGB + alpha channel) Input format: *'#fa4496dd'* ++ Inputfield with **Spectrum Color Picker** (JavaScript) +Options modifiable ++ Inputfield type='text' with **custom JavaScript** and/or CSS + + +## Output + +Define output format under **Details** - Tab in field settings. Select from the following options: + ++ *string* 6-digit hex color. Example: **'#4496dd'** ++ *string* 8-digit hex color with leading Alpha channel (limited browser support). Example: **'#fa4496dd'** ++ *string* CSS color value **RGB**. Example: **'rgb(68, 100, 221)'** ++ *string* CSS color value **RGBA**. Example: **'rgba(68, 100, 221, 0.98)'** ++ *string* CSS color value **HSL**. Example: **'hsl(227, 69.2%, 56.7%)'** ++ *string* CSS color value **HSLA**. Example: **'hsla(227, 69.2%, 56.7%, 0.98)'** ++ *string* 32bit raw hex value. Example: **'fa4496dd'** (unformatted output value) ++ *int 32bit*. Example: **'4198799069'** (storage value) ++ *array(R,G,B)* ++ *array(R,G,B,Alpha)* ++ *array(H,S,L)* ++ *array(H,S,L,Alpha)* + + +``` + array( + [0] => 0-255, // opacity + [1],['r'] => 0-255, + [2],['g'] => 0-255, + [3],['b'] => 0-255, + ['rx'] => 00-ff, + ['gx'] => 00-ff, + ['bx'] => 00-ff, + ['ox'] => 00-ff, // opacity + ['o'] => 0-1 // opacity + ) +``` + + +## Templates & API +You can always modify values or output format via ProcessWire API. + +**Modify output format** + +``` +$f = $page->fields->get('myColorField'); +$f->outputFormat = 8; +echo $page->color['rx']; +``` + +**Modify values** + ++ Delete the page field value by setting empty string or *NULL*. ++ The values (int) 0, (string) '0', '00000000' and '#00000000' are similar and stored as (int) 0 (black, full transparent). + +``` +$page->of(false); +$page->myColorField = 'ff0000'; // red +$page->save('myColorField'); +``` + +## Notes +**Deleting values** is only possible with inputfields of type='text' and via API. + +If a **default value** is set, the field is filled with it if the field is empty (for example on newly created pages). +If Inputfield of type='text' 32bit is selected you can set the value to '#00000000' and the default value will be ignored. + +The Fieldtype includes +[**Spectrum Color Picker** by Brian Grinstead](https://github.com/bgrins/spectrum) + +Any custom Javascript based Inputfield can be used. + +If the **Inputfield** is **used as is** e.g. for Module Settings, the following properties are provided: + +``` +$f->wire('modules')->get('InputfieldColor); +$f->inputType = 0; // int 0 - 4 +$f->alpha = 0; // int 0 or 1, will be set automatically dependend on inputType. To disable explicitly for inputType = 3 (spectrum color picker) set to bool false +$f->spectrum = ''; // options for spectrum Color Picker if inputType = 3 @see https://bgrins.github.io/spectrum/ + +// properties for inputType = 4 only +$f->initJS = ''; // initial JS +$f->fileJS = ''; // path to JS file +$f->fileCSS = ''; // path to CSS file +$f->jqueryCore = 0; // enable jqueryCore +$f->jqueryUI = 0; // enable jqueryUI +``` + +--- + +Fieldtype Select Color Options +============================== + +This fieldtype is included in the package. The module is an extension of the Core **FieldtypeOptions** module and offers colors as predefined selectable options via 4 different input field types (Select, SelectMultiple, Checkboxes and Radios). diff --git a/site/modules/FieldtypeColor/colornames.json b/site/modules/FieldtypeColor/colornames.json new file mode 100644 index 0000000..5df7793 --- /dev/null +++ b/site/modules/FieldtypeColor/colornames.json @@ -0,0 +1,143 @@ +{ + "AliceBlue": "f0f8ff", + "AntiqueWhite": "faebd7", + "Aqua": "00ffff", + "AquaMarine": "7fffd4", + "Azure": "f0ffff", + "Beige": "f5f5dc", + "Bisque": "ffe4c4", + "Black": "000000", + "BlanchedAlmond": "ffebcd", + "Blue": "0000ff", + "BlueViolet": "8a2be2", + "Brown": "a52a2a", + "BurlyWood": "deb887", + "CadetBlue": "5f9ea0", + "Chartreuse": "7fff00", + "Chocolate": "d2691e", + "Coral": "ff7f50", + "CornFlowerBlue": "6495ed", + "Cornsilk": "fff8dc", + "Crimson": "dc143c", + "Cyan": "00ffff", + "DarkBlue": "00008b", + "DarkCyan": "008b8b", + "DarkGoldenRod": "b8860b", + "DarkGray": "a9a9a9", + "DarkGreen": "006400", + "DarkKhaki": "bdb76b", + "DarkMagenta": "8b008b", + "DarkOliveGreen": "556b2f", + "DarkOrange": "ff8c00", + "DarkOrchid": "9932cc", + "DarkRed": "8b0000", + "DarkSalmon": "e9967a", + "DarkSeaGreen": "8fbc8f", + "DarkSlateBlue": "483d8b", + "DarkSlateGray": "2f4f4f", + "DarkTurquoise": "00ced1", + "DarkViolet": "9400d3", + "DeepPink": "ff1493", + "DeepSkyBlue": "00bfff", + "DimGray": "696969", + "DodgerBlue": "1e90ff", + "FireBrick": "b22222", + "FloralWhite": "fffaf0", + "ForestGreen": "228b22", + "Fuchsia": "ff00ff", + "Gainsboro": "dcdcdc", + "GhostWhite": "f8f8ff", + "Gold": "ffd700", + "GoldenRod": "daa520", + "Gray": "808080", + "Green": "008000", + "GreenYellow": "adff2f", + "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", + "LightPink": "ffb6c1", + "LightSalmon": "ffa07a", + "LightSeaGreen": "20b2aa", + "LightSkyBlue": "87cefa", + "LightSlateGray": "778899", + "LightSteelBlue": "b0c4de", + "LightYellow": "ffffe0", + "Lime": "00ff00", + "LimeGreen": "32cd32", + "Linen": "faf0e6", + "Magenta": "ff00ff", + "Maroon": "800000", + "MediumAquaMarine": "66cdaa", + "MediumBlue": "0000cd", + "MediumOrchid": "ba55d3", + "MediumPurple": "9370d8", + "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": "ff0000", + "RosyBrown": "bc8f8f", + "RoyalBlue": "4169e1", + "SaddleBrown": "8b4513", + "Salmon": "fa8072", + "SandyBrown": "f4a460", + "SeaGreen": "2e8b57", + "SeaShell": "fff5ee", + "Sienna": "a0522d", + "Silver": "c0c0c0", + "SkyBlue": "87ceeb", + "SlateBlue": "6a5acd", + "SlateGray": "708090", + "Snow": "fffafa", + "SpringGreen": "00ff7f", + "SteelBlue": "4682b4", + "Tan": "d2b48c", + "Teal": "008080", + "Thistle": "d8bfd8", + "Tomato": "ff6347", + "Turquoise": "40e0d0", + "Violet": "ee82ee", + "Wheat": "f5deb3", + "White": "ffffff", + "WhiteSmoke": "f5f5f5", + "Yellow": "ffff00", + "YellowGreen": "9acd32" +} \ No newline at end of file diff --git a/site/modules/FieldtypeColor/spectrum/spectrum.css b/site/modules/FieldtypeColor/spectrum/spectrum.css new file mode 100644 index 0000000..e68f492 --- /dev/null +++ b/site/modules/FieldtypeColor/spectrum/spectrum.css @@ -0,0 +1,507 @@ +/*** +Spectrum Colorpicker v1.8.1 +https://github.com/bgrins/spectrum +Author: Brian Grinstead +License: MIT +***/ + +.sp-container { + position:absolute; + top:0; + left:0; + display:inline-block; + *display: inline; + *zoom: 1; + /* https://github.com/bgrins/spectrum/issues/40 */ + z-index: 9999994; + overflow: hidden; +} +.sp-container.sp-flat { + position: relative; +} + +/* Fix for * { box-sizing: border-box; } */ +.sp-container, +.sp-container * { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */ +.sp-top { + position:relative; + width: 100%; + display:inline-block; +} +.sp-top-inner { + position:absolute; + top:0; + left:0; + bottom:0; + right:0; +} +.sp-color { + position: absolute; + top:0; + left:0; + bottom:0; + right:20%; +} +.sp-hue { + position: absolute; + top:0; + right:0; + bottom:0; + left:84%; + height: 100%; +} + +.sp-clear-enabled .sp-hue { + top:33px; + height: 77.5%; +} + +.sp-fill { + padding-top: 80%; +} +.sp-sat, .sp-val { + position: absolute; + top:0; + left:0; + right:0; + bottom:0; +} + +.sp-alpha-enabled .sp-top { + margin-bottom: 18px; +} +.sp-alpha-enabled .sp-alpha { + display: block; +} +.sp-alpha-handle { + position:absolute; + top:-4px; + bottom: -4px; + width: 6px; + left: 50%; + cursor: pointer; + border: 1px solid black; + background: white; + opacity: .8; +} +.sp-alpha { + display: none; + position: absolute; + bottom: -14px; + right: 0; + left: 0; + height: 8px; +} +.sp-alpha-inner { + border: solid 1px #333; +} + +.sp-clear { + display: none; +} + +.sp-clear.sp-clear-display { + background-position: center; +} + +.sp-clear-enabled .sp-clear { + display: block; + position:absolute; + top:0px; + right:0; + bottom:0; + left:84%; + height: 28px; +} + +/* Don't allow text selection */ +.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button { + -webkit-user-select:none; + -moz-user-select: -moz-none; + -o-user-select:none; + user-select: none; +} + +.sp-container.sp-input-disabled .sp-input-container { + display: none; +} +.sp-container.sp-buttons-disabled .sp-button-container { + display: none; +} +.sp-container.sp-palette-buttons-disabled .sp-palette-button-container { + display: none; +} +.sp-palette-only .sp-picker-container { + display: none; +} +.sp-palette-disabled .sp-palette-container { + display: none; +} + +.sp-initial-disabled .sp-initial { + display: none; +} + + +/* Gradients for hue, saturation and value instead of images. Not pretty... but it works */ +.sp-sat { + background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0))); + background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0)); + background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); + background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); + background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); + background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0)); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)"; + filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81'); +} +.sp-val { + background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0))); + background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0)); + background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); + background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); + background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); + background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0)); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)"; + filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000'); +} + +.sp-hue { + background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000)); + background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); +} + +/* IE filters do not support multiple color stops. + Generate 6 divs, line them up, and do two color gradients for each. + Yes, really. + */ +.sp-1 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00'); +} +.sp-2 { + height:16%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00'); +} +.sp-3 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff'); +} +.sp-4 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff'); +} +.sp-5 { + height:16%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff'); +} +.sp-6 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000'); +} + +.sp-hidden { + display: none !important; +} + +/* Clearfix hack */ +.sp-cf:before, .sp-cf:after { content: ""; display: table; } +.sp-cf:after { clear: both; } +.sp-cf { *zoom: 1; } + +/* Mobile devices, make hue slider bigger so it is easier to slide */ +@media (max-device-width: 480px) { + .sp-color { right: 40%; } + .sp-hue { left: 63%; } + .sp-fill { padding-top: 60%; } +} +.sp-dragger { + border-radius: 5px; + height: 5px; + width: 5px; + border: 1px solid #fff; + background: #000; + cursor: pointer; + position:absolute; + top:0; + left: 0; +} +.sp-slider { + position: absolute; + top:0; + cursor:pointer; + height: 3px; + left: -1px; + right: -1px; + border: 1px solid #000; + background: white; + opacity: .8; +} + +/* +Theme authors: +Here are the basic themeable display options (colors, fonts, global widths). +See http://bgrins.github.io/spectrum/themes/ for instructions. +*/ + +.sp-container { + border-radius: 0; + background-color: #ECECEC; + border: solid 1px #f0c49B; + padding: 0; +} +.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear { + font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} +.sp-top { + margin-bottom: 3px; +} +.sp-color, .sp-hue, .sp-clear { + border: solid 1px #666; +} + +/* Input */ +.sp-input-container { + float:right; + width: 100px; + margin-bottom: 4px; +} +.sp-initial-disabled .sp-input-container { + width: 100%; +} +.sp-input { + font-size: 12px !important; + border: 1px inset; + padding: 4px 5px; + margin: 0; + width: 100%; + background:transparent; + border-radius: 3px; + color: #222; +} +.sp-input:focus { + border: 1px solid orange; +} +.sp-input.sp-validation-error { + border: 1px solid red; + background: #fdd; +} +.sp-picker-container , .sp-palette-container { + float:left; + position: relative; + padding: 10px; + padding-bottom: 300px; + margin-bottom: -290px; +} +.sp-picker-container { + width: 172px; + border-left: solid 1px #fff; +} + +/* Palettes */ +.sp-palette-container { + border-right: solid 1px #ccc; +} + +.sp-palette-only .sp-palette-container { + border: 0; +} + +.sp-palette .sp-thumb-el { + display: block; + position:relative; + float:left; + width: 24px; + height: 15px; + margin: 3px; + cursor: pointer; + border:solid 2px transparent; +} +.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active { + border-color: orange; +} +.sp-thumb-el { + position:relative; +} + +/* Initial */ +.sp-initial { + float: left; + border: solid 1px #333; +} +.sp-initial span { + width: 30px; + height: 25px; + border:none; + display:block; + float:left; + margin:0; +} + +.sp-initial .sp-clear-display { + background-position: center; +} + +/* Buttons */ +.sp-palette-button-container, +.sp-button-container { + float: right; +} + +/* Replacer (the little preview div that shows up instead of the ) */ +.sp-replacer { + margin:0; + overflow:hidden; + cursor:pointer; + padding: 4px; + display:inline-block; + *zoom: 1; + *display: inline; + border: solid 1px #91765d; + background: #eee; + color: #333; + vertical-align: middle; +} +.sp-replacer:hover, .sp-replacer.sp-active { + border-color: #F0C49B; + color: #111; +} +.sp-replacer.sp-disabled { + cursor:default; + border-color: silver; + color: silver; +} +.sp-dd { + padding: 2px 0; + height: 16px; + line-height: 16px; + float:left; + font-size:10px; +} +.sp-preview { + position:relative; + width:25px; + height: 20px; + border: solid 1px #222; + margin-right: 5px; + float:left; + z-index: 0; +} + +.sp-palette { + *width: 220px; + max-width: 220px; +} +.sp-palette .sp-thumb-el { + width:16px; + height: 16px; + margin:2px 1px; + border: solid 1px #d0d0d0; +} + +.sp-container { + padding-bottom:0; +} + + +/* Buttons: http://hellohappy.org/css3-buttons/ */ +.sp-container button { + background-color: #eeeeee; + background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc); + background-image: -moz-linear-gradient(top, #eeeeee, #cccccc); + background-image: -ms-linear-gradient(top, #eeeeee, #cccccc); + background-image: -o-linear-gradient(top, #eeeeee, #cccccc); + background-image: linear-gradient(to bottom, #eeeeee, #cccccc); + border: 1px solid #ccc; + border-bottom: 1px solid #bbb; + border-radius: 3px; + color: #333; + font-size: 14px; + line-height: 1; + padding: 5px 4px; + text-align: center; + text-shadow: 0 1px 0 #eee; + vertical-align: middle; +} +.sp-container button:hover { + background-color: #dddddd; + background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb); + background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb); + background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb); + background-image: -o-linear-gradient(top, #dddddd, #bbbbbb); + background-image: linear-gradient(to bottom, #dddddd, #bbbbbb); + border: 1px solid #bbb; + border-bottom: 1px solid #999; + cursor: pointer; + text-shadow: 0 1px 0 #ddd; +} +.sp-container button:active { + border: 1px solid #aaa; + border-bottom: 1px solid #888; + -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; +} +.sp-cancel { + font-size: 11px; + color: #d93f3f !important; + margin:0; + padding:2px; + margin-right: 5px; + vertical-align: middle; + text-decoration:none; + +} +.sp-cancel:hover { + color: #d93f3f !important; + text-decoration: underline; +} + + +.sp-palette span:hover, .sp-palette span.sp-thumb-active { + border-color: #000; +} + +.sp-preview, .sp-alpha, .sp-thumb-el { + position:relative; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==); +} +.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner { + display:block; + position:absolute; + top:0;left:0;bottom:0;right:0; +} + +.sp-palette .sp-thumb-inner { + background-position: 50% 50%; + background-repeat: no-repeat; +} + +.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=); +} + +.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=); +} + +.sp-clear-display { + background-repeat:no-repeat; + background-position: center; + background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==); +} diff --git a/site/modules/FieldtypeColor/spectrum/spectrum.js b/site/modules/FieldtypeColor/spectrum/spectrum.js new file mode 100644 index 0000000..6c48c12 --- /dev/null +++ b/site/modules/FieldtypeColor/spectrum/spectrum.js @@ -0,0 +1,2341 @@ +// Spectrum Colorpicker v1.8.1 +// https://github.com/bgrins/spectrum +// Author: Brian Grinstead +// License: MIT + +(function (factory) { + "use strict"; + + if (typeof define === 'function' && define.amd) { // AMD + define(['jquery'], factory); + } + else if (typeof exports == "object" && typeof module == "object") { // CommonJS + module.exports = factory(require('jquery')); + } + else { // Browser + factory(jQuery); + } +})(function($, undefined) { + "use strict"; + + var defaultOpts = { + + // Callbacks + beforeShow: noop, + move: noop, + change: noop, + show: noop, + hide: noop, + + // Options + color: false, + flat: false, + showInput: false, + allowEmpty: false, + showButtons: true, + clickoutFiresChange: true, + showInitial: false, + showPalette: false, + showPaletteOnly: false, + hideAfterPaletteSelect: false, + togglePaletteOnly: false, + showSelectionPalette: true, + localStorageKey: false, + appendTo: "body", + maxSelectionSize: 7, + cancelText: "cancel", + chooseText: "choose", + togglePaletteMoreText: "more", + togglePaletteLessText: "less", + clearText: "Clear Color Selection", + noColorSelectedText: "No Color Selected", + preferredFormat: false, + className: "", // Deprecated - use containerClassName and replacerClassName instead. + containerClassName: "", + replacerClassName: "", + showAlpha: false, + theme: "sp-light", + palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]], + selectionPalette: [], + disabled: false, + offset: null + }, + spectrums = [], + IE = !!/msie/i.exec( window.navigator.userAgent ), + rgbaSupport = (function() { + function contains( str, substr ) { + return !!~('' + str).indexOf(substr); + } + + var elem = document.createElement('div'); + var style = elem.style; + style.cssText = 'background-color:rgba(0,0,0,.5)'; + return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla'); + })(), + replaceInput = [ + "
", + "
", + "
", + "
" + ].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,