wp/wp-admin/js/color-picker.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     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 ) );