Make WordPress Core

Ticket #16434: 16434.16.diff

File 16434.16.diff, 21.7 KB (added by obenland, 9 years ago)
  • src/wp-admin/admin-ajax.php

     
    6262        'send-attachment-to-editor', 'save-attachment-order', 'heartbeat', 'get-revision-diffs',
    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
    6868// Deprecated
  • src/wp-admin/css/customize-controls.css

     
    771771.customize-control-upload .current,
    772772.customize-control-image .current,
    773773.customize-control-background .current,
     774.customize-control-cropped_image .current,
     775.customize-control-site_icon .current,
    774776.customize-control-header .current {
    775777        margin-bottom: 8px;
    776778}
     
    806808.customize-control-background .remove-button,
    807809.customize-control-background .default-button,
    808810.customize-control-background .upload-button,
     811.customize-control-cropped_image .remove-button,
     812.customize-control-cropped_image .default-button,
     813.customize-control-cropped_image .upload-button,
     814.customize-control-site_icon .remove-button,
     815.customize-control-site_icon .default-button,
     816.customize-control-site_icon .upload-button,
    809817.customize-control-header button.new,
    810818.customize-control-header button.remove {
    811819        white-space: normal;
     
    817825.customize-control-upload .current .container,
    818826.customize-control-image .current .container,
    819827.customize-control-background .current .container,
     828.customize-control-cropped_image .current .container,
     829.customize-control-site_icon .current .container,
    820830.customize-control-header .current .container {
    821831        overflow: hidden;
    822832        -webkit-border-radius: 2px;
     
    828838.customize-control-media .current .container,
    829839.customize-control-upload .current .container,
    830840.customize-control-background .current .container,
     841.customize-control-cropped_image .current .container,
     842.customize-control-site_icon .current .container,
    831843.customize-control-image .current .container {
    832844        min-height: 40px;
    833845}
     
    836848.customize-control-upload .placeholder,
    837849.customize-control-image .placeholder,
    838850.customize-control-background .placeholder,
     851.customize-control-cropped_image .placeholder,
     852.customize-control-site_icon .placeholder,
    839853.customize-control-header .placeholder {
    840854        width: 100%;
    841855        position: relative;
     
    847861.customize-control-upload .inner,
    848862.customize-control-image .inner,
    849863.customize-control-background .inner,
     864.customize-control-cropped_image .inner,
     865.customize-control-site_icon .inner,
    850866.customize-control-header .inner {
    851867        display: none;
    852868        position: absolute;
     
    860876.customize-control-media .inner,
    861877.customize-control-upload .inner,
    862878.customize-control-background .inner,
     879.customize-control-cropped_image .inner,
     880.customize-control-site_icon .inner,
    863881.customize-control-image .inner {
    864882        display: block;
    865883        min-height: 40px;
     
    869887.customize-control-upload .inner,
    870888.customize-control-image .inner,
    871889.customize-control-background .inner,
     890.customize-control-cropped_image .inner,
     891.customize-control-site_icon .inner,
    872892.customize-control-header .inner,
    873893.customize-control-header .inner .dashicons {
    874894        line-height: 20px;
     
    972992.customize-control-upload .actions,
    973993.customize-control-image .actions,
    974994.customize-control-background .actions,
     995.customize-control-cropped_image .actions,
     996.customize-control-site_icon .actions,
    975997.customize-control-header .actions {
    976998        margin-bottom: 32px;
    977999}
     
    9901012.customize-control-upload img,
    9911013.customize-control-image img,
    9921014.customize-control-background img,
     1015.customize-control-cropped_image img,
     1016.customize-control-site_icon img,
    9931017.customize-control-header img {
    9941018        width: 100%;
    9951019        -webkit-border-radius: 2px;
     
    10041028.customize-control-image .default-button,
    10051029.customize-control-background .remove-button,
    10061030.customize-control-background .default-button,
     1031.customize-control-cropped_image .remove-button,
     1032.customize-control-cropped_image .default-button,
     1033.customize-control-site_icon .remove-button,
     1034.customize-control-site_icon .default-button,
    10071035.customize-control-header .remove {
    10081036        float: left;
    10091037        margin-right: 3px;
     
    10131041.customize-control-upload .upload-button,
    10141042.customize-control-image .upload-button,
    10151043.customize-control-background .upload-button,
     1044.customize-control-cropped_image .upload-button,
     1045.customize-control-site_icon .upload-button,
    10161046.customize-control-header .new {
    10171047        float: right;
    10181048}
  • src/wp-admin/includes/ajax-actions.php

     
    30523052
    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 = $_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                        add_filter( 'image_size_names_choose', array( $wp_site_icon, 'additional_sizes' ) );
     3095                        break;
     3096
     3097                default:
     3098
     3099                        /**
     3100                         * Filters the attachment id for a cropped image.
     3101                         *
     3102                         * @since 4.3.0
     3103                         *
     3104                         * @param int    $attachment_id The ID of the cropped image.
     3105                         * @param string $context       The feature requesting the cropped image.
     3106                         */
     3107                        $attachment_id = apply_filters( 'wp_ajax_cropped_attachment_id', 0, $context );
     3108        }
     3109
     3110        if ( ! $attachment_id ) {
     3111                wp_send_json_error();
     3112        }
     3113
     3114        wp_send_json_success( wp_prepare_attachment_for_js( $attachment_id ) );
     3115}
  • src/wp-admin/includes/class-wp-site-icon.php

     
    274274
    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' ); ?>"/>
    280280
     
    284284                                                        <span class="site-icon-browser-title"><?php bloginfo( 'name' ); ?></span>
    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' ); ?>"/>
    290290                                                </div>
     
    505505
    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                        }
    511511                }
  • src/wp-admin/js/customize-controls.js

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

     
    163163        <a class="button hide-if-js" href="<?php echo esc_url( $upload_url ); ?>"><?php _e( 'Add a Site Icon' ); ?></a>
    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>
    169169<?php if ( !is_multisite() ) { ?>
  • src/wp-includes/class-wp-customize-control.php

     
    10011001}
    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         * @access public
     1014         * @var string
     1015         */
     1016        public $type = 'cropped_image';
     1017
     1018        /**
     1019         * @access public
     1020         * @var int
     1021         */
     1022        public $width = 150;
     1023
     1024        /**
     1025         * @access public
     1026         * @var int
     1027         */
     1028        public $height = 150;
     1029
     1030        /**
     1031         * @access public
     1032         * @var bool
     1033         */
     1034        public $flex_width = false;
     1035
     1036        /**
     1037         * @access public
     1038         * @var bool
     1039         */
     1040        public $flex_height = false;
     1041
     1042        /**
     1043         * Enqueue control related scripts/styles.
     1044         *
     1045         * @access public
     1046         */
     1047        public function enqueue() {
     1048                wp_enqueue_script( 'customize-views' );
     1049
     1050                parent::enqueue();
     1051        }
     1052
     1053        /**
     1054         * Refresh the parameters passed to the JavaScript via JSON.
     1055         *
     1056         * @since 4.3.0
     1057         * @access public
     1058         * @uses WP_Customize_Image_Control::to_json()
     1059         *
     1060         * @see WP_Customize_Control::to_json()
     1061         */
     1062        public function to_json() {
     1063                parent::to_json();
     1064
     1065                $this->json['width']       = absint( $this->width );
     1066                $this->json['height']      = absint( $this->height );
     1067                $this->json['flex_width']  = absint( $this->flex_width );
     1068                $this->json['flex_height'] = absint( $this->flex_height );
     1069        }
     1070
     1071}
     1072
     1073/**
     1074 * Customize Site Icon control class.
     1075 *
     1076 * Used only for custom functionality in JavaScript.
     1077 *
     1078 * @since 4.3.0
     1079 *
     1080 * @see WP_Customize_Cropped_Image_Control
     1081 */
     1082class WP_Customize_Site_Icon_Control extends WP_Customize_Cropped_Image_Control {
     1083
     1084        /**
     1085         * @access public
     1086         * @var string
     1087         */
     1088        public $type = 'site_icon';
     1089
     1090        /**
     1091         * Constructor.
     1092         *
     1093         * @since 4.3.0
     1094         *
     1095         * @param WP_Customize_Manager $manager
     1096         * @param string               $id
     1097         * @param array                $args
     1098         */
     1099        public function __construct( $manager, $id, $args = array() ) {
     1100                parent::__construct( $manager, $id, $args );
     1101                add_action( 'customize_controls_print_styles', 'wp_site_icon', 99 );
     1102        }
     1103}
     1104
     1105/**
    10041106 * Customize Header Image Control class.
    10051107 *
    10061108 * @since 3.4.0
  • src/wp-includes/class-wp-customize-manager.php

     
    12781278                $this->register_control_type( 'WP_Customize_Upload_Control' );
    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
    12831285                /* Themes */
     
    13241326                        ) ) );
    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                ) );
    13331335
     
    13531355                        'section'    => 'title_tagline',
    13541356                ) );
    13551357
     1358                $icon = wp_get_attachment_image_src( absint( get_option( 'site_icon' ) ), 'medium' );
     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                ) ) );
     1374
    13561375                /* Colors */
    13571376
    13581377                $this->add_section( 'colors', array(
     
    13751394                        'label'    => __( 'Display Header Text' ),
    13761395                        'section'  => 'title_tagline',
    13771396                        'type'     => 'checkbox',
     1397                        'priority' => 40,
    13781398                ) );
    13791399
    13801400                $this->add_control( new WP_Customize_Color_Control( $this, 'header_textcolor', array(
  • src/wp-includes/general-template.php

     
    24452445 * @link http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#rel-icon HTML5 specification link icon.
    24462446 */
    24472447function wp_site_icon() {
    2448         if ( ! has_site_icon() ) {
     2448        if ( ! has_site_icon() && ! is_customize_preview() ) {
    24492449                return;
    24502450        }
    24512451
  • src/wp-includes/js/customize-views.js

     
    33        if ( ! wp || ! wp.customize ) { return; }
    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.params.type,
     22                                cropDetails: cropDetails
     23                        } );
     24                }
     25        } );
    626
    727        /**
    828         * wp.customize.HeaderTool.CurrentView