Add header image uploads with cropping to the customizer.
props mcsf, ehg, gcorne. see #21785. Built from https://develop.svn.wordpress.org/trunk@27497 git-svn-id: http://core.svn.wordpress.org/trunk@27339 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
45bc43515c
commit
a589d9d757
|
@ -455,6 +455,167 @@ body {
|
|||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/** Header control **/
|
||||
|
||||
#customize-control-header_image .current {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .uploaded {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
/* Header control: current image container */
|
||||
|
||||
#customize-control-header_image .current .container {
|
||||
overflow: hidden;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .placeholder {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
background: #262626;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#customize-control-header_image .inner {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
margin-top: -9px;
|
||||
top: 50%;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
/* Header control: overlay "close" button */
|
||||
|
||||
#customize-control-header_image .header-view {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#customize-control-header_image .uploaded .header-view .close {
|
||||
font-size: 2em;
|
||||
color: grey;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 1;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#customize-control-header_image .uploaded .header-view .close:hover {
|
||||
color: black;
|
||||
text-shadow:
|
||||
-1px -1px 0 #fff,
|
||||
1px -1px 0 #fff,
|
||||
-1px 1px 0 #fff,
|
||||
1px 1px 0 #fff;
|
||||
}
|
||||
|
||||
#customize-control-header_image .header-view:hover .close {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* Header control: randomiz(s)er */
|
||||
|
||||
#customize-control-header_image .random.placeholder {
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .random .inner {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#customize-control-header_image .dice {
|
||||
font-size: 16px;
|
||||
vertical-align: -1px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .placeholder:hover .dice {
|
||||
-webkit-animation: dice-color-change 3s infinite;
|
||||
-moz-animation: dice-color-change 3s infinite;
|
||||
-ms-animation: dice-color-change 3s infinite;
|
||||
animation: dice-color-change 3s infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes dice-color-change {
|
||||
0% { color: #d4b146; }
|
||||
50% { color: #ef54b0; }
|
||||
75% { color: #7190d3; }
|
||||
100% { color: #d4b146; }
|
||||
}
|
||||
|
||||
@-moz-keyframes dice-color-change {
|
||||
0% { color: #d4b146; }
|
||||
50% { color: #ef54b0; }
|
||||
75% { color: #7190d3; }
|
||||
100% { color: #d4b146; }
|
||||
}
|
||||
|
||||
@-ms-keyframes dice-color-change {
|
||||
0% { color: #d4b146; }
|
||||
50% { color: #ef54b0; }
|
||||
75% { color: #7190d3; }
|
||||
100% { color: #d4b146; }
|
||||
}
|
||||
|
||||
@keyframes dice-color-change {
|
||||
0% { color: #d4b146; }
|
||||
50% { color: #ef54b0; }
|
||||
75% { color: #7190d3; }
|
||||
100% { color: #d4b146; }
|
||||
}
|
||||
|
||||
/* Header control: actions and choices */
|
||||
|
||||
#customize-control-header_image .actions {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .choice {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .choice.random:before {
|
||||
position: absolute;
|
||||
content: attr(data-label);
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#customize-control-header_image .uploaded div:last-child > .choice {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#customize-control-header_image .choices hr {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#customize-control-header_image img {
|
||||
width: 100%;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .remove {
|
||||
float: right;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .new {
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
/** Handle cheaters. */
|
||||
body.cheatin {
|
||||
min-width: 0;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -455,6 +455,167 @@ body {
|
|||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/** Header control **/
|
||||
|
||||
#customize-control-header_image .current {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .uploaded {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
/* Header control: current image container */
|
||||
|
||||
#customize-control-header_image .current .container {
|
||||
overflow: hidden;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .placeholder {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
background: #262626;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#customize-control-header_image .inner {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
margin-top: -9px;
|
||||
top: 50%;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
/* Header control: overlay "close" button */
|
||||
|
||||
#customize-control-header_image .header-view {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#customize-control-header_image .uploaded .header-view .close {
|
||||
font-size: 2em;
|
||||
color: grey;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 1;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#customize-control-header_image .uploaded .header-view .close:hover {
|
||||
color: black;
|
||||
text-shadow:
|
||||
-1px -1px 0 #fff,
|
||||
1px -1px 0 #fff,
|
||||
-1px 1px 0 #fff,
|
||||
1px 1px 0 #fff;
|
||||
}
|
||||
|
||||
#customize-control-header_image .header-view:hover .close {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* Header control: randomiz(s)er */
|
||||
|
||||
#customize-control-header_image .random.placeholder {
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .random .inner {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#customize-control-header_image .dice {
|
||||
font-size: 16px;
|
||||
vertical-align: -1px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .placeholder:hover .dice {
|
||||
-webkit-animation: dice-color-change 3s infinite;
|
||||
-moz-animation: dice-color-change 3s infinite;
|
||||
-ms-animation: dice-color-change 3s infinite;
|
||||
animation: dice-color-change 3s infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes dice-color-change {
|
||||
0% { color: #d4b146; }
|
||||
50% { color: #ef54b0; }
|
||||
75% { color: #7190d3; }
|
||||
100% { color: #d4b146; }
|
||||
}
|
||||
|
||||
@-moz-keyframes dice-color-change {
|
||||
0% { color: #d4b146; }
|
||||
50% { color: #ef54b0; }
|
||||
75% { color: #7190d3; }
|
||||
100% { color: #d4b146; }
|
||||
}
|
||||
|
||||
@-ms-keyframes dice-color-change {
|
||||
0% { color: #d4b146; }
|
||||
50% { color: #ef54b0; }
|
||||
75% { color: #7190d3; }
|
||||
100% { color: #d4b146; }
|
||||
}
|
||||
|
||||
@keyframes dice-color-change {
|
||||
0% { color: #d4b146; }
|
||||
50% { color: #ef54b0; }
|
||||
75% { color: #7190d3; }
|
||||
100% { color: #d4b146; }
|
||||
}
|
||||
|
||||
/* Header control: actions and choices */
|
||||
|
||||
#customize-control-header_image .actions {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .choice {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .choice.random:before {
|
||||
position: absolute;
|
||||
content: attr(data-label);
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#customize-control-header_image .uploaded div:last-child > .choice {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#customize-control-header_image .choices hr {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#customize-control-header_image img {
|
||||
width: 100%;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .remove {
|
||||
float: left;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
#customize-control-header_image .new {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
/** Handle cheaters. */
|
||||
body.cheatin {
|
||||
min-width: 0;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -43,7 +43,7 @@ class Custom_Image_Header {
|
|||
var $default_headers = array();
|
||||
|
||||
/**
|
||||
* Holds custom headers uploaded by the user
|
||||
* Holds custom headers uploaded by the user.
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
|
@ -73,6 +73,11 @@ class Custom_Image_Header {
|
|||
$this->admin_image_div_callback = $admin_image_div_callback;
|
||||
|
||||
add_action( 'admin_menu', array( $this, 'init' ) );
|
||||
|
||||
add_action( 'customize_save_after', array( $this, 'customize_set_last_used' ) );
|
||||
add_action( 'wp_ajax_custom-header-crop', array( $this, 'ajax_header_crop' ) );
|
||||
add_action( 'wp_ajax_custom-header-add', array( $this, 'ajax_header_add' ) );
|
||||
add_action( 'wp_ajax_custom-header-remove', array( $this, 'ajax_header_remove' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,6 +98,7 @@ class Custom_Image_Header {
|
|||
add_action("admin_head-$page", array($this, 'js'), 50);
|
||||
if ( $this->admin_header_callback )
|
||||
add_action("admin_head-$page", $this->admin_header_callback, 51);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -819,32 +825,15 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?>
|
|||
$attachment_id = absint( $_POST['attachment_id'] );
|
||||
$original = get_attached_file($attachment_id);
|
||||
|
||||
|
||||
$max_width = 0;
|
||||
// For flex, limit size of image displayed to 1500px unless theme says otherwise
|
||||
if ( current_theme_supports( 'custom-header', 'flex-width' ) )
|
||||
$max_width = 1500;
|
||||
|
||||
if ( current_theme_supports( 'custom-header', 'max-width' ) )
|
||||
$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
|
||||
$max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
|
||||
|
||||
if ( ( current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) || $_POST['width'] > $max_width )
|
||||
$dst_height = absint( $_POST['height'] * ( $max_width / $_POST['width'] ) );
|
||||
elseif ( current_theme_supports( 'custom-header', 'flex-height' ) && current_theme_supports( 'custom-header', 'flex-width' ) )
|
||||
$dst_height = absint( $_POST['height'] );
|
||||
else
|
||||
$dst_height = get_theme_support( 'custom-header', 'height' );
|
||||
|
||||
if ( ( current_theme_supports( 'custom-header', 'flex-width' ) && ! current_theme_supports( 'custom-header', 'flex-height' ) ) || $_POST['width'] > $max_width )
|
||||
$dst_width = absint( $_POST['width'] * ( $max_width / $_POST['width'] ) );
|
||||
elseif ( current_theme_supports( 'custom-header', 'flex-width' ) && current_theme_supports( 'custom-header', 'flex-height' ) )
|
||||
$dst_width = absint( $_POST['width'] );
|
||||
else
|
||||
$dst_width = get_theme_support( 'custom-header', 'width' );
|
||||
$dimensions = $this->get_header_dimensions( array(
|
||||
'height' => $_POST['height'],
|
||||
'width' => $_POST['width'],
|
||||
) );
|
||||
$height = $dimensions['dst_height'];
|
||||
$width = $dimensions['dst_width'];
|
||||
|
||||
if ( empty( $_POST['skip-cropping'] ) )
|
||||
$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $dst_width, $dst_height );
|
||||
$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $width, $height );
|
||||
elseif ( ! empty( $_POST['create-new-attachment'] ) )
|
||||
$cropped = _copy_image_file( $attachment_id );
|
||||
else
|
||||
|
@ -856,31 +845,15 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?>
|
|||
/** This filter is documented in wp-admin/custom-header.php */
|
||||
$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
|
||||
|
||||
$parent = get_post($attachment_id);
|
||||
$parent_url = $parent->guid;
|
||||
$url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
|
||||
$object = $this->create_attachment_object( $cropped, $attachment_id );
|
||||
|
||||
$size = @getimagesize( $cropped );
|
||||
$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
|
||||
|
||||
// Construct the object array
|
||||
$object = array(
|
||||
'ID' => $attachment_id,
|
||||
'post_title' => basename($cropped),
|
||||
'post_content' => $url,
|
||||
'post_mime_type' => $image_type,
|
||||
'guid' => $url,
|
||||
'context' => 'custom-header'
|
||||
);
|
||||
if ( ! empty( $_POST['create-new-attachment'] ) )
|
||||
unset( $object['ID'] );
|
||||
|
||||
// Update the attachment
|
||||
$attachment_id = wp_insert_attachment( $object, $cropped );
|
||||
wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $cropped ) );
|
||||
$attachment_id = $this->insert_attachment( $object, $cropped );
|
||||
|
||||
$width = $dst_width;
|
||||
$height = $dst_height;
|
||||
$url = $object['guid'];
|
||||
$this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );
|
||||
|
||||
// cleanup
|
||||
|
@ -1041,4 +1014,218 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?>
|
|||
set_theme_mod( 'header_image', $default );
|
||||
set_theme_mod( 'header_image_data', (object) $default_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate width and height based on what the currently selected theme supports.
|
||||
*
|
||||
* @return array dst_height and dst_width of header image.
|
||||
*/
|
||||
final public function get_header_dimensions( $dimensions ) {
|
||||
$max_width = 0;
|
||||
$width = absint( $dimensions['width'] );
|
||||
$height = absint( $dimensions['height'] );
|
||||
$theme_height = get_theme_support( 'custom-header', 'height' );
|
||||
$theme_width = get_theme_support( 'custom-header', 'width' );
|
||||
$has_flex_width = current_theme_supports( 'custom-header', 'flex-width' );
|
||||
$has_flex_height = current_theme_supports( 'custom-header', 'flex-height' );
|
||||
$has_max_width = current_theme_supports( 'custom-header', 'max-width' ) ;
|
||||
$dst = array( 'dst_height' => null, 'dst_height' => null );
|
||||
|
||||
// For flex, limit size of image displayed to 1500px unless theme says otherwise
|
||||
if ( $has_flex_width ) {
|
||||
$max_width = 1500;
|
||||
}
|
||||
|
||||
if ( $has_max_width ) {
|
||||
$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
|
||||
}
|
||||
$max_width = max( $max_width, $theme_width );
|
||||
|
||||
if ( $has_flex_height && ( ! $has_flex_width || $width > $max_width ) ) {
|
||||
$dst['dst_height'] = absint( $height * ( $max_width / $width ) );
|
||||
}
|
||||
elseif ( $has_flex_height && $has_flex_width ) {
|
||||
$dst['dst_height'] = $height;
|
||||
}
|
||||
else {
|
||||
$dst['dst_height'] = $theme_height;
|
||||
}
|
||||
|
||||
if ( $has_flex_width && ( ! $has_flex_height || $width > $max_width ) ) {
|
||||
$dst['dst_width'] = absint( $width * ( $max_width / $width ) );
|
||||
}
|
||||
elseif ( $has_flex_width && $has_flex_height ) {
|
||||
$dst['dst_width'] = $width;
|
||||
}
|
||||
else {
|
||||
$dst['dst_width'] = $theme_width;
|
||||
}
|
||||
|
||||
return $dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an attachment 'object'.
|
||||
*
|
||||
* @param string $cropped Cropped image URL.
|
||||
* @param int $parent_attachment_id Attachment ID of parent image.
|
||||
*
|
||||
* @return array Attachment object.
|
||||
*/
|
||||
final public function create_attachment_object( $cropped, $parent_attachment_id ) {
|
||||
$parent = get_post( $parent_attachment_id );
|
||||
$parent_url = $parent->guid;
|
||||
$url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
|
||||
|
||||
$size = @getimagesize( $cropped );
|
||||
$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
|
||||
|
||||
$object = array(
|
||||
'ID' => $parent_attachment_id,
|
||||
'post_title' => basename($cropped),
|
||||
'post_content' => $url,
|
||||
'post_mime_type' => $image_type,
|
||||
'guid' => $url,
|
||||
'context' => 'custom-header'
|
||||
);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an attachment & its metadata.
|
||||
*
|
||||
* @param array $object Attachment object.
|
||||
* @param string $cropped Cropped image URL.
|
||||
*
|
||||
* @return int Attachment ID.
|
||||
*/
|
||||
final public function insert_attachment( $object, $cropped ) {
|
||||
$attachment_id = wp_insert_attachment( $object, $cropped );
|
||||
$metadata = wp_generate_attachment_metadata( $attachment_id, $cropped );
|
||||
/**
|
||||
* Allows us to insert custom meta data for an attachment.
|
||||
*
|
||||
*/
|
||||
$metadata = apply_filters( 'wp_header_image_attachment_metadata', $metadata );
|
||||
wp_update_attachment_metadata( $attachment_id, $metadata );
|
||||
return $attachment_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets attachment uploaded by Media Manager, crops it, then saves it as a
|
||||
* new object. Returns JSON-encoded object details.
|
||||
*/
|
||||
function ajax_header_crop() {
|
||||
check_ajax_referer( 'image_editor-' . $_POST['id'], 'nonce' );
|
||||
|
||||
if ( ! current_user_can( 'edit_theme_options' ) ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
if ( ! current_theme_supports( 'custom-header', 'uploads' ) ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
$crop_details = $_POST['cropDetails'];
|
||||
|
||||
$dimensions = $this->get_header_dimensions( array(
|
||||
'height' => $crop_details['height'],
|
||||
'width' => $crop_details['width'],
|
||||
) );
|
||||
|
||||
$attachment_id = absint( $_POST['id'] );
|
||||
|
||||
$cropped = wp_crop_image(
|
||||
$attachment_id,
|
||||
(int) $crop_details['x1'],
|
||||
(int) $crop_details['y1'],
|
||||
(int) $crop_details['width'],
|
||||
(int) $crop_details['height'],
|
||||
(int) $dimensions['dst_width'],
|
||||
(int) $dimensions['dst_height']
|
||||
);
|
||||
|
||||
if ( ! $cropped || is_wp_error( $cropped ) ) {
|
||||
wp_send_json_error( array( 'message' => __( 'Image could not be processed. Please go back and try again.' ) ) );
|
||||
}
|
||||
|
||||
$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
|
||||
|
||||
$object = $this->create_attachment_object( $cropped, $attachment_id );
|
||||
|
||||
unset( $object['ID'] );
|
||||
|
||||
$new_attachment_id = $this->insert_attachment( $object, $cropped );
|
||||
|
||||
$object['attachment_id'] = $new_attachment_id;
|
||||
$object['width'] = $dimensions['dst_width'];
|
||||
$object['height'] = $dimensions['dst_height'];
|
||||
|
||||
wp_send_json_success( $object );
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an attachment ID for a header image, updates its "last used"
|
||||
* timestamp to now.
|
||||
*
|
||||
* Triggered when the user tries adds a new header image from the
|
||||
* Media Manager, even if s/he doesn't save that change.
|
||||
*/
|
||||
function ajax_header_add() {
|
||||
check_ajax_referer( 'header-add', 'nonce' );
|
||||
|
||||
if ( ! current_user_can( 'edit_theme_options' ) ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
$attachment_id = absint( $_POST['attachment_id'] );
|
||||
if ( $attachment_id < 1 ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
|
||||
update_post_meta( $attachment_id, $key, time() );
|
||||
update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an attachment ID for a header image, unsets it as a user-uploaded
|
||||
* header image for the current theme.
|
||||
*
|
||||
* Triggered when the user clicks the overlay "X" button next to each image
|
||||
* choice in the Customizer's Header tool.
|
||||
*/
|
||||
function ajax_header_remove() {
|
||||
check_ajax_referer( 'header-remove', 'nonce' );
|
||||
|
||||
if ( ! current_user_can( 'edit_theme_options' ) ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
$attachment_id = absint( $_POST['attachment_id'] );
|
||||
if ( $attachment_id < 1 ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
|
||||
delete_post_meta( $attachment_id, $key );
|
||||
delete_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
function customize_set_last_used( $wp_customize ) {
|
||||
$data = $wp_customize->get_setting( 'header_image_data' )->post_value();
|
||||
|
||||
if ( ! isset( $data['attachment_id'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$attachment_id = $data['attachment_id'];
|
||||
$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
|
||||
update_post_meta( $attachment_id, $key, time() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* globals _wpCustomizeHeader, _wpMediaViewsL10n */
|
||||
(function( exports, $ ){
|
||||
var api = wp.customize;
|
||||
|
||||
|
@ -306,6 +307,217 @@
|
|||
}
|
||||
});
|
||||
|
||||
api.HeaderControl = api.Control.extend({
|
||||
ready: function() {
|
||||
this.btnRemove = $('.actions .remove');
|
||||
this.btnNew = $('.actions .new');
|
||||
|
||||
_.bindAll(this, 'openMedia', 'removeImage');
|
||||
|
||||
this.btnNew.on( 'click', this.openMedia );
|
||||
this.btnRemove.on( 'click', this.removeImage );
|
||||
|
||||
api.HeaderTool.currentHeader = new api.HeaderTool.ImageModel();
|
||||
|
||||
new api.HeaderTool.CurrentView({
|
||||
model: api.HeaderTool.currentHeader,
|
||||
el: '.current .container'
|
||||
});
|
||||
|
||||
new api.HeaderTool.ChoiceListView({
|
||||
collection: api.HeaderTool.UploadsList = new api.HeaderTool.ChoiceList(),
|
||||
el: '.choices .uploaded .list'
|
||||
});
|
||||
|
||||
new api.HeaderTool.ChoiceListView({
|
||||
collection: api.HeaderTool.DefaultsList = new api.HeaderTool.DefaultsList(),
|
||||
el: '.choices .default .list'
|
||||
});
|
||||
|
||||
api.HeaderTool.combinedList = api.HeaderTool.CombinedList = new api.HeaderTool.CombinedList([
|
||||
api.HeaderTool.UploadsList,
|
||||
api.HeaderTool.DefaultsList
|
||||
]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a set of options, computed from the attached image data and
|
||||
* theme-specific data, to be fed to the imgAreaSelect plugin in
|
||||
* wp.media.view.Cropper.
|
||||
*
|
||||
* @param {wp.media.model.Attachment} attachment
|
||||
* @param {wp.media.controller.Cropper} controller
|
||||
* @returns {Object} Options
|
||||
*/
|
||||
calculateImageSelectOptions: function(attachment, controller) {
|
||||
var xInit = parseInt(_wpCustomizeHeader.data.width, 10),
|
||||
yInit = parseInt(_wpCustomizeHeader.data.height, 10),
|
||||
flexWidth = !! parseInt(_wpCustomizeHeader.data['flex-width'], 10),
|
||||
flexHeight = !! parseInt(_wpCustomizeHeader.data['flex-height'], 10),
|
||||
ratio, xImg, yImg, realHeight, realWidth,
|
||||
imgSelectOptions;
|
||||
|
||||
realWidth = attachment.get('width');
|
||||
realHeight = attachment.get('height');
|
||||
|
||||
this.headerImage = new api.HeaderTool.ImageModel();
|
||||
this.headerImage.set({
|
||||
themeWidth: xInit,
|
||||
themeHeight: yInit,
|
||||
themeFlexWidth: flexWidth,
|
||||
themeFlexHeight: flexHeight,
|
||||
imageWidth: realWidth,
|
||||
imageHeight: realHeight
|
||||
});
|
||||
|
||||
controller.set( 'canSkipCrop', ! this.headerImage.shouldBeCropped() );
|
||||
|
||||
ratio = xInit / yInit;
|
||||
xImg = realWidth;
|
||||
yImg = realHeight;
|
||||
|
||||
if ( xImg / yImg > ratio ) {
|
||||
yInit = yImg;
|
||||
xInit = yInit * ratio;
|
||||
} else {
|
||||
xInit = xImg;
|
||||
yInit = xInit / ratio;
|
||||
}
|
||||
|
||||
imgSelectOptions = {
|
||||
handles: true,
|
||||
keys: true,
|
||||
instance: true,
|
||||
persistent: true,
|
||||
parent: this.$el,
|
||||
imageWidth: realWidth,
|
||||
imageHeight: realHeight,
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: xInit,
|
||||
y2: yInit
|
||||
};
|
||||
|
||||
if (flexHeight === false && flexWidth === false) {
|
||||
imgSelectOptions.aspectRatio = xInit + ':' + yInit;
|
||||
}
|
||||
if (flexHeight === false ) {
|
||||
imgSelectOptions.maxHeight = yInit;
|
||||
}
|
||||
if (flexWidth === false ) {
|
||||
imgSelectOptions.maxWidth = xInit;
|
||||
}
|
||||
|
||||
return imgSelectOptions;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets up and opens the Media Manager in order to select an image.
|
||||
* Depending on both the size of the image and the properties of the
|
||||
* current theme, a cropping step after selection may be required or
|
||||
* skippable.
|
||||
*
|
||||
* @param {event} event
|
||||
*/
|
||||
openMedia: function(event) {
|
||||
var title, suggestedWidth, suggestedHeight,
|
||||
l10n = _wpMediaViewsL10n;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
suggestedWidth = l10n.suggestedWidth.replace('%d', _wpCustomizeHeader.data.width);
|
||||
suggestedHeight = l10n.suggestedHeight.replace('%d', _wpCustomizeHeader.data.height);
|
||||
|
||||
/* '<span class="suggested-dimensions">' + suggestedWidth + ' ' + suggestedHeight + '</span>' */
|
||||
|
||||
this.frame = wp.media({
|
||||
title: l10n.chooseImage,
|
||||
library: {
|
||||
type: 'image'
|
||||
},
|
||||
button: {
|
||||
text: l10n.selectAndCrop,
|
||||
close: false
|
||||
},
|
||||
multiple: false,
|
||||
imgSelectOptions: this.calculateImageSelectOptions
|
||||
});
|
||||
|
||||
this.frame.states.add([new wp.media.controller.Cropper()]);
|
||||
|
||||
this.frame.on('select', this.onSelect, this);
|
||||
this.frame.on('cropped', this.onCropped, this);
|
||||
this.frame.on('skippedcrop', this.onSkippedCrop, this);
|
||||
|
||||
this.frame.open();
|
||||
},
|
||||
|
||||
onSelect: function() {
|
||||
this.frame.setState('cropper');
|
||||
},
|
||||
onCropped: function(croppedImage) {
|
||||
var url = croppedImage.post_content,
|
||||
attachmentId = croppedImage.attachment_id,
|
||||
w = croppedImage.width,
|
||||
h = croppedImage.height;
|
||||
this.setImageFromURL(url, attachmentId, w, h);
|
||||
},
|
||||
onSkippedCrop: function(selection) {
|
||||
var url = selection.get('url'),
|
||||
w = selection.get('width'),
|
||||
h = selection.get('height');
|
||||
this.setImageFromURL(url, selection.id, w, h);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new wp.customize.HeaderTool.ImageModel from provided
|
||||
* header image data and inserts it into the user-uploaded headers
|
||||
* collection.
|
||||
*
|
||||
* @param {String} url
|
||||
* @param {Number} attachmentId
|
||||
* @param {Number} width
|
||||
* @param {Number} height
|
||||
*/
|
||||
setImageFromURL: function(url, attachmentId, width, height) {
|
||||
var choice, data = {};
|
||||
|
||||
data.url = url;
|
||||
data.thumbnail_url = url;
|
||||
|
||||
if (attachmentId) {
|
||||
data.attachment_id = attachmentId;
|
||||
}
|
||||
|
||||
if (width) {
|
||||
data.width = width;
|
||||
}
|
||||
|
||||
if (height) {
|
||||
data.height = height;
|
||||
}
|
||||
|
||||
choice = new api.HeaderTool.ImageModel({
|
||||
header: data,
|
||||
choice: url.split('/').pop()
|
||||
});
|
||||
api.HeaderTool.UploadsList.add(choice);
|
||||
api.HeaderTool.currentHeader.set(choice.toJSON());
|
||||
choice.save();
|
||||
choice.importImage();
|
||||
},
|
||||
|
||||
/**
|
||||
* Triggers the necessary events to deselect an image which was set as
|
||||
* the currently selected one.
|
||||
*/
|
||||
removeImage: function() {
|
||||
api.HeaderTool.currentHeader.trigger('hide');
|
||||
api.HeaderTool.CombinedList.trigger('control:removeImage');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Change objects contained within the main customize object to Settings.
|
||||
api.defaultConstructor = api.Setting;
|
||||
|
||||
|
@ -686,7 +898,8 @@
|
|||
api.controlConstructor = {
|
||||
color: api.ColorControl,
|
||||
upload: api.UploadControl,
|
||||
image: api.ImageControl
|
||||
image: api.ImageControl,
|
||||
header: api.HeaderControl
|
||||
};
|
||||
|
||||
$( function() {
|
||||
|
@ -961,35 +1174,6 @@
|
|||
});
|
||||
});
|
||||
|
||||
// Handle header image data
|
||||
api.control( 'header_image', function( control ) {
|
||||
control.setting.bind( function( to ) {
|
||||
if ( to === control.params.removed )
|
||||
control.settings.data.set( false );
|
||||
});
|
||||
|
||||
control.library.on( 'click', 'a', function() {
|
||||
control.settings.data.set( $(this).data('customizeHeaderImageData') );
|
||||
});
|
||||
|
||||
control.uploader.success = function( attachment ) {
|
||||
var data;
|
||||
|
||||
api.ImageControl.prototype.success.call( control, attachment );
|
||||
|
||||
data = {
|
||||
attachment_id: attachment.get('id'),
|
||||
url: attachment.get('url'),
|
||||
thumbnail_url: attachment.get('url'),
|
||||
height: attachment.get('height'),
|
||||
width: attachment.get('width')
|
||||
};
|
||||
|
||||
attachment.element.data( 'customizeHeaderImageData', data );
|
||||
control.settings.data.set( data );
|
||||
};
|
||||
});
|
||||
|
||||
api.trigger( 'ready' );
|
||||
|
||||
// Make sure left column gets focus
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -708,37 +708,9 @@ class WP_Customize_Background_Image_Control extends WP_Customize_Image_Control {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize Header Image Control Class
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Customize
|
||||
* @since 3.4.0
|
||||
*/
|
||||
class WP_Customize_Header_Image_Control extends WP_Customize_Image_Control {
|
||||
/**
|
||||
* The processed default headers.
|
||||
* @since 3.4.2
|
||||
* @var array
|
||||
*/
|
||||
protected $default_headers;
|
||||
final class WP_Customize_Header_Image_Control extends WP_Customize_Image_Control {
|
||||
public $type = 'header';
|
||||
|
||||
/**
|
||||
* The uploaded headers.
|
||||
* @since 3.4.2
|
||||
* @var array
|
||||
*/
|
||||
protected $uploaded_headers;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 3.4.0
|
||||
* @uses WP_Customize_Image_Control::__construct()
|
||||
* @uses WP_Customize_Image_Control::add_tab()
|
||||
*
|
||||
* @param WP_Customize_Manager $manager
|
||||
*/
|
||||
public function __construct( $manager ) {
|
||||
parent::__construct( $manager, 'header_image', array(
|
||||
'label' => __( 'Header Image' ),
|
||||
|
@ -750,86 +722,305 @@ class WP_Customize_Header_Image_Control extends WP_Customize_Image_Control {
|
|||
'context' => 'custom-header',
|
||||
'removed' => 'remove-header',
|
||||
'get_url' => 'get_header_image',
|
||||
'statuses' => array(
|
||||
'' => __('Default'),
|
||||
'remove-header' => __('No Image'),
|
||||
'random-default-image' => __('Random Default Image'),
|
||||
'random-uploaded-image' => __('Random Uploaded Image'),
|
||||
) );
|
||||
|
||||
}
|
||||
|
||||
public function to_json() {
|
||||
parent::to_json();
|
||||
}
|
||||
|
||||
public function enqueue() {
|
||||
wp_enqueue_media();
|
||||
wp_enqueue_script( 'customize-views' );
|
||||
|
||||
$this->prepare_control();
|
||||
|
||||
wp_localize_script( 'customize-views', '_wpCustomizeHeader', array(
|
||||
'data' => array(
|
||||
'width' => absint( get_theme_support( 'custom-header', 'width' ) ),
|
||||
'height' => absint( get_theme_support( 'custom-header', 'height' ) ),
|
||||
'flex-width' => absint( get_theme_support( 'custom-header', 'flex-width' ) ),
|
||||
'flex-height' => absint( get_theme_support( 'custom-header', 'flex-height' ) ),
|
||||
'currentImgSrc' => $this->get_current_image_src(),
|
||||
),
|
||||
'nonces' => array(
|
||||
'add' => wp_create_nonce( 'header-add' ),
|
||||
'remove' => wp_create_nonce( 'header-remove' ),
|
||||
),
|
||||
'l10n' => array(
|
||||
/* translators: header images uploaded by user */
|
||||
'uploaded' => __( 'uploaded' ),
|
||||
/* translators: header images suggested by the current theme */
|
||||
'default' => __( 'suggested' )
|
||||
),
|
||||
'uploads' => $this->uploaded_headers,
|
||||
'defaults' => $this->default_headers
|
||||
) );
|
||||
|
||||
parent::enqueue();
|
||||
}
|
||||
|
||||
public function get_default_header_images() {
|
||||
global $custom_image_header;
|
||||
|
||||
// Get *the* default image if there is one
|
||||
$default = get_theme_support( 'custom-header', 'default-image' );
|
||||
|
||||
if ( ! $default ) { // If not,
|
||||
return $custom_image_header->default_headers; // easy peasy.
|
||||
}
|
||||
|
||||
$default = sprintf( $default,
|
||||
get_template_directory_uri(),
|
||||
get_stylesheet_directory_uri() );
|
||||
|
||||
$header_images = array();
|
||||
$already_has_default = false;
|
||||
|
||||
// Get the whole set of default images
|
||||
$default_header_images = $custom_image_header->default_headers;
|
||||
foreach ( $default_header_images as $k => $h ) {
|
||||
if ( $h['url'] == $default ) {
|
||||
$already_has_default = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If *the one true image* isn't included in the default set, add it in
|
||||
// first position
|
||||
if ( ! $already_has_default ) {
|
||||
$header_images['default'] = array(
|
||||
'url' => $default,
|
||||
'thumbnail_url' => $default,
|
||||
'description' => 'Default'
|
||||
);
|
||||
}
|
||||
|
||||
// The rest of the set comes after
|
||||
$header_images = array_merge( $header_images, $default_header_images );
|
||||
|
||||
return $header_images;
|
||||
}
|
||||
|
||||
public function get_uploaded_header_images() {
|
||||
$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
|
||||
$header_images = array();
|
||||
|
||||
$headers_not_dated = get_posts( array(
|
||||
'post_type' => 'attachment',
|
||||
'meta_key' => '_wp_attachment_is_custom_header',
|
||||
'meta_value' => get_option('stylesheet'),
|
||||
'orderby' => 'none',
|
||||
'nopaging' => true,
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_wp_attachment_is_custom_header',
|
||||
'value' => get_option( 'stylesheet' ),
|
||||
'compare' => 'LIKE'
|
||||
),
|
||||
array(
|
||||
'key' => $key,
|
||||
'value' => 'this string must not be empty',
|
||||
'compare' => 'NOT EXISTS'
|
||||
),
|
||||
)
|
||||
) );
|
||||
|
||||
// Remove the upload tab.
|
||||
$this->remove_tab( 'upload-new' );
|
||||
$headers_dated = get_posts( array(
|
||||
'post_type' => 'attachment',
|
||||
'meta_key' => $key,
|
||||
'orderby' => 'meta_value_num',
|
||||
'order' => 'DESC',
|
||||
'nopaging' => true,
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_wp_attachment_is_custom_header',
|
||||
'value' => get_option( 'stylesheet' ),
|
||||
'compare' => 'LIKE'
|
||||
),
|
||||
),
|
||||
) );
|
||||
|
||||
$limit = apply_filters( 'custom_header_uploaded_limit', 15 );
|
||||
$headers = array_merge( $headers_dated, $headers_not_dated );
|
||||
$headers = array_slice( $headers, 0, $limit );
|
||||
|
||||
foreach ( (array) $headers as $header ) {
|
||||
$url = esc_url_raw( $header->guid );
|
||||
$header_data = wp_get_attachment_metadata( $header->ID );
|
||||
$timestamp = get_post_meta( $header->ID,
|
||||
'_wp_attachment_custom_header_last_used_' . get_stylesheet(),
|
||||
true );
|
||||
|
||||
$h = array(
|
||||
'attachment_id' => $header->ID,
|
||||
'url' => $url,
|
||||
'thumbnail_url' => $url,
|
||||
'timestamp' => $timestamp ? $timestamp : 0,
|
||||
);
|
||||
|
||||
if ( isset( $header_data['width'] ) ) {
|
||||
$h['width'] = $header_data['width'];
|
||||
}
|
||||
if ( isset( $header_data['height'] ) ) {
|
||||
$h['height'] = $header_data['height'];
|
||||
}
|
||||
|
||||
$header_images[] = $h;
|
||||
}
|
||||
|
||||
return $header_images;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the control.
|
||||
*
|
||||
* If no tabs exist, removes the control from the manager.
|
||||
*
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public function prepare_control() {
|
||||
global $custom_image_header;
|
||||
if ( empty( $custom_image_header ) )
|
||||
return parent::prepare_control();
|
||||
if ( empty( $custom_image_header ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process default headers and uploaded headers.
|
||||
$custom_image_header->process_default_headers();
|
||||
$this->default_headers = $custom_image_header->default_headers;
|
||||
$this->uploaded_headers = get_uploaded_header_images();
|
||||
|
||||
if ( $this->default_headers )
|
||||
$this->add_tab( 'default', __('Default'), array( $this, 'tab_default_headers' ) );
|
||||
|
||||
if ( ! $this->uploaded_headers )
|
||||
$this->remove_tab( 'uploaded' );
|
||||
|
||||
return parent::prepare_control();
|
||||
$this->default_headers = $this->get_default_header_images();
|
||||
$this->uploaded_headers = $this->get_uploaded_header_images();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.0
|
||||
*
|
||||
* @param mixed $choice Which header image to select. (@see Custom_Image_Header::get_header_image() )
|
||||
* @param array $header
|
||||
*/
|
||||
public function print_header_image( $choice, $header ) {
|
||||
$header['url'] = set_url_scheme( $header['url'] );
|
||||
$header['thumbnail_url'] = set_url_scheme( $header['thumbnail_url'] );
|
||||
|
||||
$header_image_data = array( 'choice' => $choice );
|
||||
foreach ( array( 'attachment_id', 'width', 'height', 'url', 'thumbnail_url' ) as $key ) {
|
||||
if ( isset( $header[ $key ] ) )
|
||||
$header_image_data[ $key ] = $header[ $key ];
|
||||
}
|
||||
|
||||
|
||||
function print_header_image_template() {
|
||||
?>
|
||||
<a href="#" class="thumbnail"
|
||||
data-customize-image-value="<?php echo esc_url( $header['url'] ); ?>"
|
||||
data-customize-header-image-data="<?php echo esc_attr( json_encode( $header_image_data ) ); ?>">
|
||||
<img src="<?php echo esc_url( $header['thumbnail_url'] ); ?>" />
|
||||
<script type="text/template" id="tmpl-header-choice">
|
||||
<# if (data.random) { #>
|
||||
|
||||
<div class="placeholder random">
|
||||
<div class="inner">
|
||||
<span><span class="dice">⚄</span>
|
||||
<# if ( data.type === 'uploaded' ) { #>
|
||||
<?php _e( 'Randomize uploaded headers' ); ?>
|
||||
<# } else if ( data.type === 'suggested' ) { #>
|
||||
<?php _e( 'Randomize suggested headers' ); ?>
|
||||
<# } #>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<# } else { #>
|
||||
|
||||
<# if (data.type === 'uploaded') { #>
|
||||
<div class="dashicons dashicons-no close"></div>
|
||||
<# } #>
|
||||
|
||||
<a href="#" class="choice thumbnail #>"
|
||||
data-customize-image-value="{{{data.header.url}}}"
|
||||
data-customize-header-image-data="{{JSON.stringify(data.header)}}">
|
||||
<img src="{{{data.header.thumbnail_url}}}">
|
||||
</a>
|
||||
|
||||
<# } #>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-header-current">
|
||||
<# if (data.choice) { #>
|
||||
<# if (data.random) { #>
|
||||
|
||||
<div class="placeholder">
|
||||
<div class="inner">
|
||||
<span><span class="dice">⚄</span>
|
||||
<# if ( data.type === 'uploaded' ) { #>
|
||||
<?php _e( 'Randomizing uploaded headers' ); ?>
|
||||
<# } else if ( data.type === 'suggested' ) { #>
|
||||
<?php _e( 'Randomizing suggested headers' ); ?>
|
||||
<# } #>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<# } else { #>
|
||||
|
||||
<img src="{{{data.header.thumbnail_url}}}" />
|
||||
|
||||
<# } #>
|
||||
<# } else { #>
|
||||
|
||||
<div class="placeholder">
|
||||
<div class="inner">
|
||||
<span>
|
||||
<?php _e( 'No image set' ); ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<# } #>
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public function tab_uploaded() {
|
||||
?><div class="uploaded-target"></div><?php
|
||||
|
||||
foreach ( $this->uploaded_headers as $choice => $header )
|
||||
$this->print_header_image( $choice, $header );
|
||||
public function get_current_image_src() {
|
||||
$src = $this->value();
|
||||
if ( isset( $this->get_url ) ) {
|
||||
$src = call_user_func( $this->get_url, $src );
|
||||
return $src;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public function tab_default_headers() {
|
||||
foreach ( $this->default_headers as $choice => $header )
|
||||
$this->print_header_image( $choice, $header );
|
||||
public function render_content() {
|
||||
$this->print_header_image_template();
|
||||
$visibility = $this->get_current_image_src() ? '' : ' style="display:none" ';
|
||||
$width = absint( get_theme_support( 'custom-header', 'width' ) );
|
||||
$height = absint( get_theme_support( 'custom-header', 'height' ) );
|
||||
?>
|
||||
|
||||
|
||||
<div class="customize-control-content">
|
||||
<p class="customizer-section-intro">
|
||||
<?php _e( 'Personalize your site with your own header image.' ); ?>
|
||||
<?php
|
||||
if ( $width && $height ) {
|
||||
printf( __( 'While you can crop images to your liking after clicking <strong>%s</strong>, your theme recommends a header size of <strong>%dx%d</strong> pixels.' ),
|
||||
_x( 'Add new', 'header image' ), $width, $height );
|
||||
} else {
|
||||
if ( $width ) {
|
||||
printf( __( 'While you can crop images to your liking after clicking <strong>%s</strong>, your theme recommends a header width of <strong>%d</strong> pixels.' ),
|
||||
_x( 'Add new', 'header image' ), $width );
|
||||
}
|
||||
if ( $height ) {
|
||||
printf( __( 'While you can crop images to your liking after clicking <strong>%s</strong>, your theme recommends a header height of <strong>%d</strong> pixels.' ),
|
||||
_x( 'Add new', 'header image' ), $height );
|
||||
}
|
||||
}
|
||||
?>
|
||||
</p>
|
||||
<div class="current">
|
||||
<span class="customize-control-title">
|
||||
<?php _e( 'Current header' ); ?>
|
||||
</span>
|
||||
<div class="container">
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<?php /* translators: Hide as in hide header image via the Customizer */ ?>
|
||||
<a href="#" <?php echo $visibility ?> class="button remove"><?php _ex( 'Hide', 'custom header' ); ?></a>
|
||||
<?php /* translators: New as in add new header image via the Customizer */ ?>
|
||||
<a href="#" class="button new"><?php _ex( 'Add new', 'header image' ); ?></a>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
<div class="choices">
|
||||
<span class="customize-control-title header-previously-uploaded">
|
||||
<?php _ex( 'Previously uploaded', 'custom headers' ); ?>
|
||||
</span>
|
||||
<div class="uploaded">
|
||||
<div class="list">
|
||||
</div>
|
||||
</div>
|
||||
<span class="customize-control-title header-default">
|
||||
<?php _ex( 'Suggested', 'custom headers' ); ?>
|
||||
</span>
|
||||
<div class="default">
|
||||
<div class="list">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -602,6 +602,19 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.media-frame-title .suggested-dimensions {
|
||||
font-size: 14px;
|
||||
float: left;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.media-frame-content .crop-content {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iframes
|
||||
*/
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -602,6 +602,19 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.media-frame-title .suggested-dimensions {
|
||||
font-size: 14px;
|
||||
float: right;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.media-frame-content .crop-content {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iframes
|
||||
*/
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,249 @@
|
|||
/* globals _wpCustomizeHeader, _wpCustomizeSettings */
|
||||
(function( $, wp ) {
|
||||
var api = wp.customize;
|
||||
api.HeaderTool = {};
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.ImageModel
|
||||
*
|
||||
* A header image. This is where saves via the Customizer API are
|
||||
* abstracted away, plus our own AJAX calls to add images to and remove
|
||||
* images from the user's recently uploaded images setting on the server.
|
||||
* These calls are made regardless of whether the user actually saves new
|
||||
* Customizer settings.
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
api.HeaderTool.ImageModel = Backbone.Model.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
header: {
|
||||
attachment_id: 0,
|
||||
url: '',
|
||||
timestamp: Date.now(),
|
||||
thumbnail_url: ''
|
||||
},
|
||||
choice: '',
|
||||
hidden: false,
|
||||
random: false
|
||||
};
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this.on('hide', this.hide, this);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.set('choice', '');
|
||||
api('header_image').set('remove-header');
|
||||
api('header_image_data').set('remove-header');
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var data = this.get('header'),
|
||||
curr = api.HeaderTool.currentHeader.get('header').attachment_id;
|
||||
|
||||
// If the image we're removing is also the current header, unset
|
||||
// the latter
|
||||
if (curr && data.attachment_id === curr) {
|
||||
api.HeaderTool.currentHeader.trigger('hide');
|
||||
}
|
||||
|
||||
wp.ajax.post( 'custom-header-remove', {
|
||||
nonce: _wpCustomizeHeader.nonces.remove,
|
||||
wp_customize: 'on',
|
||||
theme: api.settings.theme.stylesheet,
|
||||
attachment_id: data.attachment_id
|
||||
});
|
||||
|
||||
this.trigger('destroy', this, this.collection);
|
||||
},
|
||||
|
||||
save: function() {
|
||||
if (this.get('random')) {
|
||||
api('header_image').set(this.get('header').random);
|
||||
api('header_image_data').set(this.get('header').random);
|
||||
} else {
|
||||
if (this.get('header').defaultName) {
|
||||
api('header_image').set(this.get('header').url);
|
||||
api('header_image_data').set(this.get('header').defaultName);
|
||||
} else {
|
||||
api('header_image').set(this.get('header').url);
|
||||
api('header_image_data').set(this.get('header'));
|
||||
}
|
||||
}
|
||||
|
||||
api.HeaderTool.combinedList.trigger('control:setImage', this);
|
||||
},
|
||||
|
||||
importImage: function() {
|
||||
var data = this.get('header');
|
||||
if (data.attachment_id === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp.ajax.post( 'custom-header-add', {
|
||||
nonce: _wpCustomizeHeader.nonces.add,
|
||||
wp_customize: 'on',
|
||||
theme: api.settings.theme.stylesheet,
|
||||
attachment_id: data.attachment_id,
|
||||
} );
|
||||
},
|
||||
|
||||
shouldBeCropped: function() {
|
||||
if (this.get('themeFlexWidth') === true &&
|
||||
this.get('themeFlexHeight') === true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.get('themeFlexWidth') === true &&
|
||||
this.get('themeHeight') === this.get('imageHeight')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.get('themeFlexHeight') === true &&
|
||||
this.get('themeWidth') === this.get('imageWidth')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.get('themeWidth') === this.get('imageWidth') &&
|
||||
this.get('themeHeight') === this.get('imageHeight')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.ChoiceList
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Collection
|
||||
*/
|
||||
api.HeaderTool.ChoiceList = Backbone.Collection.extend({
|
||||
model: api.HeaderTool.ImageModel,
|
||||
|
||||
// Ordered from most recently used to least
|
||||
comparator: function(model) {
|
||||
return -model.get('header').timestamp;
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
var current = api.HeaderTool.currentHeader.get('choice').replace(/^https?:\/\//, ''),
|
||||
isRandom = this.isRandomChoice(api.get().header_image);
|
||||
|
||||
// Overridable by an extending class
|
||||
if (!this.type) {
|
||||
this.type = 'uploaded';
|
||||
}
|
||||
|
||||
// Overridable by an extending class
|
||||
if (!this.data) {
|
||||
this.data = _wpCustomizeHeader.uploads;
|
||||
}
|
||||
|
||||
if (isRandom) {
|
||||
// So that when adding data we don't hide regular images
|
||||
current = api.get().header_image;
|
||||
}
|
||||
|
||||
this.on('control:setImage', this.setImage, this);
|
||||
this.on('control:removeImage', this.removeImage, this);
|
||||
this.on('add', this.maybeAddRandomChoice, this);
|
||||
|
||||
_.each(this.data, function(elt, index) {
|
||||
if (!elt.attachment_id) {
|
||||
elt.defaultName = index;
|
||||
}
|
||||
|
||||
this.add({
|
||||
header: elt,
|
||||
choice: elt.url.split('/').pop(),
|
||||
hidden: current === elt.url.replace(/^https?:\/\//, '')
|
||||
}, { silent: true });
|
||||
}, this);
|
||||
|
||||
if (this.size() > 0) {
|
||||
this.addRandomChoice(current);
|
||||
}
|
||||
},
|
||||
|
||||
maybeAddRandomChoice: function() {
|
||||
if (this.size() === 1) {
|
||||
this.addRandomChoice();
|
||||
}
|
||||
},
|
||||
|
||||
addRandomChoice: function(initialChoice) {
|
||||
var isRandomSameType = RegExp(this.type).test(initialChoice),
|
||||
randomChoice = 'random-' + this.type + '-image';
|
||||
|
||||
this.add({
|
||||
header: {
|
||||
timestamp: 0,
|
||||
random: randomChoice,
|
||||
width: 245,
|
||||
height: 41
|
||||
},
|
||||
choice: randomChoice,
|
||||
random: true,
|
||||
hidden: isRandomSameType
|
||||
});
|
||||
},
|
||||
|
||||
isRandomChoice: function(choice) {
|
||||
return (/^random-(uploaded|default)-image$/).test(choice);
|
||||
},
|
||||
|
||||
shouldHideTitle: function() {
|
||||
return _.every(this.pluck('hidden'));
|
||||
},
|
||||
|
||||
setImage: function(model) {
|
||||
this.each(function(m) {
|
||||
m.set('hidden', false);
|
||||
});
|
||||
|
||||
if (model) {
|
||||
model.set('hidden', true);
|
||||
// Bump images to top except for special "Randomize" images
|
||||
if (!model.get('random')) {
|
||||
model.get('header').timestamp = Date.now();
|
||||
this.sort();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
removeImage: function() {
|
||||
this.each(function(m) {
|
||||
m.set('hidden', false);
|
||||
});
|
||||
},
|
||||
|
||||
shown: function() {
|
||||
var filtered = this.where({ hidden: false });
|
||||
return new api.HeaderTool.ChoiceList( filtered );
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.DefaultsList
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.customize.HeaderTool.ChoiceList
|
||||
* @augments Backbone.Collection
|
||||
*/
|
||||
api.HeaderTool.DefaultsList = api.HeaderTool.ChoiceList.extend({
|
||||
initialize: function() {
|
||||
this.type = 'default';
|
||||
this.data = _wpCustomizeHeader.defaults;
|
||||
api.HeaderTool.ChoiceList.prototype.initialize.apply(this);
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery, window.wp );
|
|
@ -0,0 +1 @@
|
|||
!function(a,b){var c=b.customize;c.HeaderTool={},c.HeaderTool.ImageModel=Backbone.Model.extend({defaults:function(){return{header:{attachment_id:0,url:"",timestamp:Date.now(),thumbnail_url:""},choice:"",hidden:!1,random:!1}},initialize:function(){this.on("hide",this.hide,this)},hide:function(){this.set("choice",""),c("header_image").set("remove-header"),c("header_image_data").set("remove-header")},destroy:function(){var a=this.get("header"),d=c.HeaderTool.currentHeader.get("header").attachment_id;d&&a.attachment_id===d&&c.HeaderTool.currentHeader.trigger("hide"),b.ajax.post("custom-header-remove",{nonce:_wpCustomizeHeader.nonces.remove,wp_customize:"on",theme:c.settings.theme.stylesheet,attachment_id:a.attachment_id}),this.trigger("destroy",this,this.collection)},save:function(){this.get("random")?(c("header_image").set(this.get("header").random),c("header_image_data").set(this.get("header").random)):this.get("header").defaultName?(c("header_image").set(this.get("header").url),c("header_image_data").set(this.get("header").defaultName)):(c("header_image").set(this.get("header").url),c("header_image_data").set(this.get("header"))),c.HeaderTool.combinedList.trigger("control:setImage",this)},importImage:function(){var a=this.get("header");void 0!==a.attachment_id&&b.ajax.post("custom-header-add",{nonce:_wpCustomizeHeader.nonces.add,wp_customize:"on",theme:c.settings.theme.stylesheet,attachment_id:a.attachment_id})},shouldBeCropped:function(){return this.get("themeFlexWidth")===!0&&this.get("themeFlexHeight")===!0?!1:this.get("themeFlexWidth")===!0&&this.get("themeHeight")===this.get("imageHeight")?!1:this.get("themeFlexHeight")===!0&&this.get("themeWidth")===this.get("imageWidth")?!1:this.get("themeWidth")===this.get("imageWidth")&&this.get("themeHeight")===this.get("imageHeight")?!1:!0}}),c.HeaderTool.ChoiceList=Backbone.Collection.extend({model:c.HeaderTool.ImageModel,comparator:function(a){return-a.get("header").timestamp},initialize:function(){var a=c.HeaderTool.currentHeader.get("choice").replace(/^https?:\/\//,""),b=this.isRandomChoice(c.get().header_image);this.type||(this.type="uploaded"),this.data||(this.data=_wpCustomizeHeader.uploads),b&&(a=c.get().header_image),this.on("control:setImage",this.setImage,this),this.on("control:removeImage",this.removeImage,this),this.on("add",this.maybeAddRandomChoice,this),_.each(this.data,function(b,c){b.attachment_id||(b.defaultName=c),this.add({header:b,choice:b.url.split("/").pop(),hidden:a===b.url.replace(/^https?:\/\//,"")},{silent:!0})},this),this.size()>0&&this.addRandomChoice(a)},maybeAddRandomChoice:function(){1===this.size()&&this.addRandomChoice()},addRandomChoice:function(a){var b=RegExp(this.type).test(a),c="random-"+this.type+"-image";this.add({header:{timestamp:0,random:c,width:245,height:41},choice:c,random:!0,hidden:b})},isRandomChoice:function(a){return/^random-(uploaded|default)-image$/.test(a)},shouldHideTitle:function(){return _.every(this.pluck("hidden"))},setImage:function(a){this.each(function(a){a.set("hidden",!1)}),a&&(a.set("hidden",!0),a.get("random")||(a.get("header").timestamp=Date.now(),this.sort()))},removeImage:function(){this.each(function(a){a.set("hidden",!1)})},shown:function(){var a=this.where({hidden:!1});return new c.HeaderTool.ChoiceList(a)}}),c.HeaderTool.DefaultsList=c.HeaderTool.ChoiceList.extend({initialize:function(){this.type="default",this.data=_wpCustomizeHeader.defaults,c.HeaderTool.ChoiceList.prototype.initialize.apply(this)}})}(jQuery,window.wp);
|
|
@ -0,0 +1,232 @@
|
|||
/* globals _wpCustomizeHeader */
|
||||
(function( $, wp, _ ) {
|
||||
|
||||
if ( ! wp || ! wp.customize ) { return; }
|
||||
var api = wp.customize;
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.CurrentView
|
||||
*
|
||||
* Displays the currently selected header image, or a placeholder in lack
|
||||
* thereof.
|
||||
*
|
||||
* Instantiate with model wp.customize.HeaderTool.currentHeader.
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.Backbone.View
|
||||
*/
|
||||
api.HeaderTool.CurrentView = wp.Backbone.View.extend({
|
||||
template: wp.template('header-current'),
|
||||
|
||||
initialize: function() {
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(this.template(this.model.toJSON()));
|
||||
this.setPlaceholder();
|
||||
this.setButtons();
|
||||
return this;
|
||||
},
|
||||
|
||||
getHeight: function() {
|
||||
var image = this.$el.find('img'),
|
||||
saved = this.model.get('savedHeight'),
|
||||
height = image.height() || saved,
|
||||
headerImageData;
|
||||
|
||||
if (image.length) {
|
||||
this.$el.find('.inner').hide();
|
||||
} else {
|
||||
this.$el.find('.inner').show();
|
||||
}
|
||||
|
||||
// happens at ready
|
||||
if (!height) {
|
||||
headerImageData = api.get().header_image_data;
|
||||
|
||||
if (headerImageData && headerImageData.width && headerImageData.height) {
|
||||
// hardcoded container width
|
||||
height = 260 / headerImageData.width * headerImageData.height;
|
||||
}
|
||||
else {
|
||||
// fallback for when no image is set
|
||||
height = 40;
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
},
|
||||
|
||||
setPlaceholder: function(_height) {
|
||||
var height = _height || this.getHeight();
|
||||
this.model.set('savedHeight', height);
|
||||
this.$el
|
||||
.add(this.$el.find('.placeholder'))
|
||||
.height(height);
|
||||
},
|
||||
|
||||
setButtons: function() {
|
||||
var elements = $('.actions .remove');
|
||||
if (this.model.get('choice')) {
|
||||
elements.show();
|
||||
} else {
|
||||
elements.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.ChoiceView
|
||||
*
|
||||
* Represents a choosable header image, be it user-uploaded,
|
||||
* theme-suggested or a special Randomize choice.
|
||||
*
|
||||
* Takes a wp.customize.HeaderTool.ImageModel.
|
||||
*
|
||||
* Manually changes model wp.customize.HeaderTool.currentHeader via the
|
||||
* `select` method.
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.Backbone.View
|
||||
*/
|
||||
(function () { // closures FTW
|
||||
var lastHeight = 0;
|
||||
api.HeaderTool.ChoiceView = wp.Backbone.View.extend({
|
||||
template: wp.template('header-choice'),
|
||||
|
||||
className: 'header-view',
|
||||
|
||||
events: {
|
||||
'click .choice,.random': 'select',
|
||||
'click .close': 'removeImage'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
var properties = [
|
||||
this.model.get('header').url,
|
||||
this.model.get('choice')
|
||||
];
|
||||
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
|
||||
if (_.contains(properties, api.get().header_image)) {
|
||||
api.HeaderTool.currentHeader.set(this.extendedModel());
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var model = this.model;
|
||||
|
||||
this.$el.html(this.template(this.extendedModel()));
|
||||
|
||||
if (model.get('random')) {
|
||||
this.setPlaceholder(40);
|
||||
}
|
||||
else {
|
||||
lastHeight = this.getHeight();
|
||||
}
|
||||
|
||||
this.$el.toggleClass('hidden', model.get('hidden'));
|
||||
return this;
|
||||
},
|
||||
|
||||
extendedModel: function() {
|
||||
var c = this.model.get('collection'),
|
||||
t = _wpCustomizeHeader.l10n[c.type] || '';
|
||||
|
||||
return _.extend(this.model.toJSON(), {
|
||||
// -1 to exclude the randomize button
|
||||
nImages: c.size() - 1,
|
||||
type: t
|
||||
});
|
||||
},
|
||||
|
||||
getHeight: api.HeaderTool.CurrentView.prototype.getHeight,
|
||||
|
||||
setPlaceholder: api.HeaderTool.CurrentView.prototype.setPlaceholder,
|
||||
|
||||
select: function() {
|
||||
this.model.save();
|
||||
api.HeaderTool.currentHeader.set(this.extendedModel());
|
||||
},
|
||||
|
||||
removeImage: function(e) {
|
||||
e.stopPropagation();
|
||||
this.model.destroy();
|
||||
this.remove();
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.ChoiceListView
|
||||
*
|
||||
* A container for ChoiceViews. These choices should be of one same type:
|
||||
* user-uploaded headers or theme-defined ones.
|
||||
*
|
||||
* Takes a wp.customize.HeaderTool.ChoiceList.
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.Backbone.View
|
||||
*/
|
||||
api.HeaderTool.ChoiceListView = wp.Backbone.View.extend({
|
||||
initialize: function() {
|
||||
this.listenTo(this.collection, 'add', this.addOne);
|
||||
this.listenTo(this.collection, 'remove', this.render);
|
||||
this.listenTo(this.collection, 'sort', this.render);
|
||||
this.listenTo(this.collection, 'change:hidden', this.toggleTitle);
|
||||
this.listenTo(this.collection, 'change:hidden', this.setMaxListHeight);
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.empty();
|
||||
this.collection.each(this.addOne, this);
|
||||
this.toggleTitle();
|
||||
},
|
||||
|
||||
addOne: function(choice) {
|
||||
var view;
|
||||
choice.set({ collection: this.collection });
|
||||
view = new api.HeaderTool.ChoiceView({ model: choice });
|
||||
this.$el.append(view.render().el);
|
||||
},
|
||||
|
||||
toggleTitle: function() {
|
||||
var title = this.$el.parents().prev('.customize-control-title');
|
||||
if (this.collection.shouldHideTitle()) {
|
||||
title.hide();
|
||||
} else {
|
||||
title.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.CombinedList
|
||||
*
|
||||
* Aggregates wp.customize.HeaderTool.ChoiceList collections (or any
|
||||
* Backbone object, really) and acts as a bus to feed them events.
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.Backbone.View
|
||||
*/
|
||||
api.HeaderTool.CombinedList = wp.Backbone.View.extend({
|
||||
initialize: function(collections) {
|
||||
this.collections = collections;
|
||||
this.on('all', this.propagate, this);
|
||||
},
|
||||
propagate: function(event, arg) {
|
||||
_.each(this.collections, function(collection) {
|
||||
collection.trigger(event, arg);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery, window.wp, _ );
|
|
@ -0,0 +1 @@
|
|||
!function(a,b,c){if(b&&b.customize){var d=b.customize;d.HeaderTool.CurrentView=b.Backbone.View.extend({template:b.template("header-current"),initialize:function(){this.listenTo(this.model,"change",this.render),this.render()},render:function(){return this.$el.html(this.template(this.model.toJSON())),this.setPlaceholder(),this.setButtons(),this},getHeight:function(){var a,b=this.$el.find("img"),c=this.model.get("savedHeight"),e=b.height()||c;return b.length?this.$el.find(".inner").hide():this.$el.find(".inner").show(),e||(a=d.get().header_image_data,e=a&&a.width&&a.height?260/a.width*a.height:40),e},setPlaceholder:function(a){var b=a||this.getHeight();this.model.set("savedHeight",b),this.$el.add(this.$el.find(".placeholder")).height(b)},setButtons:function(){var b=a(".actions .remove");this.model.get("choice")?b.show():b.hide()}}),function(){var a=0;d.HeaderTool.ChoiceView=b.Backbone.View.extend({template:b.template("header-choice"),className:"header-view",events:{"click .choice,.random":"select","click .close":"removeImage"},initialize:function(){var a=[this.model.get("header").url,this.model.get("choice")];this.listenTo(this.model,"change",this.render),c.contains(a,d.get().header_image)&&d.HeaderTool.currentHeader.set(this.extendedModel())},render:function(){var b=this.model;return this.$el.html(this.template(this.extendedModel())),b.get("random")?this.setPlaceholder(40):a=this.getHeight(),this.$el.toggleClass("hidden",b.get("hidden")),this},extendedModel:function(){var a=this.model.get("collection"),b=_wpCustomizeHeader.l10n[a.type]||"";return c.extend(this.model.toJSON(),{nImages:a.size()-1,type:b})},getHeight:d.HeaderTool.CurrentView.prototype.getHeight,setPlaceholder:d.HeaderTool.CurrentView.prototype.setPlaceholder,select:function(){this.model.save(),d.HeaderTool.currentHeader.set(this.extendedModel())},removeImage:function(a){a.stopPropagation(),this.model.destroy(),this.remove()}})}(),d.HeaderTool.ChoiceListView=b.Backbone.View.extend({initialize:function(){this.listenTo(this.collection,"add",this.addOne),this.listenTo(this.collection,"remove",this.render),this.listenTo(this.collection,"sort",this.render),this.listenTo(this.collection,"change:hidden",this.toggleTitle),this.listenTo(this.collection,"change:hidden",this.setMaxListHeight),this.render()},render:function(){this.$el.empty(),this.collection.each(this.addOne,this),this.toggleTitle()},addOne:function(a){var b;a.set({collection:this.collection}),b=new d.HeaderTool.ChoiceView({model:a}),this.$el.append(b.render().el)},toggleTitle:function(){var a=this.$el.parents().prev(".customize-control-title");this.collection.shouldHideTitle()?a.hide():a.show()}}),d.HeaderTool.CombinedList=b.Backbone.View.extend({initialize:function(a){this.collections=a,this.on("all",this.propagate,this)},propagate:function(a,b){c.each(this.collections,function(c){c.trigger(a,b)})}})}}(jQuery,window.wp,_);
|
|
@ -1316,6 +1316,109 @@
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* wp.media.controller.Cropper
|
||||
*
|
||||
* Allows for a cropping step.
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.media.controller.State
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
media.controller.Cropper = media.controller.State.extend({
|
||||
defaults: {
|
||||
id: 'cropper',
|
||||
title: l10n.cropImage,
|
||||
toolbar: 'crop',
|
||||
content: 'crop',
|
||||
router: false,
|
||||
canSkipCrop: false
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this.frame.on( 'content:create:crop', this.createCropContent, this );
|
||||
this.frame.on( 'close', this.removeCropper, this );
|
||||
this.set('selection', new Backbone.Collection(this.frame._selection.single));
|
||||
},
|
||||
|
||||
deactivate: function() {
|
||||
this.frame.toolbar.mode('browse');
|
||||
},
|
||||
|
||||
createCropContent: function() {
|
||||
this.cropperView = new wp.media.view.Cropper({controller: this,
|
||||
attachment: this.get('selection').first() });
|
||||
this.cropperView.on('image-loaded', this.createCropToolbar, this);
|
||||
this.frame.content.set(this.cropperView);
|
||||
|
||||
},
|
||||
removeCropper: function() {
|
||||
this.imgSelect.cancelSelection();
|
||||
this.imgSelect.setOptions({remove: true});
|
||||
this.imgSelect.update();
|
||||
this.cropperView.remove();
|
||||
},
|
||||
createCropToolbar: function() {
|
||||
var canSkipCrop, toolbarOptions;
|
||||
|
||||
canSkipCrop = this.get('canSkipCrop') || false;
|
||||
|
||||
toolbarOptions = {
|
||||
controller: this.frame,
|
||||
items: {
|
||||
insert: {
|
||||
style: 'primary',
|
||||
text: l10n.cropImage,
|
||||
priority: 80,
|
||||
requires: { library: false, selection: false },
|
||||
|
||||
click: function() {
|
||||
var self = this,
|
||||
selection = this.controller.state().get('selection').first();
|
||||
|
||||
selection.set({cropDetails: this.controller.state().imgSelect.getSelection()});
|
||||
|
||||
this.$el.text(l10n.cropping);
|
||||
this.$el.attr('disabled', true);
|
||||
this.controller.state().doCrop( selection ).done( function( croppedImage ) {
|
||||
console.log( croppedImage );
|
||||
self.controller.trigger('cropped', croppedImage );
|
||||
self.controller.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if ( canSkipCrop ) {
|
||||
_.extend( toolbarOptions.items, {
|
||||
skip: {
|
||||
style: 'secondary',
|
||||
text: l10n.skipCropping,
|
||||
priority: 70,
|
||||
requires: { library: false, selection: false },
|
||||
click: function() {
|
||||
var selection = this.controller.state().get('selection').first();
|
||||
this.controller.state().cropperView.remove();
|
||||
this.controller.trigger('skippedcrop', selection);
|
||||
this.controller.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.frame.toolbar.set( new wp.media.view.Toolbar(toolbarOptions) );
|
||||
},
|
||||
|
||||
doCrop: function( attachment ) {
|
||||
return wp.ajax.post( 'custom-header-crop', {
|
||||
nonce: attachment.get('nonces').edit,
|
||||
id: attachment.get('id'),
|
||||
cropDetails: attachment.get('cropDetails')
|
||||
} );
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* ========================================================================
|
||||
* VIEWS
|
||||
|
@ -6323,6 +6426,53 @@
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* wp.media.view.Cropper
|
||||
*
|
||||
* Uses the imgAreaSelect plugin to allow a user to crop an image.
|
||||
*
|
||||
* Takes imgAreaSelect options from
|
||||
* wp.customize.HeaderControl.calculateImageSelectOptions via
|
||||
* wp.customize.HeaderControl.openMM.
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.media.View
|
||||
* @augments wp.Backbone.View
|
||||
* @augments Backbone.View
|
||||
*/
|
||||
media.view.Cropper = media.View.extend({
|
||||
tagName: 'img',
|
||||
className: 'crop-content',
|
||||
initialize: function() {
|
||||
_.bindAll(this, 'onImageLoad');
|
||||
this.$el.attr('src', this.options.attachment.get('url'));
|
||||
},
|
||||
ready: function() {
|
||||
this.$el.on('load', this.onImageLoad);
|
||||
$(window).on('resize.cropper', _.debounce(this.onImageLoad, 250));
|
||||
},
|
||||
remove: function() {
|
||||
$(window).off('resize.cropper');
|
||||
this.$el.remove();
|
||||
this.$el.off();
|
||||
wp.media.View.prototype.remove.apply(this, arguments);
|
||||
},
|
||||
prepare: function() {
|
||||
return {
|
||||
title: l10n.cropYourImage,
|
||||
url: this.options.attachment.get('url')
|
||||
};
|
||||
},
|
||||
onImageLoad: function() {
|
||||
var imgOptions = this.controller.frame.options.imgSelectOptions;
|
||||
if (typeof imgOptions === 'function') {
|
||||
imgOptions = imgOptions(this.options.attachment, this.controller);
|
||||
}
|
||||
this.trigger('image-loaded');
|
||||
this.controller.imgSelect = this.$el.imgAreaSelect(imgOptions);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
media.view.EditImage = media.View.extend({
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2476,6 +2476,23 @@ function wp_enqueue_media( $args = array() ) {
|
|||
'imageDetailsCancel' => __( 'Cancel Edit' ),
|
||||
'editImage' => __( 'Edit Image' ),
|
||||
|
||||
// Crop Image
|
||||
/* translators: title for Media Manager library view */
|
||||
'chooseImage' => __( 'Choose Image' ),
|
||||
/* translators: button to select an image from the MM library to crop */
|
||||
'selectAndCrop' => __( 'Select and Crop' ),
|
||||
/* translators: button to choose not to crop the selected image */
|
||||
'skipCropping' => __( 'Skip Cropping' ),
|
||||
/* translators: button to choose to crop the selected image */
|
||||
'cropImage' => __( 'Crop Image' ),
|
||||
'cropYourImage' => __( 'Crop your image' ),
|
||||
/* translators: button label changes to this while the image is being cropped server-side */
|
||||
'cropping' => __( 'Cropping...' ),
|
||||
/* translators: suggested width of header image in pixels */
|
||||
'suggestedWidth' => __( 'Suggested width is %d pixels.' ),
|
||||
/* translators: suggested height of header image in pixels */
|
||||
'suggestedHeight' => __( 'Suggested height is %d pixels.' ),
|
||||
|
||||
// Edit Audio
|
||||
'audioDetailsTitle' => __( 'Audio Details' ),
|
||||
'audioReplaceTitle' => __( 'Replace Audio' ),
|
||||
|
|
|
@ -363,6 +363,8 @@ function wp_default_scripts( &$scripts ) {
|
|||
$scripts->add( 'customize-base', "/wp-includes/js/customize-base$suffix.js", array( 'jquery', 'json2' ), false, 1 );
|
||||
$scripts->add( 'customize-loader', "/wp-includes/js/customize-loader$suffix.js", array( 'customize-base' ), false, 1 );
|
||||
$scripts->add( 'customize-preview', "/wp-includes/js/customize-preview$suffix.js", array( 'customize-base' ), false, 1 );
|
||||
$scripts->add( 'customize-models', "/wp-includes/js/customize-models.js", array( 'underscore', 'backbone' ), false, 1 );
|
||||
$scripts->add( 'customize-views', "/wp-includes/js/customize-views.js", array( 'jquery', 'underscore', 'imgareaselect', 'customize-models' ), false, 1 );
|
||||
$scripts->add( 'customize-controls', "/wp-admin/js/customize-controls$suffix.js", array( 'customize-base' ), false, 1 );
|
||||
did_action( 'init' ) && $scripts->localize( 'customize-controls', '_wpCustomizeControlsL10n', array(
|
||||
'activate' => __( 'Save & Activate' ),
|
||||
|
@ -600,7 +602,7 @@ function wp_default_styles( &$styles ) {
|
|||
$styles->add( 'login', "/wp-admin/css/login$suffix.css", array( 'buttons', 'open-sans', 'dashicons' ) );
|
||||
$styles->add( 'install', "/wp-admin/css/install$suffix.css", array( 'buttons', 'open-sans' ) );
|
||||
$styles->add( 'wp-color-picker', "/wp-admin/css/color-picker$suffix.css" );
|
||||
$styles->add( 'customize-controls', "/wp-admin/css/customize-controls$suffix.css", array( 'wp-admin', 'colors', 'ie' ) );
|
||||
$styles->add( 'customize-controls', "/wp-admin/css/customize-controls$suffix.css", array( 'wp-admin', 'colors', 'ie', 'imgareaselect' ) );
|
||||
$styles->add( 'ie', "/wp-admin/css/ie$suffix.css" );
|
||||
|
||||
$styles->add_data( 'ie', 'conditional', 'lte IE 7' );
|
||||
|
|
Loading…
Reference in New Issue