Add attributes with ajax and don't load all attributes at once.

Significantly improves performance with many attributes in admin.
Closes #6852 cc @claudiosmweb
This commit is contained in:
Mike Jolley 2014-12-22 14:16:12 +00:00
parent 8df8c9b482
commit 22cc1fb0c7
5 changed files with 165 additions and 221 deletions

View File

@ -278,66 +278,38 @@ jQuery( function( $ ){
}); });
// Add rows // Add rows
$('button.add_attribute').on('click', function(){ $( 'button.add_attribute' ).on('click', function(){
var size = $( '.product_attributes .woocommerce_attribute' ).size();
var attribute = $( 'select.attribute_taxonomy' ).val();
var $wrapper = $( this ).closest( '#product_attributes' ).find( '.product_attributes' );
var product_type = $( 'select#product-type' ).val();
var data = {
action : 'woocommerce_add_attribute',
taxonomy : attribute,
i : size,
security : woocommerce_admin_meta_boxes.add_attribute_nonce
};
var size = $('.product_attributes .woocommerce_attribute').size(); $wrapper.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });
var attribute_type = $('select.attribute_taxonomy').val(); $.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
$wrapper.append( response );
if ( ! attribute_type ) { if ( product_type !== 'variable' ) {
$wrapper.find( '.enable_variation' ).hide();
}
var product_type = $('select#product-type').val(); $wrapper.find( 'select.multiselect' ).chosen();
if (product_type!='variable') enable_variation = 'style="display:none;"'; else enable_variation = '';
// Add custom attribute row
$('.product_attributes').append('<div class="woocommerce_attribute wc-metabox">\
<h3>\
<button type="button" class="remove_row button">' + woocommerce_admin_meta_boxes.remove_label + '</button>\
<div class="handlediv" title="' + woocommerce_admin_meta_boxes.click_to_toggle + '"></div>\
<strong class="attribute_name"></strong>\
</h3>\
<table cellpadding="0" cellspacing="0" class="woocommerce_attribute_data">\
<tbody>\
<tr>\
<td class="attribute_name">\
<label>' + woocommerce_admin_meta_boxes.name_label + ':</label>\
<input type="text" class="attribute_name" name="attribute_names[' + size + ']" />\
<input type="hidden" name="attribute_is_taxonomy[' + size + ']" value="0" />\
<input type="hidden" name="attribute_position[' + size + ']" class="attribute_position" value="' + size + '" />\
</td>\
<td rowspan="3">\
<label>' + woocommerce_admin_meta_boxes.values_label + ':</label>\
<textarea name="attribute_values[' + size + ']" cols="5" rows="5" placeholder="' + woocommerce_admin_meta_boxes.text_attribute_tip + '"></textarea>\
</td>\
</tr>\
<tr>\
<td>\
<label><input type="checkbox" class="checkbox" ' + ( woocommerce_admin_meta_boxes.default_attribute_visibility ? 'checked="checked"' : '' ) + ' name="attribute_visibility[' + size + ']" value="1" /> ' + woocommerce_admin_meta_boxes.visible_label + '</label>\
</td>\
</tr>\
<tr>\
<td>\
<div class="enable_variation show_if_variable" ' + enable_variation + '>\
<label><input type="checkbox" class="checkbox" ' + ( woocommerce_admin_meta_boxes.default_attribute_variation ? 'checked="checked"' : '' ) + ' name="attribute_variation[' + size + ']" value="1" /> ' + woocommerce_admin_meta_boxes.used_for_variations_label + '</label>\
</div>\
</td>\
</tr>\
</tbody>\
</table>\
</div>');
} else {
// Reveal taxonomy row
var thisrow = $('.product_attributes .woocommerce_attribute.' + attribute_type);
$('.product_attributes').append( $(thisrow) );
$(thisrow).show().find('.woocommerce_attribute_data').show();
attribute_row_indexes(); attribute_row_indexes();
$('select.attribute_taxonomy').find('option[value="' + attribute_type + '"]').attr('disabled','disabled'); $wrapper.unblock();
});
if ( attribute ) {
$( 'select.attribute_taxonomy' ).find( 'option[value="' + attribute + '"]' ).attr( 'disabled','disabled' );
$( 'select.attribute_taxonomy' ).val( '' );
} }
$('select.attribute_taxonomy').val(''); return false;
}); });
$('.product_attributes').on('blur', 'input.attribute_name', function(){ $('.product_attributes').on('blur', 'input.attribute_name', function(){
@ -399,8 +371,8 @@ jQuery( function( $ ){
$('.product_attributes').block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } }); $('.product_attributes').block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });
var attribute = $(this).attr('data-attribute'); var $wrapper = $(this).closest('.woocommerce_attribute');
var $wrapper = $(this).closest('.woocommerce_attribute_data'); var attribute = $wrapper.data('taxonomy');
var new_attribute_name = prompt( woocommerce_admin_meta_boxes.new_attribute_prompt ); var new_attribute_name = prompt( woocommerce_admin_meta_boxes.new_attribute_prompt );
if ( new_attribute_name ) { if ( new_attribute_name ) {
@ -432,7 +404,6 @@ jQuery( function( $ ){
} }
return false; return false;
}); });
// Save attributes and update variations // Save attributes and update variations

