Files
woocommerce-subscriptions/assets/js/admin/admin.js
2025-05-21 10:18:23 +00:00

1447 lines
41 KiB
JavaScript

jQuery( function ( $ ) {
$.extend( {
getParameterByName: function ( name ) {
name = name.replace( /[\[]/, '\\[' ).replace( /[\]]/, '\\]' );
var regexS = '[\\?&]' + name + '=([^&#]*)';
var regex = new RegExp( regexS );
var results = regex.exec( window.location.search );
if ( results == null ) {
return '';
} else {
return decodeURIComponent( results[ 1 ].replace( /\+/g, ' ' ) );
}
},
daysInMonth: function ( month ) {
// Intentionally choose a non-leap year because we want february to have only 28 days.
return new Date( Date.UTC( 2001, month, 0 ) ).getUTCDate();
},
showHideSubscriptionMeta: function () {
if (
$( 'select#product-type' ).val() == WCSubscriptions.productType
) {
$( '.show_if_simple' ).show();
$( '.grouping_options' ).hide();
$( '.options_group.pricing ._regular_price_field' ).hide();
$( '#sale-price-period' ).show();
$( '.hide_if_subscription' ).hide();
$( 'input#_manage_stock' ).trigger( 'change' );
if ( 'day' == $( '#_subscription_period' ).val() ) {
$( '.subscription_sync' ).hide();
}
} else {
$( '.options_group.pricing ._regular_price_field' ).show();
$( '#sale-price-period' ).hide();
}
},
showHideVariableSubscriptionMeta: function () {
// In order for WooCommerce not to show the stock_status_field on variable subscriptions, make sure it has the hide if variable subscription class.
$( 'p.stock_status_field' ).addClass(
'hide_if_variable-subscription'
);
var product_type = $( 'select#product-type' ).val();
if ( 'variable-subscription' === product_type ) {
// Hide and show subscription fields when variable subscription is selected
$( 'input#_downloadable' ).prop( 'checked', false );
$( 'input#_virtual' ).prop( 'checked', false );
// Variable subscriptions inherit fields from variable products.
$( '.show_if_variable' ).show();
$( '.hide_if_variable' ).hide();
$( '.show_if_variable-subscription' ).show();
$( '.hide_if_variable-subscription' ).hide();
$.showOrHideStockFields();
// Make the sale price row full width
$( '.sale_price_dates_fields' )
.prev( '.form-row' )
.addClass( 'form-row-full' )
.removeClass( 'form-row-last' );
} else {
if ( 'subscription' === product_type ) {
$( '.show_if_subscription' ).show();
$( '.hide_if_subscription' ).hide();
}
// Restore the sale price row width to half
$( '.sale_price_dates_fields' )
.prev( '.form-row' )
.removeClass( 'form-row-full' )
.addClass( 'form-row-last' );
}
},
enableSubscriptionProductFields: function () {
product_type = $( 'select#product-type' ).val();
enable_type = '';
// Variable subscriptions need to enable variable product fields and subscriptions products need to enable simple product fields.
if ( 'variable-subscription' === product_type ) {
enable_type = 'variable'
} else if ( 'subscription' === product_type ) {
enable_type = 'simple';
}
if ( enable_type ) {
$( `.enable_if_${ enable_type }` ).each( function () {
$( this ).removeClass( 'disabled' );
if ( $( this ).is( 'input' ) ) {
$( this ).prop( 'disabled', false );
}
} );
}
},
showOrHideStockFields: function () {
if ( $( 'input#_manage_stock' ).is( ':checked' ) ) {
$( 'div.stock_fields' ).show();
} else {
$( 'div.stock_fields' ).hide();
}
},
setSubscriptionLengths: function () {
$(
'[name^="_subscription_length"], [name^="variable_subscription_length"]'
).each( function () {
var $lengthElement = $( this ),
selectedLength = $lengthElement.val(),
hasSelectedLength = false,
matches = $lengthElement
.attr( 'name' )
.match( /\[(.*?)\]/ ),
periodSelector,
interval;
if ( matches ) {
// Variation
periodSelector =
'[name="variable_subscription_period[' +
matches[ 1 ] +
']"]';
billingInterval = parseInt(
$(
'[name="variable_subscription_period_interval[' +
matches[ 1 ] +
']"]'
).val()
);
} else {
periodSelector = '#_subscription_period';
billingInterval = parseInt(
$( '#_subscription_period_interval' ).val()
);
}
$lengthElement.empty();
$.each(
WCSubscriptions.subscriptionLengths[
$( periodSelector ).val()
],
function ( length, description ) {
if (
parseInt( length ) == 0 ||
0 == parseInt( length ) % billingInterval
) {
$lengthElement.append(
$( '<option></option>' )
.attr( 'value', length )
.text( description )
);
}
}
);
$lengthElement.children( 'option' ).each( function () {
if ( this.value == selectedLength ) {
hasSelectedLength = true;
return false;
}
} );
if ( hasSelectedLength ) {
$lengthElement.val( selectedLength );
} else {
$lengthElement.val( 0 );
}
} );
},
setTrialPeriods: function () {
$(
'[name^="_subscription_trial_length"], [name^="variable_subscription_trial_length"]'
).each( function () {
var $trialLengthElement = $( this ),
trialLength = $trialLengthElement.val(),
matches = $trialLengthElement
.attr( 'name' )
.match( /\[(.*?)\]/ ),
periodStrings;
if ( matches ) {
// Variation
$trialPeriodElement = $(
'[name="variable_subscription_trial_period[' +
matches[ 1 ] +
']"]'
);
} else {
$trialPeriodElement = $( '#_subscription_trial_period' );
}
selectedTrialPeriod = $trialPeriodElement.val();
$trialPeriodElement.empty();
if ( parseInt( trialLength ) == 1 ) {
periodStrings = WCSubscriptions.trialPeriodSingular;
} else {
periodStrings = WCSubscriptions.trialPeriodPlurals;
}
$.each( periodStrings, function ( key, description ) {
$trialPeriodElement.append(
$( '<option></option>' )
.attr( 'value', key )
.text( description )
);
} );
$trialPeriodElement.val( selectedTrialPeriod );
} );
},
setSalePeriod: function () {
$( '#sale-price-period' ).fadeOut( 80, function () {
$( '#sale-price-period' ).text(
$(
'#_subscription_period_interval option:selected'
).text() +
' ' +
$( '#_subscription_period option:selected' ).text()
);
$( '#sale-price-period' ).fadeIn( 180 );
} );
},
setSyncOptions: function ( periodField ) {
if ( typeof periodField != 'undefined' ) {
if (
$( 'select#product-type' ).val() == 'variable-subscription'
) {
var $container = periodField
.closest( '.woocommerce_variable_attributes' )
.find( '.variable_subscription_sync' );
} else {
$container = periodField
.closest( '#general_product_data' )
.find( '.subscription_sync' );
}
var $syncWeekMonthContainer = $container.find(
'.subscription_sync_week_month'
),
$syncWeekMonthSelect = $syncWeekMonthContainer.find(
'select'
),
$syncAnnualContainer = $container.find(
'.subscription_sync_annual'
),
$varSubField = $container.find(
'[name^="variable_subscription_payment_sync_date"]'
),
billingPeriod;
if ( $varSubField.length > 0 ) {
// Variation
var matches = $varSubField
.attr( 'name' )
.match( /\[(.*?)\]/ );
$subscriptionPeriodElement = $(
'[name="variable_subscription_period[' +
matches[ 1 ] +
']"]'
);
} else {
$subscriptionPeriodElement = $( '#_subscription_period' );
}
billingPeriod = $subscriptionPeriodElement.val();
if ( 'day' == billingPeriod ) {
$syncWeekMonthSelect.val( 0 );
$syncAnnualContainer
.find( 'input[type="number"]' )
.val( 0 )
.trigger( 'change' );
} else {
if ( 'year' == billingPeriod ) {
// Make sure the year sync fields are reset
$syncAnnualContainer
.find( 'input[type="number"]' )
.val( 0 )
.trigger( 'change' );
// And the week/month field has no option selected
$syncWeekMonthSelect.val( 0 );
} else {
// Make sure the year sync value is 0
$syncAnnualContainer
.find( 'input[type="number"]' )
.val( 0 )
.trigger( 'change' );
// And the week/month field has the appropriate options
$syncWeekMonthSelect.empty();
$.each(
WCSubscriptions.syncOptions[ billingPeriod ],
function ( key, description ) {
$syncWeekMonthSelect.append(
$( '<option></option>' )
.attr( 'value', key )
.text( description )
);
}
);
}
}
}
},
showHideSyncOptions: function () {
if (
$( '#_subscription_payment_sync_date' ).length > 0 ||
$( '.wc_input_subscription_payment_sync' ).length > 0
) {
$( '.subscription_sync, .variable_subscription_sync' ).each(
function () {
// loop through all sync field groups
var $syncWeekMonthContainer = $( this ).find(
'.subscription_sync_week_month'
),
$syncWeekMonthSelect = $syncWeekMonthContainer.find(
'select'
),
$syncAnnualContainer = $( this ).find(
'.subscription_sync_annual'
),
$varSubField = $( this ).find(
'[name^="variable_subscription_payment_sync_date"]'
),
$slideSwitch = false, // stop the general sync field group sliding down if editing a variable subscription
billingPeriod;
if ( $varSubField.length > 0 ) {
// Variation
var matches = $varSubField
.attr( 'name' )
.match( /\[(.*?)\]/ );
$subscriptionPeriodElement = $(
'[name="variable_subscription_period[' +
matches[ 1 ] +
']"]'
);
if (
$( 'select#product-type' ).val() ==
'variable-subscription'
) {
$slideSwitch = true;
}
} else {
$subscriptionPeriodElement = $(
'#_subscription_period'
);
if (
$( 'select#product-type' ).val() ==
WCSubscriptions.productType
) {
$slideSwitch = true;
}
}
billingPeriod = $subscriptionPeriodElement.val();
if ( 'day' == billingPeriod ) {
$( this ).slideUp( 400 );
} else {
if ( $slideSwitch ) {
$( this ).slideDown( 400 );
if ( 'year' == billingPeriod ) {
// Make sure the year sync fields are visible
$syncAnnualContainer.slideDown( 400 );
// And the week/month field is hidden
$syncWeekMonthContainer.slideUp( 400 );
} else {
// Make sure the year sync fields are hidden
$syncAnnualContainer.slideUp( 400 );
// And the week/month field is visible
$syncWeekMonthContainer.slideDown( 400 );
}
}
}
}
);
}
},
moveSubscriptionVariationFields: function () {
$( '#variable_product_options .variable_subscription_pricing' )
.not( 'wcs_moved' )
.each( function () {
var $regularPriceRow = $( this ).siblings(
'.variable_pricing'
),
$trialSignUpRow = $( this ).siblings(
'.variable_subscription_trial_sign_up'
),
$saleDatesRow;
$saleDatesRow = $( this ).siblings( '.variable_pricing' );
// Add the subscription price fields above the standard price fields
$( this ).insertBefore( $regularPriceRow );
$trialSignUpRow.insertAfter( $( this ) );
// Replace the regular price field with the trial period field
$regularPriceRow
.children( ':first' )
.addClass( 'hide_if_variable-subscription' );
$( this ).addClass( 'wcs_moved' );
} );
},
getVariationBulkEditValue: function ( variation_action ) {
var value;
switch ( variation_action ) {
case 'variable_subscription_period':
case 'variable_subscription_trial_period':
value = prompt( WCSubscriptions.bulkEditPeriodMessage );
break;
case 'variable_subscription_period_interval':
value = prompt( WCSubscriptions.bulkEditIntervalhMessage );
break;
case 'variable_subscription_trial_length':
case 'variable_subscription_length':
value = prompt( WCSubscriptions.bulkEditLengthMessage );
break;
case 'variable_subscription_sign_up_fee':
value = prompt(
woocommerce_admin_meta_boxes_variations.i18n_enter_a_value
);
value = accounting.unformat(
value,
woocommerce_admin.mon_decimal_point
);
break;
}
return value;
},
disableEnableOneTimeShipping: function () {
var is_synced_or_has_trial = false;
if ( 'variable-subscription' == $( 'select#product-type' ).val() ) {
var variations = $(
'.woocommerce_variations .woocommerce_variation'
),
variations_checked = {},
number_of_pages = $( '.woocommerce_variations' ).attr(
'data-total_pages'
);
$( variations ).each( function () {
var period_field = $( this ).find(
'.wc_input_subscription_period'
),
variation_index = $( period_field )
.attr( 'name' )
.match( /\[(.*?)\]/ ),
variation_id = $(
'[name="variable_post_id[' +
variation_index[ 1 ] +
']"]'
).val(),
period = period_field.val(),
trial = $( this )
.find( '.wc_input_subscription_trial_length' )
.val(),
sync_date = 0;
if ( 0 != trial ) {
is_synced_or_has_trial = true;
// break
return false;
}
if (
$( this ).find( '.variable_subscription_sync' ).length
) {
if ( 'month' == period || 'week' == period ) {
sync_date = $(
'[name="variable_subscription_payment_sync_date[' +
variation_index[ 1 ] +
']"]'
).val();
} else if ( 'year' == period ) {
sync_date = $(
'[name="variable_subscription_payment_sync_date_day[' +
variation_index[ 1 ] +
']"]'
).val();
}
if ( 0 != sync_date ) {
is_synced_or_has_trial = true;
// break
return false;
}
}
variations_checked[ variation_index[ 1 ] ] = variation_id;
} );
// if we haven't found a variation synced or with a trial at this point check the backend for other product variations
if (
( number_of_pages > 1 || 0 == variations.length ) &&
false == is_synced_or_has_trial
) {
var data = {
action: 'wcs_product_has_trial_or_is_synced',
product_id:
woocommerce_admin_meta_boxes_variations.post_id,
variations_checked: variations_checked,
nonce: WCSubscriptions.oneTimeShippingCheckNonce,
};
$.ajax( {
url: WCSubscriptions.ajaxUrl,
data: data,
type: 'POST',
success: function ( response ) {
$( '#_subscription_one_time_shipping' ).prop(
'disabled',
response.is_synced_or_has_trial
);
// trigger an event now we have determined the one time shipping availability, in case we need to update the backend
$(
'#_subscription_one_time_shipping'
).trigger(
'subscription_one_time_shipping_updated',
[ response.is_synced_or_has_trial ]
);
},
} );
} else {
// trigger an event now we have determined the one time shipping availability, in case we need to update the backend
$(
'#_subscription_one_time_shipping'
).trigger( 'subscription_one_time_shipping_updated', [
is_synced_or_has_trial,
] );
}
} else {
var trial = $(
'#general_product_data #_subscription_trial_length'
).val();
if ( 0 != trial ) {
is_synced_or_has_trial = true;
}
if (
$( '.subscription_sync' ).length &&
false == is_synced_or_has_trial
) {
var period = $( '#_subscription_period' ).val(),
sync_date = 0;
if ( 'month' == period || 'week' == period ) {
sync_date = $(
'#_subscription_payment_sync_date'
).val();
} else if ( 'year' == period ) {
sync_date = $(
'#_subscription_payment_sync_date_day'
).val();
}
if ( 0 != sync_date ) {
is_synced_or_has_trial = true;
}
}
}
$( '#_subscription_one_time_shipping' ).prop(
'disabled',
is_synced_or_has_trial
);
},
showHideSubscriptionsPanels: function () {
var tab = $( 'div.panel-wrap' )
.find( 'ul.wc-tabs li' )
.eq( 0 )
.find( 'a' );
var panel = tab.attr( 'href' );
var visible = $( panel )
.children( '.options_group' )
.filter( function () {
return 'none' != $( this ).css( 'display' );
} );
if ( 0 != visible.length ) {
tab.trigger( 'click' ).parent().show();
}
},
maybeDisableRemoveLinks: function () {
$( '#variable_product_options .woocommerce_variation' ).each(
function () {
var $removeLink = $( this ).find( '.remove_variation' );
if ( WCSubscriptions.isLargeSite ) {
$removeLink.addClass( 'wcs_validate_variation_delete' );
$removeLink.removeClass( 'remove_variation' );
} else {
var can_remove_variation =
'1' ===
$( this )
.find( 'input.wcs-can-remove-variation' )
.val();
var $msg = $( this ).find(
'.wcs-can-not-remove-variation-msg'
);
if ( ! can_remove_variation ) {
$msg.text( $removeLink.text() );
$removeLink.replaceWith( $msg );
}
}
}
);
},
} );
$( '.options_group.pricing ._sale_price_field .description' ).prepend(
'<span id="sale-price-period" style="display: none;"></span>'
);
// Move the subscription pricing section to the same location as the normal pricing section
$( '.options_group.subscription_pricing' )
.not(
'.variable_subscription_pricing .options_group.subscription_pricing'
)
.insertBefore( $( '.options_group.pricing:first' ) );
$( '.show_if_subscription.clear' ).insertAfter(
$( '.options_group.subscription_pricing' )
);
// Move the subscription variation pricing section to a better location in the DOM on load
if (
$( '#variable_product_options .variable_subscription_pricing' ).length >
0
) {
$.moveSubscriptionVariationFields();
}
// When a variation is added
$( '#woocommerce-product-data' ).on(
'woocommerce_variations_added woocommerce_variations_loaded',
function () {
$.moveSubscriptionVariationFields();
$.showHideVariableSubscriptionMeta();
$.showHideSyncOptions();
$.setSubscriptionLengths();
}
);
if ( $( '.options_group.pricing' ).length > 0 ) {
$.setSalePeriod();
$.showHideSubscriptionMeta();
$.enableSubscriptionProductFields();
$.showHideVariableSubscriptionMeta();
$.setSubscriptionLengths();
$.setTrialPeriods();
$.showHideSyncOptions();
$.disableEnableOneTimeShipping();
$.showHideSubscriptionsPanels();
}
// Update subscription ranges when subscription period or interval is changed
$( '#woocommerce-product-data' ).on(
'change',
'[name^="_subscription_period"], [name^="_subscription_period_interval"], [name^="variable_subscription_period"], [name^="variable_subscription_period_interval"]',
function () {
$.setSubscriptionLengths();
$.showHideSyncOptions();
$.setSyncOptions( $( this ) );
$.setSalePeriod();
$.disableEnableOneTimeShipping();
}
);
$( '#woocommerce-product-data' ).on(
'propertychange keyup input paste change',
'[name^="_subscription_trial_length"], [name^="variable_subscription_trial_length"]',
function () {
$.setTrialPeriods();
}
);
// Handles changes to sync date select/input for yearly subscription products.
$( '#woocommerce-product-data' )
.on(
'change',
'[name^="_subscription_payment_sync_date_day"], [name^="variable_subscription_payment_sync_date_day"]',
function () {
if ( 0 == $( this ).val() ) {
$( this )
.siblings(
'[name^="_subscription_payment_sync_date_month"], [name^="variable_subscription_payment_sync_date_month"]'
)
.val( 0 );
$( this ).prop( 'disabled', true );
}
}
)
.on(
'change',
'[name^="_subscription_payment_sync_date_month"], [name^="variable_subscription_payment_sync_date_month"]',
function () {
var $syncDayOfMonthInput = $( this ).siblings(
'[name^="_subscription_payment_sync_date_day"], [name^="variable_subscription_payment_sync_date_day"]'
);
if ( 0 < $( this ).val() ) {
// Clear existing options.
$syncDayOfMonthInput.empty();
// Add options for each day in the month.
for ( var day = 1; day <= $.daysInMonth( $( this ).val() ); day++ ) {
$syncDayOfMonthInput.append( $( '<option>', {
value: day,
text: day
} ) );
}
$syncDayOfMonthInput.prop( 'disabled', false );
} else {
$syncDayOfMonthInput.val( 0 ).trigger( 'change' );
$syncDayOfMonthInput.prop( 'disabled', true );
}
}
);
$( 'body' ).on( 'woocommerce-product-type-change', function () {
$.showHideSubscriptionMeta();
$.showHideVariableSubscriptionMeta();
$.enableSubscriptionProductFields();
$.showHideSyncOptions();
$.showHideSubscriptionsPanels();
} );
// WC Core enable/disable product fields when saving attributes. We need to make sure we re-enable our fields.
$( document.body ).on( 'woocommerce_attributes_saved', function () {
$.enableSubscriptionProductFields();
} );
/**
* This function is called after WC Core fetches new attribute HTML and appends the elements asynchronously.
* It triggers relevant functions to hide/show and enable/disable fields.
*
* @see add_attribute_to_list() in assets/js/admin/meta-boxes-product.js
*
* Since there is no specific event to hook into when the async call is resolved, we rely on WC clicking
* the attribute metabox heading after fetching the HTML but before disabling the product fields.
* We take advantage of this by attaching a click event listener to the '.woocommerce_attribute.wc-metabox h3'
* element and waiting a short time before re-enabling the product fields.
*/
$( document ).on( 'click', '.woocommerce_attribute.wc-metabox h3', function() {
setTimeout( function() {
$.showHideSubscriptionMeta();
$.showHideVariableSubscriptionMeta();
$.enableSubscriptionProductFields();
}, 100 );
});
$( 'input#_downloadable, input#_virtual' ).on( 'change', function () {
$.showHideSubscriptionMeta();
$.showHideVariableSubscriptionMeta();
} );
// Make sure the "Used for variations" checkbox is visible when adding attributes to a variable subscription
$( 'body' ).on( 'woocommerce_added_attribute', function () {
$.showHideVariableSubscriptionMeta();
} );
if ( $.getParameterByName( 'select_subscription' ) == 'true' ) {
$(
'select#product-type option[value="' +
WCSubscriptions.productType +
'"]'
).attr( 'selected', 'selected' );
$( 'select#product-type' ).trigger( 'select' ).trigger( 'change' );
}
// Before saving a subscription product, validate the trial period
$( '#post' ).on( 'submit', function ( e ) {
if ( WCSubscriptions.subscriptionLengths !== undefined ) {
var trialLength = $( '#_subscription_trial_length' ).val(),
selectedTrialPeriod = $( '#_subscription_trial_period' ).val();
if (
parseInt( trialLength ) >=
WCSubscriptions.subscriptionLengths[ selectedTrialPeriod ]
.length
) {
alert(
WCSubscriptions.trialTooLongMessages[ selectedTrialPeriod ]
);
$( '#ajax-loading' ).hide();
$( '#publish' ).removeClass( 'button-primary-disabled' );
e.preventDefault();
}
}
} );
// Notify store manager that deleting an order via the Orders screen also deletes subscriptions associated with the orders
$( '#posts-filter' ).on( 'submit', function () {
if (
$( '[name="post_type"]' ).val() == 'shop_order' &&
( $( '[name="action"]' ).val() == 'trash' ||
$( '[name="action2"]' ).val() == 'trash' )
) {
var containsSubscription = false;
$( '[name="post[]"]:checked' ).each( function () {
if (
true ===
$(
'.contains_subscription',
$( '#post-' + $( this ).val() )
).data( 'contains_subscription' )
) {
containsSubscription = true;
}
return false === containsSubscription;
} );
if ( containsSubscription ) {
return confirm( WCSubscriptions.bulkTrashWarning );
}
}
} );
$( '.order_actions .submitdelete' ).on( 'click', function () {
if ( $( '[name="contains_subscription"]' ).val() == 'true' ) {
return confirm( WCSubscriptions.trashWarning );
}
} );
$( '#variable_product_options' ).on(
'click',
'.delete.wcs-can-not-remove-variation-msg',
function ( e ) {
e.preventDefault();
e.stopPropagation();
}
);
// Notify the store manager that trashing an order via the admin orders table row action also deletes the associated subscription if it exists
$( '.row-actions .submitdelete' ).on( 'click', function () {
var order = $( this ).closest( '.type-shop_order' ).attr( 'id' );
if (
true ===
$( '.contains_subscription', $( '#' + order ) ).data(
'contains_subscription'
)
) {
return confirm( WCSubscriptions.trashWarning );
}
} );
// Editing a variable product
$( '#variable_product_options' ).on(
'change',
'[name^="variable_regular_price"]',
function () {
var matches = $( this )
.attr( 'name' )
.match( /\[(.*?)\]/ );
if ( matches ) {
var loopIndex = matches[ 1 ];
$(
'[name="variable_subscription_price[' + loopIndex + ']"]'
).val( $( this ).val() );
}
}
);
// Editing a variable product
$( '#variable_product_options' ).on(
'change',
'[name^="variable_subscription_price"]',
function () {
var matches = $( this )
.attr( 'name' )
.match( /\[(.*?)\]/ );
if ( matches ) {
var loopIndex = matches[ 1 ];
$( '[name="variable_regular_price[' + loopIndex + ']"]' ).val(
$( this ).val()
);
}
}
);
// Update hidden regular price when subscription price is update on simple products
$( '#general_product_data' ).on(
'change',
'[name^="_subscription_price"]',
function () {
$( '[name="_regular_price"]' ).val( $( this ).val() );
}
);
// Notify store manager that deleting an user via the Users screen also removed them from any subscriptions.
$( '.users-php .submitdelete' ).on( 'click', function () {
return confirm( WCSubscriptions.deleteUserWarning );
} );
// WC 2.4+ variation bulk edit handling
$( 'select.variation_actions' ).on(
'variable_subscription_sign_up_fee_ajax_data variable_subscription_period_interval_ajax_data variable_subscription_period_ajax_data variable_subscription_trial_period_ajax_data variable_subscription_trial_length_ajax_data variable_subscription_length_ajax_data',
function ( event, data ) {
bulk_action = event.type.replace( /_ajax_data/g, '' );
value = $.getVariationBulkEditValue( bulk_action );
if ( 'variable_subscription_trial_length' == bulk_action ) {
// After variations have their trial length bulk updated in the backend, flag the One Time Shipping field as needing to be updated
$( '#_subscription_one_time_shipping' ).addClass(
'wcs_ots_needs_update'
);
}
if ( value != null ) {
data.value = value;
}
return data;
}
);
var $allowSwitching = $(
document.getElementById(
'woocommerce_subscriptions_allow_switching'
)
),
$syncRenewals = $(
document.getElementById( 'woocommerce_subscriptions_sync_payments' )
),
$customerNotifications = $(
document.getElementById( 'woocommerce_subscriptions_customer_notifications_enabled' )
);
// We're on the Subscriptions settings page
if ( $allowSwitching.length > 0 ) {
var allowSwitchingEnabled = $allowSwitching.find( 'input:checked' )
.length,
$switchSettingsRows = $allowSwitching
.parents( 'tr' )
.siblings( 'tr' ),
$prorateFirstRenewal = $(
document.getElementById(
'woocommerce_subscriptions_prorate_synced_payments'
)
),
$syncRows = $syncRenewals.parents( 'tr' ).siblings( 'tr' ),
$daysNoFeeRow = $(
document.getElementById(
'woocommerce_subscriptions_days_no_fee'
)
).parents( 'tr' ),
$suspensionExtensionRow = $(
'#woocommerce_subscriptions_recoup_suspension'
).parents( 'tr' ),
$customerNotificationOffsetRow = $(
'#woocommerce_subscriptions_customer_notifications_offset'
).parents( 'tr' );
// No animation for initial hiding when switching is disabled.
if ( 0 === allowSwitchingEnabled ) {
$switchSettingsRows.hide();
}
$allowSwitching.find( 'input' ).on( 'change', function () {
var isEnabled = $allowSwitching.find( 'input:checked' ).length;
if ( 0 === isEnabled ) {
$switchSettingsRows.fadeOut();
} else if ( 0 === allowSwitchingEnabled ) {
// switching was previously disabled, so settings will be hidden
$switchSettingsRows.fadeIn();
}
allowSwitchingEnabled = isEnabled;
} );
// Show/hide suspension extension setting
$( '#woocommerce_subscriptions_max_customer_suspensions' )
.on( 'change', function () {
if ( $( this ).val() > 0 ) {
$suspensionExtensionRow.show();
} else {
$suspensionExtensionRow.hide();
}
} )
.trigger( 'change' );
// No animation when initially hiding prorated rows.
if ( ! $syncRenewals.is( ':checked' ) ) {
$syncRows.hide();
} else if ( 'recurring' !== $prorateFirstRenewal.val() ) {
$daysNoFeeRow.hide();
}
// Animate showing and hiding the synchronization rows.
$syncRenewals.on( 'change', function () {
if ( $( this ).is( ':checked' ) ) {
$syncRows.not( $daysNoFeeRow ).fadeIn();
$prorateFirstRenewal.trigger( 'change' );
} else {
$syncRows.fadeOut();
}
} );
// Watch the Prorate First Renewal field for changes.
$prorateFirstRenewal.on( 'change', function () {
if ( 'recurring' === $( this ).val() ) {
$daysNoFeeRow.fadeIn();
} else {
$daysNoFeeRow.fadeOut();
}
} );
// No animation when initially hiding customer notification offset row.
if ( ! $customerNotifications.is( ':checked' ) ) {
$customerNotificationOffsetRow.hide();
}
// Watch the enable/disable customer notifications checkbox for changes.
$customerNotifications.on( 'change', function () {
if ( $( this ).is( ':checked' ) ) {
$customerNotificationOffsetRow.fadeIn();
} else {
$customerNotificationOffsetRow.fadeOut();
}
} );
}
// Don't display the variation notice for variable subscription products
$( 'body' ).on( 'woocommerce-display-product-type-alert', function (
e,
select_val
) {
if ( select_val == 'variable-subscription' ) {
return false;
}
} );
$( '.wcs_payment_method_selector' ).on( 'change', function () {
var payment_method = $( this ).val();
$( '.wcs_payment_method_meta_fields' ).hide();
$( '#wcs_' + payment_method + '_fields' ).show();
} );
// After variations have been saved/updated in the backend, flag the One Time Shipping field as needing to be updated
$( '#woocommerce-product-data' ).on(
'woocommerce_variations_saved',
function () {
$( '#_subscription_one_time_shipping' ).addClass(
'wcs_ots_needs_update'
);
}
);
// After variations have been loaded and if the One Time Shipping field needs updating, check if One Time Shipping is still available
$( '#woocommerce-product-data' ).on(
'woocommerce_variations_loaded',
function () {
if ( $( '.wcs_ots_needs_update' ).length ) {
$.disableEnableOneTimeShipping();
}
}
);
// After variations have been loaded, check which ones are tied to subscriptions to prevent them from being deleted.
$( '#woocommerce-product-data' ).on(
'woocommerce_variations_loaded',
function () {
$.maybeDisableRemoveLinks();
}
);
// Validate the request to remove a variation on large sites.
$( document ).on( 'click', '.wcs_validate_variation_delete', function (
e
) {
e.preventDefault();
// Prevent WC from expanding the meta box on click.
$( this )
.closest( '.wc-metaboxes-wrapper' )
.find( '.wc-metabox > .wc-metabox-content' )
.hide();
var variation_id = $( this ).attr( 'rel' );
var container = $( '#woocommerce-product-data' );
var data = {
action: 'wcs_validate_variation_deletion',
variation_id: variation_id,
nonce: WCSubscriptions.nonce,
};
// Block the UI while we check if the variation can be deleted.
container.block( {
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6,
},
} );
$.ajax( {
url: WCSubscriptions.ajaxUrl,
data: data,
type: 'POST',
success: function ( response ) {
container.unblock();
remove_link = $(
'.wcs_validate_variation_delete[rel=' + variation_id + ']'
);
if ( 'yes' === response.can_remove ) {
// Restore the remove variation link and click it.
remove_link.addClass( 'remove_variation' );
remove_link.removeClass( 'wcs_validate_variation_delete' );
remove_link.trigger( 'click' );
} else {
alert( WCSubscriptions.variationDeleteFailMessage );
// Now that we know this variation cannot be deleted, block the remove variation link.
msg = $(
'.wcs-can-not-remove-variation-msg[rel=' +
variation_id +
']'
);
msg.text( remove_link.text() );
remove_link.replaceWith( msg );
}
},
error: function () {
container.unblock();
alert( WCSubscriptions.variationDeleteErrorMessage );
},
} );
return false;
} );
// Triggered by $.disableEnableOneTimeShipping() after One Time shipping has been enabled or disabled for variations.
// If the One Time Shipping field needs updating, send the ajax request to update the product setting in the backend
$( '#_subscription_one_time_shipping' ).on(
'subscription_one_time_shipping_updated',
function ( event, is_synced_or_has_trial ) {
if ( $( '.wcs_ots_needs_update' ).length ) {
var data = {
action: 'wcs_update_one_time_shipping',
product_id: woocommerce_admin_meta_boxes_variations.post_id,
one_time_shipping_enabled: ! is_synced_or_has_trial,
one_time_shipping_selected: $(
'#_subscription_one_time_shipping'
).prop( 'checked' ),
nonce: WCSubscriptions.oneTimeShippingCheckNonce,
};
$.ajax( {
url: WCSubscriptions.ajaxUrl,
data: data,
type: 'POST',
success: function ( response ) {
// remove the flag requiring the one time shipping field to be updated
$( '#_subscription_one_time_shipping' ).removeClass(
'wcs_ots_needs_update'
);
$( '#_subscription_one_time_shipping' ).prop(
'checked',
response.one_time_shipping == 'yes' ? true : false
);
},
} );
}
}
);
$( '#general_product_data, #variable_product_options' ).on(
'change',
'[class^="wc_input_subscription_payment_sync"], [class^="wc_input_subscription_trial_length"]',
function () {
$.disableEnableOneTimeShipping();
}
);
/**
* Prevents removal of variations in use by a subscription.
*/
var wcs_prevent_variation_removal = {
init: function () {
if ( 0 === $( '#woocommerce-product-data' ).length ) {
return;
}
$( 'body' ).on(
'woocommerce-product-type-change',
this.product_type_change
);
$( '#variable_product_options' ).on(
'reload',
this.product_type_change
);
$( 'select.variation_actions' ).on(
'delete_all_no_subscriptions_ajax_data',
this.bulk_action_data
);
this.product_type_change();
},
product_type_change: function () {
var product_type = $( '#product-type' ).val();
var $variation_actions = $( 'select.variation_actions' );
var $delete_all = $variation_actions.find(
'option[value="delete_all"], option[value="delete_all_no_subscriptions"]'
);
if (
'variable-subscription' === product_type &&
'delete_all' === $delete_all.val()
) {
$delete_all
.data( 'wcs_original_wc_label', $delete_all.text() )
.attr( 'value', 'delete_all_no_subscriptions' )
.text( WCSubscriptions.bulkDeleteOptionLabel );
} else if (
'variable-subscription' !== product_type &&
'delete_all_no_subscriptions' === $delete_all.val()
) {
$delete_all
.text( $delete_all.data( 'wcs_original_wc_label' ) )
.attr( 'value', 'delete_all' );
}
},
bulk_action_data: function ( event, data ) {
if (
window.confirm(
woocommerce_admin_meta_boxes_variations.i18n_delete_all_variations
)
) {
if (
window.confirm(
woocommerce_admin_meta_boxes_variations.i18n_last_warning
)
) {
data.allowed = true;
// do_variation_action() in woocommerce/assets/js/admin/meta-boxes-product-variation.js doesn't
// allow us to do anything after the AJAX request, so we need to listen to all AJAX requests for a
// little while to update the quantity and refresh the variation list.
$( document ).on(
'ajaxComplete',
wcs_prevent_variation_removal.update_qty_after_removal
);
}
}
return data;
},
update_qty_after_removal: function ( event, jqXHR, ajaxOptions ) {
var $variations = $(
'#variable_product_options .woocommerce_variations'
);
var removed;
// Not our bulk edit request. Ignore.
if (
-1 ===
ajaxOptions.data.indexOf(
'action=woocommerce_bulk_edit_variations'
) ||
-1 ===
ajaxOptions.data.indexOf(
'bulk_action=delete_all_no_subscriptions'
)
) {
return;
}
// Unbind so this doesn't get called every time an AJAX request is performed.
$( document ).off(
'ajaxComplete',
wcs_prevent_variation_removal.update_qty_after_removal
);
// Update variation quantity.
removed =
'OK' === jqXHR.statusText
? parseInt( jqXHR.responseText, 10 )
: 0;
$variations.attr(
'data-total',
Math.max(
0,
parseInt( $variations.attr( 'data-total' ), 10 ) - removed
)
);
$( '#variable_product_options' ).trigger( 'reload' );
},
};
wcs_prevent_variation_removal.init();
/*
* Prevents changing of the product type for subscription products in use by a subscription.
*/
var wcs_prevent_product_type_change = {
init: function () {
if ( 'yes' !== WCSubscriptions.productHasSubscriptions ) {
return;
}
var $select = $( 'select#product-type' );
var $options = $select.find( 'option' );
var $selection = $options.filter( 'option:selected' );
if (
'subscription' !== $selection.val() &&
'variable-subscription' !== $selection.val()
) {
return;
}
$options.not( $selection ).prop( 'disabled', true );
$select
.addClass( 'tips' )
.attr( 'data-tip', WCSubscriptions.productTypeWarning );
},
};
wcs_prevent_product_type_change.init();
/*
* Handles enabling and disabling PayPal Standard for Subscriptions.
*/
var wcs_paypal_standard_settings = {
init: function () {
if ( 0 === $( '#woocommerce_paypal_enabled' ).length ) {
return;
}
$( '#woocommerce_paypal_enabled' ).on(
'change',
this.paypal_enabled_change
);
$( '#woocommerce_paypal_enabled_for_subscriptions' ).on(
'change',
this.paypal_for_subscriptions_enabled
);
this.paypal_enabled_change();
},
/**
* Show and hide the enable PayPal for Subscriptions checkbox when PayPal is enabled or disabled.
*/
paypal_enabled_change: function () {
var $enabled_for_subscriptions_element = $(
'#woocommerce_paypal_enabled_for_subscriptions'
).closest( 'tr' );
if ( $( '#woocommerce_paypal_enabled' ).is( ':checked' ) ) {
$enabled_for_subscriptions_element.show();
} else {
$enabled_for_subscriptions_element.hide();
}
},
/**
* Display a confirm dialog when PayPal for Subscriptions is enabled (checked).
*/
paypal_for_subscriptions_enabled: function () {
if (
$( this ).is( ':checked' ) &&
! confirm( WCSubscriptions.enablePayPalWarning )
) {
$( this ).prop( 'checked', false );
}
},
};
wcs_paypal_standard_settings.init();
/*
* Handles showing and hiding subscription related settings on the Accounts and Privacy settings page
*/
var wcs_accounts_and_privacy_settings = {
init: function () {
if (
0 ===
$( '#woocommerce_enable_signup_and_login_from_checkout' ).length
) {
return;
}
$( '#woocommerce_enable_signup_and_login_from_checkout' ).on(
'change',
this.checkout_account_creation_changed
);
this.checkout_account_creation_changed( 'no_animation' );
},
/**
* Hides or shows the setting to allow customers to create an account on checkout while purchasing subscriptions.
*/
checkout_account_creation_changed: function (
animation_behaviour = ''
) {
var subscription_registration_setting = $(
'#woocommerce_enable_signup_from_checkout_for_subscriptions'
).closest( 'fieldset' );
var hide_function =
animation_behaviour === 'no_animation' ? 'hide' : 'slideUp';
var show_function =
animation_behaviour === 'no_animation' ? 'show' : 'slideDown';
// This setting isn't necessary if the store already allows registration on checkout.
if (
$( '#woocommerce_enable_signup_and_login_from_checkout' ).is(
':checked'
)
) {
subscription_registration_setting[ hide_function ]();
} else {
subscription_registration_setting[ show_function ]();
}
},
};
wcs_accounts_and_privacy_settings.init();
$( '#wpbody' ).on( 'click', '#doaction, #doaction2', function () {
var action = $( this ).is( '#doaction' )
? $( '#bulk-action-selector-top' ).val()
: $( '#bulk-action-selector-bottom' ).val();
if ( 'wcs_remove_personal_data' === action ) {
return window.confirm(
WCSubscriptions.i18n_remove_personal_data_notice
);
}
} );
// On the subscriptions list table empty state screen, add the is-busy class to the button when clicked.
$( '.woo_subscriptions_empty_state__button_container a' ).on( 'click', function ( e ) {
$( this ).addClass( 'is-busy' );
} );
} );