Theme Customizer: Ensure that JS color controls always use real color values, even if the server-side value is a hex value without a hash. fixes #20448, see #19910.
Adds WP_Customize_Setting->sanitize_js_callback and 'customize_sanitize_js_$settingID' filter, to filter values before they're passed to JS using WP_Customize_Setting->js_value(). Adds support for regular hex colors to the color picker. Changes color methods: * sanitize_hex_color() accepts 3 and 6 digit hex colors (with hashes) and the empty string. * sanitize_hex_color_no_hash() accepts 3 and 6 digit hex colors (without hashes) and the empty string. * maybe_hash_hex_color() ensures that a hex color has a hash, and otherwise leaves the value untouched. git-svn-id: http://core.svn.wordpress.org/trunk@20936 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
0b1958f333
commit
0df3218cc2
|
@ -483,7 +483,7 @@ function twentyeleven_customize_register( $wp_customize ) {
|
||||||
$wp_customize->add_setting( 'twentyeleven_theme_options[link_color]', array(
|
$wp_customize->add_setting( 'twentyeleven_theme_options[link_color]', array(
|
||||||
'default' => twentyeleven_get_default_link_color( $options['color_scheme'] ),
|
'default' => twentyeleven_get_default_link_color( $options['color_scheme'] ),
|
||||||
'type' => 'option',
|
'type' => 'option',
|
||||||
'sanitize_callback' => 'twentyeleven_sanitize_hexcolor',
|
'sanitize_callback' => 'sanitize_hex_color',
|
||||||
'capability' => 'edit_theme_options',
|
'capability' => 'edit_theme_options',
|
||||||
) );
|
) );
|
||||||
|
|
||||||
|
@ -519,17 +519,6 @@ function twentyeleven_customize_register( $wp_customize ) {
|
||||||
}
|
}
|
||||||
add_action( 'customize_register', 'twentyeleven_customize_register' );
|
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.
|
* Bind JS handlers to make Theme Customizer preview reload changes asynchronously.
|
||||||
* Used with blogname and blogdescription.
|
* Used with blogname and blogdescription.
|
||||||
|
|
|
@ -265,10 +265,7 @@ class WP_Customize_Color_Control extends WP_Customize_Control {
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-arrow"></div>
|
<div class="dropdown-arrow"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="color-picker-hex">
|
<input class="color-picker-hex" type="text" maxlength="7" placeholder="<?php esc_attr_e('Hex Value'); ?>" />
|
||||||
<span>#</span>
|
|
||||||
<input type="text" <?php $this->link(); ?> />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="farbtastic-placeholder"></div>
|
<div class="farbtastic-placeholder"></div>
|
||||||
</label>
|
</label>
|
||||||
|
|
|
@ -667,9 +667,11 @@ final class WP_Customize_Manager {
|
||||||
) );
|
) );
|
||||||
|
|
||||||
$this->add_setting( 'header_textcolor', array(
|
$this->add_setting( 'header_textcolor', array(
|
||||||
'sanitize_callback' => 'sanitize_header_textcolor',
|
|
||||||
'theme_supports' => array( 'custom-header', 'header-text' ),
|
'theme_supports' => array( 'custom-header', 'header-text' ),
|
||||||
'default' => get_theme_support( 'custom-header', 'default-text-color' ),
|
'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
|
// Input type: checkbox
|
||||||
|
@ -689,9 +691,11 @@ final class WP_Customize_Manager {
|
||||||
// Input type: Color
|
// Input type: Color
|
||||||
// With sanitize_callback
|
// With sanitize_callback
|
||||||
$this->add_setting( 'background_color', array(
|
$this->add_setting( 'background_color', array(
|
||||||
'default' => get_theme_support( 'custom-background', 'default-color' ),
|
'default' => get_theme_support( 'custom-background', 'default-color' ),
|
||||||
'sanitize_callback' => 'sanitize_hexcolor',
|
'theme_supports' => 'custom-background',
|
||||||
'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(
|
$this->add_control( new WP_Customize_Color_Control( $this, 'background_color', array(
|
||||||
|
@ -876,23 +880,69 @@ final class WP_Customize_Manager {
|
||||||
'type' => 'dropdown-pages',
|
'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 ) {
|
* Validates a hex color.
|
||||||
if ( $color == 'blank' )
|
*
|
||||||
return 'blank';
|
* Returns either '', a 3 or 6 digit hex color (with #), or null.
|
||||||
|
* For validating values without a #, see sanitize_hex_color_no_hash().
|
||||||
return sanitize_hexcolor( $color );
|
*
|
||||||
}
|
* @since 3.4.0
|
||||||
|
*/
|
||||||
// Callback function for sanitizing a hex color
|
function sanitize_hex_color( $color ) {
|
||||||
function sanitize_hexcolor( $color ) {
|
if ( '' === $color )
|
||||||
$color = preg_replace( '/[^0-9a-fA-F]/', '', $color );
|
return '';
|
||||||
|
|
||||||
// 3 or 6 hex digits, or the empty string.
|
// 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 $color;
|
||||||
|
|
||||||
return null;
|
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;
|
||||||
|
}
|
|
@ -11,12 +11,14 @@ class WP_Customize_Setting {
|
||||||
public $manager;
|
public $manager;
|
||||||
public $id;
|
public $id;
|
||||||
|
|
||||||
public $type = 'theme_mod';
|
public $type = 'theme_mod';
|
||||||
public $capability = 'edit_theme_options';
|
public $capability = 'edit_theme_options';
|
||||||
public $theme_supports = '';
|
public $theme_supports = '';
|
||||||
public $default = '';
|
public $default = '';
|
||||||
public $sanitize_callback = '';
|
public $transport = 'refresh';
|
||||||
public $transport = 'refresh';
|
|
||||||
|
public $sanitize_callback = '';
|
||||||
|
public $sanitize_js_callback = '';
|
||||||
|
|
||||||
protected $id_data = array();
|
protected $id_data = array();
|
||||||
private $_post_value; // Cached, sanitized $_POST value.
|
private $_post_value; // Cached, sanitized $_POST value.
|
||||||
|
@ -49,8 +51,11 @@ class WP_Customize_Setting {
|
||||||
if ( ! empty( $this->id_data[ 'keys' ] ) )
|
if ( ! empty( $this->id_data[ 'keys' ] ) )
|
||||||
$this->id .= '[' . implode( '][', $this->id_data[ 'keys' ] ) . ']';
|
$this->id .= '[' . implode( '][', $this->id_data[ 'keys' ] ) . ']';
|
||||||
|
|
||||||
if ( $this->sanitize_callback != '' )
|
if ( $this->sanitize_callback )
|
||||||
add_filter( "customize_sanitize_{$this->id}", $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;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -138,7 +143,7 @@ class WP_Customize_Setting {
|
||||||
*/
|
*/
|
||||||
public function sanitize( $value ) {
|
public function sanitize( $value ) {
|
||||||
$value = stripslashes_deep( $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.
|
* @return mixed The requested escaped value.
|
||||||
*/
|
*/
|
||||||
public function js_value() {
|
public function js_value() {
|
||||||
$value = $this->value();
|
$value = apply_filters( "customize_sanitize_js_{$this->id}", $this->value(), $this );
|
||||||
|
|
||||||
if ( is_string( $value ) )
|
if ( is_string( $value ) )
|
||||||
return html_entity_decode( $value, ENT_QUOTES, 'UTF-8');
|
return html_entity_decode( $value, ENT_QUOTES, 'UTF-8');
|
||||||
|
|
|
@ -319,37 +319,19 @@ body {
|
||||||
border-color: rgba( 0, 0, 0, 0.25 );
|
border-color: rgba( 0, 0, 0, 0.25 );
|
||||||
}
|
}
|
||||||
|
|
||||||
.customize-section .color-picker-hex {
|
.customize-section input[type="text"].color-picker-hex {
|
||||||
float: left;
|
float: left;
|
||||||
width: 70px;
|
width: 85px;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
background-color: #fff;
|
text-align: center;
|
||||||
color: #777;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
-webkit-border-radius: 3px;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.customize-section .color-picker-hex span {
|
/* The centered cursor overlaps the placeholder in webkit. Hide it when selected. */
|
||||||
float: left;
|
.customize-section input[type="text"].color-picker-hex:focus::-webkit-input-placeholder {
|
||||||
display: block;
|
color: transparent;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
.customize-section input[type="text"].color-picker-hex:-moz-placeholder {
|
||||||
.customize-section .color-picker-hex input[type="text"] {
|
color: #999;
|
||||||
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-control-color .farbtastic-placeholder {
|
.customize-control-color .farbtastic-placeholder {
|
||||||
|
|
|
@ -109,18 +109,22 @@
|
||||||
api.ColorControl = api.Control.extend({
|
api.ColorControl = api.Control.extend({
|
||||||
ready: function() {
|
ready: function() {
|
||||||
var control = this,
|
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');
|
spot = this.container.find('.dropdown-content');
|
||||||
|
input = new api.Element( this.container.find('.color-picker-hex') );
|
||||||
update = function( color ) {
|
update = function( color ) {
|
||||||
color = color ? '#' + color : '';
|
|
||||||
spot.css( 'background', color );
|
spot.css( 'background', color );
|
||||||
control.farbtastic.setColor( color );
|
control.farbtastic.setColor( color );
|
||||||
};
|
};
|
||||||
|
|
||||||
this.farbtastic = $.farbtastic( this.container.find('.farbtastic-placeholder'), function( color ) {
|
this.farbtastic = $.farbtastic( this.container.find('.farbtastic-placeholder'), control.setting.set );
|
||||||
control.setting.set( color.replace( '#', '' ) );
|
|
||||||
});
|
// 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 );
|
this.setting.bind( update );
|
||||||
update( this.setting() );
|
update( this.setting() );
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
body.toggleClass( 'custom-background', !! ( color() || image() ) );
|
body.toggleClass( 'custom-background', !! ( color() || image() ) );
|
||||||
|
|
||||||
if ( color() )
|
if ( color() )
|
||||||
css += 'background-color: #' + color() + ';';
|
css += 'background-color: ' + color() + ';';
|
||||||
|
|
||||||
if ( image() ) {
|
if ( image() ) {
|
||||||
css += 'background-image: url("' + image() + '");';
|
css += 'background-image: url("' + image() + '");';
|
||||||
|
|
Loading…
Reference in New Issue