diff --git a/wp-content/themes/twentyeleven/inc/theme-options.php b/wp-content/themes/twentyeleven/inc/theme-options.php
index 833ba4c54..698f2a0b5 100644
--- a/wp-content/themes/twentyeleven/inc/theme-options.php
+++ b/wp-content/themes/twentyeleven/inc/theme-options.php
@@ -483,7 +483,7 @@ function twentyeleven_customize_register( $wp_customize ) {
$wp_customize->add_setting( 'twentyeleven_theme_options[link_color]', array(
'default' => twentyeleven_get_default_link_color( $options['color_scheme'] ),
'type' => 'option',
- 'sanitize_callback' => 'twentyeleven_sanitize_hexcolor',
+ 'sanitize_callback' => 'sanitize_hex_color',
'capability' => 'edit_theme_options',
) );
@@ -519,17 +519,6 @@ function twentyeleven_customize_register( $wp_customize ) {
}
add_action( 'customize_register', 'twentyeleven_customize_register' );
-/**
- * Sanitize user input hex color value
- *
- * @uses sanitize_hexcolor()
- * @param $color string
- * @return string sanitized with prefixed # character
- */
-function twentyeleven_sanitize_hexcolor( $color ) {
- return '#' . sanitize_hexcolor( $color );
-}
-
/**
* Bind JS handlers to make Theme Customizer preview reload changes asynchronously.
* Used with blogname and blogdescription.
diff --git a/wp-includes/class-wp-customize-control.php b/wp-includes/class-wp-customize-control.php
index 554aa3593..3f936f39e 100644
--- a/wp-includes/class-wp-customize-control.php
+++ b/wp-includes/class-wp-customize-control.php
@@ -265,10 +265,7 @@ class WP_Customize_Color_Control extends WP_Customize_Control {
-
- #
- link(); ?> />
-
+
diff --git a/wp-includes/class-wp-customize-manager.php b/wp-includes/class-wp-customize-manager.php
index 55e46a907..40ae19b47 100644
--- a/wp-includes/class-wp-customize-manager.php
+++ b/wp-includes/class-wp-customize-manager.php
@@ -667,9 +667,11 @@ final class WP_Customize_Manager {
) );
$this->add_setting( 'header_textcolor', array(
- 'sanitize_callback' => 'sanitize_header_textcolor',
'theme_supports' => array( 'custom-header', 'header-text' ),
'default' => get_theme_support( 'custom-header', 'default-text-color' ),
+
+ 'sanitize_callback' => array( $this, '_sanitize_header_textcolor' ),
+ 'sanitize_js_callback' => 'maybe_hash_hex_color',
) );
// Input type: checkbox
@@ -689,9 +691,11 @@ final class WP_Customize_Manager {
// Input type: Color
// With sanitize_callback
$this->add_setting( 'background_color', array(
- 'default' => get_theme_support( 'custom-background', 'default-color' ),
- 'sanitize_callback' => 'sanitize_hexcolor',
- 'theme_supports' => 'custom-background',
+ 'default' => get_theme_support( 'custom-background', 'default-color' ),
+ 'theme_supports' => 'custom-background',
+
+ 'sanitize_callback' => 'sanitize_hex_color_no_hash',
+ 'sanitize_js_callback' => 'maybe_hash_hex_color',
) );
$this->add_control( new WP_Customize_Color_Control( $this, 'background_color', array(
@@ -876,23 +880,69 @@ final class WP_Customize_Manager {
'type' => 'dropdown-pages',
) );
}
+
+ /**
+ * Callback for validating the header_textcolor value.
+ *
+ * Accepts 'blank', and otherwise uses sanitize_hex_color_no_hash().
+ *
+ * @since 3.4.0
+ */
+ public function _sanitize_header_textcolor( $color ) {
+ return ( 'blank' === $color ) ? 'blank' : sanitize_hex_color_no_hash( $color );
+ }
};
-// Callback function for sanitizing the header textcolor setting.
-function sanitize_header_textcolor( $color ) {
- if ( $color == 'blank' )
- return 'blank';
-
- return sanitize_hexcolor( $color );
-}
-
-// Callback function for sanitizing a hex color
-function sanitize_hexcolor( $color ) {
- $color = preg_replace( '/[^0-9a-fA-F]/', '', $color );
+/**
+ * Validates a hex color.
+ *
+ * Returns either '', a 3 or 6 digit hex color (with #), or null.
+ * For validating values without a #, see sanitize_hex_color_no_hash().
+ *
+ * @since 3.4.0
+ */
+function sanitize_hex_color( $color ) {
+ if ( '' === $color )
+ return '';
// 3 or 6 hex digits, or the empty string.
- if ( preg_match('|^([A-Fa-f0-9]{3}){0,2}$|', $color ) )
+ if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) )
return $color;
return null;
}
+
+/**
+ * Sanitizes a hex color without a hash. Use sanitize_hex_color() when possible.
+ *
+ * Saving hex colors without a hash puts the burden of adding the hash on the
+ * UI, which makes it difficult to use or upgrade to other color types such as
+ * rgba, hsl, rgb, and html color names.
+ *
+ * Returns either '', a 3 or 6 digit hex color (without a #), or null.
+ *
+ * @since 3.4.0
+ */
+function sanitize_hex_color_no_hash( $color ) {
+ $color = ltrim( $color, '#' );
+
+ if ( '' === $color )
+ return '';
+
+ return sanitize_hex_color( '#' . $color ) ? $color : null;
+}
+
+/**
+ * Ensures that any hex color is properly hashed.
+ * Otherwise, returns value untouched.
+ *
+ * This method should only be necessary if using sanitize_hex_color_no_hash().
+ *
+ * @since 3.4.0
+ */
+function maybe_hash_hex_color( $color ) {
+ if ( $unhashed = sanitize_hex_color_no_hash( $color ) )
+ return '#' . $unhashed;
+
+ return $color;
+}
\ No newline at end of file
diff --git a/wp-includes/class-wp-customize-setting.php b/wp-includes/class-wp-customize-setting.php
index f6088c9f4..92584f063 100644
--- a/wp-includes/class-wp-customize-setting.php
+++ b/wp-includes/class-wp-customize-setting.php
@@ -11,12 +11,14 @@ class WP_Customize_Setting {
public $manager;
public $id;
- public $type = 'theme_mod';
- public $capability = 'edit_theme_options';
- public $theme_supports = '';
- public $default = '';
- public $sanitize_callback = '';
- public $transport = 'refresh';
+ public $type = 'theme_mod';
+ public $capability = 'edit_theme_options';
+ public $theme_supports = '';
+ public $default = '';
+ public $transport = 'refresh';
+
+ public $sanitize_callback = '';
+ public $sanitize_js_callback = '';
protected $id_data = array();
private $_post_value; // Cached, sanitized $_POST value.
@@ -49,8 +51,11 @@ class WP_Customize_Setting {
if ( ! empty( $this->id_data[ 'keys' ] ) )
$this->id .= '[' . implode( '][', $this->id_data[ 'keys' ] ) . ']';
- if ( $this->sanitize_callback != '' )
- add_filter( "customize_sanitize_{$this->id}", $this->sanitize_callback );
+ if ( $this->sanitize_callback )
+ add_filter( "customize_sanitize_{$this->id}", $this->sanitize_callback, 10, 2 );
+
+ if ( $this->sanitize_js_callback )
+ add_filter( "customize_sanitize_js_{$this->id}", $this->sanitize_js_callback, 10, 2 );
return $this;
}
@@ -138,7 +143,7 @@ class WP_Customize_Setting {
*/
public function sanitize( $value ) {
$value = stripslashes_deep( $value );
- return apply_filters( "customize_sanitize_{$this->id}", $value );
+ return apply_filters( "customize_sanitize_{$this->id}", $value, $this );
}
/**
@@ -238,7 +243,7 @@ class WP_Customize_Setting {
* @return mixed The requested escaped value.
*/
public function js_value() {
- $value = $this->value();
+ $value = apply_filters( "customize_sanitize_js_{$this->id}", $this->value(), $this );
if ( is_string( $value ) )
return html_entity_decode( $value, ENT_QUOTES, 'UTF-8');
diff --git a/wp-includes/css/customize-controls.dev.css b/wp-includes/css/customize-controls.dev.css
index d9aeaae61..fd51845dd 100644
--- a/wp-includes/css/customize-controls.dev.css
+++ b/wp-includes/css/customize-controls.dev.css
@@ -319,37 +319,19 @@ body {
border-color: rgba( 0, 0, 0, 0.25 );
}
-.customize-section .color-picker-hex {
+.customize-section input[type="text"].color-picker-hex {
float: left;
- width: 70px;
+ width: 85px;
font-family: monospace;
- background-color: #fff;
- color: #777;
- border: 1px solid #ccc;
- -webkit-border-radius: 3px;
- border-radius: 3px;
+ text-align: center;
}
-.customize-section .color-picker-hex span {
- float: left;
- display: block;
- margin: 1px -2px 0 0;
- line-height: 16px;
- padding: 3px 0 3px 8px;
- text-align: right;
- -webkit-border-radius: 3px 0 0 3px;
- border-radius: 3px 0 0 3px;
+/* The centered cursor overlaps the placeholder in webkit. Hide it when selected. */
+.customize-section input[type="text"].color-picker-hex:focus::-webkit-input-placeholder {
+ color: transparent;
}
-
-.customize-section .color-picker-hex input[type="text"] {
- width: 50px;
- height: 22px;
- line-height: 16px;
- color: #777;
- background: transparent;
- border: 0;
- -webkit-border-radius: 0 3px 3px 0;
- border-radius: 0 3px 3px 0;
+.customize-section input[type="text"].color-picker-hex:-moz-placeholder {
+ color: #999;
}
.customize-control-color .farbtastic-placeholder {
diff --git a/wp-includes/js/customize-controls.dev.js b/wp-includes/js/customize-controls.dev.js
index 57f4c7000..59283e79e 100644
--- a/wp-includes/js/customize-controls.dev.js
+++ b/wp-includes/js/customize-controls.dev.js
@@ -109,18 +109,22 @@
api.ColorControl = api.Control.extend({
ready: function() {
var control = this,
- spot, text, update;
+ rhex, spot, input, text, update;
+ rhex = /^#([A-Fa-f0-9]{3}){0,2}$/;
spot = this.container.find('.dropdown-content');
+ input = new api.Element( this.container.find('.color-picker-hex') );
update = function( color ) {
- color = color ? '#' + color : '';
spot.css( 'background', color );
control.farbtastic.setColor( color );
};
- this.farbtastic = $.farbtastic( this.container.find('.farbtastic-placeholder'), function( color ) {
- control.setting.set( color.replace( '#', '' ) );
- });
+ this.farbtastic = $.farbtastic( this.container.find('.farbtastic-placeholder'), control.setting.set );
+
+ // Only pass through values that are valid hexes/empty.
+ input.link( this.setting ).validate = function( to ) {
+ return rhex.test( to ) ? to : null;
+ };
this.setting.bind( update );
update( this.setting() );
diff --git a/wp-includes/js/customize-preview.dev.js b/wp-includes/js/customize-preview.dev.js
index 1aef6aa23..a80cf4422 100644
--- a/wp-includes/js/customize-preview.dev.js
+++ b/wp-includes/js/customize-preview.dev.js
@@ -101,7 +101,7 @@
body.toggleClass( 'custom-background', !! ( color() || image() ) );
if ( color() )
- css += 'background-color: #' + color() + ';';
+ css += 'background-color: ' + color() + ';';
if ( image() ) {
css += 'background-image: url("' + image() + '");';