├── .gitignore ├── LICENSE ├── README.md ├── bower.json ├── demo.html ├── img ├── icon │ ├── palette-color-picker-icon.ai │ └── palette-color-picker-icon.svg └── snapshot.png ├── ready.js └── src ├── palette-color-picker.css ├── palette-color-picker.js ├── palette-color-picker.min.js └── palette-color-picker.scss /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | #CSS / JS auto minify 30 | minify.bat 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Carlos Cabo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JQuery Palette Color Picker v1.13 2 | JS component to pick colors from a predefined / restricted palette. Take a look to the `demo.html` included in this repository to see it in action. 3 | 4 | ![Snapshot](https://raw.githubusercontent.com/carloscabo/jquery-palette-color-picker/master/img/snapshot.png) 5 | 6 | [Watch the demo included in the repo](https://htmlpreview.github.io/?https://raw.githubusercontent.com/carloscabo/jquery-palette-color-picker/master/demo.html) 7 | 8 | # Requirements 9 | 10 | `JQuery 1.7+` 11 | `palette-color-picker.js` 12 | `palette-color-picker.css / scss` 13 | 14 | # Basic usage 15 | 16 | Create a `` in your `` document. The `name` attribute is used to **bind the color picker to the input**, so its recommended to be **unique** if you have several inputs with the same name, **all of them will change simultaneously when user picks a color**. 17 | 18 | Call `.paletteColorPicker()` over the input element. 19 | ```javascript 20 | $(document).ready(function(){ 21 | $('[name="UNIQUE_NAME"]').paletteColorPicker(); 22 | // You can use something like... 23 | // $('[data-palette]').paletteColorPicker(); 24 | }); 25 | ``` 26 | 27 | # Color data 28 | The color options for the picker are automatically get from the `data-palette` attribute. You can define the colors as an array of **string values**. 29 | ````html 30 | 31 | 32 | ```` 33 | 34 | Alternativelly you can use an **array of objects** in **key: value pairs**. If you set the data this way, the keys will be used as value in the `input` field, this is useful if you want to work with class names... or strings representing the colors instead the color value itself. 35 | 36 | ````html 37 | 38 | 39 | ```` 40 | 41 | # Color data on plugin initialization 42 | Additionally you can set the color palette in the options for the plugin initialization, doing so if `data-palette` attribute is present **will be ignored**. 43 | ```javascript 44 | // Basic usage, array of color values 45 | $(document).ready(function(){ 46 | $('[name="UNIQUE_NAME"]').paletteColorPicker({ 47 | colors: ["#0F8DFC","rgba(135,1,101,1)","#F00285","hsla(190,41%,95%,1)"] 48 | }); 49 | }); 50 | ``` 51 | 52 | # All available settings 53 | ```javascript 54 | $(document).ready(function(){ 55 | // Advanced exacmple 56 | $('[name="UNIQUE_NAME"]').paletteColorPicker({ 57 | // Color in { key: value } format 58 | colors: [ 59 | {"primary": "#E91E63"}, 60 | {"primary_dark": "#C2185B"}, 61 | {"primary_light": "#F8BBD0"}, 62 | {"accent": "#CDDC39"}, 63 | {"primary_text": "#212121"}, 64 | {"secondary_text": "#727272"}, 65 | {"divider": "#B6B6B6"} 66 | ], 67 | // Add custom class to the picker 68 | custom_class: 'double', 69 | // Force the position of picker's bubble 70 | position: 'downside', // default -> 'upside' 71 | // Where is inserted the color picker's button, related to the input 72 | insert: 'after', // default -> 'before' 73 | // Don't add clear_btn 74 | clear_btn: 'last', // null -> without clear button, default -> 'first' 75 | // Timeout for the picker's fade out in ms 76 | timeout: 2000, // default -> 2000 77 | // Forces closin all bubbles that are open before opening the current one 78 | close_all_but_this: false, // default is false 79 | // Sets the input's background color to the selected one on click 80 | // seems that some users find this useful ;) 81 | set_background: false, // default is false 82 | 83 | // Events 84 | // Callback on bubbl show 85 | onbeforeshow_callback: function( what ) { 86 | console.log(what); 87 | }, 88 | 89 | // Callback on change value 90 | onchange_callback: function( clicked_color ) { 91 | console.log(clicked_color); 92 | } 93 | }); 94 | }); 95 | ``` 96 | 97 | # Destroy instance of paletteColorPicker 98 | 99 | ```javascript 100 | $( input_element ).data('paletteColorPickerPlugin').destroy(); 101 | ``` 102 | 103 | # Clear 104 | 105 | Clear current control and value of related input. 106 | 107 | ```javascript 108 | $( input_element ).data('paletteColorPickerPlugin').clear(); 109 | ``` 110 | 111 | # Reset to inital state 112 | 113 | Resets the color picker (and its related input field) to the initial value it had when it was initialized. 114 | 115 | ```javascript 116 | $( input_element ).data('paletteColorPickerPlugin').reset(); 117 | ``` 118 | 119 | # Callback functions 120 | 121 | Define your own callback function that will be fired when a color swatch its clicked. Returns the color swatch item itlsef. 122 | 123 | ```javascript 124 | $( input_element ).paletteColorPicker({ 125 | onchange_callback: function ( clicked_color ) { 126 | console.log( 'onchange_callback!!!' ); 127 | console.log( $(clicked_color) ); 128 | console.log( clicked_color ); 129 | } 130 | }); 131 | ``` 132 | 133 | There is an aditional callback is fired **right before the color's bubble is shwon**. 134 | 135 | ```javascript 136 | $( input_element ).paletteColorPicker({ 137 | onbeforeshow_callback: function ( color_picker_button ) { 138 | console.log( 'onbeforeshow_callback!!!' ); 139 | console.log( $(color_picker_button) ); 140 | console.log( color_picker_button ); 141 | } 142 | }); 143 | ``` 144 | 145 | # Reload the value after it has been changed programatically 146 | 147 | The new color should exists in the initial options otherwise the selection will be reset to initial value. 148 | 149 | ```javascript 150 | $( input_element ).data('paletteColorPickerPlugin').reload(); 151 | ``` 152 | 153 | # Changelog 154 | * V.1.13 (2017/07/06) New features 155 | * [eafarooqi](https://github.com/eafarooqi) Bugfix 156 | * V.1.12 (2017/06/27) New features 157 | * close_all_but_this 158 | * onbeforeshow_callback() 159 | * Style to force bubble to be shown on left side 160 | * More samples 161 | * V.1.10 (2017/06/27) Some improvements by several people, thx! 162 | * [slavede](https://github.com/slavede) Added bower.json 163 | * [eafarooqi](https://github.com/eafarooqi) Reload value after programatically update 164 | * [wirthm](https://github.com/wirthm) Allow touch and click events simultaneously 165 | * [evalibantova](https://github.com/) Callback feature and better closing 166 | * [kleber099](https://github.com/kleber099) Add option of set background color select in input 167 | * [Desprit](https://github.com/Desprit) Fix rgba typo and comma 168 | * V.1.03 (2016/10/03) Added option to **disable clear button**, added methods to **reset** and **clear** plugin 169 | * V.1.02 (2016/06/08) Improved iOS / Android click / touch behaviour 170 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-palette-color-picker", 3 | "authors": [ 4 | "Slaven Tomac ", 5 | "Carlos Cabo " 6 | ], 7 | "description": "JS component to pick colors from a predefined palette Edit", 8 | "main": ["./src/palette-color-picker.min.js", "./src/palette-color-picker.css"], 9 | "keywords": [ 10 | "colorpicker", 11 | "color", 12 | "jquery", 13 | "predefined", 14 | "colors" 15 | ], 16 | "license": "MIT", 17 | "homepage": "https://github.com/carloscabo/jquery-palette-color-picker", 18 | "ignore": [ 19 | "**/.*", 20 | "node_modules", 21 | "bower_components", 22 | "test", 23 | "tests" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Colorpicker from palette demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 |

