1 /* global wpColorPickerL10n */ |
1 /* global wpColorPickerL10n */ |
2 ( function( $, undef ){ |
2 ( function( $, undef ) { |
3 |
3 |
4 var ColorPicker, |
4 var ColorPicker, |
5 // html stuff |
5 _before = '<button type="button" class="button wp-color-result" aria-expanded="false"><span class="wp-color-result-text"></span></button>', |
6 _before = '<a tabindex="0" class="wp-color-result" />', |
|
7 _after = '<div class="wp-picker-holder" />', |
6 _after = '<div class="wp-picker-holder" />', |
8 _wrap = '<div class="wp-picker-container" />', |
7 _wrap = '<div class="wp-picker-container" />', |
9 _button = '<input type="button" class="button button-small hidden" />'; |
8 _button = '<input type="button" class="button button-small" />', |
10 |
9 _wrappingLabel = '<label></label>', |
11 // jQuery UI Widget constructor |
10 _wrappingLabelText = '<span class="screen-reader-text"></span>'; |
|
11 |
|
12 /** |
|
13 * @summary Creates a jQuery UI color picker. |
|
14 * |
|
15 * Creates a jQuery UI color picker that is used in the theme customizer. |
|
16 * |
|
17 * @since 3.5.0 |
|
18 */ |
12 ColorPicker = { |
19 ColorPicker = { |
13 options: { |
20 options: { |
14 defaultColor: false, |
21 defaultColor: false, |
15 change: false, |
22 change: false, |
16 clear: false, |
23 clear: false, |
17 hide: true, |
24 hide: true, |
18 palettes: true, |
25 palettes: true, |
19 width: 255, |
26 width: 255, |
20 mode: 'hsv' |
27 mode: 'hsv', |
21 }, |
28 type: 'full', |
|
29 slider: 'horizontal' |
|
30 }, |
|
31 /** |
|
32 * @summary Creates a color picker that only allows you to adjust the hue. |
|
33 * |
|
34 * @since 3.5.0 |
|
35 * |
|
36 * @access private |
|
37 * |
|
38 * @returns {void} |
|
39 */ |
|
40 _createHueOnly: function() { |
|
41 var self = this, |
|
42 el = self.element, |
|
43 color; |
|
44 |
|
45 el.hide(); |
|
46 |
|
47 // Set the saturation to the maximum level. |
|
48 color = 'hsl(' + el.val() + ', 100, 50)'; |
|
49 |
|
50 // Create an instance of the color picker, using the hsl mode. |
|
51 el.iris( { |
|
52 mode: 'hsl', |
|
53 type: 'hue', |
|
54 hide: false, |
|
55 color: color, |
|
56 /** |
|
57 * @summary Handles the onChange event if one has been defined in the options. |
|
58 * |
|
59 * @param {Event} event The event that's being called. |
|
60 * @param {HTMLElement} ui The HTMLElement containing the color picker. |
|
61 * |
|
62 * @returns {void} |
|
63 */ |
|
64 change: function( event, ui ) { |
|
65 if ( $.isFunction( self.options.change ) ) { |
|
66 self.options.change.call( this, event, ui ); |
|
67 } |
|
68 }, |
|
69 width: self.options.width, |
|
70 slider: self.options.slider |
|
71 } ); |
|
72 }, |
|
73 /** |
|
74 * @summary Creates the color picker. |
|
75 * |
|
76 * Creates the color picker, sets default values, css classes and wraps it all in HTML. |
|
77 * |
|
78 * @since 3.5.0 |
|
79 * |
|
80 * @access private |
|
81 * |
|
82 * @returns {void} |
|
83 */ |
22 _create: function() { |
84 _create: function() { |
23 // bail early for unsupported Iris. |
85 // Return early if Iris support is missing. |
24 if ( ! $.support.iris ) { |
86 if ( ! $.support.iris ) { |
25 return; |
87 return; |
26 } |
88 } |
27 |
89 |
28 var self = this, |
90 var self = this, |
29 el = self.element; |
91 el = self.element; |
30 |
92 |
|
93 // Override default options with options bound to the element. |
31 $.extend( self.options, el.data() ); |
94 $.extend( self.options, el.data() ); |
32 |
95 |
33 // keep close bound so it can be attached to a body listener |
96 // Create a color picker which only allows adjustments to the hue. |
|
97 if ( self.options.type === 'hue' ) { |
|
98 return self._createHueOnly(); |
|
99 } |
|
100 |
|
101 // Bind the close event. |
34 self.close = $.proxy( self.close, self ); |
102 self.close = $.proxy( self.close, self ); |
35 |
103 |
36 self.initialValue = el.val(); |
104 self.initialValue = el.val(); |
37 |
105 |
38 // Set up HTML structure, hide things |
106 // Add a CSS class to the input field. |
39 el.addClass( 'wp-color-picker' ).hide().wrap( _wrap ); |
107 el.addClass( 'wp-color-picker' ); |
40 self.wrap = el.parent(); |
108 |
41 self.toggler = $( _before ).insertBefore( el ).css( { backgroundColor: self.initialValue } ).attr( 'title', wpColorPickerL10n.pick ).attr( 'data-current', wpColorPickerL10n.current ); |
109 /* |
42 self.pickerContainer = $( _after ).insertAfter( el ); |
110 * Check if there's already a wrapping label, e.g. in the Customizer. |
|
111 * If there's no label, add a default one to match the Customizer template. |
|
112 */ |
|
113 if ( ! el.parent( 'label' ).length ) { |
|
114 // Wrap the input field in the default label. |
|
115 el.wrap( _wrappingLabel ); |
|
116 // Insert the default label text. |
|
117 self.wrappingLabelText = $( _wrappingLabelText ) |
|
118 .insertBefore( el ) |
|
119 .text( wpColorPickerL10n.defaultLabel ); |
|
120 } |
|
121 |
|
122 /* |
|
123 * At this point, either it's the standalone version or the Customizer |
|
124 * one, we have a wrapping label to use as hook in the DOM, let's store it. |
|
125 */ |
|
126 self.wrappingLabel = el.parent(); |
|
127 |
|
128 // Wrap the label in the main wrapper. |
|
129 self.wrappingLabel.wrap( _wrap ); |
|
130 // Store a reference to the main wrapper. |
|
131 self.wrap = self.wrappingLabel.parent(); |
|
132 // Set up the toggle button and insert it before the wrapping label. |
|
133 self.toggler = $( _before ) |
|
134 .insertBefore( self.wrappingLabel ) |
|
135 .css( { backgroundColor: self.initialValue } ); |
|
136 // Set the toggle button span element text. |
|
137 self.toggler.find( '.wp-color-result-text' ).text( wpColorPickerL10n.pick ); |
|
138 // Set up the Iris container and insert it after the wrapping label. |
|
139 self.pickerContainer = $( _after ).insertAfter( self.wrappingLabel ); |
|
140 // Store a reference to the Clear/Default button. |
43 self.button = $( _button ); |
141 self.button = $( _button ); |
44 |
142 |
|
143 // Set up the Clear/Default button. |
45 if ( self.options.defaultColor ) { |
144 if ( self.options.defaultColor ) { |
46 self.button.addClass( 'wp-picker-default' ).val( wpColorPickerL10n.defaultString ); |
145 self.button |
|
146 .addClass( 'wp-picker-default' ) |
|
147 .val( wpColorPickerL10n.defaultString ) |
|
148 .attr( 'aria-label', wpColorPickerL10n.defaultAriaLabel ); |
47 } else { |
149 } else { |
48 self.button.addClass( 'wp-picker-clear' ).val( wpColorPickerL10n.clear ); |
150 self.button |
49 } |
151 .addClass( 'wp-picker-clear' ) |
50 |
152 .val( wpColorPickerL10n.clear ) |
51 el.wrap( '<span class="wp-picker-input-wrap" />' ).after(self.button); |
153 .attr( 'aria-label', wpColorPickerL10n.clearAriaLabel ); |
|
154 } |
|
155 |
|
156 // Wrap the wrapping label in its wrapper and append the Clear/Default button. |
|
157 self.wrappingLabel |
|
158 .wrap( '<span class="wp-picker-input-wrap hidden" />' ) |
|
159 .after( self.button ); |
|
160 |
|
161 /* |
|
162 * The input wrapper now contains the label+input+Clear/Default button. |
|
163 * Store a reference to the input wrapper: we'll use this to toggle |
|
164 * the controls visibility. |
|
165 */ |
|
166 self.inputWrapper = el.closest( '.wp-picker-input-wrap' ); |
52 |
167 |
53 el.iris( { |
168 el.iris( { |
54 target: self.pickerContainer, |
169 target: self.pickerContainer, |
55 hide: self.options.hide, |
170 hide: self.options.hide, |
56 width: self.options.width, |
171 width: self.options.width, |
57 mode: self.options.mode, |
172 mode: self.options.mode, |
58 palettes: self.options.palettes, |
173 palettes: self.options.palettes, |
|
174 /** |
|
175 * @summary Handles the onChange event if one has been defined in the options. |
|
176 * |
|
177 * Handles the onChange event if one has been defined in the options and additionally |
|
178 * sets the background color for the toggler element. |
|
179 * |
|
180 * @since 3.5.0 |
|
181 * |
|
182 * @param {Event} event The event that's being called. |
|
183 * @param {HTMLElement} ui The HTMLElement containing the color picker. |
|
184 * |
|
185 * @returns {void} |
|
186 */ |
59 change: function( event, ui ) { |
187 change: function( event, ui ) { |
60 self.toggler.css( { backgroundColor: ui.color.toString() } ); |
188 self.toggler.css( { backgroundColor: ui.color.toString() } ); |
61 // check for a custom cb |
189 |
62 if ( $.isFunction( self.options.change ) ) { |
190 if ( $.isFunction( self.options.change ) ) { |
63 self.options.change.call( this, event, ui ); |
191 self.options.change.call( this, event, ui ); |
64 } |
192 } |
65 } |
193 } |
66 } ); |
194 } ); |
67 |
195 |
68 el.val( self.initialValue ); |
196 el.val( self.initialValue ); |
69 self._addListeners(); |
197 self._addListeners(); |
|
198 |
|
199 // Force the color picker to always be closed on initial load. |
70 if ( ! self.options.hide ) { |
200 if ( ! self.options.hide ) { |
71 self.toggler.click(); |
201 self.toggler.click(); |
72 } |
202 } |
73 }, |
203 }, |
|
204 /** |
|
205 * @summary Binds event listeners to the color picker. |
|
206 * |
|
207 * @since 3.5.0 |
|
208 * |
|
209 * @access private |
|
210 * |
|
211 * @returns {void} |
|
212 */ |
74 _addListeners: function() { |
213 _addListeners: function() { |
75 var self = this; |
214 var self = this; |
76 |
215 |
77 // prevent any clicks inside this widget from leaking to the top and closing it |
216 /** |
|
217 * @summary Prevent any clicks inside this widget from leaking to the top and closing it. |
|
218 * |
|
219 * @since 3.5.0 |
|
220 * |
|
221 * @param {Event} event The event that's being called. |
|
222 * |
|
223 * @returs {void} |
|
224 */ |
78 self.wrap.on( 'click.wpcolorpicker', function( event ) { |
225 self.wrap.on( 'click.wpcolorpicker', function( event ) { |
79 event.stopPropagation(); |
226 event.stopPropagation(); |
80 }); |
227 }); |
81 |
228 |
|
229 /** |
|
230 * @summary Open or close the color picker depending on the class. |
|
231 * |
|
232 * @since 3.5 |
|
233 */ |
82 self.toggler.click( function(){ |
234 self.toggler.click( function(){ |
83 if ( self.toggler.hasClass( 'wp-picker-open' ) ) { |
235 if ( self.toggler.hasClass( 'wp-picker-open' ) ) { |
84 self.close(); |
236 self.close(); |
85 } else { |
237 } else { |
86 self.open(); |
238 self.open(); |
87 } |
239 } |
88 }); |
240 }); |
89 |
241 |
|
242 /** |
|
243 * @summary Checks if value is empty when changing the color in the color picker. |
|
244 * |
|
245 * Checks if value is empty when changing the color in the color picker. |
|
246 * If so, the background color is cleared. |
|
247 * |
|
248 * @since 3.5.0 |
|
249 * |
|
250 * @param {Event} event The event that's being called. |
|
251 * |
|
252 * @returns {void} |
|
253 */ |
90 self.element.change( function( event ) { |
254 self.element.change( function( event ) { |
91 var me = $( this ), |
255 var me = $( this ), |
92 val = me.val(); |
256 val = me.val(); |
93 // Empty = clear |
257 |
94 if ( val === '' || val === '#' ) { |
258 if ( val === '' || val === '#' ) { |
95 self.toggler.css( 'backgroundColor', '' ); |
259 self.toggler.css( 'backgroundColor', '' ); |
96 // fire clear callback if we have one |
260 // Fire clear callback if we have one. |
97 if ( $.isFunction( self.options.clear ) ) { |
261 if ( $.isFunction( self.options.clear ) ) { |
98 self.options.clear.call( this, event ); |
262 self.options.clear.call( this, event ); |
99 } |
263 } |
100 } |
264 } |
101 }); |
265 }); |
102 |
266 |
103 // open a keyboard-focused closed picker with space or enter |
267 /** |
104 self.toggler.on( 'keyup', function( event ) { |
268 * @summary Enables the user to clear or revert the color in the color picker. |
105 if ( event.keyCode === 13 || event.keyCode === 32 ) { |
269 * |
106 event.preventDefault(); |
270 * Enables the user to either clear the color in the color picker or revert back to the default color. |
107 self.toggler.trigger( 'click' ).next().focus(); |
271 * |
108 } |
272 * @since 3.5.0 |
109 }); |
273 * |
110 |
274 * @param {Event} event The event that's being called. |
|
275 * |
|
276 * @returns {void} |
|
277 */ |
111 self.button.click( function( event ) { |
278 self.button.click( function( event ) { |
112 var me = $( this ); |
279 var me = $( this ); |
113 if ( me.hasClass( 'wp-picker-clear' ) ) { |
280 if ( me.hasClass( 'wp-picker-clear' ) ) { |
114 self.element.val( '' ); |
281 self.element.val( '' ); |
115 self.toggler.css( 'backgroundColor', '' ); |
282 self.toggler.css( 'backgroundColor', '' ); |
119 } else if ( me.hasClass( 'wp-picker-default' ) ) { |
286 } else if ( me.hasClass( 'wp-picker-default' ) ) { |
120 self.element.val( self.options.defaultColor ).change(); |
287 self.element.val( self.options.defaultColor ).change(); |
121 } |
288 } |
122 }); |
289 }); |
123 }, |
290 }, |
|
291 /** |
|
292 * @summary Opens the color picker dialog. |
|
293 * |
|
294 * @since 3.5.0 |
|
295 * |
|
296 * @returns {void} |
|
297 */ |
124 open: function() { |
298 open: function() { |
125 this.element.show().iris( 'toggle' ).focus(); |
299 this.element.iris( 'toggle' ); |
126 this.button.removeClass( 'hidden' ); |
300 this.inputWrapper.removeClass( 'hidden' ); |
127 this.toggler.addClass( 'wp-picker-open' ); |
301 this.wrap.addClass( 'wp-picker-active' ); |
|
302 this.toggler |
|
303 .addClass( 'wp-picker-open' ) |
|
304 .attr( 'aria-expanded', 'true' ); |
128 $( 'body' ).trigger( 'click.wpcolorpicker' ).on( 'click.wpcolorpicker', this.close ); |
305 $( 'body' ).trigger( 'click.wpcolorpicker' ).on( 'click.wpcolorpicker', this.close ); |
129 }, |
306 }, |
|
307 /** |
|
308 * @summary Closes the color picker dialog. |
|
309 * |
|
310 * @since 3.5.0 |
|
311 * |
|
312 * @returns {void} |
|
313 */ |
130 close: function() { |
314 close: function() { |
131 this.element.hide().iris( 'toggle' ); |
315 this.element.iris( 'toggle' ); |
132 this.button.addClass( 'hidden' ); |
316 this.inputWrapper.addClass( 'hidden' ); |
133 this.toggler.removeClass( 'wp-picker-open' ); |
317 this.wrap.removeClass( 'wp-picker-active' ); |
|
318 this.toggler |
|
319 .removeClass( 'wp-picker-open' ) |
|
320 .attr( 'aria-expanded', 'false' ); |
134 $( 'body' ).off( 'click.wpcolorpicker', this.close ); |
321 $( 'body' ).off( 'click.wpcolorpicker', this.close ); |
135 }, |
322 }, |
136 // $("#input").wpColorPicker('color') returns the current color |
323 /** |
137 // $("#input").wpColorPicker('color', '#bada55') to set |
324 * @summary Returns iris object or sets new color. |
|
325 * |
|
326 * Returns the iris object if no new color is provided. If a new color is provided, it sets the new color. |
|
327 * |
|
328 * @param newColor {string|*} The new color to use. Can be undefined. |
|
329 * |
|
330 * @since 3.5.0 |
|
331 * |
|
332 * @returns {string} The element's color |
|
333 */ |
138 color: function( newColor ) { |
334 color: function( newColor ) { |
139 if ( newColor === undef ) { |
335 if ( newColor === undef ) { |
140 return this.element.iris( 'option', 'color' ); |
336 return this.element.iris( 'option', 'color' ); |
141 } |
337 } |
142 |
|
143 this.element.iris( 'option', 'color', newColor ); |
338 this.element.iris( 'option', 'color', newColor ); |
144 }, |
339 }, |
145 //$("#input").wpColorPicker('defaultColor') returns the current default color |
340 /** |
146 //$("#input").wpColorPicker('defaultColor', newDefaultColor) to set |
341 * @summary Returns iris object or sets new default color. |
|
342 * |
|
343 * Returns the iris object if no new default color is provided. |
|
344 * If a new default color is provided, it sets the new default color. |
|
345 * |
|
346 * @param newDefaultColor {string|*} The new default color to use. Can be undefined. |
|
347 * |
|
348 * @since 3.5.0 |
|
349 * |
|
350 * @returns {boolean|string} The element's color. |
|
351 */ |
147 defaultColor: function( newDefaultColor ) { |
352 defaultColor: function( newDefaultColor ) { |
148 if ( newDefaultColor === undef ) { |
353 if ( newDefaultColor === undef ) { |
149 return this.options.defaultColor; |
354 return this.options.defaultColor; |
150 } |
355 } |
151 |
356 |
152 this.options.defaultColor = newDefaultColor; |
357 this.options.defaultColor = newDefaultColor; |
153 } |
358 } |
154 }; |
359 }; |
155 |
360 |
|
361 // Register the color picker as a widget. |
156 $.widget( 'wp.wpColorPicker', ColorPicker ); |
362 $.widget( 'wp.wpColorPicker', ColorPicker ); |
157 }( jQuery ) ); |
363 }( jQuery ) ); |