File "products-admin.js"
Full Path: /home/vantageo/public_html/cache/.wp-cli/wp-content/plugins/facebook-for-woocommerce/assets/js/admin/products-admin.js
File size: 18.79 KB
MIME-type: text/plain
Charset: utf-8
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
*
* @package FacebookCommerce
*/
jQuery( document ).ready( function( $ ) {
const pagenow = window.pagenow.length ? window.pagenow : '',
typenow = window.typenow.length ? window.typenow : '';
// products list edit screen
if ( 'edit-product' === pagenow ) {
// handle bulk actions
let submitProductBulkAction = false;
$( 'input#doaction, input#doaction2' ).on( 'click', function( e ) {
if ( ! submitProductBulkAction ) {
e.preventDefault();
} else {
return true;
}
let $submitButton = $( this ),
chosenBulkAction = $submitButton.prev( 'select' ).val();
if ( 'facebook_include' === chosenBulkAction ) {
let products = [];
$.each( $( 'input[name="post[]"]:checked' ), function() {
products.push( parseInt( $( this ).val(), 10 ) );
} );
$.post( facebook_for_woocommerce_products_admin.ajax_url, {
action: 'facebook_for_woocommerce_set_product_sync_bulk_action_prompt',
security: facebook_for_woocommerce_products_admin.set_product_sync_bulk_action_prompt_nonce,
toggle: chosenBulkAction,
products: products
}, function( response ) {
if ( response && ! response.success ) {
closeExistingModal();
// open new modal, populate template with AJAX response data
new $.WCBackboneModal.View( {
target: 'facebook-for-woocommerce-modal',
string: response.data
} );
} else {
// no modal displayed: submit form as normal
submitProductBulkAction = true;
$submitButton.trigger( 'click' );
}
} );
} else {
// no modal displayed: submit form as normal
submitProductBulkAction = true;
$submitButton.trigger( 'click' );
}
} );
}
// individual product edit screen
if ( 'product' === pagenow ) {
/**
* Toggles (enables/disables) Facebook setting fields.
*
* @since 1.10.0
*
* @param {boolean} enabled whether the settings fields should be enabled or not
* @param {jQuery} $container a common ancestor of all the elements that can be enabled/disabled
*/
function toggleFacebookSettings( enabled, $container ) {
$container.find( '.enable-if-sync-enabled' ).prop( 'disabled', ! enabled );
}
/**
* Toggles (shows/hides) Sync and show option and changes the select value if needed.
*
* @since 2.0.0
*
* @param {boolean} show whether the Sync and show option should be displayed or not
* @param {jQuery} $select the sync mode select
*/
function toggleSyncAndShowOption( show, $select ) {
if ( ! show ) {
// hide Sync and show option
$select.find( 'option[value=\'sync_and_show\']' ).hide();
if ( 'sync_and_show' === $select.val() ) {
// change selected option to Sync and hide
$select.val( 'sync_and_hide' );
}
} else {
// show Sync and Show option
$select.find( 'option[value=\'sync_and_show\']' ).show();
// restore originally selected option
if ( $select.prop( 'original' ) ) {
$select.val( $select.prop( 'original' ) );
}
}
}
/**
* Toggles (shows/hides) the visibility of Facebook Commerce setting fields.
*
* @since 2.1.0
*
* @param {boolean} enabled whether the settings fields should be enabled or not
* @param {jQuery} $container a common ancestor of all the elements that can be shown/hidden
*/
function toggleFacebookCommerceSettings( enabled, $container ) {
let $group = $container.find( '.wc-facebook-commerce-options-group' );
if ( enabled ) {
$group.show();
} else {
$group.hide();
}
}
/**
* Disables and changes the checked status of the Sell on Instagram setting field.
*
* Additionally, shows/hides messages explaining that the product is not ready for Commerce.
*
* @since 2.1.0
*
* @param {boolean} enabled whether the setting field should be enabled or not
* @param {jQuery} $container a common ancestor of all the elements that need to modified
*/
function toggleFacebookSellOnInstagramSetting( enabled, $container ) {
let $field = $container.find( '#wc_facebook_commerce_enabled' );
let checked = $field.prop( 'original' );
$field.prop( 'checked', enabled ? checked : false ).prop( 'disabled', ! enabled );
// trigger change to hide fields based on the new state
$field.trigger( 'change' );
// restore previously stored value so that we can later restore the field to the status it had before we disabled it here
$field.prop( 'original', checked );
$container.find( '#product-not-ready-notice, #variable-product-not-ready-notice' ).hide();
if ( isVariableProduct() && ! isSyncEnabledForVariableProduct() ) {
$container.find( '#variable-product-not-ready-notice' ).show();
} else if ( ! enabled ) {
$container.find( '#product-not-ready-notice' ).show();
}
}
/**
* Determines whether product properties are configured using appropriate values for Commerce.
*
* @since 2.1.0
*
* @return {boolean}
*/
function isProductReadyForCommerce() {
if ( ! isSyncEnabledForProduct() ) {
return false;
}
if ( ! isPriceDefinedForProduct() ) {
return false;
}
if ( ! isStockManagementEnabledForProduct() ) {
return false;
}
return true;
}
/**
* Determines whether the product or one of its variations has Facebook Sync enabled.
*
* @since 2.1.0
*
* @return {boolean}
*/
function isSyncEnabledForProduct() {
if ( isVariableProduct() ) {
return isSyncEnabledForVariableProduct();
}
return isSyncEnabledForSimpleProduct();
}
/**
* Determines whether the current product has synced variations.
*
* @since 2.1.0
*
* @returns {boolean}
*/
function isSyncEnabledForVariableProduct() {
let $fields = $( '.js-variable-fb-sync-toggle' );
// fallback to the value at page load if the variation fields haven't been loaded
if ( 0 === $fields.length ) {
return !! facebook_for_woocommerce_products_admin.is_sync_enabled_for_product;
}
// returns true if any of the Facebook Sync settings is set to a value other than 'sync_disabled'
return !! $fields.map( ( i, element ) => $( element ).val() !== 'sync_disabled' ? element : null ).length;
}
/**
* Determines whether the product has Facebook Sync enabled.
*
* @since 2.1.0
*
* @return {boolean}
*/
function isSyncEnabledForSimpleProduct() {
return simpleProductSyncModeSelect.val() !== 'sync_disabled';
}
/**
* Determines whether the product has a Regular Price or Facebook Price defined.
*
* @since 2.1.0
*
* @return {boolean}
*/
function isPriceDefinedForProduct() {
if ( isVariableProduct() ) {
// TODO: determine whether variations enabled for sync have a Regular Price or Facebook Price defined {WV 2020-09-19}
return true;
}
return isPriceDefinedForSimpleProduct();
}
/**
* Determines whether the product is a Variable product.
*
* @since 2.1.2
*
* @return {boolean}
*/
function isVariableProduct() {
var productType = $( 'select#product-type' ).val();
return !! ( productType && productType.match( /variable/ ) );
}
/**
* Determines whether a simple product has a Regular Price or Facebook Price defined.
*
* @since 2.1.0
*
* @return {boolean}
*/
function isPriceDefinedForSimpleProduct() {
return !! ( $( '#_regular_price' ).val() || $( '#fb_product_price' ).val() );
}
/**
* Determines whether the product has Manage Stock enabled and Stock quantity defined.
*
* @since 2.1.0
*
* @return {boolean}
*/
function isStockManagementEnabledForProduct() {
// TODO: determine whether variations enabled for sync have stock management enabled {WV 2020-09-19}
return isStockManagementEnabledForSimpleProduct();
}
/**
* Determines whether a simple product has Manage Stock enabled and Stock quantity defined.
*
* @since 2.1.0
*
* @return {boolean}
*/
function isStockManagementEnabledForSimpleProduct() {
return !! ( $( '#_manage_stock' ).prop( 'checked' ) && $( '#_stock' ).val() );
}
/**
* Determines whether we should ask the user to select a Google Product Category.
*
* @since 2.1.0
*
* @return {boolean}
*/
function shouldShowMissingGoogleProductCategoryAlert() {
if ( ! $( '#wc_facebook_commerce_enabled' ).prop( 'checked' ) ) {
return false;
}
if ( ! isProductReadyForCommerce() ) {
return false;
}
let selectedCategories = $( '.wc_facebook_commerce_fields .wc-facebook-google-product-category-select' ).map( ( i, element ) => {
return $( element ).val() ? $( element ).val() : null;
} );
return selectedCategories.length < 2;
}
/**
* Shows an alert asking the user to select a Google product category and sub-category.
*
* @since 2.1.0
*
* @param {jQuery.Event} event a jQuery Event object for the submit event
* @returns {boolean}
*/
function showMissingGoogleProductCategoryAlert( event ) {
event.preventDefault();
alert( facebook_for_woocommerce_products_admin.i18n.missing_google_product_category_message );
return false;
}
/**
* Store the original value of the given element for later use.
*
* @since 2.3.0
*
* @param {jQuery} $syncModeSelect a jQuery element object
*/
function storeSyncModeOriginalValue( $syncModeSelect ) {
$syncModeSelect.attr( 'data-original-value', $syncModeSelect.val() );
}
/**
* Reverts the value of the given sync mode element to its original value.
*
* @since 2.3.0
*
* @param {jQuery} $syncModeSelect a jQuery element object
*/
function revertSyncModeToOriginalValue( $syncModeSelect ) {
$syncModeSelect.val( $syncModeSelect.attr( 'data-original-value') );
}
/**
* Determines whether we should show the product removed from sync confirm modal.
*
* @since 2.3.0
*
* @param {jQuery} $syncModeSelect a jQuery object with one or more sync mode select elements
* @return {boolean}
*/
function shouldShowProductRemovedFromSyncConfirmModal( $syncModeSelect ) {
let syncValuesStatus = $syncModeSelect.map( function ( index, selectElement ) {
let $syncMode = $( selectElement );
let syncModeValue = $syncMode.val();
let isProductPublished = !! facebook_for_woocommerce_products_admin.is_product_published;
return isProductPublished && 'sync_disabled' === syncModeValue && syncModeValue !== $syncMode.attr( 'data-original-value' );
} ).toArray();
return syncValuesStatus.indexOf( true ) > -1;
}
/**
* Gets the target product ID based on the given sync select element.
*
* @since 2.3.0
*
* @param {jQuery} $syncModeSelect a jQuery element object
*/
function getSyncTargetProductID( $syncModeSelect ) {
if ( simpleProductSyncModeSelect === $syncModeSelect ) {
// simple product
return $( 'input#post_ID' ).val();
}
// variable product
return $syncModeSelect.closest( '.woocommerce_variation' ).find( 'input[name^=variable_post_id]' ).val();
}
/**
* Shows the product removed from sync confirm modal.
*
* @since 2.3.0
*
* @param {jQuery} $syncModeSelect a jQuery element object
*/
function showProductRemovedFromSyncConfirmModal( $syncModeSelect ) {
closeExistingModal();
$maybeRemoveFromSyncModeSelect = $syncModeSelect;
maybeRemoveFromSyncProductID = getSyncTargetProductID( $syncModeSelect )
new $.WCBackboneModal.View( {
target: 'facebook-for-woocommerce-modal',
string: {
message: facebook_for_woocommerce_products_admin.product_removed_from_sync_confirm_modal_message,
buttons: facebook_for_woocommerce_products_admin.product_removed_from_sync_confirm_modal_buttons
}
} );
}
/**
* Fills in product IDs to remove from Sync.
*
* @since 2.3.0
*/
function populateRemoveFromSyncProductIDsField() {
$( facebook_for_woocommerce_products_admin.product_removed_from_sync_field_id ).val( removeFromSyncProductIDs.join( ',' ) );
}
/**
* Removes the given product ID from the list of product to delete from Sync.
*
* @since 2.3.0
*
* @param {String} productID Product ID to remove
*/
function removeProductIDFromUnSyncList( productID ) {
removeFromSyncProductIDs = removeFromSyncProductIDs.filter( function ( value ) {
return value !== productID;
} );
populateRemoveFromSyncProductIDsField();
}
let $maybeRemoveFromSyncModeSelect = null;
let maybeRemoveFromSyncProductID = null;
let removeFromSyncProductIDs = [];
$( document.body ).on( 'click', 'button.button-product-removed-from-sync-delete', function () {
if ( maybeRemoveFromSyncProductID ) {
closeExistingModal();
removeFromSyncProductIDs.push( maybeRemoveFromSyncProductID );
populateRemoveFromSyncProductIDsField();
}
} )
.on( 'click', 'button.button-product-removed-from-sync-cancel', function () {
closeExistingModal();
if ( $maybeRemoveFromSyncModeSelect ) {
revertSyncModeToOriginalValue( $maybeRemoveFromSyncModeSelect );
$maybeRemoveFromSyncModeSelect = null;
}
populateRemoveFromSyncProductIDsField();
} );
// handle change events for the Sell on Instagram checkbox field
$( '#facebook_options #wc_facebook_commerce_enabled' ).on( 'change', function() {
let checked = $( this ).prop( 'checked' );
// toggle visibility of all commerce fields
if ( checked ) {
$( '.wc_facebook_commerce_fields' ).show();
} else {
$( '.wc_facebook_commerce_fields').hide();
}
// toggle visibility of attribute fields
if ( $( '.product_attributes' ).find( '.woocommerce_attribute' ).length ) {
$( '.show_if_has_attributes' ).show();
} else {
$( '.show_if_has_attributes' ).hide();
}
$( this ).prop( 'original', checked );
} ).trigger( 'change' );
// toggle Facebook settings fields for simple products
const simpleProductSyncModeSelect = $( '#wc_facebook_sync_mode' );
const facebookSettingsPanel = simpleProductSyncModeSelect.closest( '.woocommerce_options_panel' );
// store sync mode original value for later use
storeSyncModeOriginalValue( simpleProductSyncModeSelect );
simpleProductSyncModeSelect.on( 'change', function() {
let syncEnabled = simpleProductSyncModeSelect.val() !== 'sync_disabled';
toggleFacebookSettings( syncEnabled, facebookSettingsPanel );
toggleFacebookCommerceSettings( syncEnabled, facebookSettingsPanel );
if ( syncEnabled ) {
removeProductIDFromUnSyncList( getSyncTargetProductID( simpleProductSyncModeSelect ) );
}
simpleProductSyncModeSelect.prop( 'original', simpleProductSyncModeSelect.val() );
if ( shouldShowProductRemovedFromSyncConfirmModal( simpleProductSyncModeSelect ) ) {
showProductRemovedFromSyncConfirmModal( simpleProductSyncModeSelect );
}
} ).trigger( 'change' );
$( '#_virtual' ).on( 'change', function () {
toggleSyncAndShowOption( ! $( this ).prop( 'checked' ), simpleProductSyncModeSelect );
} ).trigger( 'change' );
// Update the sync when catalog visibility changes.
$( 'input[name=_visibility]' ).on ( 'change', function(){
if ( $( this ).val() !== 'hidden' && $( this ).val() !== 'search' ) {
if ( simpleProductSyncModeSelect.val() === 'sync_disabled' ) {
simpleProductSyncModeSelect.val( 'sync_and_show' ).trigger( 'change' );;
}
}
})
const $productData = $( '#woocommerce-product-data' );
// check whether the product meets the requirements for Commerce
$productData.on(
'change',
'#_regular_price, #_manage_stock, #_stock, #wc_facebook_sync_mode, #fb_product_price',
function( event ) {
// allow validation handlers that run on change to run before we check any field values
setTimeout( function() {
toggleFacebookSellOnInstagramSetting( isProductReadyForCommerce(), $( '#facebook_options' ) );
}, 1 );
}
);
// toggle Facebook settings fields for variations
$( '.woocommerce_variations' ).on( 'change', '.js-variable-fb-sync-toggle', function () {
let $syncModeSelect = $( this );
let syncEnabled = $syncModeSelect.val() !== 'sync_disabled';
toggleFacebookSettings( syncEnabled, $syncModeSelect.closest( '.wc-metabox-content' ) );
toggleFacebookSellOnInstagramSetting( isProductReadyForCommerce(), $( '#facebook_options' ) );
if ( syncEnabled ) {
removeProductIDFromUnSyncList( getSyncTargetProductID( $syncModeSelect ) );
}
$syncModeSelect.prop( 'original', $syncModeSelect.val() );
if ( shouldShowProductRemovedFromSyncConfirmModal( $syncModeSelect ) ) {
showProductRemovedFromSyncConfirmModal( $syncModeSelect );
}
} );
$productData.on( 'woocommerce_variations_loaded', function () {
$productData.find( '.js-variable-fb-sync-toggle' ).each( function ( index, element ) {
let $syncModeSelect = $( element );
toggleFacebookSettings( $syncModeSelect.val() !== 'sync_disabled', $syncModeSelect.closest( '.wc-metabox-content' ) );
$syncModeSelect.prop( 'original', $syncModeSelect.val() );
storeSyncModeOriginalValue( $syncModeSelect );
} );
$( '.variable_is_virtual' ).on( 'change', function () {
const jsSyncModeToggle = $( this ).closest( '.wc-metabox-content' ).find( '.js-variable-fb-sync-toggle' );
toggleSyncAndShowOption( ! $( this ).prop( 'checked' ), jsSyncModeToggle );
} );
toggleFacebookSellOnInstagramSetting( isProductReadyForCommerce(), $( '#facebook_options' ) );
} );
// show/hide Custom Image URL setting
$productData.on( 'change', '.js-fb-product-image-source', function() {
let $container = $( this ).closest( '.woocommerce_options_panel, .wc-metabox-content' );
let imageSource = $( this ).val();
$container.find( '.product-image-source-field' ).closest( '.form-field' ).hide();
$container.find( `.show-if-product-image-source-${imageSource}` ).closest( '.form-field' ).show();
} );
$( '.js-fb-product-image-source:checked:visible' ).trigger( 'change' );
// trigger settings fields modifiers when variations are loaded
$productData.on( 'woocommerce_variations_loaded', function() {
$( '.js-variable-fb-sync-toggle:visible' ).trigger( 'change' );
$( '.js-fb-product-image-source:checked:visible' ).trigger( 'change' );
$( '.variable_is_virtual:visible' ).trigger( 'change' );
} );
// open modal explaining sell on Instagram requirements
$( '#facebook_options' ).on( 'click', '#product-not-ready-notice-open-modal', function( event ) {
event.preventDefault();
closeExistingModal();
new $.WCBackboneModal.View( {
target: 'facebook-for-woocommerce-modal',
string: {
message: facebook_for_woocommerce_products_admin.product_not_ready_modal_message,
buttons: facebook_for_woocommerce_products_admin.product_not_ready_modal_buttons
}
} );
} );
// toggle Sell on Instagram checkbox on page load
toggleFacebookSellOnInstagramSetting( isProductReadyForCommerce(), facebookSettingsPanel );
}
} );