Sample 1

52 | 53 |

If there is not enough free space from the control to the upper side of the screen the selector opens downwards automatically.

54 |

This sample has also a callback function that logs to the web broser console the color swatch clicked ( onchange_callback ) and also just before the colors bubble is shown ( onbeforeshow_callback )

55 |
56 | 57 |
58 |

Sample 2

59 | 60 | 61 |

If there are several inputs with the same name all all them are updated on color selection. In this sample the clear button is set to be last one.

62 |
63 | 64 |
65 |

Sample 3

66 | 67 |

The control can be inserted before or after the input. You can also customize the style of the color swatches, with the custom_class .double the swatches are wider. 68 |

69 | 70 |
71 |

Sample 3B

72 | 74 |

The bubble is forced to the left side of the button adding the f.force-left class.

75 |
76 | 77 |
78 |

Sample 4

79 | 80 |

In this sample the color palette is forced to open downwards.

81 |
82 | 83 |
84 |

Sample 5

85 | 86 |

With tha custom_class .wide swatches expand to be fullwidth.

87 |
88 | 89 |
90 |

Sample 6 A/B

91 | 92 | 93 |

Without clear button, you can clear the selection programatically calling:

$( input_element ).data('paletteColorPickerPlugin').reset();

94 | Reset sample 6A | Reset sample 6B

