/*global wc_add_to_cart_variation_params */ ;(function ( $, window, document, undefined ) { /** * VariationForm class which handles variation forms and attributes. */ var VariationForm = function( $form ) { this.$form = $form; this.$attributeFields = $form.find( '.variations select' ); this.$singleVariation = $form.find( '.single_variation' ); this.$singleVariationWrap = $form.find( '.single_variation_wrap' ); this.$resetVariations = $form.find( '.reset_variations' ); this.$product = $form.closest( '.product' ); this.variationData = $form.data( 'product_variations' ); this.useAjax = false === this.variationData; this.xhr = false; // Initial state. this.$singleVariationWrap.show(); this.$form.off( '.wc-variation-form' ); // Methods. this.getChosenAttributes = this.getChosenAttributes.bind( this ); this.findMatchingVariations = this.findMatchingVariations.bind( this ); this.isMatch = this.isMatch.bind( this ); this.toggleResetLink = this.toggleResetLink.bind( this ); // Events. $form.on( 'click.wc-variation-form', '.reset_variations', { variationForm: this }, this.onReset ); $form.on( 'reload_product_variations', { variationForm: this }, this.onReload ); $form.on( 'hide_variation', { variationForm: this }, this.onHide ); $form.on( 'show_variation', { variationForm: this }, this.onShow ); $form.on( 'click', '.single_add_to_cart_button', { variationForm: this }, this.onAddToCart ); $form.on( 'reset_data', { variationForm: this }, this.onResetDisplayedVariation ); $form.on( 'reset_image', { variationForm: this }, this.onResetImage ); $form.on( 'change.wc-variation-form', '.variations select', { variationForm: this }, this.onChange ); $form.on( 'found_variation.wc-variation-form', { variationForm: this }, this.onFoundVariation ); $form.on( 'check_variations.wc-variation-form', { variationForm: this }, this.onFindVariation ); $form.on( 'update_variation_values.wc-variation-form', { variationForm: this }, this.onUpdateAttributes ); // Init after gallery. setTimeout( function() { $form.trigger( 'check_variations' ); $form.trigger( 'wc_variation_form' ); }, 100 ); }; /** * Reset all fields. */ VariationForm.prototype.onReset = function( event ) { event.preventDefault(); event.data.variationForm.$attributeFields.val( '' ).change(); event.data.variationForm.$form.trigger( 'reset_data' ); }; /** * Reload variation data from the DOM. */ VariationForm.prototype.onReload = function( event ) { var form = event.data.variationForm; form.variationData = form.$form.data( 'product_variations' ); form.useAjax = false === form.variationData; form.$form.trigger( 'check_variations' ); }; /** * When a variation is hidden. */ VariationForm.prototype.onHide = function( event ) { event.preventDefault(); event.data.variationForm.$form.find( '.single_add_to_cart_button' ).removeClass( 'wc-variation-is-unavailable' ).addClass( 'disabled wc-variation-selection-needed' ); event.data.variationForm.$form.find( '.woocommerce-variation-add-to-cart' ).removeClass( 'woocommerce-variation-add-to-cart-enabled' ).addClass( 'woocommerce-variation-add-to-cart-disabled' ); }; /** * When a variation is shown. */ VariationForm.prototype.onShow = function( event, variation, purchasable ) { event.preventDefault(); if ( purchasable ) { event.data.variationForm.$form.find( '.single_add_to_cart_button' ).removeClass( 'disabled wc-variation-selection-needed wc-variation-is-unavailable' ); event.data.variationForm.$form.find( '.woocommerce-variation-add-to-cart' ).removeClass( 'woocommerce-variation-add-to-cart-disabled' ).addClass( 'woocommerce-variation-add-to-cart-enabled' ); } else { event.data.variationForm.$form.find( '.single_add_to_cart_button' ).removeClass( 'wc-variation-selection-needed' ).addClass( 'disabled wc-variation-is-unavailable' ); event.data.variationForm.$form.find( '.woocommerce-variation-add-to-cart' ).removeClass( 'woocommerce-variation-add-to-cart-enabled' ).addClass( 'woocommerce-variation-add-to-cart-disabled' ); } }; /** * When the cart button is pressed. */ VariationForm.prototype.onAddToCart = function( event ) { if ( $( this ).is('.disabled') ) { event.preventDefault(); if ( $( this ).is('.wc-variation-is-unavailable') ) { window.alert( wc_add_to_cart_variation_params.i18n_unavailable_text ); } else if ( $( this ).is('.wc-variation-selection-needed') ) { window.alert( wc_add_to_cart_variation_params.i18n_make_a_selection_text ); } } }; /** * When displayed variation data is reset. */ VariationForm.prototype.onResetDisplayedVariation = function( event ) { var form = event.data.variationForm; form.$product.find( '.product_meta' ).find( '.sku' ).wc_reset_content(); form.$product.find( '.product_weight' ).wc_reset_content(); form.$product.find( '.product_dimensions' ).wc_reset_content(); form.$form.trigger( 'reset_image' ); form.$singleVariation.slideUp( 200 ).trigger( 'hide_variation' ); }; /** * When the product image is reset. */ VariationForm.prototype.onResetImage = function( event ) { event.data.variationForm.$form.wc_variations_image_update( false ); }; /** * Looks for matching variations for current selected attributes. */ VariationForm.prototype.onFindVariation = function( event ) { var form = event.data.variationForm, attributes = form.getChosenAttributes(), currentAttributes = attributes.data; if ( attributes.count === attributes.chosenCount ) { if ( form.useAjax ) { if ( form.xhr ) { form.xhr.abort(); } form.$form.block( { message: null, overlayCSS: { background: '#fff', opacity: 0.6 } } ); currentAttributes.product_id = parseInt( form.$form.data( 'product_id' ), 10 ); currentAttributes.custom_data = form.$form.data( 'custom_data' ); form.xhr = $.ajax( { url: wc_add_to_cart_variation_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_variation' ), type: 'POST', data: currentAttributes, success: function( variation ) { if ( variation ) { form.$form.trigger( 'found_variation', [ variation ] ); } else { form.$form.trigger( 'reset_data' ); form.$form.find( '.single_variation' ).after( '

' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '

' ); form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 ); } }, complete: function() { form.$form.unblock(); } } ); } else { form.$form.trigger( 'update_variation_values' ); var matching_variations = form.findMatchingVariations( form.variationData, currentAttributes ), variation = matching_variations.shift(); if ( variation ) { form.$form.trigger( 'found_variation', [ variation ] ); } else { form.$form.trigger( 'reset_data' ); form.$form.find( '.single_variation' ).after( '

' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '

' ); form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 ); } } } else { form.$form.trigger( 'update_variation_values' ); form.$form.trigger( 'reset_data' ); } // Show reset link. form.toggleResetLink( attributes.chosenCount > 0 ); }; /** * Triggered when a variation has been found which matches all attributes. */ VariationForm.prototype.onFoundVariation = function( event, variation ) { var form = event.data.variationForm, $sku = form.$product.find( '.product_meta' ).find( '.sku' ), $weight = form.$product.find( '.product_weight' ), $dimensions = form.$product.find( '.product_dimensions' ), $qty = form.$singleVariationWrap.find( '.quantity' ), purchasable = true, variation_id = '', template = false, $template_html = ''; if ( variation.sku ) { $sku.wc_set_content( variation.sku ); } else { $sku.wc_reset_content(); } if ( variation.weight ) { $weight.wc_set_content( variation.weight_html ); } else { $weight.wc_reset_content(); } if ( variation.dimensions ) { $dimensions.wc_set_content( variation.dimensions_html ); } else { $dimensions.wc_reset_content(); } form.$form.wc_variations_image_update( variation ); if ( ! variation.variation_is_visible ) { template = wp_template( 'unavailable-variation-template' ); } else { template = wp_template( 'variation-template' ); variation_id = variation.variation_id; } $template_html = template( { variation: variation } ); $template_html = $template_html.replace( '/**/', '' ); form.$singleVariation.html( $template_html ); form.$form.find( 'input[name="variation_id"], input.variation_id' ).val( variation.variation_id ).change(); // Hide or show qty input if ( variation.is_sold_individually === 'yes' ) { $qty.find( 'input.qty' ).val( '1' ).attr( 'min', '1' ).attr( 'max', '' ); $qty.hide(); } else { $qty.find( 'input.qty' ).attr( 'min', variation.min_qty ).attr( 'max', variation.max_qty ); $qty.show(); } // Enable or disable the add to cart button if ( ! variation.is_purchasable || ! variation.is_in_stock || ! variation.variation_is_visible ) { purchasable = false; } // Reveal if ( $.trim( form.$singleVariation.text() ) ) { form.$singleVariation.slideDown( 200 ).trigger( 'show_variation', [ variation, purchasable ] ); } else { form.$singleVariation.show().trigger( 'show_variation', [ variation, purchasable ] ); } }; /** * Triggered when an attribute field changes. */ VariationForm.prototype.onChange = function( event ) { var form = event.data.variationForm; form.$form.find( 'input[name="variation_id"], input.variation_id' ).val( '' ).change(); form.$form.find( '.wc-no-matching-variations' ).remove(); if ( form.useAjax ) { form.$form.trigger( 'check_variations' ); } else { form.$form.trigger( 'woocommerce_variation_select_change' ); form.$form.trigger( 'check_variations' ); $( this ).blur(); } // Custom event for when variation selection has been changed form.$form.trigger( 'woocommerce_variation_has_changed' ); }; /** * Escape quotes in a string. * @param {string} string * @return {string} */ VariationForm.prototype.addSlashes = function( string ) { string = string.replace( /'/g, '\\\'' ); string = string.replace( /"/g, '\\\"' ); return string; }; /** * Updates attributes in the DOM to show valid values. */ VariationForm.prototype.onUpdateAttributes = function( event ) { var form = event.data.variationForm, attributes = form.getChosenAttributes(), currentAttributes = attributes.data; if ( form.useAjax ) { return; } // Loop through selects and disable/enable options based on selections. form.$attributeFields.each( function( index, el ) { var current_attr_select = $( el ), current_attr_name = current_attr_select.data( 'attribute_name' ) || current_attr_select.attr( 'name' ), show_option_none = $( el ).data( 'show_option_none' ), option_gt_filter = ':gt(0)', attached_options_count = 0, new_attr_select = $( '').attr({ type: 'hidden', name: 'bookings_field_start_date_time', value: $value }).appendTo('#request-info-popup form'); } }); // Variations & Addons $("input[name^=addon-], select[name^=addon-], input[name^=attribute_pa_], select[name^=attribute_pa_]").each(function() { let $name = this.name; let $label = $(this).closest('.wc-pao-addon-container').find('label'); $label = $label.attr('data-addon-name'); $(document).on('click', '.wc-pao-addon-image-swatch', function() { let $value = $(this).attr('data-value'); let $option = $(this).closest('.wc-pao-addon-container').find('option[value="' + $value + '"]'); let $label = $option.attr('data-label'); if ($value) { $('#request-info-popup form [name="' + $label + '"]').remove(); $('').attr({ type: 'hidden', name: $label, value: $value }).appendTo('#request-info-popup form'); } }); $(document).on('change', '[name="' + $name + '"]', function() { let $value = this.value; if ($value) { $('#request-info-popup form [name="' + $label + '"]').remove(); $('').attr({ type: 'hidden', name: $label, value: $value }).appendTo('#request-info-popup form'); } }); }); } if ($('label[for="delivery-next-slot"]').length > 0 || $('input[name="delivery_moment"]').val() !== 'custom_date') { $('.delivery-calendar-wrapper').hide(); } let $delivery_wrapper = function () { $(document).on('change', 'input[name="delivery_moment"]', function() { let $this = $(this); if ($this.val() === 'custom_date') { $('.delivery-calendar-wrapper').show(); } else { $('.delivery-calendar-wrapper').hide(); } }); } $delivery_wrapper(); $(document).ajaxComplete(function() { $delivery_wrapper(); if ($('label[for="delivery-next-slot"]').length > 0 || $('input[name="delivery_moment"]').val() !== 'custom_date') { $('.delivery-calendar-wrapper').hide(); } }); if ($('input[name="delivery_calendar_date"]').length > 0) { let $load_datepicker = function() { const $calendar = $('#delivery-calendar'); const $allowed_days = $calendar.attr('data-allowed_week_days').split(',').map(Number); const $time_slots = JSON.parse($calendar.attr('data-time_slots')); const $today = new Date(); const $dayIndex = $today.getDay(); /** * Calculates all dates between two dates. */ let $disabled_dates = []; const $disabled_date_ranges = !!$calendar.attr('data-disabled_dates') ? $calendar.attr('data-disabled_dates').split(',') : []; $.each( $disabled_date_ranges, function(key, value) { let $range_dates = value.split('/'); const $from = new Date($range_dates[0]); let $to = new Date($range_dates[1]); while ($from < $to) { $disabled_dates = [...$disabled_dates, new Date($from).toISOString().split('T')[0]] $from.setDate($from.getDate() + 1) } $disabled_dates = [...$disabled_dates, $to.toISOString().split('T')[0]] }); let $today_time_slots = !!$time_slots[$dayIndex] ? $time_slots[$dayIndex].split(',') : ''; let $get_date_picker_times = function($currentDateTime) { // 'this' is jquery object datetimepicker let $day = $currentDateTime.getDay(); this.setOptions({ allowTimes: $time_slots[$day].split(',') }); // Update hidden value with selected date timestamp let d = new Date($currentDateTime); let ms = d.valueOf(); let s = ms / 1000; if (s > 0) { //store in hidden field. $('input[name="delivery_date_timestamp"]').val(s); } } /*let $get_default_date = function () { let $date = new Date(); while (!is_valid($date)) { $date.setDate($date.getDate() + 1); } return $date; }*/ $calendar.datetimepicker({ minDate: 0, dayOfWeekStart: 1, format: 'd/m/Y H:i', timepicker: true, allowTimes: $today_time_slots, //defaultDate: $get_default_date(), onChangeDateTime: $get_date_picker_times, beforeShowDay: function ($date) { return [ $.inArray($date.getDay(), $allowed_days) !== -1 && $disabled_dates.indexOf($date.toISOString().split('T')[0]) === -1 ]; }, }); } $load_datepicker(); $(document).ajaxComplete(function() { $load_datepicker(); }); } $(document).on('click', '.woocommerce-checkout .cross-sell-items .add_to_cart_button.ajax_add_to_cart', function () { setTimeout(() => { $('body').trigger('update_checkout'); }, 1000); }); });