Site Icon: Add Customizer UI.
Second part of the Site Icon feature after [32994] introduced it for Settings. Props celloexpressions. See #16434. Built from https://develop.svn.wordpress.org/trunk@33154 git-svn-id: http://core.svn.wordpress.org/trunk@33126 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
@@ -1835,6 +1835,245 @@
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* A control for selecting and cropping an image.
|
||||
*
|
||||
* @class
|
||||
* @augments wp.customize.MediaControl
|
||||
* @augments wp.customize.Control
|
||||
* @augments wp.customize.Class
|
||||
*/
|
||||
api.CroppedImageControl = api.MediaControl.extend({
|
||||
|
||||
/**
|
||||
* Open the media modal to the library state.
|
||||
*/
|
||||
openFrame: function( event ) {
|
||||
if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initFrame();
|
||||
this.frame.setState( 'library' ).open();
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a media modal select frame, and store it so the instance can be reused when needed.
|
||||
*/
|
||||
initFrame: function() {
|
||||
var l10n = _wpMediaViewsL10n;
|
||||
|
||||
this.frame = wp.media({
|
||||
button: {
|
||||
text: l10n.select,
|
||||
close: false
|
||||
},
|
||||
states: [
|
||||
new wp.media.controller.Library({
|
||||
title: this.params.button_labels.frame_title,
|
||||
library: wp.media.query({ type: 'image' }),
|
||||
multiple: false,
|
||||
date: false,
|
||||
priority: 20,
|
||||
suggestedWidth: this.params.width,
|
||||
suggestedHeight: this.params.height
|
||||
}),
|
||||
new wp.media.controller.customizeImageCropper({
|
||||
imgSelectOptions: this.calculateImageSelectOptions,
|
||||
control: this
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
this.frame.on( 'select', this.onSelect, this );
|
||||
this.frame.on( 'cropped', this.onCropped, this );
|
||||
this.frame.on( 'skippedcrop', this.onSkippedCrop, this );
|
||||
},
|
||||
|
||||
/**
|
||||
* After an image is selected in the media modal, switch to the cropper
|
||||
* state if the image isn't the right size.
|
||||
*/
|
||||
onSelect: function() {
|
||||
var attachment = this.frame.state().get( 'selection' ).first().toJSON();
|
||||
|
||||
if ( this.params.width === attachment.width && this.params.height === attachment.height && ! this.params.flex_width && ! this.params.flex_height ) {
|
||||
this.setImageFromAttachment( attachment );
|
||||
this.frame.close();
|
||||
} else {
|
||||
this.frame.setState( 'cropper' );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* After the image has been cropped, apply the cropped image data to the setting.
|
||||
*
|
||||
* @param {object} croppedImage Cropped attachment data.
|
||||
*/
|
||||
onCropped: function( croppedImage ) {
|
||||
this.setImageFromAttachment( croppedImage );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a set of options, computed from the attached image data and
|
||||
* control-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 control = controller.get( 'control' ),
|
||||
flexWidth = !! parseInt( control.params.flex_width, 10 ),
|
||||
flexHeight = !! parseInt( control.params.flex_height, 10 ),
|
||||
realWidth = attachment.get( 'width' ),
|
||||
realHeight = attachment.get( 'height' ),
|
||||
xInit = parseInt( control.params.width, 10 ),
|
||||
yInit = parseInt( control.params.height, 10 ),
|
||||
ratio = xInit / yInit,
|
||||
xImg = realWidth,
|
||||
yImg = realHeight,
|
||||
imgSelectOptions;
|
||||
|
||||
controller.set( 'canSkipCrop', ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, 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,
|
||||
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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return whether the image must be cropped, based on required dimensions.
|
||||
*
|
||||
* @param {bool} flexW
|
||||
* @param {bool} flexH
|
||||
* @param {int} dstW
|
||||
* @param {int} dstH
|
||||
* @param {int} imgW
|
||||
* @param {int} imgH
|
||||
* @return {bool}
|
||||
*/
|
||||
mustBeCropped: function( flexW, flexH, dstW, dstH, imgW, imgH ) {
|
||||
if ( true === flexW && true === flexH ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( true === flexW && dstH === imgH ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( true === flexH && dstW === imgW ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( dstW === imgW && dstH === imgH ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( imgW <= dstW ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* If cropping was skipped, apply the image data directly to the setting.
|
||||
*/
|
||||
onSkippedCrop: function() {
|
||||
var attachment = this.frame.state().get( 'selection' ).first().toJSON();
|
||||
this.setImageFromAttachment( attachment );
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the setting and re-renders the control UI.
|
||||
*
|
||||
* @param {object} attachment
|
||||
*/
|
||||
setImageFromAttachment: function( attachment ) {
|
||||
this.params.attachment = attachment;
|
||||
|
||||
// Set the Customizer setting; the callback takes care of rendering.
|
||||
this.setting( attachment.id );
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* A control for selecting and cropping Site Icons.
|
||||
*
|
||||
* @class
|
||||
* @augments wp.customize.CroppedImageControl
|
||||
* @augments wp.customize.MediaControl
|
||||
* @augments wp.customize.Control
|
||||
* @augments wp.customize.Class
|
||||
*/
|
||||
api.SiteIconControl = api.CroppedImageControl.extend({
|
||||
/**
|
||||
* Updates the setting and re-renders the control UI.
|
||||
*
|
||||
* @param {object} attachment
|
||||
*/
|
||||
setImageFromAttachment: function( attachment ) {
|
||||
var icon = typeof attachment.sizes['site_icon-32'] !== 'undefined' ? attachment.sizes['site_icon-32'] : attachment.sizes.thumbnail;
|
||||
|
||||
this.params.attachment = attachment;
|
||||
|
||||
// Set the Customizer setting; the callback takes care of rendering.
|
||||
this.setting( attachment.id );
|
||||
|
||||
|
||||
// Update the icon in-browser.
|
||||
$( 'link[rel="icon"]' ).attr( 'href', icon.url );
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the "Remove" link is clicked. Empties the setting.
|
||||
*
|
||||
* @param {object} event jQuery Event object
|
||||
*/
|
||||
removeFile: function( event ) {
|
||||
if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
|
||||
this.params.attachment = {};
|
||||
this.setting( '' );
|
||||
this.renderContent(); // Not bound to setting change when emptying.
|
||||
$( 'link[rel="icon"]' ).attr( 'href', '' );
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @augments wp.customize.Control
|
||||
@@ -2695,13 +2934,15 @@
|
||||
});
|
||||
|
||||
api.controlConstructor = {
|
||||
color: api.ColorControl,
|
||||
media: api.MediaControl,
|
||||
upload: api.UploadControl,
|
||||
image: api.ImageControl,
|
||||
header: api.HeaderControl,
|
||||
background: api.BackgroundControl,
|
||||
theme: api.ThemeControl
|
||||
color: api.ColorControl,
|
||||
media: api.MediaControl,
|
||||
upload: api.UploadControl,
|
||||
image: api.ImageControl,
|
||||
cropped_image: api.CroppedImageControl,
|
||||
site_icon: api.SiteIconControl,
|
||||
header: api.HeaderControl,
|
||||
background: api.BackgroundControl,
|
||||
theme: api.ThemeControl
|
||||
};
|
||||
api.panelConstructor = {};
|
||||
api.sectionConstructor = {
|
||||
|
||||
Reference in New Issue
Block a user