95 |
96 | 97 |
98 |

Sample 7

99 | 100 |

Reload the value after it has been changed programatically. The new color should exists in the initial options otherwise the selection will be reset to initial value.You can reload the value after programatically changing the value of input calling:

$( input_element ).data('paletteColorPickerPlugin').reload();

101 | Change to existing value of #69F0AE | Change to non-existing value of #808080 (will reset to initial value)

102 |
103 | 104 |
105 |

Sample 8

106 | 108 |

This sample has the set_background:true; that sets the input's background color to the selected one. Seems that 109 | some users find this useful ;)

110 |
111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /img/icon/palette-color-picker-icon.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carloscabo/jquery-palette-color-picker/6dfdd4763545a3b9d42dac33d93f6a819a76158b/img/icon/palette-color-picker-icon.ai -------------------------------------------------------------------------------- /img/icon/palette-color-picker-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carloscabo/jquery-palette-color-picker/6dfdd4763545a3b9d42dac33d93f6a819a76158b/img/snapshot.png -------------------------------------------------------------------------------- /ready.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | //La magia aquí 3 | 4 | // Sample 1 5 | $('[name="unique-name-1"]').paletteColorPicker({ 6 | onbeforeshow_callback: function ( color_picker_button ) { 7 | console.log( 'onbeforeshow_callback!!!' ); 8 | console.log( $(color_picker_button) ); 9 | console.log( color_picker_button ); 10 | }, 11 | onchange_callback: function ( clicked_color ) { 12 | console.log( 'onchange_callback!!!' ); 13 | console.log( $(clicked_color) ); 14 | console.log( clicked_color ); 15 | } 16 | }); 17 | 18 | // Sample 2 19 | $('[name="duplicated-name-2"]').paletteColorPicker({ 20 | clear_btn: 'last', 21 | close_all_but_this: true // Default is false 22 | }); 23 | 24 | // Sample 3 25 | $('#unique-id-3').paletteColorPicker({ 26 | custom_class: 'double', 27 | insert: 'after' // default -> 'before' 28 | }); 29 | 30 | // Sample 3B 31 | $('#unique-id-3b').paletteColorPicker({ 32 | custom_class: 'force-left', 33 | insert: 'after', // default -> 'before' 34 | }); 35 | 36 | // Sample 4 37 | $('#unique-id-4').paletteColorPicker({ 38 | colors: [ 39 | {"primary": "#E91E63"}, 40 | {"primary_dark": "#C2185B"}, 41 | {"primary_light": "#F8BBD0"}, 42 | {"accent": "#CDDC39"}, 43 | {"primary_text": "#212121"}, 44 | {"secondary_text": "#727272"}, 45 | {"divider": "#B6B6B6"} 46 | ], 47 | position: 'downside', // default -> 'upside' 48 | }); 49 | 50 | // Sample 5 51 | $('#unique-id-5').paletteColorPicker({ 52 | custom_class: 'wide', 53 | clear_btn: 'last' 54 | }); 55 | 56 | // Sample 6A 57 | $('#unique-id-6A').paletteColorPicker({ 58 | colors: ['#D50000','#304FFE','#00B8D4','#69F0AE','#FFFF00','#F8BBD0'], 59 | clear_btn: null 60 | }); 61 | // Reset sample 6A 62 | $('.clear-sample-6A').on('click', function(e) { 63 | e.preventDefault(); 64 | $('#unique-id-6A').data('paletteColorPickerPlugin').reset(); 65 | }); 66 | 67 | // Sample 6B 68 | $('#unique-id-6B').paletteColorPicker({ 69 | colors: ['#D50000','#304FFE','#00B8D4','#69F0AE','#FFFF00','#F8BBD0'], 70 | clear_btn: null 71 | }); 72 | // Reset sample 6B 73 | $('.clear-sample-6B').on('click', function(e) { 74 | e.preventDefault(); 75 | $('#unique-id-6B').data('paletteColorPickerPlugin').reset(); 76 | }); 77 | 78 | // Sample 7 79 | $('#unique-id-7').paletteColorPicker({ 80 | colors: ['#D50000','#304FFE','#00B8D4','#69F0AE','#FFFF00','#F8BBD0'], 81 | clear_btn: null 82 | }); 83 | 84 | // Reload sample 7 existing value 85 | $('.change-sample-7').on('click', function(e) { 86 | e.preventDefault(); 87 | $('#unique-id-7').val("#69F0AE"); 88 | $('#unique-id-7').data('paletteColorPickerPlugin').reload(); 89 | }); 90 | 91 | // Reload sample 7B non existing value 92 | $('.change-sample-7B').on('click', function(e) { 93 | e.preventDefault(); 94 | $('#unique-id-7').val("#808080"); 95 | $('#unique-id-7').data('paletteColorPickerPlugin').reload(); 96 | }); 97 | 98 | // Sample 8 99 | $('#unique-id-8').paletteColorPicker({ 100 | set_background: true 101 | }); 102 | }); 103 | -------------------------------------------------------------------------------- /src/palette-color-picker.css: -------------------------------------------------------------------------------- 1 | .palette-color-picker-button{position:relative;display:inline-block;width:28px;height:28px;margin-right:8px;background:url('data:image/svg+xml;utf8,') center center no-repeat;background-size:cover;cursor:pointer;box-shadow:0 0 0 1px #bbb;border:2px solid #fff}.palette-color-picker-bubble{display:none;margin:12px 0;position:absolute;bottom:100%;width:220px;padding:10px 8px 8px 8px;border:1px solid #bbb;border-radius:3px;background-color:#fff}.palette-color-picker-bubble:after,.palette-color-picker-bubble:before{top:100%;left:14px;border:solid transparent;content:' ';height:0;width:0;position:absolute;pointer-events:none}.palette-color-picker-bubble:after{border-color:transparent;border-top-color:#fff;border-width:8px;margin-left:-8px}.palette-color-picker-bubble:before{border-color:transparent;border-top-color:#bbb;border-width:9px;margin-left:-9px}.palette-color-picker-bubble.downside{bottom:auto;top:100%}.palette-color-picker-bubble.downside:after,.palette-color-picker-bubble.downside:before{top:auto;bottom:100%}.palette-color-picker-bubble.downside:after{border-top-color:transparent;border-bottom-color:#fff}.palette-color-picker-bubble.downside:before{border-top-color:transparent;border-bottom-color:#bbb}.palette-color-picker-bubble .swatch{position:relative;display:inline-block;font:0/0 a;width:12.66%;padding-top:11.00%;margin:1% 2%;outline:1px solid #bbb;border:2px solid #fff;border-radius:3px;cursor:pointer;overflow:hidden}.palette-color-picker-bubble .swatch.active{outline-color:#000;-webkit-box-shadow:0px 0px 5px 0px rgba(0,0,0,0.75);-moz-box-shadow:0px 0px 5px 0px rgba(0,0,0,0.75);box-shadow:0px 0px 5px 0px rgba(0,0,0,0.75)}.palette-color-picker-bubble .swatch.clear{background-color:#fff}.palette-color-picker-bubble .swatch.clear:before{position:absolute;content:'';display:block;top:-1px;left:0;width:100px;height:2px;background-color:#e00;transform-origin:0 0;transform:rotate(45deg)}.palette-color-picker-bubble.double .swatch{width:29.30%;padding-top:11.00%;margin:1% 2%}.palette-color-picker-bubble.double .swatch.clear:before{transform:rotate(22.5deg)}.palette-color-picker-bubble.wide .swatch{width:96.2%;padding-top:11.00%;margin:1% 2%}.palette-color-picker-bubble.wide .swatch.clear{width:12.66%}.palette-color-picker-bubble.force-left{left:-178px}.palette-color-picker-bubble.force-left:after,.palette-color-picker-bubble.force-left:before{left:188px} 2 | -------------------------------------------------------------------------------- /src/palette-color-picker.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * JQuery Palette Color Picker v1.13 by Carlos Cabo ( @putuko ) 3 | * https://github.com/carloscabo/jquery-palette-color-picker 4 | */ 5 | (function($) { 6 | // La magia aquí 7 | 'use strict'; 8 | 9 | // Public core 10 | $.paletteColorPicker = function( el, options ) { 11 | var 12 | ns = 'palette-color-picker', // Base attr / class 13 | $el = $(el), 14 | plugin = this, 15 | timer = null, 16 | current_value = $el.val(), 17 | target = $el.attr('name'), 18 | $button = $('
') 19 | .addClass(ns+'-button') 20 | .attr('data-target', target), 21 | $bubble = $('
') 22 | .addClass(ns+'-bubble'), 23 | 24 | // Final settings will be stored here 25 | settings = {}, 26 | 27 | // Default settings 28 | defaults = { 29 | custom_class: null, 30 | colors: null, 31 | position: 'upside', // upside | downside 32 | insert: 'before', // default 33 | clear_btn: 'first', // default 34 | timeout: 2000, // default 35 | set_background: false, // default 36 | close_all_but_this: false // default 37 | }, 38 | 39 | click_handler = ('ontouchstart' in document.documentElement ? 'touchstart click' : 'click'); 40 | 41 | // Init 42 | plugin.init = function() { 43 | // Extand settings with user options 44 | plugin.settings = $.extend({}, defaults, options); 45 | 46 | // If input has not value add it 47 | var 48 | val = $el.attr('value'); 49 | if (typeof val === typeof undefined || val === false) { 50 | val = ''; 51 | $el.attr('value', val); 52 | } 53 | 54 | // Backup initial value 55 | $el.attr('data-initialvalue', $el.attr('value') ); 56 | 57 | // If color were not passed as options get them from data-palette attribute 58 | if (plugin.settings.colors === null) { 59 | plugin.settings.colors = $el.data('palette'); 60 | } 61 | 62 | // If color is array of string, convert to obj 63 | if (typeof plugin.settings.colors[0] === 'string') { 64 | plugin.settings.colors = $.map(plugin.settings.colors, function(el, idx) { 65 | var b = {}; b[el] = el; return b; 66 | }); 67 | } 68 | 69 | // Capitalize position 70 | plugin.settings.insert = plugin.settings.insert.charAt(0).toUpperCase() + plugin.settings.insert.slice(1); 71 | 72 | // Add custom_class 73 | if (plugin.settings.custom_class) { 74 | $bubble.addClass(plugin.settings.custom_class); 75 | } 76 | 77 | // Create color swatches 78 | $.each( plugin.settings.colors, function( idx, obj ) { 79 | var 80 | key = Object.keys( obj )[0], 81 | col = obj[key], 82 | $sw = $('').addClass('swatch') 83 | .attr({ 84 | 'title': key, 85 | 'data-color': col, 86 | 'data-name': key 87 | }).css('background-color', col); 88 | 89 | if ( key === current_value ) { 90 | $sw.addClass('active'); 91 | $button.css('background', col); 92 | } 93 | 94 | $sw.appendTo( $bubble ); 95 | }); 96 | 97 | // Create clear button if not null 98 | if (plugin.settings.clear_btn !== null) { 99 | var 100 | $clear_btn = $('').addClass('swatch clear').attr('title', 'Clear selection'); 101 | if (plugin.settings.clear_btn === 'last') { 102 | $clear_btn.addClass('last').appendTo( $bubble ); 103 | } else { 104 | $clear_btn.prependTo( $bubble ); 105 | } 106 | } 107 | 108 | // Public 109 | plugin.destroy = function() { 110 | $button.remove(); 111 | $.removeData( $el[0] ); 112 | }; 113 | 114 | // Clears all 115 | plugin.clear = function() { 116 | $bubble.find('.active').removeClass('active'); 117 | $button.removeAttr('style'); 118 | $el.val(''); 119 | }; 120 | 121 | // Reset to initial value 122 | plugin.reset = function() { 123 | // Dont had initial value 124 | if ( $el.attr('data-initialvalue') === '' ) { 125 | plugin.clear(); 126 | } else { 127 | // Had initial value 128 | var iv = $el.attr('data-initialvalue'); 129 | $bubble.find('[data-name="'+iv+'"]').trigger('click'); 130 | } 131 | }; 132 | 133 | // reload value after it has been changed programatically 134 | plugin.reload = function() { 135 | 136 | var newVal = $el.val(); 137 | if ( newVal === '' || typeof newVal === typeof undefined || newVal === false ) { 138 | // Doesn't have the value to load so loading initial value 139 | plugin.reset(); 140 | } else { 141 | // setting the value to new value 142 | if($bubble.find('[data-name="'+newVal+'"]').length) { 143 | // value will only be set if the color exists in options 144 | $bubble.find('[data-name="'+newVal+'"]').trigger('click'); 145 | } else { 146 | // setting to the initial value if color does not exists 147 | plugin.reset(); 148 | } 149 | } 150 | }; 151 | 152 | // Events 153 | // Simple click 154 | $button.append( $bubble ).on( click_handler, function(e){ 155 | e.preventDefault(); 156 | e.stopPropagation(); 157 | var $b = $( this ); 158 | 159 | // don't close on clicking the bubble 160 | if (!$(e.target).hasClass(ns+'-bubble')) { 161 | 162 | // Call the callback, if set 163 | if (typeof plugin.settings.onbeforeshow_callback === 'function') { 164 | plugin.settings.onbeforeshow_callback(this); 165 | } 166 | 167 | $b.toggleClass('active'); 168 | var $current_bubble = $b.find('.'+ns+'-bubble'); 169 | // Forces hiding other bubbles 170 | if (plugin.settings.close_all_but_this) { 171 | $('.'+ns+'-bubble').not($current_bubble).fadeOut(); 172 | } 173 | $current_bubble.fadeToggle(); 174 | 175 | if ($b.hasClass('active')) { 176 | clearTimeout(plugin.timer); 177 | plugin.timer = setTimeout(function(){ 178 | $b.trigger('pcp.fadeout'); 179 | }, plugin.settings.timeout); 180 | } 181 | } 182 | }) 183 | // Fade timer 184 | .on('pcp.fadeout', function() { 185 | $( this ).removeClass('active').find('.'+ns+'-bubble').fadeOut(); 186 | }) 187 | // Enter bubble 188 | .on('mouseenter', '.'+ns+'-bubble', function() { 189 | clearTimeout(plugin.timer); 190 | }) 191 | // Leave bubble 192 | .on('mouseleave', '.'+ns+'-bubble', function() { 193 | plugin.timer = setTimeout(function(){ 194 | $button.trigger('pcp.fadeout'); 195 | }, plugin.settings.timeout); 196 | }) 197 | // Click on swatches 198 | .on(click_handler, '.'+ns+'-bubble span.swatch', function(e){ 199 | e.preventDefault(); 200 | e.stopPropagation(); 201 | var 202 | col = $( this ).attr('data-color'), 203 | name = $( this ).attr('data-name'), 204 | // Select all button in document with same data target to keep them synconized 205 | $button = $('.'+ns+'-button[data-target="' + $( this ).closest( '.'+ns+'-button' ).attr('data-target') + '"]'), 206 | $bubble = $( this ).closest( '.'+ns+'-bubble' ); 207 | 208 | // console.log('.'+ns+'-button [data-target="' + $( this ).closest( '.'+ns+'-button' ).attr('data-target') + '"]'); 209 | $bubble.find('.active').removeClass('active'); 210 | 211 | // Set background on color 212 | // User clicked in the clear swatch 213 | if ( $(e.target).is('.clear') ) { 214 | $button.removeAttr('style'); 215 | col = ''; 216 | } else { 217 | $(this).addClass('active'); 218 | $button.css('background', col); 219 | } 220 | 221 | // Call the callback, if set 222 | if (typeof plugin.settings.onchange_callback === "function") { 223 | plugin.settings.onchange_callback(col); 224 | } 225 | 226 | if( plugin.settings.set_background === false ) { 227 | $('[name="' + $button.attr('data-target') + '"]').val(name); 228 | } else { 229 | $('[name="' + $button.attr('data-target') + '"]').css({'background-color' : col}); 230 | } 231 | })['insert'+plugin.settings.insert]( $el ); 232 | 233 | // Upside / downside, default is upside 234 | if ( plugin.settings.position === 'downside' || ($el.offset().top) + 20 < $bubble.outerHeight() ) { 235 | $bubble.addClass('downside'); 236 | } 237 | 238 | }; 239 | 240 | // Close on clicking outside the palette 241 | $('body').on(click_handler,function(event) { 242 | if (!$(event.target).hasClass(ns+'-button')) { 243 | $( $button ).removeClass('active').find('.'+ns+'-bubble').fadeOut(); 244 | } 245 | }); 246 | 247 | // Start 248 | plugin.init(); 249 | }; 250 | 251 | // add the plugin to the jQuery.fn object 252 | $.fn.paletteColorPicker = function(options) { 253 | return this.each(function() { 254 | if (typeof $(this).data('paletteColorPickerPlugin') === 'undefined') { 255 | $(this).data('paletteColorPickerPlugin', new $.paletteColorPicker(this, options)); 256 | } 257 | }); 258 | }; 259 | 260 | })(jQuery); 261 | 262 | // Sample usage 263 | // $(function() { 264 | // $('[data-palette-color-picker]').paletteColorPicker(); 265 | // }); 266 | -------------------------------------------------------------------------------- /src/palette-color-picker.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * JQuery Palette Color Picker v1.13 by Carlos Cabo ( @putuko ) 3 | * https://github.com/carloscabo/jquery-palette-color-picker 4 | */ 5 | (function(t){"use strict";t.paletteColorPicker=function(e,a){var s="palette-color-picker",i=t(e),n=this,o=null,l=i.val(),r=i.attr("name"),c=t("
").addClass(s+"-button").attr("data-target",r),u=t("
").addClass(s+"-bubble"),f={},d={custom_class:null,colors:null,position:"upside",insert:"before",clear_btn:"first",timeout:2e3,set_background:false,close_all_but_this:false},g="ontouchstart"in document.documentElement?"touchstart click":"click";n.init=function(){n.settings=t.extend({},d,a);var e=i.attr("value");if(typeof e===typeof undefined||e===false){e="";i.attr("value",e)}i.attr("data-initialvalue",i.attr("value"));if(n.settings.colors===null){n.settings.colors=i.data("palette")}if(typeof n.settings.colors[0]==="string"){n.settings.colors=t.map(n.settings.colors,function(t,e){var a={};a[t]=t;return a})}n.settings.insert=n.settings.insert.charAt(0).toUpperCase()+n.settings.insert.slice(1);if(n.settings.custom_class){u.addClass(n.settings.custom_class)}t.each(n.settings.colors,function(e,a){var s=Object.keys(a)[0],i=a[s],n=t("").addClass("swatch").attr({title:s,"data-color":i,"data-name":s}).css("background-color",i);if(s===l){n.addClass("active");c.css("background",i)}n.appendTo(u)});if(n.settings.clear_btn!==null){var o=t("").addClass("swatch clear").attr("title","Clear selection");if(n.settings.clear_btn==="last"){o.addClass("last").appendTo(u)}else{o.prependTo(u)}}n.destroy=function(){c.remove();t.removeData(i[0])};n.clear=function(){u.find(".active").removeClass("active");c.removeAttr("style");i.val("")};n.reset=function(){if(i.attr("data-initialvalue")===""){n.clear()}else{var t=i.attr("data-initialvalue");u.find('[data-name="'+t+'"]').trigger("click")}};n.reload=function(){var t=i.val();if(t===""||typeof t===typeof undefined||t===false){n.reset()}else{if(u.find('[data-name="'+t+'"]').length){u.find('[data-name="'+t+'"]').trigger("click")}else{n.reset()}}};c.append(u).on(g,function(e){e.preventDefault();e.stopPropagation();var a=t(this);if(!t(e.target).hasClass(s+"-bubble")){if(typeof n.settings.onbeforeshow_callback==="function"){n.settings.onbeforeshow_callback(this)}a.toggleClass("active");var i=a.find("."+s+"-bubble");if(n.settings.close_all_but_this){t("."+s+"-bubble").not(i).fadeOut()}i.fadeToggle();if(a.hasClass("active")){clearTimeout(n.timer);n.timer=setTimeout(function(){a.trigger("pcp.fadeout")},n.settings.timeout)}}}).on("pcp.fadeout",function(){t(this).removeClass("active").find("."+s+"-bubble").fadeOut()}).on("mouseenter","."+s+"-bubble",function(){clearTimeout(n.timer)}).on("mouseleave","."+s+"-bubble",function(){n.timer=setTimeout(function(){c.trigger("pcp.fadeout")},n.settings.timeout)}).on(g,"."+s+"-bubble span.swatch",function(e){e.preventDefault();e.stopPropagation();var a=t(this).attr("data-color"),i=t(this).attr("data-name"),o=t("."+s+'-button[data-target="'+t(this).closest("."+s+"-button").attr("data-target")+'"]'),l=t(this).closest("."+s+"-bubble");l.find(".active").removeClass("active");if(t(e.target).is(".clear")){o.removeAttr("style");a=""}else{t(this).addClass("active");o.css("background",a)}if(typeof n.settings.onchange_callback==="function"){n.settings.onchange_callback(a)}if(n.settings.set_background===false){t('[name="'+o.attr("data-target")+'"]').val(i)}else{t('[name="'+o.attr("data-target")+'"]').css({"background-color":a})}})["insert"+n.settings.insert](i);if(n.settings.position==="downside"||i.offset().top+20') center center no-repeat; 14 | background-size: cover; 15 | /*background: url(palette-color-picker-icon.svg) center center no-repeat;*/ 16 | cursor: pointer; 17 | 18 | box-shadow: 0 0 0 1px $cpfp-border; 19 | /*outline: 1px solid $cpfp-border;*/ 20 | border: 2px solid #fff; 21 | } 22 | 23 | // Bubble 24 | .palette-color-picker-bubble { 25 | display: none; 26 | margin: 12px 0; 27 | position: absolute; 28 | bottom: 100%; 29 | width: $cpfp-width; 30 | padding: 10px 8px 8px 8px; 31 | border: 1px solid $cpfp-border; 32 | border-radius: 3px; 33 | background-color: #fff; 34 | 35 | // Arrow bottom 36 | &:after, 37 | &:before { 38 | top: 100%; 39 | left: 14px; 40 | border: solid transparent; 41 | content: ' '; 42 | height: 0; 43 | width: 0; 44 | position: absolute; 45 | pointer-events: none; 46 | } 47 | &:after { 48 | border-color: transparent; 49 | border-top-color: $cpfp-background; 50 | border-width: 8px; 51 | margin-left: -8px; 52 | } 53 | &:before { 54 | border-color: transparent; 55 | border-top-color: $cpfp-border; 56 | border-width: 9px; 57 | margin-left: -9px; 58 | } 59 | 60 | // Open below 61 | &.downside { 62 | bottom: auto; 63 | top: 100%; 64 | 65 | // Arow on top 66 | &:after, &:before { 67 | top: auto; 68 | bottom: 100%; 69 | } 70 | &:after { 71 | border-top-color: transparent; 72 | border-bottom-color: $cpfp-background; 73 | } 74 | &:before { 75 | border-top-color: transparent; 76 | border-bottom-color: $cpfp-border; 77 | } 78 | } 79 | 80 | .swatch { 81 | position: relative; 82 | display: inline-block; 83 | font: 0/0 a; 84 | width: 12.66%; 85 | padding-top: 11.00%; 86 | margin: 1% 2%; 87 | outline: 1px solid $cpfp-border; 88 | border: 2px solid #fff; 89 | border-radius: 3px; 90 | cursor: pointer; 91 | overflow: hidden; 92 | 93 | 94 | &.active { 95 | outline-color: #000; 96 | 97 | -webkit-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.75); 98 | -moz-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.75); 99 | box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.75); 100 | } 101 | 102 | &.clear { 103 | background-color: #fff; 104 | &:before { 105 | position: absolute; 106 | content: ''; 107 | display: block; 108 | top: -1px; 109 | left: 0; 110 | width: 100px; 111 | height: 2px; 112 | background-color: #e00; 113 | 114 | transform-origin: 0 0; 115 | transform: rotate(45deg); 116 | } 117 | } 118 | } 119 | 120 | // x2 width swatches 121 | &.double { 122 | .swatch { 123 | width: 29.30%; 124 | padding-top: 11.00%; 125 | margin: 1% 2%; 126 | &.clear { 127 | &:before { 128 | transform: rotate(22.5deg); 129 | } 130 | } 131 | } 132 | } 133 | 134 | // full width swatches 135 | &.wide { 136 | .swatch { 137 | width: 96.2%; 138 | padding-top: 11.00%; 139 | margin: 1% 2%; 140 | &.clear { 141 | width: 12.66%; 142 | } 143 | } 144 | } 145 | 146 | // Force open on left side 147 | &.force-left { 148 | left: -178px; 149 | &:after, 150 | &:before { 151 | left: 188px; 152 | } 153 | } 154 | 155 | } 156 | --------------------------------------------------------------------------------