File diff suppressed because one or more lines are too long

View File

@ -411,181 +411,40 @@ class WC_Meta_Box_Product_Data {
<div class="product_attributes wc-metaboxes"> <div class="product_attributes wc-metaboxes">
<?php <?php
global $wc_product_attributes;
// Array of defined attribute taxonomies // Array of defined attribute taxonomies
$attribute_taxonomies = wc_get_attribute_taxonomies(); $attribute_taxonomies = wc_get_attribute_taxonomies();
// Product attributes - taxonomies and custom, ordered, with visibility and variation attributes set // Product attributes - taxonomies and custom, ordered, with visibility and variation attributes set
$attributes = maybe_unserialize( get_post_meta( $thepostid, '_product_attributes', true ) ); $attributes = maybe_unserialize( get_post_meta( $thepostid, '_product_attributes', true ) );
$i = -1; // Output All Set Attributes
// Taxonomies
if ( $attribute_taxonomies ) {
foreach ( $attribute_taxonomies as $tax ) {
// Get name of taxonomy we're now outputting (pa_xxx)
$attribute_taxonomy_name = wc_attribute_taxonomy_name( $tax->attribute_name );
// Ensure it exists
if ( ! taxonomy_exists( $attribute_taxonomy_name ) ) {
continue;
}
$i++;
// Get product data values for current taxonomy - this contains ordering and visibility data
if ( isset( $attributes[ sanitize_title( $attribute_taxonomy_name ) ] ) ) {
$attribute = $attributes[ sanitize_title( $attribute_taxonomy_name ) ];
}
$position = empty( $attribute['position'] ) ? 0 : absint( $attribute['position'] );
// Get terms of this taxonomy associated with current product
$post_terms = wp_get_post_terms( $thepostid, $attribute_taxonomy_name );
// Any set?
$has_terms = ( is_wp_error( $post_terms ) || ! $post_terms || sizeof( $post_terms ) == 0 ) ? 0 : 1;
?>
<div data-taxonomy="<?php echo esc_attr( $attribute_taxonomy_name ); ?>" class="woocommerce_attribute wc-metabox closed taxonomy <?php echo esc_attr( $attribute_taxonomy_name ); ?>" rel="<?php echo $position; ?>" <?php if ( ! $has_terms ) echo 'style="display:none"'; ?>>
<h3>
<button type="button" class="remove_row button"><?php _e( 'Remove', 'woocommerce' ); ?></button>
<div class="handlediv" title="<?php _e( 'Click to toggle', 'woocommerce' ); ?>"></div>
<strong class="attribute_name"><?php echo apply_filters( 'woocommerce_attribute_label', $tax->attribute_label ? $tax->attribute_label : $tax->attribute_name, $tax->attribute_name ); ?></strong>
</h3>
<div class="woocommerce_attribute_data wc-metabox-content">
<table cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td class="attribute_name">
<label><?php _e( 'Name', 'woocommerce' ); ?>:</label>
<strong><?php echo $tax->attribute_label ? $tax->attribute_label : $tax->attribute_name; ?></strong>
<input type="hidden" name="attribute_names[<?php echo $i; ?>]" value="<?php echo esc_attr( $attribute_taxonomy_name ); ?>" />
<input type="hidden" name="attribute_position[<?php echo $i; ?>]" class="attribute_position" value="<?php echo esc_attr( $position ); ?>" />
<input type="hidden" name="attribute_is_taxonomy[<?php echo $i; ?>]" value="1" />
</td>
<td rowspan="3">
<label><?php _e( 'Value(s)', 'woocommerce' ); ?>:</label>
<?php if ( 'select' == $tax->attribute_type ) : ?>
<select multiple="multiple" data-placeholder="<?php _e( 'Select terms', 'woocommerce' ); ?>" class="multiselect attribute_values" name="attribute_values[<?php echo $i; ?>][]">
<?php
$all_terms = get_terms( $attribute_taxonomy_name, 'orderby=name&hide_empty=0' );
if ( $all_terms ) {
foreach ( $all_terms as $term ) {
$has_term = has_term( (int) $term->term_id, $attribute_taxonomy_name, $thepostid ) ? 1 : 0;
echo '<option value="' . esc_attr( $term->slug ) . '" ' . selected( $has_term, 1, false ) . '>' . $term->name . '</option>';
}
}
?>
</select>
<button class="button plus select_all_attributes"><?php _e( 'Select all', 'woocommerce' ); ?></button> <button class="button minus select_no_attributes"><?php _e( 'Select none', 'woocommerce' ); ?></button>
<button class="button fr plus add_new_attribute" data-attribute="<?php echo $attribute_taxonomy_name; ?>"><?php _e( 'Add new', 'woocommerce' ); ?></button>
<?php elseif ( 'text' == $tax->attribute_type ) : ?>
<input type="text" name="attribute_values[<?php echo $i; ?>]" value="<?php
// Text attributes should list terms pipe separated
if ( $post_terms ) {
$values = array();
foreach ( $post_terms as $term )
$values[] = $term->name;
echo esc_attr( implode( ' ' . WC_DELIMITER . ' ', $values ) );
}
?>" placeholder="<?php _e( 'Pipe (|) separate terms', 'woocommerce' ); ?>" />
<?php endif; ?>
<?php do_action( 'woocommerce_product_option_terms', $tax, $i ); ?>
</td>
</tr>
<tr>
<td>
<label><input type="checkbox" class="checkbox" <?php
if ( isset( $attribute['is_visible'] ) ) {
checked( $attribute['is_visible'], 1 );
} else {
checked( apply_filters( 'default_attribute_visibility', false, $tax ), true );
}
?> name="attribute_visibility[<?php echo $i; ?>]" value="1" /> <?php _e( 'Visible on the product page', 'woocommerce' ); ?></label>
</td>
</tr>
<tr>
<td>
<div class="enable_variation show_if_variable">
<label><input type="checkbox" class="checkbox" <?php
if ( isset( $attribute['is_variation'] ) ) {
checked( $attribute['is_variation'], 1 );
} else {
checked( apply_filters( 'default_attribute_variation', false, $tax ), true );
}
?> name="attribute_variation[<?php echo $i; ?>]" value="1" /> <?php _e( 'Used for variations', 'woocommerce' ); ?></label>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<?php
}
}
// Custom Attributes
if ( ! empty( $attributes ) ) { if ( ! empty( $attributes ) ) {
$attribute_keys = array_keys( $attributes );
foreach ( $attributes as $attribute ) { for ( $i = 0; $i < sizeof( $attribute_keys ); $i ++ ) {
$attribute = $attributes[ $attribute_keys[ $i ] ];
$position = empty( $attribute['position'] ) ? 0 : absint( $attribute['position'] );
$taxonomy = '';
if ( $attribute['is_taxonomy'] ) { if ( $attribute['is_taxonomy'] ) {
continue; $taxonomy = $attribute['name'];
if ( ! taxonomy_exists( $taxonomy ) ) {
continue;
}
$attribute_taxonomy = $wc_product_attributes[ $taxonomy ];
$metabox_class = array();
$metabox_class[] = 'taxonomy';
$metabox_class[] = $taxonomy;
$attribute_label = wc_attribute_label( $taxonomy );
} else {
$attribute_label = apply_filters( 'woocommerce_attribute_label', $attribute['name'], $attribute['name'] );
} }
$i++; include( 'views/html-product-attribute.php' );
$position = empty( $attribute['position'] ) ? 0 : absint( $attribute['position'] );
?>
<div class="woocommerce_attribute wc-metabox closed" rel="<?php echo $position; ?>">
<h3>
<button type="button" class="remove_row button"><?php _e( 'Remove', 'woocommerce' ); ?></button>
<div class="handlediv" title="<?php _e( 'Click to toggle', 'woocommerce' ); ?>"></div>
<strong class="attribute_name"><?php echo apply_filters( 'woocommerce_attribute_label', esc_html( $attribute['name'] ), esc_html( $attribute['name'] ) ); ?></strong>
</h3>
<div class="woocommerce_attribute_data wc-metabox-content">
<table cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td class="attribute_name">
<label><?php _e( 'Name', 'woocommerce' ); ?>:</label>
<input type="text" class="attribute_name" name="attribute_names[<?php echo $i; ?>]" value="<?php echo esc_attr( $attribute['name'] ); ?>" />
<input type="hidden" name="attribute_position[<?php echo $i; ?>]" class="attribute_position" value="<?php echo esc_attr( $position ); ?>" />
<input type="hidden" name="attribute_is_taxonomy[<?php echo $i; ?>]" value="0" />
</td>
<td rowspan="3">
<label><?php _e( 'Value(s)', 'woocommerce' ); ?>:</label>
<textarea name="attribute_values[<?php echo $i; ?>]" cols="5" rows="5" placeholder="<?php _e( 'Enter some text, or some attributes by pipe (|) separating values.', 'woocommerce' ); ?>"><?php echo esc_textarea( $attribute['value'] ); ?></textarea>
</td>
</tr>
<tr>
<td>
<label><input type="checkbox" class="checkbox" <?php checked( $attribute['is_visible'], 1 ); ?> name="attribute_visibility[<?php echo $i; ?>]" value="1" /> <?php _e( 'Visible on the product page', 'woocommerce' ); ?></label>
</td>
</tr>
<tr>
<td>
<div class="enable_variation show_if_variable">
<label><input type="checkbox" class="checkbox" <?php checked( $attribute['is_variation'], 1 ); ?> name="attribute_variation[<?php echo $i; ?>]" value="1" /> <?php _e( 'Used for variations', 'woocommerce' ); ?></label>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<?php
} }
} }
?> ?>
@ -597,7 +456,6 @@ class WC_Meta_Box_Product_Data {
<option value=""><?php _e( 'Custom product attribute', 'woocommerce' ); ?></option> <option value=""><?php _e( 'Custom product attribute', 'woocommerce' ); ?></option>
<?php <?php
if ( $attribute_taxonomies ) { if ( $attribute_taxonomies ) {
foreach ( $attribute_taxonomies as $tax ) { foreach ( $attribute_taxonomies as $tax ) {
$attribute_taxonomy_name = wc_attribute_taxonomy_name( $tax->attribute_name ); $attribute_taxonomy_name = wc_attribute_taxonomy_name( $tax->attribute_name );
$label = $tax->attribute_label ? $tax->attribute_label : $tax->attribute_name; $label = $tax->attribute_label ? $tax->attribute_label : $tax->attribute_name;

View File

@ -0,0 +1,79 @@
<div data-taxonomy="<?php echo esc_attr( $taxonomy ); ?>" class="woocommerce_attribute wc-metabox closed <?php echo esc_attr( implode( ' ', $metabox_class ) ); ?>" rel="<?php echo $position; ?>">
<h3>
<button type="button" class="remove_row button"><?php _e( 'Remove', 'woocommerce' ); ?></button>
<div class="handlediv" title="<?php _e( 'Click to toggle', 'woocommerce' ); ?>"></div>
<strong class="attribute_name"><?php echo esc_html( $attribute_label ); ?></strong>
</h3>
<div class="woocommerce_attribute_data wc-metabox-content">
<table cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td class="attribute_name">
<label><?php _e( 'Name', 'woocommerce' ); ?>:</label>
<?php if ( $attribute['is_taxonomy'] ) : ?>
<strong><?php echo esc_html( $attribute_label ); ?></strong>
<input type="hidden" name="attribute_names[<?php echo $i; ?>]" value="<?php echo esc_attr( $taxonomy ); ?>" />
<?php else : ?>
<input type="text" class="attribute_name" name="attribute_names[<?php echo $i; ?>]" value="<?php echo esc_attr( $attribute['name'] ); ?>" />
<?php endif; ?>
<input type="hidden" name="attribute_position[<?php echo $i; ?>]" class="attribute_position" value="<?php echo esc_attr( $position ); ?>" />
<input type="hidden" name="attribute_is_taxonomy[<?php echo $i; ?>]" value="<?php echo $attribute['is_taxonomy'] ? 1 : 0; ?>" />
</td>
<td rowspan="3">
<label><?php _e( 'Value(s)', 'woocommerce' ); ?>:</label>
<?php if ( $attribute['is_taxonomy'] ) : ?>
<?php if ( 'select' === $attribute_taxonomy->attribute_type ) : ?>
<select multiple="multiple" data-placeholder="<?php _e( 'Select terms', 'woocommerce' ); ?>" class="multiselect attribute_values" name="attribute_values[<?php echo $i; ?>][]">
<?php
$all_terms = get_terms( $taxonomy, 'orderby=name&hide_empty=0' );
if ( $all_terms ) {
foreach ( $all_terms as $term ) {
echo '<option value="' . esc_attr( $term->slug ) . '" ' . selected( has_term( absint( $term->term_id ), $taxonomy, $thepostid ), true, false ) . '>' . $term->name . '</option>';
}
}
?>
</select>
<button class="button plus select_all_attributes"><?php _e( 'Select all', 'woocommerce' ); ?></button>
<button class="button minus select_no_attributes"><?php _e( 'Select none', 'woocommerce' ); ?></button>
<button class="button fr plus add_new_attribute"><?php _e( 'Add new', 'woocommerce' ); ?></button>
<?php elseif ( 'text' == $attribute_taxonomy->attribute_type ) : ?>
<input type="text" name="attribute_values[<?php echo $i; ?>]" value="<?php
// Text attributes should list terms pipe separated
echo esc_attr( implode( ' ' . WC_DELIMITER . ' ', wp_get_post_terms( $thepostid, $taxonomy, array( 'fields' => 'names' ) ) ) );
?>" placeholder="<?php echo esc_attr( sprintf( __( '"%s" separate terms', 'woocommerce' ), WC_DELIMITER ) ); ?>" />
<?php endif; ?>
<?php do_action( 'woocommerce_product_option_terms', $attribute_taxonomy, $i ); ?>
<?php else : ?>
<textarea name="attribute_values[<?php echo $i; ?>]" cols="5" rows="5" placeholder="<?php echo esc_attr( sprintf( __( 'Enter some text, or some attributes by "%s" separating values.', 'woocommerce' ), WC_DELIMITER ) ); ?>"><?php echo esc_textarea( $attribute['value'] ); ?></textarea>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<label><input type="checkbox" class="checkbox" <?php checked( $attribute['is_visible'], 1 ); ?> name="attribute_visibility[<?php echo $i; ?>]" value="1" /> <?php _e( 'Visible on the product page', 'woocommerce' ); ?></label>
</td>
</tr>
<tr>
<td>
<div class="enable_variation show_if_variable">
<label><input type="checkbox" class="checkbox" <?php checked( $attribute['is_variation'], 1 ); ?> name="attribute_variation[<?php echo $i; ?>]" value="1" /> <?php _e( 'Used for variations', 'woocommerce' ); ?></label>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>

View File

@ -33,6 +33,7 @@ class WC_AJAX {
'checkout' => true, 'checkout' => true,
'feature_product' => false, 'feature_product' => false,
'mark_order_status' => false, 'mark_order_status' => false,
'add_attribute' => false,
'add_new_attribute' => false, 'add_new_attribute' => false,
'remove_variation' => false, 'remove_variation' => false,
'remove_variations' => false, 'remove_variations' => false,
@ -404,6 +405,41 @@ class WC_AJAX {
die(); die();
} }
/**
* Add an attribute row
*/
public static function add_attribute() {
ob_start();
check_ajax_referer( 'add-attribute', 'security' );
global $wc_product_attributes;
$taxonomy = sanitize_text_field( $_POST['taxonomy'] );
$i = absint( $_POST['i'] );
$position = 0;
$attribute = array(
'name' => $taxonomy,
'value' => '',
'is_visible' => 1,
'is_variation' => 0,
'is_taxonomy' => $taxonomy ? 1 : 0
);
if ( $taxonomy ) {
$attribute_taxonomy = $wc_product_attributes[ $taxonomy ];
$metabox_class = array();
$metabox_class[] = 'taxonomy';
$metabox_class[] = $taxonomy;
$attribute_label = wc_attribute_label( $taxonomy );
} else {
$attribute_label = '';
}
include( 'admin/meta-boxes/views/html-product-attribute.php' );
die();
}
/** /**
* Add a new attribute via ajax function * Add a new attribute via ajax function
*/ */