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 c0893ad..0000000 Binary files a/site/modules/ColorPicker/colorpicker/.DS_Store and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/css/colorpicker.css b/site/modules/ColorPicker/colorpicker/css/colorpicker.css deleted file mode 100644 index bf08d25..0000000 --- a/site/modules/ColorPicker/colorpicker/css/colorpicker.css +++ /dev/null @@ -1,164 +0,0 @@ - -.colorpicker { - width: 356px; - height: 176px; - overflow: hidden; - position: absolute; - background: url(../images/colorpicker_background.png); - font-family: Arial, Helvetica, sans-serif; - display: none; - z-index:1; -} -.colorpicker_color { - width: 150px; - height: 150px; - left: 14px; - top: 13px; - position: absolute; - background: #f00; - overflow: hidden; - cursor: crosshair; -} -.colorpicker_color div { - position: absolute; - top: 0; - left: 0; - width: 150px; - height: 150px; - background: url(../images/colorpicker_overlay.png); -} -.colorpicker_color div div { - position: absolute; - top: 0; - left: 0; - width: 11px; - height: 11px; - overflow: hidden; - background: url(../images/colorpicker_select.gif); - margin: -5px 0 0 -5px; -} -.colorpicker_hue { - position: absolute; - top: 13px; - left: 171px; - width: 35px; - height: 150px; - cursor: n-resize; -} -.colorpicker_hue div { - position: absolute; - width: 35px; - height: 9px; - overflow: hidden; - background: url(../images/colorpicker_indic.gif) left top; - margin: -4px 0 0 0; - left: 0px; -} -.colorpicker_new_color { - position: absolute; - width: 60px; - height: 30px; - left: 213px; - top: 13px; - background: #f00; -} -.colorpicker_current_color { - position: absolute; - width: 60px; - height: 30px; - left: 283px; - top: 13px; - background: #f00; -} -.colorpicker input { - background-color: transparent; - border: 1px solid transparent; - position: absolute; - font-size: 10px; - font-family: Arial, Helvetica, sans-serif; - color: #898989; - top: 4px; - right: 11px; - text-align: right; - margin: 0; - padding: 0; - height: 15px; - -} -.colorpicker_hex { - position: absolute; - width: 72px; - height: 22px; - background: url(../images/colorpicker_hex.png) top; - left: 212px; - top: 142px; -} -.colorpicker_hex input { - right: 6px; -} -.colorpicker_field { - height: 22px; - width: 62px; - background-position: top; - position: absolute; -} -.colorpicker_field span { - position: absolute; - width: 12px; - height: 22px; - overflow: hidden; - top: 0; - right: 0; - cursor: n-resize; -} -.colorpicker_rgb_r { - background-image: url(../images/colorpicker_rgb_r.png); - top: 52px; - left: 212px; -} -.colorpicker_rgb_g { - background-image: url(../images/colorpicker_rgb_g.png); - top: 82px; - left: 212px; -} -.colorpicker_rgb_b { - background-image: url(../images/colorpicker_rgb_b.png); - top: 112px; - left: 212px; -} -.colorpicker_hsb_h { - background-image: url(../images/colorpicker_hsb_h.png); - top: 52px; - left: 282px; -} -.colorpicker_hsb_s { - background-image: url(../images/colorpicker_hsb_s.png); - top: 82px; - left: 282px; -} -.colorpicker_hsb_b { - background-image: url(../images/colorpicker_hsb_b.png); - top: 112px; - left: 282px; -} -.colorpicker_submit { - position: absolute; - width: 22px; - height: 22px; - background: url(../images/colorpicker_submit.png) top; - left: 322px; - top: 142px; - overflow: hidden; -} -.colorpicker_focus { - background-position: center; -} -.colorpicker_hex.colorpicker_focus { - background-position: bottom; -} -.colorpicker_submit.colorpicker_focus { - background-position: bottom; -} -.colorpicker_slider { - background-position: bottom; -} diff --git a/site/modules/ColorPicker/colorpicker/images/Thumbs.db b/site/modules/ColorPicker/colorpicker/images/Thumbs.db deleted file mode 100644 index d396c36..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/Thumbs.db and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/blank.gif b/site/modules/ColorPicker/colorpicker/images/blank.gif deleted file mode 100644 index 75b945d..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/blank.gif and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_background.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_background.png deleted file mode 100644 index 8401572..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_background.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_hex.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_hex.png deleted file mode 100644 index 4e532d7..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_hex.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_b.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_b.png deleted file mode 100644 index dfac595..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_b.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_h.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_h.png deleted file mode 100644 index 3977ed9..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_h.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_s.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_s.png deleted file mode 100644 index a2a6997..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_hsb_s.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_indic.gif b/site/modules/ColorPicker/colorpicker/images/colorpicker_indic.gif deleted file mode 100644 index f9fa95e..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_indic.gif and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_overlay.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_overlay.png deleted file mode 100644 index 561cdd9..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_overlay.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_b.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_b.png deleted file mode 100644 index dfac595..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_b.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_g.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_g.png deleted file mode 100644 index 72b3276..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_g.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_r.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_r.png deleted file mode 100644 index 4855fe0..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_rgb_r.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_select.gif b/site/modules/ColorPicker/colorpicker/images/colorpicker_select.gif deleted file mode 100644 index 599f7f1..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_select.gif and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/colorpicker_submit.png b/site/modules/ColorPicker/colorpicker/images/colorpicker_submit.png deleted file mode 100644 index 7f4c082..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/colorpicker_submit.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_background.png b/site/modules/ColorPicker/colorpicker/images/custom_background.png deleted file mode 100644 index cf55ffd..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_background.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_hex.png b/site/modules/ColorPicker/colorpicker/images/custom_hex.png deleted file mode 100644 index 888f444..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_hex.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_hsb_b.png b/site/modules/ColorPicker/colorpicker/images/custom_hsb_b.png deleted file mode 100644 index 2f99dae..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_hsb_b.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_hsb_h.png b/site/modules/ColorPicker/colorpicker/images/custom_hsb_h.png deleted file mode 100644 index a217e92..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_hsb_h.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_hsb_s.png b/site/modules/ColorPicker/colorpicker/images/custom_hsb_s.png deleted file mode 100644 index 7826b41..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_hsb_s.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_indic.gif b/site/modules/ColorPicker/colorpicker/images/custom_indic.gif deleted file mode 100644 index 222fb94..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_indic.gif and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_rgb_b.png b/site/modules/ColorPicker/colorpicker/images/custom_rgb_b.png deleted file mode 100644 index 80764e5..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_rgb_b.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_rgb_g.png b/site/modules/ColorPicker/colorpicker/images/custom_rgb_g.png deleted file mode 100644 index fc9778b..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_rgb_g.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_rgb_r.png b/site/modules/ColorPicker/colorpicker/images/custom_rgb_r.png deleted file mode 100644 index 91b0cd4..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_rgb_r.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/custom_submit.png b/site/modules/ColorPicker/colorpicker/images/custom_submit.png deleted file mode 100644 index cd202cd..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/custom_submit.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/select.png b/site/modules/ColorPicker/colorpicker/images/select.png deleted file mode 100644 index 21213bf..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/select.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/select2.png b/site/modules/ColorPicker/colorpicker/images/select2.png deleted file mode 100644 index 2cd2cab..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/select2.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/images/slider.png b/site/modules/ColorPicker/colorpicker/images/slider.png deleted file mode 100644 index 8b03da9..0000000 Binary files a/site/modules/ColorPicker/colorpicker/images/slider.png and /dev/null differ diff --git a/site/modules/ColorPicker/colorpicker/js/colorpicker.js b/site/modules/ColorPicker/colorpicker/js/colorpicker.js deleted file mode 100644 index 10a2b22..0000000 --- a/site/modules/ColorPicker/colorpicker/js/colorpicker.js +++ /dev/null @@ -1,484 +0,0 @@ -/** - * - * Color picker - * Author: Stefan Petre www.eyecon.ro - * - * Dual licensed under the MIT and GPL licenses - * - */ -(function ($) { - var ColorPicker = function () { - var - ids = {}, - inAction, - charMin = 65, - visible, - tpl = '

', - 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 87241ae..0000000 Binary files a/site/modules/ColorPicker/pw-colorpicker.jpg and /dev/null differ diff --git a/site/modules/ColorPicker/transparent.gif b/site/modules/ColorPicker/transparent.gif deleted file mode 100644 index bc3c235..0000000 Binary files a/site/modules/ColorPicker/transparent.gif and /dev/null differ 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,