Ticket #21811: trac-21811-extensible-image-editor.patch
File trac-21811-extensible-image-editor.patch, 58.5 KB (added by , 11 years ago) |
---|
-
wp-admin/edit-form-advanced.php
135 135 if ( 'attachment' == $post_type ) { 136 136 wp_enqueue_script( 'image-edit' ); 137 137 wp_enqueue_style( 'imgareaselect' ); 138 139 /** 140 * Allows plugin and theme developers to hook in their own enqueued scripts and styles to be used 141 * exclusively in the Image Editor 142 */ 143 do_action( 'enqueue_image_editor_scripts' ); 144 138 145 add_meta_box( 'submitdiv', __('Save'), 'attachment_submit_meta_box', null, 'side', 'core' ); 139 146 add_action( 'edit_form_after_title', 'edit_form_image_editor' ); 140 147 } else { -
wp-admin/includes/image-edit.php
6 6 * @subpackage Administration 7 7 */ 8 8 9 $image_editor_groups = array(); 10 11 /** 12 * @uses do_action( 'add_image_editor_groups' ) to allow plugins / themes to register / unregister image editor groups 13 * @uses apply_filters( 'image_editor_groups' ) to allow direct filtering of the $image_editor_groups global array 14 * 15 * @global array $image_editor_groups 16 * @param type $post_id 17 * @param type $msg 18 */ 9 19 function wp_image_editor($post_id, $msg = false) { 10 20 $nonce = wp_create_nonce("image_editor-$post_id"); 11 21 $meta = wp_get_attachment_metadata($post_id); … … 13 23 $sub_sizes = isset($meta['sizes']) && is_array($meta['sizes']); 14 24 $note = ''; 15 25 26 if ( $thumb && $sub_sizes ) { 27 $thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 ); 28 29 add_image_edit_group ( 30 'thumbnail-settings', 31 __( 'Thumbnail Settings' ), 32 'imgedit_group_thumbnail_settings', 33 'default', 34 __('The thumbnail image can be cropped differently. For example it can be square or contain only a portion of the original image to showcase it better. Here you can select whether to apply changes to all image sizes or make the thumbnail different.'), 35 'imgedit-applyto', 36 compact( 'thumb', 'thumb_img', 'sub_sizes' ) 37 ); 38 } 39 40 add_image_edit_group( 41 'image-scale', 42 __( 'Scale Image' ), 43 'imgedit_group_scale_image', 44 'default', 45 __( 'You can proportionally scale the original image. For best results the scaling should be done before performing any other operations on it like crop, rotate, etc. Note that images can only be scaled down, not up.' ), 46 '', 47 compact( 'meta' ) 48 ); 49 50 51 add_image_edit_group( 52 'image-crop', 53 __( 'Crop Image' ), 54 'imgedit_group_crop_image', 55 'default', 56 sprintf( 57 '<p>%1$s</p><p><strong>%2$s</strong><br />%3$s</p><p><strong>%4s</strong><br />%5$s</p>', 58 __('The image can be cropped by clicking on it and dragging to select the desired part. While dragging the dimensions of the selection are displayed below.'), 59 __('Crop Aspect Ratio'), 60 __('You can specify the crop selection aspect ratio then hold down the Shift key while dragging to lock it. The values can be 1:1 (square), 4:3, 16:9, etc. If there is a selection, specifying aspect ratio will set it immediately.'), 61 __('Crop Selection'), 62 __('Once started, the selection can be adjusted by entering new values (in pixels). Note that these values are scaled to approximately match the original image dimensions. The minimum selection size equals the thumbnail size as set in the Media settings.') 63 ) 64 ); 65 16 66 if ( isset( $meta['width'], $meta['height'] ) ) 17 67 $big = max( $meta['width'], $meta['height'] ); 18 68 else … … 25 75 if ( ! empty( $backup_sizes ) && isset( $backup_sizes['full-orig'], $meta['file'] ) ) 26 76 $can_restore = $backup_sizes['full-orig']['file'] != basename( $meta['file'] ); 27 77 78 if ( $can_restore ) { 79 add_image_edit_group( 80 'image-restore', 81 __( 'Restore Original Image'), 82 'imgedit_group_restore_image', 83 'default', 84 __('Discard any changes and restore the original image.'), 85 '' 86 ); 87 } 88 89 28 90 if ( $msg ) { 29 91 if ( isset($msg->error) ) 30 92 $note = "<div class='error'><p>$msg->error</p></div>"; … … 35 97 ?> 36 98 <div class="imgedit-wrap"> 37 99 <?php echo $note; ?> 38 <table id="imgedit-panel-<?php echo $post_id; ?>"><tbody>39 <tr><td>40 <div class="imgedit-menu">41 <div onclick="imageEdit.crop(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-crop disabled" title="<?php esc_attr_e( 'Crop' ); ?>"></div><?php100 <table id="imgedit-panel-<?php echo $post_id; ?>"><tbody> 101 <tr><td> 102 <div class="imgedit-menu"> 103 <div onclick="imageEdit.crop(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-crop disabled" title="<?php esc_attr_e( 'Crop' ); ?>"></div><?php 42 104 43 // On some setups GD library does not provide imagerotate() - Ticket #1153644 if ( wp_image_editor_supports( array( 'mime_type' => get_post_mime_type( $post_id ), 'methods' => array( 'rotate' ) ) ) ) { ?>45 <div class="imgedit-rleft" onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate counter-clockwise' ); ?>"></div>46 <div class="imgedit-rright" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate clockwise' ); ?>"></div>47 <?php } else {48 $note_no_rotate = esc_attr__('Image rotation is not supported by your web host.');49 ?>50 51 52 <?php } ?>105 // On some setups GD library does not provide imagerotate() - Ticket #11536 106 if ( wp_image_editor_supports( array( 'mime_type' => get_post_mime_type( $post_id ), 'methods' => array( 'rotate' ) ) ) ) { ?> 107 <div class="imgedit-rleft" onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate counter-clockwise' ); ?>"></div> 108 <div class="imgedit-rright" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate clockwise' ); ?>"></div> 109 <?php } else { 110 $note_no_rotate = esc_attr__('Image rotation is not supported by your web host.'); 111 ?> 112 <div class="imgedit-rleft disabled" title="<?php echo $note_no_rotate; ?>"></div> 113 <div class="imgedit-rright disabled" title="<?php echo $note_no_rotate; ?>"></div> 114 <?php } ?> 53 115 54 <div onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv" title="<?php esc_attr_e( 'Flip vertically' ); ?>"></div>55 <div onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph" title="<?php esc_attr_e( 'Flip horizontally' ); ?>"></div>116 <div onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv" title="<?php esc_attr_e( 'Flip vertically' ); ?>"></div> 117 <div onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph" title="<?php esc_attr_e( 'Flip horizontally' ); ?>"></div> 56 118 57 <div id="image-undo-<?php echo $post_id; ?>" onclick="imageEdit.undo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-undo disabled" title="<?php esc_attr_e( 'Undo' ); ?>"></div>58 <div id="image-redo-<?php echo $post_id; ?>" onclick="imageEdit.redo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-redo disabled" title="<?php esc_attr_e( 'Redo' ); ?>"></div>59 <br class="clear" />60 </div>119 <div id="image-undo-<?php echo $post_id; ?>" onclick="imageEdit.undo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-undo disabled" title="<?php esc_attr_e( 'Undo' ); ?>"></div> 120 <div id="image-redo-<?php echo $post_id; ?>" onclick="imageEdit.redo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-redo disabled" title="<?php esc_attr_e( 'Redo' ); ?>"></div> 121 <br class="clear" /> 122 </div> 61 123 62 <input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />63 <input type="hidden" id="imgedit-minthumb-<?php echo $post_id; ?>" value="<?php echo ( get_option('thumbnail_size_w') . ':' . get_option('thumbnail_size_h') ); ?>" />64 <input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />65 <input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />66 <input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />67 <input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />68 <input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />124 <input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" /> 125 <input type="hidden" id="imgedit-minthumb-<?php echo $post_id; ?>" value="<?php echo ( get_option('thumbnail_size_w') . ':' . get_option('thumbnail_size_h') ); ?>" /> 126 <input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" /> 127 <input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" /> 128 <input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" /> 129 <input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" /> 130 <input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" /> 69 131 70 <div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">71 <img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')" src="<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>?action=imgedit-preview&_ajax_nonce=<?php echo $nonce; ?>&postid=<?php echo $post_id; ?>&rand=<?php echo rand(1, 99999); ?>" />72 </div>132 <div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap"> 133 <img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')" src="<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>?action=imgedit-preview&_ajax_nonce=<?php echo $nonce; ?>&postid=<?php echo $post_id; ?>&rand=<?php echo rand(1, 99999); ?>" /> 134 </div> 73 135 74 <div class="imgedit-submit"> 75 <input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button" value="<?php esc_attr_e( 'Cancel' ); ?>" /> 76 <input type="button" onclick="imageEdit.save(<?php echo "$post_id, '$nonce'"; ?>)" disabled="disabled" class="button-primary imgedit-submit-btn" value="<?php esc_attr_e( 'Save' ); ?>" /> 77 </div> 78 </td> 136 <?php do_action( 'image_editor_below_image' ) ?> 137 </td> 79 138 80 <td class="imgedit-settings"> 81 <div class="imgedit-group"> 82 <div class="imgedit-group-top"> 83 <a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><strong><?php _e('Scale Image'); ?></strong></a> 84 <div class="imgedit-help"> 85 <p><?php _e('You can proportionally scale the original image. For best results the scaling should be done before performing any other operations on it like crop, rotate, etc. Note that images can only be scaled down, not up.'); ?></p> 86 <?php if ( isset( $meta['width'], $meta['height'] ) ): ?> 87 <p><?php printf( __('Original dimensions %s'), $meta['width'] . '×' . $meta['height'] ); ?></p> 88 <?php endif ?> 89 <div class="imgedit-submit"> 90 <span class="nowrap"><input type="text" id="imgedit-scale-width-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" style="width:4em;" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />×<input type="text" id="imgedit-scale-height-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" style="width:4em;" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" /> 91 <span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>">!</span></span> 92 <input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'scale')" class="button-primary" value="<?php esc_attr_e( 'Scale' ); ?>" /> 93 </div> 94 </div> 95 </div> 139 <td class="imgedit-settings"> 96 140 97 <?php if ( $can_restore ) { ?> 141 <?php 142 /* Image Editor Groups */ 143 do_action( 'add_image_editor_groups', $post_id ); 98 144 99 <div class="imgedit-group-top"> 100 <a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><strong><?php _e('Restore Original Image'); ?></strong></a> 101 <div class="imgedit-help"> 102 <p><?php _e('Discard any changes and restore the original image.'); 145 do_image_edit_groups( $post_id, $nonce ); 146 ?> 103 147 104 if ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) 105 echo ' '.__('Previously edited copies of the image will not be deleted.'); 148 <div class="imgedit-submit"> 149 <input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button" value="<?php esc_attr_e( 'Cancel' ); ?>" /> 150 <input type="button" onclick="imageEdit.save(<?php echo "$post_id, '$nonce'"; ?>)" disabled="disabled" class="button-primary imgedit-submit-btn" value="<?php esc_attr_e( 'Save' ); ?>" /> 151 </div> 106 152 107 ?></p>108 <div class="imgedit-submit">109 <input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'restore')" class="button-primary" value="<?php esc_attr_e( 'Restore image' ); ?>" <?php echo $can_restore; ?> />110 </div>111 </div>112 </div>113 153 114 <?php } ?>154 </td><!-- /.imgedit-settings --></tr> 115 155 116 </div>156 </tbody></table> 117 157 118 <div class="imgedit-group"> 119 <div class="imgedit-group-top"> 120 <strong><?php _e('Image Crop'); ?></strong> 121 <a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('(help)'); ?></a> 122 <div class="imgedit-help"> 123 <p><?php _e('The image can be cropped by clicking on it and dragging to select the desired part. While dragging the dimensions of the selection are displayed below.'); ?></p> 124 125 <p><strong><?php _e('Crop Aspect Ratio'); ?></strong><br /> 126 <?php _e('You can specify the crop selection aspect ratio then hold down the Shift key while dragging to lock it. The values can be 1:1 (square), 4:3, 16:9, etc. If there is a selection, specifying aspect ratio will set it immediately.'); ?></p> 127 128 <p><strong><?php _e('Crop Selection'); ?></strong><br /> 129 <?php _e('Once started, the selection can be adjusted by entering new values (in pixels). Note that these values are scaled to approximately match the original image dimensions. The minimum selection size equals the thumbnail size as set in the Media settings.'); ?></p> 130 </div> 158 <div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div> 159 <script type="text/javascript">jQuery( function() { imageEdit.init(<?php echo $post_id; ?>); });</script> 160 <div class="hidden" id="imgedit-leaving-<?php echo $post_id; ?>"><?php _e("There are unsaved changes that will be lost. 'OK' to continue, 'Cancel' to return to the Image Editor."); ?></div> 131 161 </div> 132 133 <p>134 <?php _e('Aspect ratio:'); ?>135 <span class="nowrap">136 <input type="text" id="imgedit-crop-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 0, this)" style="width:3em;" />137 :138 <input type="text" id="imgedit-crop-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 1, this)" style="width:3em;" />139 </span>140 </p>141 142 <p id="imgedit-crop-sel-<?php echo $post_id; ?>">143 <?php _e('Selection:'); ?>144 <span class="nowrap">145 <input type="text" id="imgedit-sel-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />146 :147 <input type="text" id="imgedit-sel-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />148 </span>149 </p>150 </div>151 152 <?php if ( $thumb && $sub_sizes ) {153 $thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 );154 ?>155 156 <div class="imgedit-group imgedit-applyto">157 <div class="imgedit-group-top">158 <strong><?php _e('Thumbnail Settings'); ?></strong>159 <a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('(help)'); ?></a>160 <p class="imgedit-help"><?php _e('The thumbnail image can be cropped differently. For example it can be square or contain only a portion of the original image to showcase it better. Here you can select whether to apply changes to all image sizes or make the thumbnail different.'); ?></p>161 </div>162 163 <p>164 <img src="<?php echo $thumb['url']; ?>" width="<?php echo $thumb_img[0]; ?>" height="<?php echo $thumb_img[1]; ?>" class="imgedit-size-preview" alt="" /><br /><?php _e('Current thumbnail'); ?>165 </p>166 167 <p id="imgedit-save-target-<?php echo $post_id; ?>">168 <strong><?php _e('Apply changes to:'); ?></strong><br />169 170 <label class="imgedit-label">171 <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="all" checked="checked" />172 <?php _e('All image sizes'); ?></label>173 174 <label class="imgedit-label">175 <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="thumbnail" />176 <?php _e('Thumbnail'); ?></label>177 178 <label class="imgedit-label">179 <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="nothumb" />180 <?php _e('All sizes except thumbnail'); ?></label>181 </p>182 </div>183 184 <?php } ?>185 186 </td></tr>187 </tbody></table>188 <div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>189 <script type="text/javascript">jQuery( function() { imageEdit.init(<?php echo $post_id; ?>); });</script>190 <div class="hidden" id="imgedit-leaving-<?php echo $post_id; ?>"><?php _e("There are unsaved changes that will be lost. 'OK' to continue, 'Cancel' to return to the Image Editor."); ?></div>191 </div>192 162 <?php 193 163 } 194 164 … … 733 703 $return->msg = esc_js( __('Image saved') ); 734 704 return $return; 735 705 } 706 707 /** 708 * Adds a new image editor group to the Edit Image view. 709 * 710 * Should be called before {@link do_image_edit_groups()}, preferably from a 'add_image_edit_group' action callback. 711 * 712 * @global array $image_editor_groups 713 * 714 * @param int $id Unique ID for this editor group 715 * @param string $title Title that appears in the editor group box 716 * @param string|array $callback Function to be called to render the editor group content. Function signature is `( $post_id, $imgedit_group, $args )` 717 * @param string $tab Optional. Default "default". The name of the tab this group appears in 718 * @param string $help_text Optional. Help text that appears in the editor box content 719 * @param string $class Optional. CSS class to be added to the editor group DIV 720 * @param array $callback_args Optional. Additional arguments to be passed to the callback function. 721 */ 722 function add_image_edit_group( $id, $title, $callback, $tab = "default", $help_text = "", $class = "", $callback_args = null ){ 723 global $image_editor_groups; 724 725 /** @TODO make sure $id is unique **/ 726 $image_editor_groups[$tab][$id] = array( 727 'id' => $id, 728 'title' => $title, 729 'callback' => $callback, 730 'class' => $class, 731 'help' => $help_text, 732 'callback_args' => $callback_args 733 ); 734 } 735 736 function remove_image_edit_group( $remove_id ){ 737 global $image_editor_groups; 738 739 foreach ( $image_editor_groups as $tab_group => &$groups ){ 740 foreach ( $groups as $id => $group ){ 741 if ( $id == $remove_id ){ 742 unset ( $groups[$id] ); 743 return true; 744 } 745 } 746 } 747 return false; 748 } 749 750 function imgedit_group_scale_image( $post_id, $imgedit_group, $args ){ 751 extract( $args ); 752 ?> 753 754 <?php if ( isset( $meta['width'], $meta['height'] ) ): ?> 755 <p><?php printf( __('Original dimensions %s'), $meta['width'] . '×' . $meta['height'] ); ?></p> 756 <?php endif ?> 757 <div class="imgedit-submit"> 758 <span class="nowrap"><input type="text" id="imgedit-scale-width-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" style="width:4em;" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />×<input type="text" id="imgedit-scale-height-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" style="width:4em;" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" /> 759 <span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>">!</span></span> 760 <input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'scale')" class="button-primary" value="<?php esc_attr_e( 'Scale' ); ?>" /> 761 </div> 762 </div> 763 764 <?php 765 } 766 767 function imgedit_group_crop_image( $post_id, $imgedit_group, $args ){ 768 extract( $args ); 769 ?> 770 <p> 771 <?php _e('Aspect ratio:'); ?> 772 <span class="nowrap"> 773 <input type="text" id="imgedit-crop-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 0, this)" style="width:3em;" /> 774 : 775 <input type="text" id="imgedit-crop-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 1, this)" style="width:3em;" /> 776 </span> 777 </p> 778 779 <p id="imgedit-crop-sel-<?php echo $post_id; ?>"> 780 <?php _e('Selection:'); ?> 781 <span class="nowrap"> 782 <input type="text" id="imgedit-sel-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" /> 783 × 784 <input type="text" id="imgedit-sel-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" /> 785 </span> 786 </p> 787 <?php 788 } 789 790 function imgedit_group_thumbnail_settings( $post_id, $imgedit_group, $args ){ 791 extract( $args ); 792 ?> 793 794 <?php if ( isset( $thumb ) ): ?> 795 <p> 796 <img src="<?php echo $thumb['url']; ?>" width="<?php echo $thumb_img[0]; ?>" height="<?php echo $thumb_img[1]; ?>" class="imgedit-size-preview" alt="" /><br /><?php _e('Current thumbnail'); ?> 797 </p> 798 <?php endif; ?> 799 800 <p id="imgedit-save-target-<?php echo $post_id; ?>"> 801 <strong><?php _e('Apply changes to:'); ?></strong><br /> 802 803 <label class="imgedit-label"> 804 <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="all" checked="checked" /> 805 <?php _e('All image sizes'); ?></label> 806 807 <label class="imgedit-label"> 808 <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="thumbnail" /> 809 <?php _e('Thumbnail'); ?></label> 810 811 <label class="imgedit-label"> 812 <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="nothumb" /> 813 <?php _e('All sizes except thumbnail'); ?></label> 814 </p> 815 816 <?php 817 } 818 819 function imgedit_group_restore_image( $post_id, $imgedit_group, $args ){ 820 extract( $args ); 821 ?> 822 823 <p> 824 <?php 825 if ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) 826 echo ' '.__('Previously edited copies of the image will not be deleted.'); 827 ?> 828 </p> 829 830 <div class="imgedit-submit"> 831 <input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'restore')" class="button-primary" value="<?php esc_attr_e( 'Restore image' ); ?>" /> 832 </div> 833 834 <?php 835 } 836 837 /** 838 * @global array $image_editor_groups 839 * 840 * @param int $post_id 841 * @param string $nonce 842 * 843 * @TODO Currently, tabs auto-create themselves just by defining them in add_image_edit_group(). Eventually we'll want a add_editor_tab() suite of functions so we can better control these tabs. 844 */ 845 function do_image_edit_groups( $post_id, $nonce ){ 846 global $image_editor_groups; 847 848 /** 849 * Allow modification of image editor groups. 850 * 851 * @since 3.9 852 * 853 * @param int $post_id The ID of the WP_Post (attachment) currently being edited. 854 */ 855 $editor_groups = apply_filters( 'image_editor_groups', $image_editor_groups, $post_id ); 856 857 // Only create the tabs structure if needed 858 $has_tabs = count( $editor_groups ) > 1; 859 860 if ( $has_tabs ){ 861 echo '<div id="image-editor-group-tabs"><ul>'; 862 863 foreach ( $editor_groups as $tab => $tab_groups ){ 864 if ( $has_tabs ){ 865 $tab_title = str_replace( array( '-', '_' ), ' ', strtoupper( $tab ) ); 866 echo '<li><a href="#imgedit-group-tab-' . $tab . '">' . $tab_title . '</a></li>'; 867 } 868 } 869 870 echo '</ul>'; 871 } 872 873 foreach ( $editor_groups as $tab => $tab_groups ){ 874 if ( $has_tabs ) echo '<div id="#imgedit-group-tab-' . $tab . '">'; 875 876 foreach ( $tab_groups as $imgedit_group ){ 877 ?> 878 <div class="imgedit-group <?php echo $imgedit_group['class']?>"> 879 <div class="imgedit-group-top"> 880 <strong><?php echo $imgedit_group['title'] ?></strong> 881 <?php if ( ! empty( $imgedit_group['help'] ) ): ?> 882 <a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('(help)'); ?></a> 883 <div class="imgedit-help"><?php echo $imgedit_group['help'] ?></div> 884 <?php endif; ?> 885 </div> 886 887 <?php 888 $imgedit_group['callback_args']['nonce'] = $nonce; // Add the nonce to the callback args of each item, in case it has a submit button 889 call_user_func( $imgedit_group['callback'], $post_id, $imgedit_group, $imgedit_group['callback_args'] ); 890 ?> 891 892 </div> 893 <?php 894 } 895 896 if ( $has_tabs ) echo '</div><!-- /#imgedit-group-tab-' . $tab . ' -->'; 897 } 898 899 if ( $has_tabs ) { 900 echo '</div><!-- /#image-editor-group-tabs -->'; 901 ?> 902 <script>jQuery( '#image-editor-group-tabs' ).tabs();</script> 903 <?php 904 } 905 906 } -
wp-admin/js/image-edit.js
1 1 /* global imageEditL10n, ajaxurl, confirm */ 2 2 3 (function($) { 4 var imageEdit = window.imageEdit = { 5 iasapi : {}, 6 hold : {}, 7 postid : '', 3 ;(function($) { 4 var imageEdit = window.imageEdit = { 5 iasapi : {}, 6 hold : {}, 7 eventListeners : {}, 8 postid : '', 8 9 9 intval : function(f) {10 return f | 0;11 },10 intval : function(f) { 11 return f | 0; 12 }, 12 13 13 setDisabled : function(el, s) {14 if ( s ) {15 el.removeClass('disabled');16 $('input', el).removeAttr('disabled');17 } else {18 el.addClass('disabled');19 $('input', el).prop('disabled', true);20 }21 },14 setDisabled : function(el, s) { 15 if ( s ) { 16 el.removeClass('disabled'); 17 $('input', el).removeAttr('disabled'); 18 } else { 19 el.addClass('disabled'); 20 $('input', el).prop('disabled', true); 21 } 22 }, 22 23 23 init : function(postid) {24 var t = this, old = $('#image-editor-' + t.postid),25 x = t.intval( $('#imgedit-x-' + postid).val() ),26 y = t.intval( $('#imgedit-y-' + postid).val() );24 init : function(postid) { 25 var t = this, old = $('#image-editor-' + t.postid), 26 x = t.intval( $('#imgedit-x-' + postid).val() ), 27 y = t.intval( $('#imgedit-y-' + postid).val() ); 27 28 28 if ( t.postid !== postid && old.length ) {29 t.close(t.postid);30 }29 if ( t.postid !== postid && old.length ) { 30 t.close(t.postid); 31 } 31 32 32 t.hold.w = t.hold.ow = x;33 t.hold.h = t.hold.oh = y;34 t.hold.xy_ratio = x / y;35 t.hold.sizer = parseFloat( $('#imgedit-sizer-' + postid).val() );36 t.postid = postid;37 $('#imgedit-response-' + postid).empty();33 t.hold.w = t.hold.ow = x; 34 t.hold.h = t.hold.oh = y; 35 t.hold.xy_ratio = x / y; 36 t.hold.sizer = parseFloat( $('#imgedit-sizer-' + postid).val() ); 37 t.postid = postid; 38 $('#imgedit-response-' + postid).empty(); 38 39 39 $('input[type="text"]', '#imgedit-panel-' + postid).keypress(function(e) {40 var k = e.keyCode;40 $('input[type="text"]', '#imgedit-panel-' + postid).keypress(function(e) { 41 var k = e.keyCode; 41 42 42 if ( 36 < k && k < 41 ) {43 $(this).blur();44 }43 if ( 36 < k && k < 41 ) { 44 $(this).blur(); 45 } 45 46 46 if ( 13 === k ) {47 e.preventDefault();48 e.stopPropagation();49 return false;50 }51 });52 },47 if ( 13 === k ) { 48 e.preventDefault(); 49 e.stopPropagation(); 50 return false; 51 } 52 }); 53 }, 53 54 54 toggleEditor : function(postid, toggle) {55 var wait = $('#imgedit-wait-' + postid);55 toggleEditor : function(postid, toggle) { 56 var wait = $('#imgedit-wait-' + postid); 56 57 57 if ( toggle ) { 58 wait.height( $('#imgedit-panel-' + postid).height() ).fadeIn('fast'); 59 } else { 60 wait.fadeOut('fast'); 61 } 62 }, 58 if ( toggle ) { 59 wait.height( $('#imgedit-panel-' + postid).height() ).fadeIn('fast'); 60 } else { 61 wait.fadeOut('fast'); 62 this.dispatchEvent( this.events.INIT_EVENT, this ); 63 } 64 }, 63 65 64 toggleHelp : function(el) {65 $(el).siblings('.imgedit-help').slideToggle('fast');66 return false;67 },66 toggleHelp : function(el) { 67 $(el).siblings('.imgedit-help').slideToggle('fast'); 68 return false; 69 }, 68 70 69 getTarget : function(postid) {70 return $('input[name="imgedit-target-' + postid + '"]:checked', '#imgedit-save-target-' + postid).val() || 'full';71 },71 getTarget : function(postid) { 72 return $('input[name="imgedit-target-' + postid + '"]:checked', '#imgedit-save-target-' + postid).val() || 'full'; 73 }, 72 74 73 scaleChanged : function(postid, x) {74 var w = $('#imgedit-scale-width-' + postid), h = $('#imgedit-scale-height-' + postid),75 warn = $('#imgedit-scale-warn-' + postid), w1 = '', h1 = '';75 scaleChanged : function(postid, x) { 76 var w = $('#imgedit-scale-width-' + postid), h = $('#imgedit-scale-height-' + postid), 77 warn = $('#imgedit-scale-warn-' + postid), w1 = '', h1 = ''; 76 78 77 if ( x ) {78 h1 = ( w.val() !== '' ) ? Math.round( w.val() / this.hold.xy_ratio ) : '';79 h.val( h1 );80 } else {81 w1 = ( h.val() !== '' ) ? Math.round( h.val() * this.hold.xy_ratio ) : '';82 w.val( w1 );83 }79 if ( x ) { 80 h1 = ( w.val() !== '' ) ? Math.round( w.val() / this.hold.xy_ratio ) : ''; 81 h.val( h1 ); 82 } else { 83 w1 = ( h.val() !== '' ) ? Math.round( h.val() * this.hold.xy_ratio ) : ''; 84 w.val( w1 ); 85 } 84 86 85 if ( ( h1 && h1 > this.hold.oh ) || ( w1 && w1 > this.hold.ow ) ) {86 warn.css('visibility', 'visible');87 } else {88 warn.css('visibility', 'hidden');89 }90 },87 if ( ( h1 && h1 > this.hold.oh ) || ( w1 && w1 > this.hold.ow ) ) { 88 warn.css('visibility', 'visible'); 89 } else { 90 warn.css('visibility', 'hidden'); 91 } 92 }, 91 93 92 getSelRatio : function(postid) {93 var x = this.hold.w, y = this.hold.h,94 X = this.intval( $('#imgedit-crop-width-' + postid).val() ),95 Y = this.intval( $('#imgedit-crop-height-' + postid).val() );94 getSelRatio : function(postid) { 95 var x = this.hold.w, y = this.hold.h, 96 X = this.intval( $('#imgedit-crop-width-' + postid).val() ), 97 Y = this.intval( $('#imgedit-crop-height-' + postid).val() ); 96 98 97 if ( X && Y ) {98 return X + ':' + Y;99 }99 if ( X && Y ) { 100 return X + ':' + Y; 101 } 100 102 101 if ( x && y ) {102 return x + ':' + y;103 }103 if ( x && y ) { 104 return x + ':' + y; 105 } 104 106 105 return '1:1';106 },107 return '1:1'; 108 }, 107 109 108 filterHistory : function(postid, setSize) {109 // apply undo state to history110 var history = $('#imgedit-history-' + postid).val(), pop, n, o, i, op = [];110 filterHistory : function(postid, setSize) { 111 // apply undo state to history 112 var history = $('#imgedit-history-' + postid).val(), pop, n, o, i, op = []; 111 113 112 if ( history !== '' ) { 113 history = JSON.parse(history); 114 pop = this.intval( $('#imgedit-undone-' + postid).val() ); 115 if ( pop > 0 ) { 116 while ( pop > 0 ) { 117 history.pop(); 118 pop--; 114 if ( history !== '' ) { 115 history = JSON.parse(history); 116 pop = this.intval( $('#imgedit-undone-' + postid).val() ); 117 if ( pop > 0 ) { 118 while ( pop > 0 ) { 119 history.pop(); 120 pop--; 121 } 119 122 } 120 }121 123 122 if ( setSize ) {123 if ( !history.length ) {124 this.hold.w = this.hold.ow;125 this.hold.h = this.hold.oh;126 return '';127 }124 if ( setSize ) { 125 if ( !history.length ) { 126 this.hold.w = this.hold.ow; 127 this.hold.h = this.hold.oh; 128 return ''; 129 } 128 130 129 // restore130 o = history[history.length - 1];131 o = o.c || o.r || o.f || false;131 // restore 132 o = history[history.length - 1]; 133 o = o.c || o.r || o.f || false; 132 134 133 if ( o ) { 134 this.hold.w = o.fw; 135 this.hold.h = o.fh; 135 if ( o ) { 136 this.hold.w = o.fw; 137 this.hold.h = o.fh; 138 } 136 139 } 137 }138 140 139 // filter the values 140 for ( n in history ) { 141 i = history[n]; 142 if ( i.hasOwnProperty('c') ) { 143 op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h } }; 144 } else if ( i.hasOwnProperty('r') ) { 145 op[n] = { 'r': i.r.r }; 146 } else if ( i.hasOwnProperty('f') ) { 147 op[n] = { 'f': i.f.f }; 141 // filter the values 142 for ( n in history ) { 143 i = history[n]; 144 if ( i.hasOwnProperty('c') ) { 145 op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h } }; 146 } else if ( i.hasOwnProperty('r') ) { 147 op[n] = { 'r': i.r.r }; 148 } else if ( i.hasOwnProperty('f') ) { 149 op[n] = { 'f': i.f.f }; 150 } 148 151 } 152 return JSON.stringify(op); 149 153 } 150 return JSON.stringify(op); 151 } 152 return ''; 153 }, 154 return ''; 155 }, 154 156 155 refreshEditor : function(postid, nonce, callback) {156 var t = this, data, img;157 refreshEditor : function(postid, nonce, callback) { 158 var t = this, data, img; 157 159 158 t.toggleEditor(postid, 1);159 data = {160 'action': 'imgedit-preview',161 '_ajax_nonce': nonce,162 'postid': postid,163 'history': t.filterHistory(postid, 1),164 'rand': t.intval(Math.random() * 1000000)165 };160 t.toggleEditor(postid, 1); 161 data = { 162 'action': 'imgedit-preview', 163 '_ajax_nonce': nonce, 164 'postid': postid, 165 'history': t.filterHistory(postid, 1), 166 'rand': t.intval(Math.random() * 1000000) 167 }; 166 168 167 img = $('<img id="image-preview-' + postid + '" />')168 .on('load', function() {169 var max1, max2, parent = $('#imgedit-crop-' + postid), t = imageEdit;169 img = $('<img id="image-preview-' + postid + '" />') 170 .on('load', function() { 171 var max1, max2, parent = $('#imgedit-crop-' + postid), t = imageEdit; 170 172 171 parent.empty().append(img);173 parent.empty().append(img); 172 174 173 // w, h are the new full size dims174 max1 = Math.max( t.hold.w, t.hold.h );175 max2 = Math.max( $(img).width(), $(img).height() );176 t.hold.sizer = max1 > max2 ? max2 / max1 : 1;175 // w, h are the new full size dims 176 max1 = Math.max( t.hold.w, t.hold.h ); 177 max2 = Math.max( $(img).width(), $(img).height() ); 178 t.hold.sizer = max1 > max2 ? max2 / max1 : 1; 177 179 178 t.initCrop(postid, img, parent);179 t.setCropSelection(postid, 0);180 t.initCrop(postid, img, parent); 181 t.setCropSelection(postid, 0); 180 182 181 if ( (typeof callback !== 'undefined') && callback !== null ) {182 callback();183 }183 if ( (typeof callback !== 'undefined') && callback !== null ) { 184 callback(); 185 } 184 186 185 if ( $('#imgedit-history-' + postid).val() && $('#imgedit-undone-' + postid).val() === '0' ) {186 $('input.imgedit-submit-btn', '#imgedit-panel-' + postid).removeAttr('disabled');187 } else {188 $('input.imgedit-submit-btn', '#imgedit-panel-' + postid).prop('disabled', true);189 }187 if ( $('#imgedit-history-' + postid).val() && $('#imgedit-undone-' + postid).val() === '0' ) { 188 $('input.imgedit-submit-btn', '#imgedit-panel-' + postid).removeAttr('disabled'); 189 } else { 190 $('input.imgedit-submit-btn', '#imgedit-panel-' + postid).prop('disabled', true); 191 } 190 192 191 t.toggleEditor(postid, 0);192 })193 .on('error', function() {194 $('#imgedit-crop-' + postid).empty().append('<div class="error"><p>' + imageEditL10n.error + '</p></div>');195 t.toggleEditor(postid, 0);196 })197 .attr('src', ajaxurl + '?' + $.param(data));198 },193 t.toggleEditor(postid, 0); 194 }) 195 .on('error', function() { 196 $('#imgedit-crop-' + postid).empty().append('<div class="error"><p>' + imageEditL10n.error + '</p></div>'); 197 t.toggleEditor(postid, 0); 198 }) 199 .attr('src', ajaxurl + '?' + $.param(data)); 200 }, 199 201 200 action : function(postid, nonce, action) {201 var t = this, data, w, h, fw, fh;202 action : function(postid, nonce, action) { 203 var t = this, data, w, h, fw, fh; 202 204 203 if ( t.notsaved(postid) ) {204 return false;205 }205 if ( t.notsaved(postid) ) { 206 return false; 207 } 206 208 207 data = {208 'action': 'image-editor',209 '_ajax_nonce': nonce,210 'postid': postid211 };209 data = { 210 'action': 'image-editor', 211 '_ajax_nonce': nonce, 212 'postid': postid 213 }; 212 214 213 if ( 'scale' === action ) {214 w = $('#imgedit-scale-width-' + postid),215 h = $('#imgedit-scale-height-' + postid),216 fw = t.intval(w.val()),217 fh = t.intval(h.val());215 if ( 'scale' === action ) { 216 w = $('#imgedit-scale-width-' + postid), 217 h = $('#imgedit-scale-height-' + postid), 218 fw = t.intval(w.val()), 219 fh = t.intval(h.val()); 218 220 219 if ( fw < 1 ) { 220 w.focus(); 221 if ( fw < 1 ) { 222 w.focus(); 223 return false; 224 } else if ( fh < 1 ) { 225 h.focus(); 226 return false; 227 } 228 229 if ( fw === t.hold.ow || fh === t.hold.oh ) { 230 return false; 231 } 232 233 data['do'] = 'scale'; 234 data.fwidth = fw; 235 data.fheight = fh; 236 } else if ( 'restore' === action ) { 237 data['do'] = 'restore'; 238 } else { 221 239 return false; 222 } else if ( fh < 1 ) {223 h.focus();224 return false;225 240 } 226 241 227 if ( fw === t.hold.ow || fh === t.hold.oh ) { 242 t.toggleEditor(postid, 1); 243 $.post(ajaxurl, data, function(r) { 244 $('#image-editor-' + postid).empty().append(r); 245 t.toggleEditor(postid, 0); 246 }); 247 }, 248 249 save : function(postid, nonce) { 250 var data, target = this.getTarget(postid), history = this.filterHistory(postid, 0); 251 252 if ( '' === history ) { 228 253 return false; 229 254 } 230 255 231 data['do'] = 'scale'; 232 data.fwidth = fw; 233 data.fheight = fh; 234 } else if ( 'restore' === action ) { 235 data['do'] = 'restore'; 236 } else { 237 return false; 238 } 256 this.toggleEditor(postid, 1); 257 data = { 258 'action': 'image-editor', 259 '_ajax_nonce': nonce, 260 'postid': postid, 261 'history': history, 262 'target': target, 263 'context': $('#image-edit-context').length ? $('#image-edit-context').val() : null, 264 'do': 'save' 265 }; 239 266 240 t.toggleEditor(postid, 1); 241 $.post(ajaxurl, data, function(r) { 242 $('#image-editor-' + postid).empty().append(r); 243 t.toggleEditor(postid, 0); 244 }); 245 }, 267 $.post(ajaxurl, data, function(r) { 268 var ret = JSON.parse(r); 246 269 247 save : function(postid, nonce) { 248 var data, target = this.getTarget(postid), history = this.filterHistory(postid, 0); 270 if ( ret.error ) { 271 $('#imgedit-response-' + postid).html('<div class="error"><p>' + ret.error + '</p><div>'); 272 imageEdit.close(postid); 273 return; 274 } 249 275 250 if ( '' === history) {251 return false;252 }276 if ( ret.fw && ret.fh ) { 277 $('#media-dims-' + postid).html( ret.fw + ' × ' + ret.fh ); 278 } 253 279 254 this.toggleEditor(postid, 1); 255 data = { 256 'action': 'image-editor', 257 '_ajax_nonce': nonce, 258 'postid': postid, 259 'history': history, 260 'target': target, 261 'context': $('#image-edit-context').length ? $('#image-edit-context').val() : null, 262 'do': 'save' 263 }; 280 if ( ret.thumbnail ) { 281 $('.thumbnail', '#thumbnail-head-' + postid).attr('src', ''+ret.thumbnail); 282 } 264 283 265 $.post(ajaxurl, data, function(r) { 266 var ret = JSON.parse(r); 284 if ( ret.msg ) { 285 $('#imgedit-response-' + postid).html('<div class="updated"><p>' + ret.msg + '</p></div>'); 286 } 267 287 268 if ( ret.error ) {269 $('#imgedit-response-' + postid).html('<div class="error"><p>' + ret.error + '</p><div>');270 288 imageEdit.close(postid); 271 return;272 }289 }); 290 }, 273 291 274 if ( ret.fw && ret.fh ) { 275 $('#media-dims-' + postid).html( ret.fw + ' × ' + ret.fh ); 276 } 292 open : function(postid, nonce) { 293 var data, 294 elem = $('#image-editor-' + postid), 295 head = $('#media-head-' + postid), 296 btn = $('#imgedit-open-btn-' + postid), 297 spin = btn.siblings('.spinner'), 298 // Capture the arguments passed to open(). Used in dispatchEvent(). 299 args = arguments; 277 300 278 if ( ret.thumbnail ) { 279 $('.thumbnail', '#thumbnail-head-' + postid).attr('src', ''+ret.thumbnail); 280 } 301 btn.prop('disabled', true); 302 spin.show(); 281 303 282 if ( ret.msg ) { 283 $('#imgedit-response-' + postid).html('<div class="updated"><p>' + ret.msg + '</p></div>'); 284 } 304 data = { 305 'action': 'image-editor', 306 '_ajax_nonce': nonce, 307 'postid': postid, 308 'do': 'open' 309 }; 285 310 286 imageEdit.close(postid); 287 }); 288 }, 311 elem.load(ajaxurl, data, function() { 312 elem.fadeIn('fast'); 313 head.fadeOut('fast', function(){ 314 btn.removeAttr('disabled'); 315 spin.hide(); 316 }); 317 // Dispatch an event. Note that if you need to work with any of the editorGroup HTML, you should use the INIT_EVENT event instead. 318 imageEdit.dispatchEvent( imageEdit.events.OPEN_EVENT, this, { args: args } ); 319 }); 320 }, 289 321 290 open : function(postid, nonce) { 291 var data, elem = $('#image-editor-' + postid), head = $('#media-head-' + postid), 292 btn = $('#imgedit-open-btn-' + postid), spin = btn.siblings('.spinner'); 322 imgLoaded : function(postid) { 323 var img = $('#image-preview-' + postid), parent = $('#imgedit-crop-' + postid); 293 324 294 btn.prop('disabled', true); 295 spin.show(); 325 this.initCrop(postid, img, parent); 326 this.setCropSelection(postid, 0); 327 this.toggleEditor(postid, 0); 328 }, 296 329 297 data = { 298 'action': 'image-editor', 299 '_ajax_nonce': nonce, 300 'postid': postid, 301 'do': 'open' 302 }; 330 initCrop : function(postid, image, parent) { 331 var t = this, selW = $('#imgedit-sel-width-' + postid), 332 selH = $('#imgedit-sel-height-' + postid); 303 333 304 elem.load(ajaxurl, data, function() { 305 elem.fadeIn('fast'); 306 head.fadeOut('fast', function(){ 307 btn.removeAttr('disabled'); 308 spin.hide(); 309 }); 310 }); 311 }, 334 t.iasapi = $(image).imgAreaSelect({ 335 parent: parent, 336 instance: true, 337 handles: true, 338 keys: true, 339 minWidth: 3, 340 minHeight: 3, 312 341 313 imgLoaded : function(postid) { 314 var img = $('#image-preview-' + postid), parent = $('#imgedit-crop-' + postid); 342 onInit: function() { 343 parent.children().mousedown(function(e){ 344 var ratio = false, sel, defRatio; 315 345 316 this.initCrop(postid, img, parent); 317 this.setCropSelection(postid, 0); 318 this.toggleEditor(postid, 0); 319 }, 346 if ( e.shiftKey ) { 347 sel = t.iasapi.getSelection(); 348 defRatio = t.getSelRatio(postid); 349 ratio = ( sel && sel.width && sel.height ) ? sel.width + ':' + sel.height : defRatio; 350 } 320 351 321 initCrop : function(postid, image, parent) { 322 var t = this, selW = $('#imgedit-sel-width-' + postid), 323 selH = $('#imgedit-sel-height-' + postid); 352 t.iasapi.setOptions({ 353 aspectRatio: ratio 354 }); 355 }); 356 }, 324 357 325 t.iasapi = $(image).imgAreaSelect({ 326 parent: parent, 327 instance: true, 328 handles: true, 329 keys: true, 330 minWidth: 3, 331 minHeight: 3, 358 onSelectStart: function() { 359 imageEdit.setDisabled($('#imgedit-crop-sel-' + postid), 1); 360 }, 332 361 333 onInit: function() {334 parent.children().mousedown(function(e){335 var ratio = false, sel, defRatio;362 onSelectEnd: function(img, c) { 363 imageEdit.setCropSelection(postid, c); 364 }, 336 365 337 if ( e.shiftKey ) { 338 sel = t.iasapi.getSelection(); 339 defRatio = t.getSelRatio(postid); 340 ratio = ( sel && sel.width && sel.height ) ? sel.width + ':' + sel.height : defRatio; 341 } 366 onSelectChange: function(img, c) { 367 var sizer = imageEdit.hold.sizer; 368 selW.val( imageEdit.round(c.width / sizer) ); 369 selH.val( imageEdit.round(c.height / sizer) ); 370 } 371 }); 372 }, 342 373 343 t.iasapi.setOptions({344 aspectRatio: ratio345 });346 });347 },374 setCropSelection : function(postid, c) { 375 var sel, min = $('#imgedit-minthumb-' + postid).val() || '128:128', 376 sizer = this.hold.sizer; 377 min = min.split(':'); 378 c = c || 0; 348 379 349 onSelectStart: function() { 350 imageEdit.setDisabled($('#imgedit-crop-sel-' + postid), 1); 351 }, 380 if ( !c || ( c.width < 3 && c.height < 3 ) ) { 381 this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 0); 382 this.setDisabled($('#imgedit-crop-sel-' + postid), 0); 383 $('#imgedit-sel-width-' + postid).val(''); 384 $('#imgedit-sel-height-' + postid).val(''); 385 $('#imgedit-selection-' + postid).val(''); 386 return false; 387 } 352 388 353 onSelectEnd: function(img, c) { 354 imageEdit.setCropSelection(postid, c); 355 }, 389 if ( c.width < (min[0] * sizer) && c.height < (min[1] * sizer) ) { 390 this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 0); 391 $('#imgedit-selection-' + postid).val(''); 392 return false; 393 } 356 394 357 onSelectChange: function(img, c) { 358 var sizer = imageEdit.hold.sizer; 359 selW.val( imageEdit.round(c.width / sizer) ); 360 selH.val( imageEdit.round(c.height / sizer) ); 395 sel = { 'x': c.x1, 'y': c.y1, 'w': c.width, 'h': c.height }; 396 this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 1); 397 $('#imgedit-selection-' + postid).val( JSON.stringify(sel) ); 398 }, 399 400 close : function(postid, warn) { 401 warn = warn || false; 402 403 if ( warn && this.notsaved(postid) ) { 404 return false; 361 405 } 362 });363 },364 406 365 setCropSelection : function(postid, c) { 366 var sel, min = $('#imgedit-minthumb-' + postid).val() || '128:128', 367 sizer = this.hold.sizer; 368 min = min.split(':'); 369 c = c || 0; 407 this.iasapi = {}; 408 this.hold = {}; 409 $('#image-editor-' + postid).fadeOut('fast', function() { 410 $('#media-head-' + postid).fadeIn('fast'); 411 $(this).empty(); 412 }); 413 }, 370 414 371 if ( !c || ( c.width < 3 && c.height < 3 ) ) { 372 this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 0); 373 this.setDisabled($('#imgedit-crop-sel-' + postid), 0); 374 $('#imgedit-sel-width-' + postid).val(''); 375 $('#imgedit-sel-height-' + postid).val(''); 376 $('#imgedit-selection-' + postid).val(''); 377 return false; 378 } 415 notsaved : function(postid) { 416 var h = $('#imgedit-history-' + postid).val(), 417 history = ( h !== '' ) ? JSON.parse(h) : [], 418 pop = this.intval( $('#imgedit-undone-' + postid).val() ); 379 419 380 if ( c.width < (min[0] * sizer) && c.height < (min[1] * sizer) ) { 381 this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 0); 382 $('#imgedit-selection-' + postid).val(''); 420 if ( pop < history.length ) { 421 if ( confirm( $('#imgedit-leaving-' + postid).html() ) ) { 422 return false; 423 } 424 return true; 425 } 383 426 return false; 384 } 427 }, 385 428 386 sel = { 'x': c.x1, 'y': c.y1, 'w': c.width, 'h': c.height }; 387 this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 1); 388 $('#imgedit-selection-' + postid).val( JSON.stringify(sel) ); 389 }, 429 addStep : function(op, postid, nonce) { 430 var t = this, elem = $('#imgedit-history-' + postid), 431 history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : [], 432 undone = $('#imgedit-undone-' + postid), 433 pop = t.intval(undone.val()); 390 434 391 close : function(postid, warn) { 392 warn = warn || false; 435 while ( pop > 0 ) { 436 history.pop(); 437 pop--; 438 } 439 undone.val(0); // reset 393 440 394 if ( warn && this.notsaved(postid) ) { 395 return false; 396 } 441 history.push(op); 442 elem.val( JSON.stringify(history) ); 397 443 398 this.iasapi = {}; 399 this.hold = {}; 400 $('#image-editor-' + postid).fadeOut('fast', function() { 401 $('#media-head-' + postid).fadeIn('fast'); 402 $(this).empty(); 403 }); 404 }, 444 t.refreshEditor(postid, nonce, function() { 445 t.setDisabled($('#image-undo-' + postid), true); 446 t.setDisabled($('#image-redo-' + postid), false); 447 }); 448 }, 405 449 406 notsaved : function(postid) {407 var h = $('#imgedit-history-' + postid).val(),408 history = ( h !== '' ) ? JSON.parse(h) : [],409 pop = this.intval( $('#imgedit-undone-' + postid).val() );450 rotate : function(angle, postid, nonce, t) { 451 if ( $(t).hasClass('disabled') ) { 452 return false; 453 } 410 454 411 if ( pop < history.length ) { 412 if ( confirm( $('#imgedit-leaving-' + postid).html() ) ) { 455 this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }}, postid, nonce); 456 }, 457 458 flip : function (axis, postid, nonce, t) { 459 if ( $(t).hasClass('disabled') ) { 413 460 return false; 414 461 } 415 return true;416 }417 return false;418 },419 462 420 addStep : function(op, postid, nonce) { 421 var t = this, elem = $('#imgedit-history-' + postid), 422 history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : [], 423 undone = $('#imgedit-undone-' + postid), 424 pop = t.intval(undone.val()); 463 this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }}, postid, nonce); 464 }, 425 465 426 while ( pop > 0 ) { 427 history.pop(); 428 pop--; 429 } 430 undone.val(0); // reset 466 crop : function (postid, nonce, t) { 467 var sel = $('#imgedit-selection-' + postid).val(), 468 w = this.intval( $('#imgedit-sel-width-' + postid).val() ), 469 h = this.intval( $('#imgedit-sel-height-' + postid).val() ); 431 470 432 history.push(op); 433 elem.val( JSON.stringify(history) ); 471 if ( $(t).hasClass('disabled') || sel === '' ) { 472 return false; 473 } 434 474 435 t.refreshEditor(postid, nonce, function() { 436 t.setDisabled($('#image-undo-' + postid), true); 437 t.setDisabled($('#image-redo-' + postid), false); 438 }); 439 }, 475 sel = JSON.parse(sel); 476 if ( sel.w > 0 && sel.h > 0 && w > 0 && h > 0 ) { 477 sel.fw = w; 478 sel.fh = h; 479 this.addStep({ 'c': sel }, postid, nonce); 480 } 481 }, 440 482 441 rotate : function(angle, postid, nonce, t) { 442 if ( $(t).hasClass('disabled') ) { 443 return false; 444 } 483 undo : function (postid, nonce) { 484 var t = this, button = $('#image-undo-' + postid), elem = $('#imgedit-undone-' + postid), 485 pop = t.intval( elem.val() ) + 1; 445 486 446 this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }}, postid, nonce); 447 }, 487 if ( button.hasClass('disabled') ) { 488 return; 489 } 448 490 449 flip : function (axis, postid, nonce, t) {450 if ( $(t).hasClass('disabled')) {451 return false;452 }491 elem.val(pop); 492 t.refreshEditor(postid, nonce, function() { 493 var elem = $('#imgedit-history-' + postid), 494 history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : []; 453 495 454 this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }}, postid, nonce); 455 }, 496 t.setDisabled($('#image-redo-' + postid), true); 497 t.setDisabled(button, pop < history.length); 498 }); 499 }, 456 500 457 crop : function (postid, nonce, t) { 458 var sel = $('#imgedit-selection-' + postid).val(), 459 w = this.intval( $('#imgedit-sel-width-' + postid).val() ), 460 h = this.intval( $('#imgedit-sel-height-' + postid).val() ); 501 redo : function(postid, nonce) { 502 var t = this, button = $('#image-redo-' + postid), elem = $('#imgedit-undone-' + postid), 503 pop = t.intval( elem.val() ) - 1; 461 504 462 if ( $(t).hasClass('disabled') || sel === '') {463 return false;464 }505 if ( button.hasClass('disabled') ) { 506 return; 507 } 465 508 466 sel = JSON.parse(sel); 467 if ( sel.w > 0 && sel.h > 0 && w > 0 && h > 0 ) { 468 sel.fw = w; 469 sel.fh = h; 470 this.addStep({ 'c': sel }, postid, nonce); 471 } 472 }, 509 elem.val(pop); 510 t.refreshEditor(postid, nonce, function() { 511 t.setDisabled($('#image-undo-' + postid), true); 512 t.setDisabled(button, pop > 0); 513 }); 514 }, 473 515 474 undo : function (postid, nonce) { 475 var t = this, button = $('#image-undo-' + postid), elem = $('#imgedit-undone-' + postid), 476 pop = t.intval( elem.val() ) + 1; 516 setNumSelection : function(postid) { 517 var sel, elX = $('#imgedit-sel-width-' + postid), elY = $('#imgedit-sel-height-' + postid), 518 x = this.intval( elX.val() ), y = this.intval( elY.val() ), 519 img = $('#image-preview-' + postid), imgh = img.height(), imgw = img.width(), 520 sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi; 477 521 478 if ( button.hasClass('disabled') ) { 479 return; 480 } 522 if ( x < 1 ) { 523 elX.val(''); 524 return false; 525 } 481 526 482 elem.val(pop);483 t.refreshEditor(postid, nonce, function() {484 var elem = $('#imgedit-history-' + postid),485 history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : [];527 if ( y < 1 ) { 528 elY.val(''); 529 return false; 530 } 486 531 487 t.setDisabled($('#image-redo-' + postid), true); 488 t.setDisabled(button, pop < history.length); 489 }); 490 }, 532 if ( x && y && ( sel = ias.getSelection() ) ) { 533 x2 = sel.x1 + Math.round( x * sizer ); 534 y2 = sel.y1 + Math.round( y * sizer ); 535 x1 = sel.x1; 536 y1 = sel.y1; 491 537 492 redo : function(postid, nonce) { 493 var t = this, button = $('#image-redo-' + postid), elem = $('#imgedit-undone-' + postid), 494 pop = t.intval( elem.val() ) - 1; 538 if ( x2 > imgw ) { 539 x1 = 0; 540 x2 = imgw; 541 elX.val( Math.round( x2 / sizer ) ); 542 } 495 543 496 if ( button.hasClass('disabled') ) { 497 return; 498 } 544 if ( y2 > imgh ) { 545 y1 = 0; 546 y2 = imgh; 547 elY.val( Math.round( y2 / sizer ) ); 548 } 499 549 500 elem.val(pop); 501 t.refreshEditor(postid, nonce, function() { 502 t.setDisabled($('#image-undo-' + postid), true); 503 t.setDisabled(button, pop > 0); 504 }); 505 }, 550 ias.setSelection( x1, y1, x2, y2 ); 551 ias.update(); 552 this.setCropSelection(postid, ias.getSelection()); 553 } 554 }, 506 555 507 setNumSelection : function(postid) { 508 var sel, elX = $('#imgedit-sel-width-' + postid), elY = $('#imgedit-sel-height-' + postid), 509 x = this.intval( elX.val() ), y = this.intval( elY.val() ), 510 img = $('#image-preview-' + postid), imgh = img.height(), imgw = img.width(), 511 sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi; 556 round : function(num) { 557 var s; 558 num = Math.round(num); 512 559 513 if ( x < 1 ) { 514 elX.val(''); 515 return false; 516 } 560 if ( this.hold.sizer > 0.6 ) { 561 return num; 562 } 517 563 518 if ( y < 1 ) { 519 elY.val(''); 520 return false; 521 } 564 s = num.toString().slice(-1); 522 565 523 if ( x && y && ( sel = ias.getSelection() ) ) { 524 x2 = sel.x1 + Math.round( x * sizer ); 525 y2 = sel.y1 + Math.round( y * sizer ); 526 x1 = sel.x1; 527 y1 = sel.y1; 528 529 if ( x2 > imgw ) { 530 x1 = 0; 531 x2 = imgw; 532 elX.val( Math.round( x2 / sizer ) ); 566 if ( '1' === s ) { 567 return num - 1; 568 } else if ( '9' === s ) { 569 return num + 1; 533 570 } 534 571 535 if ( y2 > imgh ) { 536 y1 = 0; 537 y2 = imgh; 538 elY.val( Math.round( y2 / sizer ) ); 572 return num; 573 }, 574 575 setRatioSelection : function(postid, n, el) { 576 var sel, r, x = this.intval( $('#imgedit-crop-width-' + postid).val() ), 577 y = this.intval( $('#imgedit-crop-height-' + postid).val() ), 578 h = $('#image-preview-' + postid).height(); 579 580 if ( !this.intval( $(el).val() ) ) { 581 $(el).val(''); 582 return; 539 583 } 540 584 541 ias.setSelection( x1, y1, x2, y2 ); 542 ias.update(); 543 this.setCropSelection(postid, ias.getSelection()); 544 } 545 }, 585 if ( x && y ) { 586 this.iasapi.setOptions({ 587 aspectRatio: x + ':' + y 588 }); 546 589 547 round : function(num) { 548 var s; 549 num = Math.round(num); 590 if ( sel = this.iasapi.getSelection(true) ) { 591 r = Math.ceil( sel.y1 + ( ( sel.x2 - sel.x1 ) / ( x / y ) ) ); 550 592 551 if ( this.hold.sizer > 0.6 ) { 552 return num; 553 } 593 if ( r > h ) { 594 r = h; 595 if ( n ) { 596 $('#imgedit-crop-height-' + postid).val(''); 597 } else { 598 $('#imgedit-crop-width-' + postid).val(''); 599 } 600 } 554 601 555 s = num.toString().slice(-1); 602 this.iasapi.setSelection( sel.x1, sel.y1, sel.x2, r ); 603 this.iasapi.update(); 604 } 605 } 606 }, 556 607 557 if ( '1' === s ) {558 return num - 1;559 } else if ( '9' === s ) {560 return num + 1;561 }562 608 563 return num;564 },565 609 566 setRatioSelection : function(postid, n, el) { 567 var sel, r, x = this.intval( $('#imgedit-crop-width-' + postid).val() ), 568 y = this.intval( $('#imgedit-crop-height-' + postid).val() ), 569 h = $('#image-preview-' + postid).height(); 610 /** 611 * Register an observer against a specific event type (one of the EVENT constants defined in .events) 612 * 613 * The event handler (callback) accepts a single argument - eventData, which is an object with the following structure: 614 * eventData = { 615 * event : EVENT_TYPE, 616 * [other data] : ( determined by the call to dispatchEvent ), 617 * [registrationData] : ( any additional data to be passed to the event handler, as determined by the agent that called addEventListener - the 'args' parameter ) 618 * } 619 * 620 * @param {string} event A constant defined in zgExtendImageEdit.events. Determines the type of event you want to listen for 621 * @param {function} callback The function that will be called. `this` gets set to the event target (often `imageEdit` ) 622 * @param {int} priority Not yet implemented. Allows you to specify a priority for the event 623 * @param {object} args Any number of additional arguments you would like passed to the event handler. These are available in eventData.registrationData 624 * @returns {boolean} Success 625 */ 626 addEventListener : function( event, callback, priority, args ){ 627 if ( typeof callback === 'function' ){ 628 this.eventListeners[event] = this.eventListeners[event] || []; 629 this.eventListeners[event].push( [callback, args] ); 630 return true; 631 } else { 632 console.log( "Error: callback is not a function. Event listener registration failed." ); 633 return false; 634 } 635 }, 570 636 571 if ( !this.intval( $(el).val() ) ) { 572 $(el).val(''); 573 return; 574 } 637 /** 638 * Dispatches an event, executing any callbacks registered against that event using {@link addEventListener} 639 * 640 * @param {string} event The event type, as found under zgExtendImageEdit.events. 641 * @param {object} target The object that should become `this` in the context of the callback function. Defaults to `window` if not defined. 642 * @param {object} data Additional data related to the event. 643 * @returns {int} 0 indicates there was a problem dispatching one of the events (incorrect callback); -1 indicates that there were no listeners (not necessarily an error); 1 indicates success. There is generally no need to check this return value. 644 */ 645 dispatchEvent : function( event, target, data ){ 646 var listeners, 647 dispatchSuccess = true, 648 target = target || window, 649 eventData = data || {}; 575 650 576 if ( x && y ) { 577 this.iasapi.setOptions({ 578 aspectRatio: x + ':' + y 579 }); 651 eventData.event = event; 580 652 581 if ( sel = this.iasapi.getSelection(true) ) { 582 r = Math.ceil( sel.y1 + ( ( sel.x2 - sel.x1 ) / ( x / y ) ) ); 583 584 if ( r > h ) { 585 r = h; 586 if ( n ) { 587 $('#imgedit-crop-height-' + postid).val(''); 653 if ( listeners = this.eventListeners[event] ){ 654 for ( var i=0, l=listeners.length; i<l; ++i){ 655 if ( 'function' === typeof listeners[i][0] ){ 656 // If the call to addEventListener() passed some arguments, collect these under `registrationData`. 657 if ( listeners[i][1] ){ 658 eventData.registrationData = listeners[i][1]; 659 } 660 listeners[i][0].call( target, eventData ); 588 661 } else { 589 $('#imgedit-crop-width-' + postid).val('');662 dispatchSuccess = false; 590 663 } 591 664 } 592 665 593 this.iasapi.setSelection( sel.x1, sel.y1, sel.x2, r );594 this.iasapi.update();666 if ( dispatchSuccess ) return 1; 667 return 0; 595 668 } 669 return -1; 670 }, 671 672 /** 673 * 674 * @type string Event type constants. 675 */ 676 events : { 677 INIT_EVENT : "zg-extend-image-edit-init-event", 678 OPEN_EVENT : "zg-extend-image-edit-open-event" 596 679 } 597 } 598 }; 599 })(jQuery); 680 }; 681 })( jQuery );