Work on the product images panel. Closes #1504.

This commit is contained in:
Mike Jolley 2012-10-04 18:09:18 +01:00
parent d9e3e5a94f
commit 7236192711
10 changed files with 523 additions and 13 deletions

View File

@ -0,0 +1,186 @@
<?php
/**
* Product Images
*
* Function for displaying the product images meta box.
*
* @author WooThemes
* @category Admin
* @package WooCommerce/Admin/WritePanels
* @version 1.7.0
*/
/**
* Display the product images meta box.
*
* @access public
* @return void
*/
function woocommerce_product_images_box() {
global $post;
$thumbnail_id = get_post_thumbnail_id( $post->ID );
$ajax_nonce = wp_create_nonce( "set_post_thumbnail-$post->ID" );
?>
<div id="product_images_container">
<ul>
<!-- Current images -->
<?php
$attachments =& get_children( 'post_parent=' . $post->ID . '&numberposts=-1&post_type=attachment&orderby=menu_order&order=ASC&post_mime_type=image' );
foreach ( $attachments as $attachment_id => $attachment ) {
echo '<li class="image" data-post_id="' . $attachment_id . '"><a href="' . admin_url( 'media-upload.php?post_id=' . $post->ID . '&attachment_id=' . $attachment_id . '&tab=library&width=640&height=553&TB_iframe=1' ) . '" class="thickbox" onclick="return false;">' . wp_get_attachment_image( $attachment_id, 'full' ) . '<span class="loading"></span></a></li>';
}
?>
<!-- Uploader section -->
<li id="plupload-upload-ui" class="hide-if-no-js add">
<div id="drag-drop-area">
<p class="drag-drop-info"><?php _e('Drop files here'); ?></p>
<p><?php _ex('or', 'Uploader: Drop files here - or - Select Files'); ?></p>
<p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
</div>
</li>
</ul>
</div>
<?php
// Drag and drop code adapted from Drag & Drop Featured Image by Jonathan Lundström
$plupload_init = array(
'runtimes' => 'html5,silverlight,flash,html4',
'browse_button' => 'plupload-browse-button',
'container' => 'plupload-upload-ui',
'drop_element' => 'drag-drop-area',
'file_data_name' => 'async-upload',
'multiple_queues' => true,
'max_file_size' => wp_max_upload_size() . 'b',
'url' => admin_url('admin-ajax.php'),
'flash_swf_url' => includes_url('js/plupload/plupload.flash.swf'),
'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
'filters' => array( array( 'title' => __( 'Allowed Files' ), 'extensions' => '*') ),
'multipart' => true,
'urlstream_upload' => true,
'multipart_params' => array(
'_ajax_nonce' => wp_create_nonce( 'product-images-box-upload' ),
'action' => 'woocommerce_product_images_box_upload',
'post_id' => $post->ID
)
);
// Apply filters to initiate plupload:
$plupload_init = apply_filters( 'plupload_init', $plupload_init );
?>
<script type="text/javascript">
jQuery(document).ready(function($){
// Attribute ordering
$('#product_images_container ul').sortable({
items: 'li.image',
cursor: 'move',
scrollSensitivity:40,
forcePlaceholderSize: true,
forceHelperSize: false,
helper: 'clone',
opacity: 0.65,
placeholder: 'wc-metabox-sortable-placeholder',
start:function(event,ui){
ui.item.css('background-color','#f6f6f6');
},
stop:function(event,ui){
ui.item.removeAttr('style');
},
update: function(event, ui) {
$('#product_images_container ul li').css('cursor','default');
$('#product_images_container ul').sortable('disable');
var post_id = <?php echo $post->ID; ?>;
var attachment_id = ui.item.attr( 'data-post_id' );
var prev_attachment_id = ui.item.prev().attr( 'data-post_id' );
var next_attachment_id = ui.item.next().attr( 'data-post_id' );
// show spinner
ui.item.addClass('loading');
// go do the sorting stuff via ajax
jQuery.post( ajaxurl, {
action: 'woocommerce_product_image_ordering',
post_id: post_id,
attachment_id: attachment_id,
prev_attachment_id: prev_attachment_id,
next_attachment_id: next_attachment_id,
_ajax_nonce: '<?php echo wp_create_nonce( 'product-image-ordering' ); ?>'
}, function( response ) {
ui.item.removeClass('loading');
$('#product_images_container ul li').css('cursor','move');
$('#product_images_container ul').sortable('enable');
}
);
}
});
// Drag and drop uploading of images
var uploader = new plupload.Uploader(<?php echo json_encode( $plupload_init ); ?>);
// Check for drag'n'drop functionality:
uploader.bind('Init', function(up){
var uploaddiv = $('#plupload-upload-ui');
// Add classes and bind actions:
if(up.features.dragdrop){
uploaddiv.addClass('drag-drop');
$('#drag-drop-area')
.bind('dragover.wp-uploader', function() { uploaddiv.addClass('drag-over'); })
.bind('dragleave.wp-uploader, drop.wp-uploader', function(){ uploaddiv.removeClass('drag-over'); });
} else{
uploaddiv.removeClass('drag-drop');
$('#drag-drop-area').unbind('.wp-uploader');
}
});
// Initiate uploading script:
uploader.init();
// File queue handler
uploader.bind('FilesAdded', function(up, files){
var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10);
// Loop through files:
plupload.each(files, function(file){
if ( max > hundredmb && file.size > hundredmb && up.runtime != 'html5' ) {
alert( "<?php _e( 'The file you selected exceeds the maximum filesize specified in this installation.', 'woocommerce' ); ?>" );
}
});
// Refresh and start:
up.refresh();
up.start();
// Block the UI
$('#product_images_container').block({ message: null, overlayCSS: { background: '#fff url(' + woocommerce_writepanel_params.plugin_url + '/assets/images/ajax-loader.gif) no-repeat center', opacity: 0.6 } });
});
// Handle new uploads
uploader.bind( 'FileUploaded', function( up, file, response ) {
response = $.parseJSON( response.response );
if ( response.error ) {
alert( response.error );
} else {
$('#plupload-upload-ui').before('<li class="image" data-post_id="' + response.post_id + '"><img src="' + response.src + '" /><span class="loading"></span></li>');
}
$('#product_images_container').unblock();
});
});
</script>
<?php
}

