')
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 |
--------------------------------------------------------------------------------