Improved coupon product id input. Closes #157.

This commit is contained in:
Mike Jolley 2012-03-06 15:46:53 +00:00
parent 5eedbc6607
commit 32e7140517
10 changed files with 320 additions and 58 deletions

View File

@ -26,6 +26,8 @@ function woocommerce_coupon_data_meta_box($post) {
<div id="coupon_options" class="panel woocommerce_options_panel">
<?php
echo '<div class="options_group">';
// Type
woocommerce_wp_select( array( 'id' => 'discount_type', 'label' => __('Discount type', 'woocommerce'), 'options' => $woocommerce->get_coupon_discount_types() ) );
@ -41,17 +43,63 @@ function woocommerce_coupon_data_meta_box($post) {
// Free Shipping
woocommerce_wp_checkbox( array( 'id' => 'free_shipping', 'label' => __('Enable free shipping', 'woocommerce'), 'description' => sprintf(__('Check this box if the coupon enables free shipping (see <a href="%s">Free Shipping</a>)', 'woocommerce'), admin_url('admin.php?page=woocommerce&tab=shipping_methods&subtab=shipping-free_shipping')) ) );
echo '</div><div class="options_group">';
// Product ids
woocommerce_wp_text_input( array( 'id' => 'product_ids', 'label' => __('Product IDs', 'woocommerce'), 'placeholder' => _x('N/A', 'placeholder', 'woocommerce'), 'description' => __('(optional) Comma separate IDs which need to be in the cart to use this coupon or, for "Product Discounts", which products are discounted.', 'woocommerce') ) );
?>
<p class="form-field"><label for="product_ids"><?php _e('Products', 'woocommerce') ?></label>
<select id="product_ids" name="product_ids[]" class="ajax_chosen_select_products" multiple="multiple" data-placeholder="<?php _e('Search for a product...', 'woocommerce'); ?>">
<?php
$product_ids = get_post_meta( $post->ID, 'product_ids', true );
if ($product_ids) {
$product_ids = explode(',', $product_ids);
foreach ($product_ids as $product_id) {
$title = get_the_title($product_id);
$sku = get_post_meta($product_id, '_sku', true);
if (!$title) continue;
if (isset($sku) && $sku) $sku = ' (SKU: ' . $sku . ')';
echo '<option value="'.$product_id.'" selected="selected">'. $title . $sku .'</option>';
}
}
?>
</select> <img class="help_tip" tip="<?php _e('Products which need to be in the cart to use this coupon or, for "Product Discounts", which products are discounted.', 'woocommerce') ?>" src="<?php echo $woocommerce->plugin_url(); ?>/assets/images/help.png" /></p>
<?php
// Exclude Product ids
woocommerce_wp_text_input( array( 'id' => 'exclude_product_ids', 'label' => __('Exclude Product IDs', 'woocommerce'), 'placeholder' => _x('N/A', 'placeholder', 'woocommerce'), 'description' => __('(optional) Comma separate IDs which must not be in the cart to use this coupon or, for "Product Discounts", which products are not discounted.', 'woocommerce') ) );
?>
<p class="form-field"><label for="exclude_product_ids"><?php _e('Exclude Products', 'woocommerce') ?></label>
<select id="exclude_product_ids" name="exclude_product_ids[]" class="ajax_chosen_select_products" multiple="multiple" data-placeholder="<?php _e('Search for a product…', 'woocommerce'); ?>">
<?php
$product_ids = get_post_meta( $post->ID, 'exclude_product_ids', true );
if ($product_ids) {
$product_ids = explode(',', $product_ids);
foreach ($product_ids as $product_id) {
$title = get_the_title($product_id);
$sku = get_post_meta($product_id, '_sku', true);
if (!$title) continue;
if (isset($sku) && $sku) $sku = ' (SKU: ' . $sku . ')';
echo '<option value="'.$product_id.'" selected="selected">'. $title . $sku .'</option>';
}
}
?>
</select> <img class="help_tip" tip="<?php _e('Products which must not be in the cart to use this coupon or, for "Product Discounts", which products are not discounted.', 'woocommerce') ?>" src="<?php echo $woocommerce->plugin_url(); ?>/assets/images/help.png" /></p>
<?php
echo '</div><div class="options_group">';
// Usage limit
woocommerce_wp_text_input( array( 'id' => 'usage_limit', 'label' => __('Usage limit', 'woocommerce'), 'placeholder' => _x('Unlimited usage', 'placeholder', 'woocommerce'), 'description' => __('(optional) How many times this coupon can be used before it is void', 'woocommerce') ) );
woocommerce_wp_text_input( array( 'id' => 'usage_limit', 'label' => __('Usage limit', 'woocommerce'), 'placeholder' => _x('Unlimited usage', 'placeholder', 'woocommerce'), 'description' => __('How many times this coupon can be used before it is void', 'woocommerce') ) );
// Expiry date
woocommerce_wp_text_input( array( 'id' => 'expiry_date', 'label' => __('Expiry date', 'woocommerce'), 'placeholder' => _x('Never expire', 'placeholder', 'woocommerce'), 'description' => __('(optional) The date this coupon will expire, <code>YYYY-MM-DD</code>', 'woocommerce'), 'class' => 'short date-picker' ) );
woocommerce_wp_text_input( array( 'id' => 'expiry_date', 'label' => __('Expiry date', 'woocommerce'), 'placeholder' => _x('Never expire', 'placeholder', 'woocommerce'), 'description' => __('The date this coupon will expire, <code>YYYY-MM-DD</code>', 'woocommerce'), 'class' => 'short date-picker' ) );
echo '</div>';
do_action('woocommerce_coupon_options');
@ -75,14 +123,26 @@ function woocommerce_process_shop_coupon_meta( $post_id, $post ) {
// Add/Replace data to array
$type = strip_tags(stripslashes( $_POST['discount_type'] ));
$amount = strip_tags(stripslashes( $_POST['coupon_amount'] ));
$product_ids = strip_tags(stripslashes( $_POST['product_ids'] ));
$exclude_product_ids = strip_tags(stripslashes( $_POST['exclude_product_ids'] ));
$usage_limit = (isset($_POST['usage_limit']) && $_POST['usage_limit']>0) ? (int) $_POST['usage_limit'] : '';
$individual_use = isset($_POST['individual_use']) ? 'yes' : 'no';
$expiry_date = strip_tags(stripslashes( $_POST['expiry_date'] ));
$apply_before_tax = isset($_POST['apply_before_tax']) ? 'yes' : 'no';
$free_shipping = isset($_POST['free_shipping']) ? 'yes' : 'no';
if (isset($_POST['product_ids'])) {
$product_ids = (array) $_POST['product_ids'];
$product_ids = implode(',', array_filter(array_map('intval', $product_ids)));
} else {
$product_ids = '';
}
if (isset($_POST['exclude_product_ids'])) {
$exclude_product_ids = (array) $_POST['exclude_product_ids'];
$exclude_product_ids = implode(',', array_filter(array_map('intval', $exclude_product_ids)));
} else {
$exclude_product_ids = '';
}
// Save
update_post_meta( $post_id, 'discount_type', $type );
update_post_meta( $post_id, 'coupon_amount', $amount );

View File

@ -640,7 +640,7 @@ function process_product_meta_variable( $post_id ) {
// Disabled if downloadable and no URL
if ($is_downloadable=='yes' && !$variable_file_path[$i]) $post_status = 'private';
// Generate a useful post title
/*// Generate a useful post title
$title = array();
foreach ($attributes as $attribute) :
@ -650,14 +650,16 @@ function process_product_meta_variable( $post_id ) {
endif;
endforeach;
$sku_string = '#'.$variation_id;
if ($variable_sku[$i]) $sku_string .= ' SKU: ' . $variable_sku[$i];
$sku_string = ($variable_sku[$i]) ? sprintf(__('(SKU: %s)', 'woocommerce'), $variable_sku[$i]) : sprintf(__('(ID: #%s)', 'woocommerce'), $variation_id);
*/
$variation_post_title = sprintf(__('Variation #%s of %s', 'woocommerce'), $variation_id, get_the_title($post_id));
// Update or Add post
if (!$variation_id) :
$variation = array(
'post_title' => '#' . $post_id . ' Variation ('.$sku_string.') - ' . implode(', ', $title),
'post_title' => $variation_post_title,
'post_content' => '',
'post_status' => $post_status,
'post_author' => get_current_user_id(),
@ -668,7 +670,7 @@ function process_product_meta_variable( $post_id ) {
else :
$wpdb->update( $wpdb->posts, array( 'post_status' => $post_status, 'post_title' => '#' . $post_id . ' Variation ('.$sku_string.') - ' . implode(', ', $title) ), array( 'ID' => $variation_id ) );
$wpdb->update( $wpdb->posts, array( 'post_status' => $post_status, 'post_title' => $variation_post_title ), array( 'ID' => $variation_id ) );
endif;

View File

@ -179,6 +179,7 @@ function woocommerce_admin_scripts() {
wp_register_script( 'woocommerce_admin', $woocommerce->plugin_url() . '/assets/js/admin/woocommerce_admin'.$suffix.'.js', array('jquery', 'jquery-ui-widget', 'jquery-ui-core'), '1.0' );
wp_register_script( 'jquery-ui-datepicker', $woocommerce->plugin_url() . '/assets/js/admin/ui-datepicker.js', array('jquery','jquery-ui-core'), '1.0' );
wp_register_script( 'woocommerce_writepanel', $woocommerce->plugin_url() . '/assets/js/admin/write-panels'.$suffix.'.js', array('jquery', 'jquery-ui-datepicker') );
wp_register_script( 'ajax-chosen', $woocommerce->plugin_url() . '/assets/js/ajax-chosen.jquery'.$suffix.'.js', array('jquery', 'chosen'), '1.0' );
wp_register_script( 'chosen', $woocommerce->plugin_url() . '/assets/js/chosen.jquery'.$suffix.'.js', array('jquery'), '1.0' );
// Get admin screen id
@ -189,6 +190,7 @@ function woocommerce_admin_scripts() {
wp_enqueue_script( 'woocommerce_admin' );
wp_enqueue_script('farbtastic');
wp_enqueue_script( 'ajax-chosen' );
wp_enqueue_script( 'chosen' );
wp_enqueue_script('jquery-ui-sortable');
@ -209,6 +211,7 @@ function woocommerce_admin_scripts() {
wp_enqueue_script( 'jquery-ui-datepicker' );
wp_enqueue_script( 'media-upload' );
wp_enqueue_script( 'thickbox' );
wp_enqueue_script( 'ajax-chosen' );
wp_enqueue_script( 'chosen' );
$woocommerce_witepanel_params = array(
@ -241,7 +244,7 @@ function woocommerce_admin_scripts() {
'add_order_item_nonce' => wp_create_nonce("add-order-item"),
'calc_totals_nonce' => wp_create_nonce("calc-totals"),
'get_customer_details_nonce' => wp_create_nonce("get-customer-details"),
'upsell_crosssell_search_products_nonce' => wp_create_nonce("search-products"),
'search_products_nonce' => wp_create_nonce("search-products"),
'calendar_image' => $woocommerce->plugin_url().'/assets/images/calendar.png',
'post_id' => $post->ID
);

File diff suppressed because one or more lines are too long

View File

@ -1167,33 +1167,12 @@ table.wc_gateways, table.wc_shipping {
}
}
img.help_tip {
vertical-align: middle;
margin: 0 0 0 9px;
}
.woocommerce {
table.widefat {
table.coupon_rows {
border: 0 !important;
width: 100%;
thead {
th {
padding: 1px;
border: 0;
font-weight: normal;
font-size: 11px;
color: #999;
}
}
tbody {
td {
padding: 3px 3px 0 0;
border: 0;
vertical-align: middle;
input.text {
width: 95px;
}
}
}
}
}
table.form-table {
margin: 0 0 0;
textarea.input-text {
@ -1208,6 +1187,7 @@ table.wc_gateways, table.wc_shipping {
margin: -4px 0 0 5px;
vertical-align: middle;
cursor: help;
line-height: 1;
}
}
}
@ -1340,7 +1320,7 @@ table.wc_gateways, table.wc_shipping {
}
}
#woocommerce-product-data .inside, #woocommerce-product-type-options .inside, #woocommerce-order-data .inside, #woocommerce-product-type .inside, #woocommerce-order-downloads .inside {
#woocommerce-product-data .inside, #woocommerce-product-type-options .inside, #woocommerce-order-data .inside, #woocommerce-product-type .inside, #woocommerce-order-downloads .inside, #woocommerce-coupon-data .inside {
padding: 0;
margin: 0;
}
@ -1356,12 +1336,17 @@ table.wc_gateways, table.wc_shipping {
margin: 0;
}
.woocommerce_options_panel p, #woocommerce-product-type-options .panel p {
overflow: hidden;
zoom: 1;
margin: 0 0 9px;
font-size: 12px;
padding: 5px 9px;
line-height: 24px;
&:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
}
.woocommerce_options_panel p {
margin: 9px 0 9px;
@ -1950,6 +1935,13 @@ table.bar_chart {
width: 300px !important;
}
}
.form-field .chzn-container {
width: 60% !important;
float: left;
li.search-field input {
width: 100% !important;
}
}
.chzn-container .chzn-drop {
background: #fff;
border: 1px solid #aaa;

View File

@ -19,6 +19,77 @@ jQuery( function($){
return false;
});
// Chosen selects
jQuery("select.chosen_select").chosen();
jQuery("select.chosen_select_nostd").chosen({
allow_single_deselect: 'true'
});
// Ajax Chosen Product Selector
jQuery("select.ajax_chosen_select_products").ajaxChosen({
method: 'GET',
url: woocommerce_writepanel_params.ajax_url,
dataType: 'json',
data: {
action: 'woocommerce_json_search_products',
security: woocommerce_writepanel_params.search_products_nonce
}
}, function (data) {
var terms = {};
$.each(data, function (i, val) {
terms[i] = val;
});
return terms;
});
$('.multi_select_products #product_search').bind('keyup click', function(){
$('.multi_select_products_source').addClass('loading');
$('.multi_select_products_source li:not(.product_search)').remove();
var search = $(this).val();
var input = this;
var name = $(this).attr('rel');
if (search.length<3) {
$('.multi_select_products_source').removeClass('loading');
return;
}
var data = {
name: name,
search: encodeURI(search),
action: 'woocommerce_upsell_crosssell_search_products',
security: woocommerce_writepanel_params.search_products_nonce
};
xhr = $.ajax({
url: woocommerce_writepanel_params.ajax_url,
data: data,
type: 'POST',
success: function( response ) {
$('.multi_select_products_source').removeClass('loading');
$('.multi_select_products_source li:not(.product_search)').remove();
$(input).parent().parent().append( response );
}
});
});
// ORDERS
jQuery('#woocommerce-order-actions input, #woocommerce-order-actions a').click(function(){
window.onbeforeunload = '';
@ -32,13 +103,6 @@ jQuery( function($){
event.preventDefault();
});
// Chosen selects
jQuery("select.chosen_select").chosen();
jQuery("select.chosen_select_nostd").chosen({
allow_single_deselect: 'true'
});
$('#order_items_list .remove_row').live('click', function(){
var answer = confirm(woocommerce_writepanel_params.remove_item_notice);
if (answer){
@ -48,7 +112,6 @@ jQuery( function($){
return false;
});
$('button.calc_line_taxes').live('click', function(){
// Block write panel
$('.woocommerce_order_items_wrapper').block({ message: null, overlayCSS: { background: '#fff url(' + woocommerce_writepanel_params.plugin_url + '/assets/images/ajax-loader.gif) no-repeat center', opacity: 0.6 } });
@ -185,9 +248,6 @@ jQuery( function($){
$('#woocommerce-order-totals .calculated').css('background-color', '');
});
$('button.add_shop_order_item').click(function(){
var add_item_id = $('select.add_item_id').val();
@ -733,7 +793,7 @@ jQuery( function($){
name: name,
search: encodeURI(search),
action: 'woocommerce_upsell_crosssell_search_products',
security: woocommerce_writepanel_params.upsell_crosssell_search_products_nonce
security: woocommerce_writepanel_params.search_products_nonce
};
xhr = $.ajax({

File diff suppressed because one or more lines are too long

74
assets/js/ajax-chosen.jquery.js Executable file
View File

@ -0,0 +1,74 @@
(function() {
(function($) {
var chosen_xhr;
return $.fn.ajaxChosen = function(options, callback) {
var select;
select = this;
this.chosen();
this.next('.chzn-container').find(".search-field > input").bind('keyup', function() {
var field, val;
val = $.trim($(this).attr('value'));
if (val.length < 3 || val === $(this).data('prevVal')) return false;
if (this.timer) clearTimeout(this.timer);
$(this).data('prevVal', val);
field = $(this);
options.data.term = val;
if (typeof success === "undefined" || success === null) {
success = options.success;
}
options.success = function(data) {
var items;
if (!(data != null)) return;
select.find('option').each(function() {
if (!$(this).is(":selected")) return $(this).remove();
});
items = callback(data);
$.each(items, function(value, text) {
return $("<option />").attr('value', value).html(text).appendTo(select);
});
select.trigger("liszt:updated");
field.attr('value', val);
if (typeof success !== "undefined" && success !== null) return success();
};
return this.timer = setTimeout(function() {
if (chosen_xhr) chosen_xhr.abort();
chosen_xhr = $.ajax(options);
return chosen_xhr;
}, 800);
});
return this.next('.chzn-container').find(".chzn-search > input").bind('keyup', function() {
var field, val;
val = $.trim($(this).attr('value'));
if (val.length < 3 || val === $(this).data('prevVal')) return false;
field = $(this);
options.data = {
term: val
};
if (typeof success === "undefined" || success === null) {
success = options.success;
}
options.success = function(data) {
var items;
if (!(data != null)) return;
select.find('option').each(function() {
return $(this).remove();
});
items = callback(data);
$.each(items, function(value, text) {
return $("<option />").attr('value', value).html(text).appendTo(select);
});
select.trigger("liszt:updated");
field.attr('value', val);
if (typeof success !== "undefined" && success !== null) return success();
};
return this.timer = setTimeout(function() {
if (chosen_xhr) chosen_xhr.abort();
chosen_xhr = $.ajax(options);
return chosen_xhr;
}, 800);
});
};
})(jQuery);
}).call(this);

1
assets/js/ajax-chosen.jquery.min.js vendored Normal file
View File

@ -0,0 +1 @@
((function(){(function(a){var b;return a.fn.ajaxChosen=function(c,d){var e;e=this;this.chosen();this.next(".chzn-container").find(".search-field > input").bind("keyup",function(){var f,g;g=a.trim(a(this).attr("value"));if(g.length<3||g===a(this).data("prevVal"))return!1;this.timer&&clearTimeout(this.timer);a(this).data("prevVal",g);f=a(this);c.data.term=g;if(typeof success=="undefined"||success===null)success=c.success;c.success=function(b){var c;if(b==null)return;e.find("option").each(function(){if(!a(this).is(":selected"))return a(this).remove()});c=d(b);a.each(c,function(b,c){return a("<option />").attr("value",b).html(c).appendTo(e)});e.trigger("liszt:updated");f.attr("value",g);if(typeof success!="undefined"&&success!==null)return success()};return this.timer=setTimeout(function(){b&&b.abort();b=a.ajax(c);return b},800)});return this.next(".chzn-container").find(".chzn-search > input").bind("keyup",function(){var f,g;g=a.trim(a(this).attr("value"));if(g.length<3||g===a(this).data("prevVal"))return!1;f=a(this);c.data={term:g};if(typeof success=="undefined"||success===null)success=c.success;c.success=function(b){var c;if(b==null)return;e.find("option").each(function(){return a(this).remove()});c=d(b);a.each(c,function(b,c){return a("<option />").attr("value",b).html(c).appendTo(e)});e.trigger("liszt:updated");f.attr("value",g);if(typeof success!="undefined"&&success!==null)return success()};return this.timer=setTimeout(function(){b&&b.abort();b=a.ajax(c);return b},800)})}})(jQuery)})).call(this);

View File

@ -815,6 +815,76 @@ function woocommerce_delete_order_note() {
die();
}
/**
* Search for products and return json
*/
add_action('wp_ajax_woocommerce_json_search_products', 'woocommerce_json_search_products');
function woocommerce_json_search_products() {
check_ajax_referer( 'search-products', 'security' );
$term = (string) urldecode(stripslashes(strip_tags($_GET['term'])));
if (empty($term)) die();
if (is_numeric($term)) {
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => -1,
'post__in' => array(0, $term),
'fields' => 'ids'
);
$posts = get_posts( $args );
} else {
$args = array(
'post_type' => array('product', 'product_variation'),
'post_status' => 'publish',
'posts_per_page' => -1,
's' => $term,
'fields' => 'ids'
);
$args2 = array(
'post_type' => array('product', 'product_variation'),
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => '_sku',
'value' => $term,
'compare' => 'LIKE'
)
),
'fields' => 'ids'
);
$posts = array_unique(array_merge( get_posts( $args ), get_posts( $args2 ) ));
}
$found_products = array();
if ($posts) foreach ($posts as $post) {
$SKU = get_post_meta($post, '_sku', true);
if (isset($SKU) && $SKU) $SKU = ' (SKU: ' . $SKU . ')';
$found_products[$post] = get_the_title($post) . $SKU;
}
echo json_encode( $found_products );
die();
}
/**
* Search for products for upsells/crosssells
*/