View File

@ -13,6 +13,9 @@
/** Product data writepanel */
include_once('writepanel-product_data.php');
/** Product images writepanel */
include_once('writepanel-product_images.php');
/** Coupon data writepanel */
include_once('writepanel-coupon_data.php');
@ -38,10 +41,13 @@ function woocommerce_meta_boxes() {
global $post;
// Products
add_meta_box( 'woocommerce-product-data', __('Product Data', 'woocommerce'), 'woocommerce_product_data_box', 'product', 'normal', 'high' );
add_meta_box( 'woocommerce-product-data', __( 'Product Data', 'woocommerce' ), 'woocommerce_product_data_box', 'product', 'normal', 'high' );
add_meta_box( 'woocommerce-product-images', __( 'Product Images', 'woocommerce' ), 'woocommerce_product_images_box', 'product', 'side' );
remove_meta_box( 'product_shipping_classdiv', 'product', 'side' );
remove_meta_box( 'pageparentdiv', 'product', 'side' );
remove_meta_box( 'postimagediv', 'product', 'side' );
// Excerpt
if ( function_exists('wp_editor') ) {
remove_meta_box( 'postexcerpt', 'product', 'normal' );

View File

@ -368,6 +368,7 @@ function woocommerce_admin_scripts() {
wp_enqueue_script( 'thickbox' );
wp_enqueue_script( 'ajax-chosen' );
wp_enqueue_script( 'chosen' );
wp_enqueue_script( 'plupload-all' );
$woocommerce_witepanel_params = array(
'remove_item_notice' => __("Remove this item? If you have previously reduced this item's stock, or this order was submitted by a customer, will need to manually restore the item's stock.", 'woocommerce'),

File diff suppressed because one or more lines are too long

View File

@ -2278,4 +2278,190 @@ table.bar_chart {
}
}
@import 'chosen.less';
@import 'chosen.less';
#woocommerce-product-images {
.inside {
margin: 0;
padding: 0;
#product_images_container {
padding: 9px 0 9px 9px;
ul {
overflow: hidden;
margin: 0;
padding: 0;
li {
width: 80px;
height: 80px;
overflow: hidden;
float: left;
cursor: move;
border: 1px solid #d5d5d5;
margin: 0 9px 9px 0;
background: #f7f7f7;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
position: relative;
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */
img {
width: 100%;
height: auto;
display: block;
}
.loading {
background: #fff url(../images/ajax-loader.gif) no-repeat center;
width: 100%;
height: 100%;
opacity: 0.5;
position: absolute;
display: none;
top:0;
left: 0;
}
}
li.wc-metabox-sortable-placeholder {
border: 4px dashed #dddddd;
background: #f7f7f7 url(../images/image_watermark.png) no-repeat center;
}
li.wc-metabox-sortable-placeholder:first-child {
background: #f7f7f7 url(../images/star_watermark.png) no-repeat center;
}
li.ui-sortable-helper {
width: 80px !important;
height: 80px !important;
}
li.add {
text-align: center;
color: #999;
background: none;
cursor: default !important;
border: 0;
width: 258px;
height: auto;
margin: 0;
#drag-drop-area {
padding: 20px 0;
height: auto;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */
line-height: 1.4em;
p {
color: #AAA;
font-size: 14px;
margin: 5px 0;
}
p.drag-drop-info {
font-size: 20px;
}
}
}
li.loading {
.loading {
display: block;
}
}
}
li:first-child {
margin: 0 0 9px 0;
width: 258px;
height: 258px;
}
}
}
}
div#current-uploaded-image {
width: 100%;
overflow: hidden;
margin-bottom: 10px;
position: relative;
}
div#current-uploaded-image.closed {
display: none;
}
div#current-uploaded-image p.hide-if-no-js {
width: 100%;
margin: -8px 0px 0px 0px;
position: absolute;
top: 50%; left: 0;
text-align: center;
display: none;
}
div#current-uploaded-image:hover p.hide-if-no-js { display: block; }
div#current-uploaded-image p.hide-if-no-js a {
border: none;
box-shadow: none;
}
div#current-uploaded-image img {
width: 100%;
height: auto !important;
display: block;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
div#uploaderSection div.loading {
width: 32px;
height: 32px;
position: absolute;
top: 50%; left: 50%;
margin: -16px 0px 0px -16px;
display: none;
}
div#drag-drop-area {
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
div.objectRow {
overflow: hidden;
padding-top: 5px;
}
div.toggleObject {
float: left;
width: auto;
height: auto;
margin: 0px 20px 0px 0px;
font-size: 12px;
font-weight: bold;
text-align: center;
}
div.toggleObject p { margin-top: -14px; }
input.filesizeLimit {
width: 260px;
padding: 6px 6px;
margin-top: 10px;
}
div.blobContainer { overflow: hidden; }
div.blobContainer img {
float: left;
margin-left: -2px;
filter: alpha(opacity=70);
-khtml-opacity: 0.7;
-moz-opacity: 0.7;
opacity: 0.7;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

View File

@ -145,25 +145,27 @@ class WC_Customer {
/**
* Is customer outside base country?
* Is customer outside base country (for tax purposes)?
*
* @access public
* @return bool
*/
function is_customer_outside_base() {
global $woocommerce;
if ( isset( $this->_data['country'] ) ) {
list( $country, $state, $postcode, $city ) = $this->get_taxable_address();
if ( $country ) {
$default = get_option('woocommerce_default_country');
if ( strstr( $default, ':' ) ) {
list( $country, $state ) = explode( ':', $default );
list( $default_country, $default_state ) = explode( ':', $default );
} else {
$country = $default;
$state = '';
$default_country = $default;
$default_state = '';
}
if ( $country !== $this->_data['shipping_country'] ) return true;
if ( $state && $state !== $this->_data['shipping_state'] ) return true;
if ( $default_country !== $country ) return true;
if ( $default_state && $default_state !== $state ) return true;
}
return false;

View File

@ -165,6 +165,7 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woothemes/wooc
* Feature - Added "Best Selling" shortcode
* Feature - Added "Top Rated" shortcode
* Feature - Local pickup has the option to apply base tax rates instead of customer address rates.
* Feature - New product images panel to make working with featured images + galleries easier.
* Templating - email-order-items.php change get_downloadable_file_url() to get_downloadable_file_urls() to support multiple files.
* Templating - loop-end and start for product loops, allow changing the UL's used by default to something else.

View File

@ -1335,4 +1335,132 @@ function woocommerce_product_ordering() {
die( json_encode( $new_pos ) );
}
add_action( 'wp_ajax_woocommerce_product_ordering', 'woocommerce_product_ordering' );
add_action( 'wp_ajax_woocommerce_product_ordering', 'woocommerce_product_ordering' );
/**
* woocommerce_product_images_box_upload function.
*
* @access public
* @return void
*/
function woocommerce_product_images_box_upload() {
check_ajax_referer( 'product-images-box-upload' );
// Get posted data
$file = $_FILES['async-upload'];
$post_id = absint( $_POST['post_id'] );
// Upload
$upload = wp_handle_upload( $file, array( 'test_form' => false ) );
if( ! isset( $upload['error'] ) && isset( $upload['file'] ) ) {
// Create attachment
require_once( ABSPATH . 'wp-admin/includes/image.php' );
$attachment_id = wp_insert_attachment( array(
'post_mime_type' => $upload['type'],
'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $upload['file'] ) ),
'post_content' => '',
'post_status' => 'inherit'
), $upload['file'], $post_id );
$attachment_data = wp_generate_attachment_metadata( $attachment_id, $upload['file'] );
wp_update_attachment_metadata( $attachment_id, $attachment_data );
// Return the result
$image = wp_get_attachment_image_src( $attachment_id, 'full' );
$result = array(
'src' => $image[0],
'post_id' => $post_id
);
} else {
$result = array(
'error' => $upload['error']
);
}
echo json_encode( $result );
die();
}
add_action( 'wp_ajax_woocommerce_product_images_box_upload', 'woocommerce_product_images_box_upload' );
/**
* woocommerce_product_image_ordering function.
*
* @access public
* @return void
*/
function woocommerce_product_image_ordering() {
check_ajax_referer( 'product-image-ordering' );
$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : false;
$attachment_id = isset( $_POST['attachment_id'] ) ? absint( $_POST['attachment_id'] ) : false;
$prev_attachment_id = isset( $_POST['prev_attachment_id'] ) ? absint( $_POST['prev_attachment_id'] ) : false;
$next_attachment_id = isset( $_POST['next_attachment_id'] ) ? absint( $_POST['next_attachment_id'] ) : false;
if ( ! $post_id || ! $attachment_id )
die( -1 );
$siblings = get_children( 'post_parent=' . $post_id . '&numberposts=-1&post_type=attachment&orderby=menu_order&order=ASC&post_mime_type=image' );
$new_positions = array(); // store new positions for ajax
$menu_order = 0;
foreach( $siblings as $sibling_id => $sibling ) {
if ( $sibling_id == $attachment_id )
continue;
// if this is the post that comes after our repositioned post, set our repositioned post position and increment menu order
if ( $next_attachment_id && $next_attachment_id == $sibling_id ) {
$attachment = array();
$attachment['ID'] = $attachment_id;
$attachment['menu_order'] = $menu_order;
wp_update_post( $attachment );
$new_positions[ $attachment_id ] = $menu_order;
$menu_order++;
}
// if repositioned post has been set, and new items are already in the right order, we can stop
if ( isset( $new_positions[ $attachment_id ] ) && $sibling->menu_order >= $menu_order )
break;
// set the menu order of the current sibling and increment the menu order
$attachment = array();
$attachment['ID'] = $sibling_id;
$attachment['menu_order'] = $menu_order;
wp_update_post( $attachment );
$new_positions[ $sibling_id ] = $menu_order;
$menu_order++;
if ( ! $next_attachment_id && $prev_attachment_id == $sibling_id ) {
$attachment = array();
$attachment['ID'] = $attachment_id;
$attachment['menu_order'] = $menu_order;
wp_update_post( $attachment );
$new_positions[ $attachment_id ] = $menu_order;
$menu_order++;
}
}
die();
}
add_action( 'wp_ajax_woocommerce_product_image_ordering', 'woocommerce_product_image_ordering' );