PluginProbe
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI / trunk
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI vtrunk
6.0.3 6.0.2 6.0.1 6.0.0 5.8.6 5.8.5 5.8.4 5.8.3 5.8.2 5.8.1 5.8.0 5.7.9.2 5.7.9.1 5.7.8 5.7.9 5.7.6 5.7.7 5.7.5 5.7.4 5.7.3 5.7.2 5.7.1 trunk 5.6.0 5.6.1 All 34 releases
automatorwp / libraries / cmb2 / js / wp-color-picker-alpha.js

wp-color-picker-alpha.js in AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI trunk, at libraries/cmb2/js/wp-color-picker-alpha.js

685 lines 18.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**!
2 * wp-color-picker-alpha
3 *
4 * Overwrite Automattic Iris for enabled Alpha Channel in wpColorPicker
5 * Only run in input and is defined data alpha in true
6 *
7 * Version: 3.0.4
8 * https://github.com/kallookoo/wp-color-picker-alpha
9 * Licensed under the GPLv2 license or later.
10 */
11
12 ( function ( $, undef ) {
13
14 var wpColorPickerAlpha = {
15 'version': 304
16 };
17
18 // Always try to use the last version of this script.
19 if ( 'wpColorPickerAlpha' in window && 'version' in window.wpColorPickerAlpha ) {
20 var version = parseInt( window.wpColorPickerAlpha.version, 10 );
21 if ( !isNaN( version ) && version >= wpColorPickerAlpha.version ) {
22 return;
23 }
24 }
25
26 // Prevent multiple initiations
27 if ( Color.fn.hasOwnProperty( 'to_s' ) ) {
28 return;
29 }
30
31 // Create new method to replace the `Color.toString()` inside the scripts.
32 Color.fn.to_s = function ( type ) {
33 if ( this.error ) {
34 return '';
35 }
36 type = ( type || 'hex' );
37 // Change hex to rgba to return the correct color.
38 if ( 'hex' === type && this._alpha < 1 ) {
39 type = 'rgba';
40 }
41
42 var color = '';
43 if ( 'hex' === type ) {
44 color = this.toString();
45 } else if ( 'octohex' === type ) {
46 color = this.toString();
47 var alpha = parseInt( 255 * this._alpha, 10 ).toString( 16 );
48 if ( alpha.length === 1 ) {
49 alpha = `0${alpha}`;
50 }
51 color += alpha;
52 } else {
53 color = this.toCSS( type ).replace( /\(\s+/, '(' ).replace( /\s+\)/, ')' );
54 }
55
56 return color;
57 }
58
59 Color.fn.fromHex = function ( color ) {
60 color = color.replace( /^#/, '' ).replace( /^0x/, '' );
61 if ( 3 === color.length || 4 === color.length ) {
62 var extendedColor = '';
63 for ( var index = 0; index < color.length; index++ ) {
64 extendedColor += '' + color[ index ];
65 extendedColor += '' + color[ index ];
66 }
67 color = extendedColor;
68 }
69
70 if ( color.length === 8 ) {
71 if ( /^[0-9A-F]{8}$/i.test( color ) ) {
72 var alpha = parseInt( color.substring( 6 ), 16 );
73 if ( !isNaN( alpha ) ) {
74 this.a( alpha / 255 );
75 } else {
76 this._error();
77 }
78 } else {
79 this._error();
80 }
81 color = color.substring( 0, 6 );
82 }
83
84 if ( !this.error ) {
85 this.error = ! /^[0-9A-F]{6}$/i.test( color );
86 }
87
88 // console.log(color + ': ' + this.a())
89 return this.fromInt( parseInt( color, 16 ) );
90 }
91
92 // Register the global variable.
93 window.wpColorPickerAlpha = wpColorPickerAlpha;
94
95 // Background image encoded
96 var backgroundImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAAHnlligAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNpi+P///4EDBxiAGMgCCCAGFB5AADGCRBgYDh48CCRZIJS9vT2QBAggFBkmBiSAogxFBiCAoHogAKIKAlBUYTELAiAmEtABEECk20G6BOmuIl0CIMBQ/IEMkO0myiSSraaaBhZcbkUOs0HuBwDplz5uFJ3Z4gAAAABJRU5ErkJggg==';
97
98 /**
99 * Iris
100 */
101 $.widget( 'a8c.iris', $.a8c.iris, {
102 /**
103 * Alpha options
104 *
105 * @since 3.0.0
106 *
107 * @type {Object}
108 */
109 alphaOptions: {
110 alphaEnabled: false,
111 },
112 /**
113 * Get the current color or the new color.
114 *
115 * @since 3.0.0
116 * @access private
117 *
118 * @param {Object|*} The color instance if not defined return the current color.
119 *
120 * @return {string} The element's color.
121 */
122 _getColor: function ( color ) {
123 if ( color === undef ) {
124 color = this._color;
125 }
126
127 if ( this.alphaOptions.alphaEnabled ) {
128 color = color.to_s( this.alphaOptions.alphaColorType );
129 if ( !this.alphaOptions.alphaColorWithSpace ) {
130 color = color.replace( /\s+/g, '' );
131 }
132 return color;
133 }
134 return color.toString();
135 },
136 /**
137 * Create widget
138 *
139 * @since 3.0.0
140 * @access private
141 *
142 * @return {void}
143 */
144 _create: function () {
145 try {
146 // Try to get the wpColorPicker alpha options.
147 this.alphaOptions = this.element.wpColorPicker( 'instance' ).alphaOptions;
148 } catch ( e ) { }
149
150 // We make sure there are all options
151 $.extend( {}, this.alphaOptions, {
152 alphaEnabled: false,
153 alphaCustomWidth: 130,
154 alphaReset: false,
155 alphaColorType: 'hex',
156 alphaColorWithSpace: false,
157 alphaSkipDebounce: false,
158 alphaDebounceTimeout: 100,
159 } );
160
161 this._super();
162 },
163 /**
164 * Binds event listeners to the Iris.
165 *
166 * @since 3.0.0
167 * @access private
168 *
169 * @return {void}
170 */
171 _addInputListeners: function ( input ) {
172 var self = this,
173 callback = function ( event ) {
174 var val = input.val(),
175 color = new Color( val ),
176 val = val.replace( /^(#|(rgb|hsl)a?)/, '' ),
177 type = self.alphaOptions.alphaColorType;
178
179 input.removeClass( 'iris-error' );
180
181 if ( !color.error ) {
182 // let's not do this on keyup for hex shortcodes
183 if ( 'hex' !== type || !( event.type === 'keyup' && val.match( /^[0-9a-fA-F]{3}$/ ) ) ) {
184 // Compare color ( #AARRGGBB )
185 if ( color.toIEOctoHex() !== self._color.toIEOctoHex() ) {
186 self._setOption( 'color', self._getColor( color ) );
187 }
188 }
189 } else if ( val !== '' ) {
190 input.addClass( 'iris-error' );
191 }
192 };
193
194 input.on( 'change', callback );
195
196 if ( !self.alphaOptions.alphaSkipDebounce ) {
197 input.on( 'keyup', self._debounce( callback, self.alphaOptions.alphaDebounceTimeout ) );
198 }
199
200 // If we initialized hidden, show on first focus. The rest is up to you.
201 if ( self.options.hide ) {
202 input.one( 'focus', function () {
203 self.show();
204 } );
205 }
206 },
207 /**
208 * Init Controls
209 *
210 * @since 3.0.0
211 * @access private
212 *
213 * @return {void}
214 */
215 _initControls: function () {
216 this._super();
217
218 if ( this.alphaOptions.alphaEnabled ) {
219 // Create Alpha controls
220 var self = this,
221 stripAlpha = self.controls.strip.clone( false, false ),
222 stripAlphaSlider = stripAlpha.find( '.iris-slider-offset' ),
223 controls = {
224 stripAlpha: stripAlpha,
225 stripAlphaSlider: stripAlphaSlider
226 };
227
228 stripAlpha.addClass( 'iris-strip-alpha' );
229 stripAlphaSlider.addClass( 'iris-slider-offset-alpha' );
230 stripAlpha.appendTo( self.picker.find( '.iris-picker-inner' ) );
231
232 // Push new controls
233 $.each( controls, function ( k, v ) {
234 self.controls[ k ] = v;
235 } );
236
237 // Create slider
238 self.controls.stripAlphaSlider.slider( {
239 orientation: 'vertical',
240 min: 0,
241 max: 100,
242 step: 1,
243 value: parseInt( self._color._alpha * 100 ),
244 slide: function ( event, ui ) {
245 self.active = 'strip';
246 // Update alpha value
247 self._color._alpha = parseFloat( ui.value / 100 );
248 self._change.apply( self, arguments );
249 }
250 } );
251 }
252 },
253 /**
254 * Create the controls sizes
255 *
256 * @since 3.0.0
257 * @access private
258 *
259 * @param {bool} reset Set to True for recreate the controls sizes.
260 *
261 * @return {void}
262 */
263 _dimensions: function ( reset ) {
264 this._super( reset );
265
266 if ( this.alphaOptions.alphaEnabled ) {
267 var self = this,
268 opts = self.options,
269 controls = self.controls,
270 square = controls.square,
271 strip = self.picker.find( '.iris-strip' ),
272 innerWidth, squareWidth, stripWidth, stripMargin, totalWidth;
273
274 /**
275 * I use Math.round() to avoid possible size errors,
276 * this function returns the value of a number rounded
277 * to the nearest integer.
278 *
279 * The width to append all widgets,
280 * if border is enabled, 22 is subtracted.
281 * 20 for css left and right property
282 * 2 for css border
283 */
284 innerWidth = Math.round( self.picker.outerWidth( true ) - ( opts.border ? 22 : 0 ) );
285 // The width of the draggable, aka square.
286 squareWidth = Math.round( square.outerWidth() );
287 // The width for the sliders
288 stripWidth = Math.round( ( innerWidth - squareWidth ) / 2 );
289 // The margin for the sliders
290 stripMargin = Math.round( stripWidth / 2 );
291 // The total width of the elements.
292 totalWidth = Math.round( squareWidth + ( stripWidth * 2 ) + ( stripMargin * 2 ) );
293
294 // Check and change if necessary.
295 while ( totalWidth > innerWidth ) {
296 stripWidth = Math.round( stripWidth - 2 );
297 stripMargin = Math.round( stripMargin - 1 );
298 totalWidth = Math.round( squareWidth + ( stripWidth * 2 ) + ( stripMargin * 2 ) );
299 }
300
301 square.css( 'margin', '0' );
302 strip.width( stripWidth ).css( 'margin-left', stripMargin + 'px' );
303 }
304 },
305 /**
306 * Callback to update the controls and the current color.
307 *
308 * @since 3.0.0
309 * @access private
310 *
311 * @return {void}
312 */
313 _change: function () {
314 var self = this,
315 active = self.active;
316
317 self._super();
318
319 if ( self.alphaOptions.alphaEnabled ) {
320 var controls = self.controls,
321 alpha = parseInt( self._color._alpha * 100 ),
322 color = self._color.toRgb(),
323 gradient = [
324 'rgb(' + color.r + ',' + color.g + ',' + color.b + ') 0%',
325 'rgba(' + color.r + ',' + color.g + ',' + color.b + ', 0) 100%'
326 ],
327 target = self.picker.closest( '.wp-picker-container' ).find( '.wp-color-result' );
328
329 self.options.color = self._getColor();
330 // Generate background slider alpha, only for CSS3.
331 controls.stripAlpha.css( { 'background': 'linear-gradient(to bottom, ' + gradient.join( ', ' ) + '), url(' + backgroundImage + ')' } );
332 // Update alpha value
333 if ( active ) {
334 controls.stripAlphaSlider.slider( 'value', alpha );
335 }
336
337 if ( !self._color.error ) {
338 self.element.removeClass( 'iris-error' ).val( self.options.color );
339 }
340
341 self.picker.find( '.iris-palette-container' ).on( 'click.palette', '.iris-palette', function () {
342 var color = $( this ).data( 'color' );
343 if ( self.alphaOptions.alphaReset ) {
344 self._color._alpha = 1;
345 color = self._getColor();
346 }
347 self._setOption( 'color', color );
348 } );
349 }
350 },
351 /**
352 * Paint dimensions.
353 *
354 * @since 3.0.0
355 * @access private
356 *
357 * @param {string} origin Origin (position).
358 * @param {string} control Type of the control,
359 *
360 * @return {void}
361 */
362 _paintDimension: function ( origin, control ) {
363 var self = this,
364 color = false;
365
366 // Fix for slider hue opacity.
367 if ( self.alphaOptions.alphaEnabled && 'strip' === control ) {
368 color = self._color;
369 self._color = new Color( color.toString() );
370 self.hue = self._color.h();
371 }
372
373 self._super( origin, control );
374
375 // Restore the color after paint.
376 if ( color ) {
377 self._color = color;
378 }
379 },
380 /**
381 * To update the options, see original source to view the available options.
382 *
383 * @since 3.0.0
384 *
385 * @param {string} key The Option name.
386 * @param {mixed} value The Option value to update.
387 *
388 * @return {void}
389 */
390 _setOption: function ( key, value ) {
391 var self = this;
392 if ( 'color' === key && self.alphaOptions.alphaEnabled ) {
393 // cast to string in case we have a number
394 value = '' + value;
395 newColor = new Color( value ).setHSpace( self.options.mode );
396 // Check if error && Check the color to prevent callbacks with the same color.
397 if ( !newColor.error && self._getColor( newColor ) !== self._getColor() ) {
398 self._color = newColor;
399 self.options.color = self._getColor();
400 self.active = 'external';
401 self._change();
402 }
403 } else {
404 return self._super( key, value );
405 }
406 },
407 /**
408 * Returns the iris object if no new color is provided. If a new color is provided, it sets the new color.
409 *
410 * @param newColor {string|*} The new color to use. Can be undefined.
411 *
412 * @since 3.0.0
413 *
414 * @return {string} The element's color.
415 */
416 color: function ( newColor ) {
417 if ( newColor === true ) {
418 return this._color.clone();
419 }
420 if ( newColor === undef ) {
421 return this._getColor();
422 }
423 this.option( 'color', newColor );
424 },
425 } );
426
427 /**
428 * wpColorPicker
429 */
430 $.widget( 'wp.wpColorPicker', $.wp.wpColorPicker, {
431 /**
432 * Alpha options
433 *
434 * @since 3.0.0
435 *
436 * @type {Object}
437 */
438 alphaOptions: {
439 alphaEnabled: false,
440 },
441 /**
442 * Get the alpha options.
443 *
444 * @since 3.0.0
445 * @access private
446 *
447 * @return {object} The current alpha options.
448 */
449 _getAlphaOptions: function () {
450 var el = this.element,
451 type = ( el.data( 'type' ) || this.options.type ),
452 color = ( el.data( 'defaultColor' ) || el.val() ),
453 options = {
454 alphaEnabled: ( el.data( 'alphaEnabled' ) || false ),
455 alphaCustomWidth: 130,
456 alphaReset: false,
457 alphaColorType: 'rgb',
458 alphaColorWithSpace: false,
459 alphaSkipDebounce: ( !!el.data( 'alphaSkipDebounce' ) || false ),
460 };
461
462 if ( options.alphaEnabled ) {
463 options.alphaEnabled = ( el.is( 'input' ) && 'full' === type );
464 }
465
466 if ( !options.alphaEnabled ) {
467 return options;
468 }
469
470 options.alphaColorWithSpace = ( color && color.match( /\s/ ) );
471
472 $.each( options, function ( name, defaultValue ) {
473 var value = ( el.data( name ) || defaultValue );
474 switch ( name ) {
475 case 'alphaCustomWidth':
476 value = ( value ? parseInt( value, 10 ) : 0 );
477 value = ( isNaN( value ) ? defaultValue : value );
478 break;
479 case 'alphaColorType':
480 if ( !value.match( /^((octo)?hex|(rgb|hsl)a?)$/ ) ) {
481 if ( color && color.match( /^#/ ) ) {
482 value = 'hex';
483 } else if ( color && color.match( /^hsla?/ ) ) {
484 value = 'hsl';
485 } else {
486 value = defaultValue;
487 }
488 }
489 break;
490 default:
491 value = !!value;
492 break;
493 }
494 options[ name ] = value;
495 } );
496
497 return options;
498 },
499 /**
500 * Create widget
501 *
502 * @since 3.0.0
503 * @access private
504 *
505 * @return {void}
506 */
507 _create: function () {
508 // Return early if Iris support is missing.
509 if ( !$.support.iris ) {
510 return;
511 }
512
513 // Set the alpha options for the current instance.
514 this.alphaOptions = this._getAlphaOptions();
515
516 // Create widget.
517 this._super();
518 },
519 /**
520 * Binds event listeners to the color picker and create options, etc...
521 *
522 * @since 3.0.0
523 * @access private
524 *
525 * @return {void}
526 */
527 _addListeners: function () {
528 if ( !this.alphaOptions.alphaEnabled ) {
529 return this._super();
530 }
531
532 var self = this,
533 el = self.element,
534 isDeprecated = self.toggler.is( 'a' );
535
536 this.alphaOptions.defaultWidth = el.width();
537 if ( this.alphaOptions.alphaCustomWidth ) {
538 el.width( parseInt( this.alphaOptions.defaultWidth + this.alphaOptions.alphaCustomWidth, 10 ) );
539 }
540
541 self.toggler.css( {
542 'position': 'relative',
543 'background-image': 'url(' + backgroundImage + ')'
544 } );
545
546 if ( isDeprecated ) {
547 self.toggler.html( '<span class="color-alpha" />' );
548 } else {
549 self.toggler.append( '<span class="color-alpha" />' );
550 }
551
552 self.colorAlpha = self.toggler.find( 'span.color-alpha' ).css( {
553 'width': '30px',
554 'height': '100%',
555 'position': 'absolute',
556 'top': 0,
557 'background-color': el.val(),
558 } );
559
560 // Define the correct position for ltr or rtl direction.
561 if ( 'ltr' === self.colorAlpha.css( 'direction' ) ) {
562 self.colorAlpha.css( {
563 'border-bottom-left-radius': '2px',
564 'border-top-left-radius': '2px',
565 'left': 0
566 } );
567 } else {
568 self.colorAlpha.css( {
569 'border-bottom-right-radius': '2px',
570 'border-top-right-radius': '2px',
571 'right': 0
572 } );
573 }
574
575
576 el.iris( {
577 /**
578 * @summary Handles the onChange event if one has been defined in the options.
579 *
580 * Handles the onChange event if one has been defined in the options and additionally
581 * sets the background color for the toggler element.
582 *
583 * @since 3.0.0
584 *
585 * @param {Event} event The event that's being called.
586 * @param {HTMLElement} ui The HTMLElement containing the color picker.
587 *
588 * @returns {void}
589 */
590 change: function ( event, ui ) {
591 self.colorAlpha.css( { 'background-color': ui.color.to_s( self.alphaOptions.alphaColorType ) } );
592
593 // fire change callback if we have one
594 if ( typeof self.options.change === 'function' ) {
595 self.options.change.call( this, event, ui );
596 }
597 }
598 } );
599
600
601 /**
602 * Prevent any clicks inside this widget from leaking to the top and closing it.
603 *
604 * @since 3.0.0
605 *
606 * @param {Event} event The event that's being called.
607 *
608 * @return {void}
609 */
610 self.wrap.on( 'click.wpcolorpicker', function ( event ) {
611 event.stopPropagation();
612 } );
613
614 /**
615 * Open or close the color picker depending on the class.
616 *
617 * @since 3.0.0
618 */
619 self.toggler.on( 'click', function () {
620 if ( self.toggler.hasClass( 'wp-picker-open' ) ) {
621 self.close();
622 } else {
623 self.open();
624 }
625 } );
626
627 /**
628 * Checks if value is empty when changing the color in the color picker.
629 * If so, the background color is cleared.
630 *
631 * @since 3.0.0
632 *
633 * @param {Event} event The event that's being called.
634 *
635 * @return {void}
636 */
637 el.on( 'change', function ( event ) {
638 var val = $( this ).val();
639
640 if ( el.hasClass( 'iris-error' ) || val === '' || val.match( /^(#|(rgb|hsl)a?)$/ ) ) {
641 if ( isDeprecated ) {
642 self.toggler.removeAttr( 'style' );
643 }
644
645 self.colorAlpha.css( 'background-color', '' );
646
647 // fire clear callback if we have one
648 if ( typeof self.options.clear === 'function' ) {
649 self.options.clear.call( this, event );
650 }
651 }
652 } );
653
654 /**
655 * Enables the user to either clear the color in the color picker or revert back to the default color.
656 *
657 * @since 3.0.0
658 *
659 * @param {Event} event The event that's being called.
660 *
661 * @return {void}
662 */
663 self.button.on( 'click', function ( event ) {
664 if ( $( this ).hasClass( 'wp-picker-default' ) ) {
665 el.val( self.options.defaultColor ).change();
666 } else if ( $( this ).hasClass( 'wp-picker-clear' ) ) {
667 el.val( '' );
668 if ( isDeprecated ) {
669 self.toggler.removeAttr( 'style' );
670 }
671
672 self.colorAlpha.css( 'background-color', '' );
673
674 // fire clear callback if we have one
675 if ( typeof self.options.clear === 'function' ) {
676 self.options.clear.call( this, event );
677 }
678
679 el.trigger( 'change' );
680 }
681 } );
682 },
683 } );
684 } )( jQuery );
685