Make WordPress Core

Changeset 33154


Ignore:
Timestamp:
07/10/2015 09:32:23 PM (11 years ago)
Author:
obenland
Message:

Site Icon: Add Customizer UI.

Second part of the Site Icon feature after [32994] introduced it for Settings.

Props celloexpressions.
See #16434.

Location:
trunk/src
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/admin-ajax.php

    r32677 r33154  
    6363        'save-user-color-scheme', 'update-widget', 'query-themes', 'parse-embed', 'set-attachment-thumbnail',
    6464        'parse-media-shortcode', 'destroy-sessions', 'install-plugin', 'update-plugin', 'press-this-save-post',
    65         'press-this-add-category',
     65        'press-this-add-category', 'crop-image',
    6666);
    6767
  • trunk/src/wp-admin/css/customize-controls.css

    r33153 r33154  
    752752.customize-control-image .current,
    753753.customize-control-background .current,
     754.customize-control-cropped_image .current,
     755.customize-control-site_icon .current,
    754756.customize-control-header .current {
    755757        margin-bottom: 8px;
    … …  
    787789.customize-control-background .default-button,
    788790.customize-control-background .upload-button,
     791.customize-control-cropped_image .remove-button,
     792.customize-control-cropped_image .default-button,
     793.customize-control-cropped_image .upload-button,
     794.customize-control-site_icon .remove-button,
     795.customize-control-site_icon .default-button,
     796.customize-control-site_icon .upload-button,
    789797.customize-control-header button.new,
    790798.customize-control-header button.remove {
    … …  
    798806.customize-control-image .current .container,
    799807.customize-control-background .current .container,
     808.customize-control-cropped_image .current .container,
     809.customize-control-site_icon .current .container,
    800810.customize-control-header .current .container {
    801811        overflow: hidden;
    … …  
    809819.customize-control-upload .current .container,
    810820.customize-control-background .current .container,
     821.customize-control-cropped_image .current .container,
     822.customize-control-site_icon .current .container,
    811823.customize-control-image .current .container {
    812824        min-height: 40px;
    … …  
    817829.customize-control-image .placeholder,
    818830.customize-control-background .placeholder,
     831.customize-control-cropped_image .placeholder,
     832.customize-control-site_icon .placeholder,
    819833.customize-control-header .placeholder {
    820834        width: 100%;
    … …  
    828842.customize-control-image .inner,
    829843.customize-control-background .inner,
     844.customize-control-cropped_image .inner,
     845.customize-control-site_icon .inner,
    830846.customize-control-header .inner {
    831847        display: none;
    … …  
    841857.customize-control-upload .inner,
    842858.customize-control-background .inner,
     859.customize-control-cropped_image .inner,
     860.customize-control-site_icon .inner,
    843861.customize-control-image .inner {
    844862        display: block;
    … …  
    850868.customize-control-image .inner,
    851869.customize-control-background .inner,
     870.customize-control-cropped_image .inner,
     871.customize-control-site_icon .inner,
    852872.customize-control-header .inner,
    853873.customize-control-header .inner .dashicons {
    … …  
    953973.customize-control-image .actions,
    954974.customize-control-background .actions,
     975.customize-control-cropped_image .actions,
     976.customize-control-site_icon .actions,
    955977.customize-control-header .actions {
    956978        margin-bottom: 32px;
    … …  
    971993.customize-control-image img,
    972994.customize-control-background img,
     995.customize-control-cropped_image img,
     996.customize-control-site_icon img,
    973997.customize-control-header img {
    974998        width: 100%;
    … …  
    9851009.customize-control-background .remove-button,
    9861010.customize-control-background .default-button,
     1011.customize-control-cropped_image .remove-button,
     1012.customize-control-cropped_image .default-button,
     1013.customize-control-site_icon .remove-button,
     1014.customize-control-site_icon .default-button,
    9871015.customize-control-header .remove {
    9881016        float: left;
    … …  
    9941022.customize-control-image .upload-button,
    9951023.customize-control-background .upload-button,
     1024.customize-control-cropped_image .upload-button,
     1025.customize-control-site_icon .upload-button,
    9961026.customize-control-header .new {
    9971027        float: right;
  • trunk/src/wp-admin/includes/ajax-actions.php

    r32965 r33154  
    30533053        $GLOBALS['wp_press_this']->add_category();
    30543054}
     3055
     3056/**
     3057 * AJAX handler for cropping an image.
     3058 *
     3059 * @since 4.3.0
     3060 *
     3061 * @global WP_Site_Icon $wp_site_icon
     3062 */
     3063function wp_ajax_crop_image() {
     3064        $attachment_id = absint( $_POST['id'] );
     3065
     3066        check_ajax_referer( 'image_editor-' . $attachment_id, 'nonce' );
     3067        if ( ! current_user_can( 'customize' ) ) {
     3068                wp_send_json_error();
     3069        }
     3070
     3071        $context = str_replace( '_', '-', $_POST['context'] );
     3072        $data    = array_map( 'absint', $_POST['cropDetails'] );
     3073        $cropped = wp_crop_image( $attachment_id, $data['x1'], $data['y1'], $data['width'], $data['height'], $data['dst_width'], $data['dst_height'] );
     3074
     3075        if ( ! $cropped || is_wp_error( $cropped ) ) {
     3076                wp_send_json_error( array( 'message' => __( 'Image could not be processed.' ) ) );
     3077        }
     3078
     3079        switch ( $context ) {
     3080                case 'site-icon':
     3081                        require_once ABSPATH . '/wp-admin/includes/class-wp-site-icon.php';
     3082                        global $wp_site_icon;
     3083
     3084                        /** This filter is documented in wp-admin/custom-header.php */
     3085                        $cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication.
     3086                        $object  = $wp_site_icon->create_attachment_object( $cropped, $attachment_id );
     3087                        unset( $object['ID'] );
     3088
     3089                        // Update the attachment.
     3090                        add_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );
     3091                        $attachment_id = $wp_site_icon->insert_attachment( $object, $cropped );
     3092                        remove_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );
     3093
     3094                        // Additional sizes in wp_prepare_attachment_for_js().
     3095                        add_filter( 'image_size_names_choose', array( $wp_site_icon, 'additional_sizes' ) );
     3096                        break;
     3097
     3098                default:
     3099
     3100                        /**
     3101                         * Filters the attachment id for a cropped image.
     3102                         *
     3103                         * @since 4.3.0
     3104                         *
     3105                         * @param int    $attachment_id The ID of the cropped image.
     3106                         * @param string $context       The feature requesting the cropped image.
     3107                         */
     3108                        $attachment_id = apply_filters( 'wp_ajax_cropped_attachment_id', 0, $context );
     3109
     3110                        if ( ! $attachment_id ) {
     3111                                wp_send_json_error();
     3112                        }
     3113        }
     3114
     3115        wp_send_json_success( wp_prepare_attachment_for_js( $attachment_id ) );
     3116}
  • trunk/src/wp-admin/includes/class-wp-site-icon.php

    r33084 r33154  
    275275                                        <div class="site-icon-crop-preview-shell hide-if-no-js">
    276276                                                <h3><?php _e( 'Preview' ); ?></h3>
    277                                                 <strong><?php _e( 'As your favicon' ); ?></strong>
     277                                                <strong><?php _e( 'As a browser icon' ); ?></strong>
    278278                                                <div class="site-icon-crop-favicon-preview-shell">
    279279                                                        <img src="images/browser.png" class="site-icon-browser-preview" width="182" height="" alt="<?php esc_attr_e( 'Browser Chrome' ); ?>"/>
    … …  
    285285                                                </div>
    286286
    287                                                 <strong><?php _e( 'As a mobile icon' ); ?></strong>
     287                                                <strong><?php _e( 'As an app icon' ); ?></strong>
    288288                                                <div class="site-icon-crop-preview-homeicon">
    289289                                                        <img src="<?php echo esc_url( $url ); ?>" id="preview-homeicon" alt="<?php esc_attr_e( 'Preview Home Icon' ); ?>"/>
    … …  
    506506                // ensure that we only resize the image into
    507507                foreach ( $sizes as $name => $size_array ) {
    508                         if ( $size_array['crop'] ) {
     508                        if ( isset( $size_array['crop'] ) ) {
    509509                                $only_crop_sizes[ $name ] = $size_array;
    510510                        }
  • trunk/src/wp-admin/js/customize-controls.js

    r33153 r33154  
    18371837
    18381838        /**
     1839         * A control for selecting and cropping an image.
     1840         *
     1841         * @class
     1842         * @augments wp.customize.MediaControl
     1843         * @augments wp.customize.Control
     1844         * @augments wp.customize.Class
     1845         */
     1846        api.CroppedImageControl = api.MediaControl.extend({
     1847
     1848                /**
     1849                 * Open the media modal to the library state.
     1850                 */
     1851                openFrame: function( event ) {
     1852                        if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
     1853                                return;
     1854                        }
     1855
     1856                        this.initFrame();
     1857                        this.frame.setState( 'library' ).open();
     1858                },
     1859
     1860                /**
     1861                 * Create a media modal select frame, and store it so the instance can be reused when needed.
     1862                 */
     1863                initFrame: function() {
     1864                        var l10n = _wpMediaViewsL10n;
     1865
     1866                        this.frame = wp.media({
     1867                                button: {
     1868                                        text: l10n.select,
     1869                                        close: false
     1870                                },
     1871                                states: [
     1872                                        new wp.media.controller.Library({
     1873                                                title: this.params.button_labels.frame_title,
     1874                                                library: wp.media.query({ type: 'image' }),
     1875                                                multiple: false,
     1876                                                date: false,
     1877                                                priority: 20,
     1878                                                suggestedWidth: this.params.width,
     1879                                                suggestedHeight: this.params.height
     1880                                        }),
     1881                                        new wp.media.controller.customizeImageCropper({
     1882                                                imgSelectOptions: this.calculateImageSelectOptions,
     1883                                                control: this
     1884                                        })
     1885                                ]
     1886                        });
     1887
     1888                        this.frame.on( 'select', this.onSelect, this );
     1889                        this.frame.on( 'cropped', this.onCropped, this );
     1890                        this.frame.on( 'skippedcrop', this.onSkippedCrop, this );
     1891                },
     1892
     1893                /**
     1894                 * After an image is selected in the media modal, switch to the cropper
     1895                 * state if the image isn't the right size.
     1896                 */
     1897                onSelect: function() {
     1898                        var attachment = this.frame.state().get( 'selection' ).first().toJSON();
     1899
     1900                        if ( this.params.width === attachment.width && this.params.height === attachment.height && ! this.params.flex_width && ! this.params.flex_height ) {
     1901                                this.setImageFromAttachment( attachment );
     1902                                this.frame.close();
     1903                        } else {
     1904                                this.frame.setState( 'cropper' );
     1905                        }
     1906                },
     1907
     1908                /**
     1909                 * After the image has been cropped, apply the cropped image data to the setting.
     1910                 *
     1911                 * @param {object} croppedImage Cropped attachment data.
     1912                 */
     1913                onCropped: function( croppedImage ) {
     1914                        this.setImageFromAttachment( croppedImage );
     1915                },
     1916
     1917                /**
     1918                 * Returns a set of options, computed from the attached image data and
     1919                 * control-specific data, to be fed to the imgAreaSelect plugin in
     1920                 * wp.media.view.Cropper.
     1921                 *
     1922                 * @param {wp.media.model.Attachment} attachment
     1923                 * @param {wp.media.controller.Cropper} controller
     1924                 * @returns {Object} Options
     1925                 */
     1926                calculateImageSelectOptions: function( attachment, controller ) {
     1927                        var control    = controller.get( 'control' ),
     1928                                flexWidth  = !! parseInt( control.params.flex_width, 10 ),
     1929                                flexHeight = !! parseInt( control.params.flex_height, 10 ),
     1930                                realWidth  = attachment.get( 'width' ),
     1931                                realHeight = attachment.get( 'height' ),
     1932                                xInit = parseInt( control.params.width, 10 ),
     1933                                yInit = parseInt( control.params.height, 10 ),
     1934                                ratio = xInit / yInit,
     1935                                xImg  = realWidth,
     1936                                yImg  = realHeight,
     1937                                imgSelectOptions;
     1938
     1939                        controller.set( 'canSkipCrop', ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, realHeight ) );
     1940
     1941                        if ( xImg / yImg > ratio ) {
     1942                                yInit = yImg;
     1943                                xInit = yInit * ratio;
     1944                        } else {
     1945                                xInit = xImg;
     1946                                yInit = xInit / ratio;
     1947                        }
     1948
     1949                        imgSelectOptions = {
     1950                                handles: true,
     1951                                keys: true,
     1952                                instance: true,
     1953                                persistent: true,
     1954                                imageWidth: realWidth,
     1955                                imageHeight: realHeight,
     1956                                x1: 0,
     1957                                y1: 0,
     1958                                x2: xInit,
     1959                                y2: yInit
     1960                        };
     1961
     1962                        if ( flexHeight === false && flexWidth === false ) {
     1963                                imgSelectOptions.aspectRatio = xInit + ':' + yInit;
     1964                        }
     1965                        if ( flexHeight === false ) {
     1966                                imgSelectOptions.maxHeight = yInit;
     1967                        }
     1968                        if ( flexWidth === false ) {
     1969                                imgSelectOptions.maxWidth = xInit;
     1970                        }
     1971
     1972                        return imgSelectOptions;
     1973                },
     1974
     1975                /**
     1976                 * Return whether the image must be cropped, based on required dimensions.
     1977                 *
     1978                 * @param {bool} flexW
     1979                 * @param {bool} flexH
     1980                 * @param {int}  dstW
     1981                 * @param {int}  dstH
     1982                 * @param {int}  imgW
     1983                 * @param {int}  imgH
     1984                 * @return {bool}
     1985                 */
     1986                mustBeCropped: function( flexW, flexH, dstW, dstH, imgW, imgH ) {
     1987                        if ( true === flexW && true === flexH ) {
     1988                                return false;
     1989                        }
     1990
     1991                        if ( true === flexW && dstH === imgH ) {
     1992                                return false;
     1993                        }
     1994
     1995                        if ( true === flexH && dstW === imgW ) {
     1996                                return false;
     1997                        }
     1998
     1999                        if ( dstW === imgW && dstH === imgH ) {
     2000                                return false;
     2001                        }
     2002
     2003                        if ( imgW <= dstW ) {
     2004                                return false;
     2005                        }
     2006
     2007                        return true;
     2008                },
     2009
     2010                /**
     2011                 * If cropping was skipped, apply the image data directly to the setting.
     2012                 */
     2013                onSkippedCrop: function() {
     2014                        var attachment = this.frame.state().get( 'selection' ).first().toJSON();
     2015                        this.setImageFromAttachment( attachment );
     2016                },
     2017
     2018                /**
     2019                 * Updates the setting and re-renders the control UI.
     2020                 *
     2021                 * @param {object} attachment
     2022                 */
     2023                setImageFromAttachment: function( attachment ) {
     2024                        this.params.attachment = attachment;
     2025
     2026                        // Set the Customizer setting; the callback takes care of rendering.
     2027                        this.setting( attachment.id );
     2028                }
     2029        });
     2030
     2031        /**
     2032         * A control for selecting and cropping Site Icons.
     2033         *
     2034         * @class
     2035         * @augments wp.customize.CroppedImageControl
     2036         * @augments wp.customize.MediaControl
     2037         * @augments wp.customize.Control
     2038         * @augments wp.customize.Class
     2039         */
     2040        api.SiteIconControl = api.CroppedImageControl.extend({
     2041                /**
     2042                 * Updates the setting and re-renders the control UI.
     2043                 *
     2044                 * @param {object} attachment
     2045                 */
     2046                setImageFromAttachment: function( attachment ) {
     2047                        var icon = typeof attachment.sizes['site_icon-32'] !== 'undefined' ? attachment.sizes['site_icon-32'] : attachment.sizes.thumbnail;
     2048
     2049                        this.params.attachment = attachment;
     2050
     2051                        // Set the Customizer setting; the callback takes care of rendering.
     2052                        this.setting( attachment.id );
     2053
     2054
     2055                        // Update the icon in-browser.
     2056                        $( 'link[rel="icon"]' ).attr( 'href', icon.url );
     2057                },
     2058
     2059                /**
     2060                 * Called when the "Remove" link is clicked. Empties the setting.
     2061                 *
     2062                 * @param {object} event jQuery Event object
     2063                 */
     2064                removeFile: function( event ) {
     2065                        if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
     2066                                return;
     2067                        }
     2068                        event.preventDefault();
     2069
     2070                        this.params.attachment = {};
     2071                        this.setting( '' );
     2072                        this.renderContent(); // Not bound to setting change when emptying.
     2073                        $( 'link[rel="icon"]' ).attr( 'href', '' );
     2074                }
     2075        });
     2076
     2077        /**
    18392078         * @class
    18402079         * @augments wp.customize.Control
    … …  
    26962935
    26972936        api.controlConstructor = {
    2698                 color:      api.ColorControl,
    2699                 media:      api.MediaControl,
    2700                 upload:     api.UploadControl,
    2701                 image:      api.ImageControl,
    2702                 header:     api.HeaderControl,
    2703                 background: api.BackgroundControl,
    2704                 theme:      api.ThemeControl
     2937                color:         api.ColorControl,
     2938                media:         api.MediaControl,
     2939                upload:        api.UploadControl,
     2940                image:         api.ImageControl,
     2941                cropped_image: api.CroppedImageControl,
     2942                site_icon:     api.SiteIconControl,
     2943                header:        api.HeaderControl,
     2944                background:    api.BackgroundControl,
     2945                theme:         api.ThemeControl
    27052946        };
    27062947        api.panelConstructor = {};
  • trunk/src/wp-admin/options-general.php

    r33075 r33154  
    164164
    165165        <?php endif; ?>
    166         <p class="description"><?php _e( 'Site Icon creates a favicon and app icons for your site.' ) ?></p>
     166        <p class="description"><?php _e( 'The Site Icon is used as a browser and app icon for your site.' ); ?></p>
    167167</td>
    168168</tr>
  • trunk/src/wp-includes/class-wp-customize-control.php

    r33090 r33154  
    10021002
    10031003/**
     1004 * Customize Cropped Image Control class.
     1005 *
     1006 * @since 4.3.0
     1007 *
     1008 * @see WP_Customize_Image_Control
     1009 */
     1010class WP_Customize_Cropped_Image_Control extends WP_Customize_Image_Control {
     1011
     1012        /**
     1013         * Control type.
     1014         *
     1015         * @since 4.3.0
     1016         *
     1017         * @access public
     1018         * @var string
     1019         */
     1020        public $type = 'cropped_image';
     1021
     1022        /**
     1023         * Suggested width for cropped image.
     1024         *
     1025         * @since 4.3.0
     1026         *
     1027         * @access public
     1028         * @var int
     1029         */
     1030        public $width = 150;
     1031
     1032        /**
     1033         * Suggested height for cropped image.
     1034         *
     1035         * @since 4.3.0
     1036         *
     1037         * @access public
     1038         * @var int
     1039         */
     1040        public $height = 150;
     1041
     1042        /**
     1043         * Whether the width is flexible.
     1044         *
     1045         * @since 4.3.0
     1046         *
     1047         * @access public
     1048         * @var bool
     1049         */
     1050        public $flex_width = false;
     1051
     1052        /**
     1053         * Whether the height is flexible.
     1054         *
     1055         * @since 4.3.0
     1056         *
     1057         * @access public
     1058         * @var bool
     1059         */
     1060        public $flex_height = false;
     1061
     1062        /**
     1063         * Enqueue control related scripts/styles.
     1064         *
     1065         * @since 4.3.0
     1066         *
     1067         * @access public
     1068         */
     1069        public function enqueue() {
     1070                wp_enqueue_script( 'customize-views' );
     1071
     1072                parent::enqueue();
     1073        }
     1074
     1075        /**
     1076         * Refresh the parameters passed to the JavaScript via JSON.
     1077         *
     1078         * @since 4.3.0
     1079         *
     1080         * @access public
     1081         * @uses WP_Customize_Image_Control::to_json()
     1082         * @see WP_Customize_Control::to_json()
     1083         */
     1084        public function to_json() {
     1085                parent::to_json();
     1086
     1087                $this->json['width']       = absint( $this->width );
     1088                $this->json['height']      = absint( $this->height );
     1089                $this->json['flex_width']  = absint( $this->flex_width );
     1090                $this->json['flex_height'] = absint( $this->flex_height );
     1091        }
     1092
     1093}
     1094
     1095/**
     1096 * Customize Site Icon control class.
     1097 *
     1098 * Used only for custom functionality in JavaScript.
     1099 *
     1100 * @since 4.3.0
     1101 *
     1102 * @see WP_Customize_Cropped_Image_Control
     1103 */
     1104class WP_Customize_Site_Icon_Control extends WP_Customize_Cropped_Image_Control {
     1105
     1106        /**
     1107         * Control type.
     1108         *
     1109         * @since 4.3.0
     1110         *
     1111         * @access public
     1112         * @var string
     1113         */
     1114        public $type = 'site_icon';
     1115
     1116        /**
     1117         * Constructor.
     1118         *
     1119         * @since 4.3.0
     1120         *
     1121         * @param WP_Customize_Manager $manager
     1122         * @param string               $id
     1123         * @param array                $args
     1124         */
     1125        public function __construct( $manager, $id, $args = array() ) {
     1126                parent::__construct( $manager, $id, $args );
     1127                add_action( 'customize_controls_print_styles', 'wp_site_icon', 99 );
     1128        }
     1129}
     1130
     1131/**
    10041132 * Customize Header Image Control class.
    10051133 *
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r32964 r33154  
    12791279                $this->register_control_type( 'WP_Customize_Image_Control' );
    12801280                $this->register_control_type( 'WP_Customize_Background_Image_Control' );
     1281                $this->register_control_type( 'WP_Customize_Cropped_Image_Control' );
     1282                $this->register_control_type( 'WP_Customize_Site_Icon_Control' );
    12811283                $this->register_control_type( 'WP_Customize_Theme_Control' );
    12821284
    … …  
    13251327                }
    13261328
    1327                 /* Site Title & Tagline */
     1329                /* Site Identity */
    13281330
    13291331                $this->add_section( 'title_tagline', array(
    1330                         'title'    => __( 'Site Title & Tagline' ),
     1332                        'title'    => __( 'Site Identity' ),
    13311333                        'priority' => 20,
    13321334                ) );
    … …  
    13531355                        'section'    => 'title_tagline',
    13541356                ) );
     1357
     1358                $icon = wp_get_attachment_image_src( absint( get_option( 'site_icon' ) ), 'full' );
     1359                $this->add_setting( 'site_icon', array(
     1360                        'default'    => $icon[0] ? $icon[0] : '',
     1361                        'type'       => 'option',
     1362                        'capability' => 'manage_options',
     1363                        'transport'  => 'postMessage', // Previewed with JS in the Customizer controls window.
     1364                ) );
     1365
     1366                $this->add_control( new WP_Customize_Site_Icon_Control( $this, 'site_icon', array(
     1367                        'label'       => __( 'Site Icon' ),
     1368                        'description' => __( 'The Site Icon is used as a browser and app icon for your site. Icons must be square, and at least 512px wide and tall.' ),
     1369                        'section'     => 'title_tagline',
     1370                        'priority'    => 60,
     1371                        'height'      => 512,
     1372                        'width'       => 512,
     1373                ) ) );
    13551374
    13561375                /* Colors */
    … …  
    13761395                        'section'  => 'title_tagline',
    13771396                        'type'     => 'checkbox',
     1397                        'priority' => 40,
    13781398                ) );
    13791399
  • trunk/src/wp-includes/general-template.php

    r32994 r33154  
    24462446 */
    24472447function wp_site_icon() {
    2448         if ( ! has_site_icon() ) {
     2448        if ( ! has_site_icon() && ! is_customize_preview() ) {
    24492449                return;
    24502450        }
  • trunk/src/wp-includes/js/customize-views.js

    r31471 r33154  
    44        var api = wp.customize;
    55
     6        /**
     7         * Use a custom ajax action for cropped image controls.
     8         */
     9        wp.media.controller.customizeImageCropper = wp.media.controller.Cropper.extend( {
     10                doCrop: function( attachment ) {
     11                        var cropDetails = attachment.get( 'cropDetails' ),
     12                                control = this.get( 'control' );
     13
     14                        cropDetails.dst_width  = control.params.width;
     15                        cropDetails.dst_height = control.params.height;
     16
     17                        return wp.ajax.post( 'crop-image', {
     18                                wp_customize: 'on',
     19                                nonce: attachment.get( 'nonces' ).edit,
     20                                id: attachment.get( 'id' ),
     21                                context: control.id,
     22                                cropDetails: cropDetails
     23                        } );
     24                }
     25        } );
    626
    727        /**
Note: See TracChangeset for help on using the changeset viewer.