Plugin Directory

Changeset 3237969


Ignore:
Timestamp:
02/10/2025 01:47:37 PM (14 months ago)
Author:
orderable
Message:

Update to version 1.17.1 from GitHub

Location:
orderable
Files:
4 added
2 deleted
12 edited
1 copied

Legend:

Unmodified
Added
Removed
  • orderable/tags/1.17.1/assets/frontend/js/main.js

    r3192586 r3237969  
    11
     2(function ($, document) {
     3  'use strict';
     4
     5  var orderable_accordion = {
     6    /**
     7     * On doc ready.
     8     */
     9    on_ready() {
     10      orderable_accordion.cache();
     11      orderable_accordion.watch();
     12    },
     13    /**
     14     * Cache.
     15     */
     16    cache() {
     17      orderable_accordion.vars = {
     18        classes: {
     19          parent: 'orderable-accordion',
     20          link: 'orderable-accordion__item-link',
     21          content: 'orderable-accordion__item-content',
     22          link_active: 'orderable-accordion__item-link--active',
     23          content_active: 'orderable-accordion__item-content--active'
     24        }
     25      };
     26    },
     27    /**
     28     * Watch.
     29     */
     30    watch() {
     31      /**
     32       * When click accordion link.
     33       */
     34      $(document.body).on('click', '.' + orderable_accordion.vars.classes.link, function (e) {
     35        e.preventDefault();
     36        const $link = $(this),
     37          $parent = $link.closest('.' + orderable_accordion.vars.classes.parent),
     38          content_id = $link.attr('href'),
     39          $content = $(content_id),
     40          is_active = $link.hasClass(orderable_accordion.vars.classes.link_active);
     41        $parent.find('.' + orderable_accordion.vars.classes.link).removeClass(orderable_accordion.vars.classes.link_active);
     42        $parent.find('.' + orderable_accordion.vars.classes.content).removeClass(orderable_accordion.vars.classes.content_active);
     43        if (!is_active) {
     44          $link.addClass(orderable_accordion.vars.classes.link_active);
     45          $content.addClass(orderable_accordion.vars.classes.content_active);
     46        }
     47        $(document.body).trigger('orderable-accordion.toggled', {
     48          link: $link,
     49          content: $content
     50        });
     51      });
     52
     53      /**
     54       * When drawer is opened.
     55       */
     56      $(document.body).on('orderable-scrollbar.created', function (e, args) {
     57        const $active_accordion = $('.orderable-drawer .' + orderable_accordion.vars.classes.link_active);
     58        if ($active_accordion.length <= 0) {
     59          return;
     60        }
     61        const $scroll_content = args.content,
     62          scroll_position = $scroll_content.scrollTop() - $scroll_content.offset().top + $active_accordion.offset().top;
     63        $scroll_content.scrollTop(scroll_position);
     64      });
     65    }
     66  };
     67  $(document).ready(orderable_accordion.on_ready);
     68})(jQuery, document);
     69(function ($, document) {
     70  'use strict';
     71
     72  var orderable_drawer = {
     73    /**
     74     * Delays invoking function
     75     *
     76     * @param {Function} func    The function to debounce.
     77     * @param {number}   timeout The number of milliseconds to delay.
     78     * @return {Function} Returns the new debounced function.
     79     */
     80    debounce(func, timeout = 700) {
     81      let timer;
     82      return (...args) => {
     83        clearTimeout(timer);
     84        timer = setTimeout(() => {
     85          func.apply(this, args);
     86        }, timeout);
     87      };
     88    },
     89    /**
     90     * Allow only number for events like keypress
     91     *
     92     * @param {Event} event
     93     */
     94    allow_only_numbers(event) {
     95      const value = String.fromCharCode(event.which);
     96      if (!/^\d+$/.test(value)) {
     97        event.preventDefault();
     98      }
     99    },
     100    /**
     101     * Send a request to change the quantity.
     102     *
     103     * @param {Event} event
     104     */
     105    on_change_quantity(event) {
     106      const quantityElement = $(event.currentTarget);
     107      const product_id = quantityElement.data('orderable-product-id');
     108      const cart_item_key = quantityElement.data('orderable-cart-item-key');
     109      const quantity = parseInt(quantityElement.text());
     110      const data = {
     111        action: 'orderable_cart_quantity',
     112        cart_item_key,
     113        product_id,
     114        quantity
     115      };
     116      jQuery.post(orderable_vars.ajax_url, data, function (response) {
     117        if (!response) {
     118          return;
     119        }
     120        $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, quantityElement]);
     121        $(document.body).trigger('orderable-drawer.quantity-updated');
     122      });
     123    },
     124    /**
     125     * On doc ready.
     126     */
     127    on_ready() {
     128      orderable_drawer.cache();
     129      orderable_drawer.watch();
     130
     131      /**
     132       * Handle manually changing the quantity of a product.
     133       */
     134      $(document.body).on('keypress', '.orderable-quantity-roller__quantity', orderable_drawer.allow_only_numbers);
     135      $('.orderable-drawer__cart, .orderable-product--add-to-cart, .orderable-products-list').on('input', '.orderable-quantity-roller__quantity', orderable_drawer.debounce(orderable_drawer.on_change_quantity));
     136      $(document.body).on('click', '.orderable-quantity-roller__quantity', function (event) {
     137        event.stopPropagation();
     138      });
     139
     140      /**
     141       * We turn off the click event for .add_to_cart_button elements
     142       * to keep the AJAX behaviour only on Mini cart when the option
     143       * "Enable AJAX add to cart buttons on archives" is disabled.
     144       */
     145      if (orderable_vars && !orderable_vars.woocommerce_enable_ajax_add_to_cart) {
     146        $(document.body).off('click', '.add_to_cart_button');
     147      }
     148    },
     149    /**
     150     * Cache.
     151     */
     152    cache() {
     153      orderable_drawer.vars = {
     154        classes: {
     155          overlay: 'orderable-drawer-overlay',
     156          drawer: 'orderable-drawer',
     157          drawer_cart: 'orderable-drawer__cart',
     158          drawer_html: 'orderable-drawer__html',
     159          overlay_open: 'orderable-drawer-overlay--open',
     160          drawer_open: 'orderable-drawer--open',
     161          drawer_open_body: 'orderable-drawer-open'
     162        }
     163      };
     164      orderable_drawer.elements = {
     165        body: $('body'),
     166        overlay: $('.' + orderable_drawer.vars.classes.overlay),
     167        drawer: $('.' + orderable_drawer.vars.classes.drawer),
     168        drawer_cart: $('.' + orderable_drawer.vars.classes.drawer_cart),
     169        drawer_html: $('.' + orderable_drawer.vars.classes.drawer_html),
     170        floating_cart_button_class: '.orderable-floating-cart__button'
     171      };
     172    },
     173    /**
     174     * Watch for trigger events.
     175     */
     176    watch() {
     177      if (typeof orderable_drawer.elements.drawer === 'undefined') {
     178        return;
     179      }
     180      $(document.body).on('orderable-drawer.open', orderable_drawer.open);
     181      $(document.body).on('orderable-drawer.close', orderable_drawer.close);
     182      $(document.body).on('click', orderable_drawer.elements.floating_cart_button_class, function () {
     183        $(document.body).trigger('orderable-drawer.open', {
     184          show_cart: true
     185        });
     186      });
     187      $(document.body).on('orderable-increase-quantity', orderable_drawer.cart.handle_quantity_change_by_button);
     188      $(document.body).on('orderable-decrease-quantity', orderable_drawer.cart.handle_quantity_change_by_button);
     189      const updateQuantityRequest = orderable_drawer.debounce(orderable_drawer.cart.click_increase_decrease_quantity);
     190      $(document.body).on('orderable-increase-quantity', updateQuantityRequest);
     191      $(document.body).on('orderable-decrease-quantity', updateQuantityRequest);
     192      const drawer = document.querySelector('body:not( .rtl ) .orderable-drawer');
     193      const drawer_rtl = document.querySelector('body.rtl .orderable-drawer');
     194      if (drawer) {
     195        drawer.addEventListener('swiped-right', function (e) {
     196          orderable_drawer.close();
     197        });
     198      }
     199      if (drawer_rtl) {
     200        drawer_rtl.addEventListener('swiped-left', function (e) {
     201          orderable_drawer.close();
     202        });
     203      }
     204    },
     205    /**
     206     * Open the drawer.
     207     * @param event
     208     * @param args
     209     */
     210    open(event, args) {
     211      args.html = args.html || false;
     212      args.show_cart = args.show_cart || false;
     213      orderable_drawer.elements.drawer_html.hide();
     214      orderable_drawer.elements.drawer_cart.hide();
     215      if (args.html) {
     216        orderable_drawer.elements.drawer_html.html(args.html);
     217        orderable_drawer.elements.drawer_html.show();
     218      }
     219      if (args.show_cart) {
     220        // Empty drawer HTML before showing cart. Prevents options
     221        // interfering with subsequent cart additions.
     222        orderable_drawer.elements.drawer_html.html('');
     223        orderable_drawer.elements.drawer_cart.show();
     224      }
     225      orderable_drawer.elements.overlay.addClass(orderable_drawer.vars.classes.overlay_open);
     226      orderable_drawer.elements.drawer.addClass(orderable_drawer.vars.classes.drawer_open);
     227      orderable_drawer.elements.body.addClass(orderable_drawer.vars.classes.drawer_open_body);
     228      $(document.body).trigger('orderable-drawer.opened', args);
     229    },
     230    /**
     231     * Close the drawer.
     232     */
     233    close() {
     234      orderable_drawer.elements.overlay.removeClass(orderable_drawer.vars.classes.overlay_open);
     235      orderable_drawer.elements.drawer.removeClass(orderable_drawer.vars.classes.drawer_open);
     236      orderable_drawer.elements.body.removeClass(orderable_drawer.vars.classes.drawer_open_body);
     237      orderable_drawer.elements.drawer_html.html('');
     238      $(document.body).trigger('orderable-drawer.closed');
     239    },
     240    /**
     241     * Mini cart related functions.
     242     */
     243    cart: {
     244      /**
     245       * When increase qty is clicked.
     246       *
     247       * @param e
     248       * @param $button
     249       */
     250      click_increase_decrease_quantity(e, $button) {
     251        const direction = $button.data('orderable-trigger');
     252        const product_id = $button.attr('data-orderable-product-id'),
     253          cart_item_key = $button.attr('data-orderable-cart-item-key'),
     254          quantity = $button.attr('data-orderable-quantity');
     255        const siblingButtonName = 'increase-quantity' === direction ? 'decrease' : 'increase';
     256        const $siblingButton = $button.siblings(`.orderable-quantity-roller__button--${siblingButtonName}`);
     257        const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
     258        const data = {
     259          action: 'orderable_cart_quantity',
     260          cart_item_key,
     261          product_id,
     262          quantity
     263        };
     264        if (this.currentRequest) {
     265          this.currentRequest.abort();
     266          this.currentRequest = undefined;
     267        }
     268        $button.addClass('orderable-button--loading');
     269        $button.attr('disabled', true);
     270        $siblingButton.attr('disabled', true);
     271        $quantityElement.attr('contenteditable', false);
     272        this.currentRequest = jQuery.post(orderable_vars.ajax_url, data, function (response) {
     273          if (!response) {
     274            return;
     275          }
     276          const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
     277          if (response && response.fragments && response.fragments['.orderable-mini-cart__notices']) {
     278            $(document.body).trigger('orderable-drawer.open', {
     279              show_cart: true
     280            });
     281          }
     282          switch (data.quantity) {
     283            case '0':
     284              $(document.body).trigger('removed_from_cart', [response.fragments, response.cart_hash, $button]);
     285              break;
     286            case $quantityElement.attr('data-orderable-updating-quantity'):
     287              $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, $button]);
     288              $(document.body).trigger('orderable-drawer.quantity-updated');
     289              break;
     290            default:
     291              break;
     292          }
     293        }.bind(this)).always(function () {
     294          this.currentRequest = undefined;
     295          $button.removeClass('orderable-button--loading');
     296          $button.attr('disabled', false);
     297          $siblingButton.attr('disabled', false);
     298          $quantityElement.attr('contenteditable', true);
     299        }.bind(this));
     300      },
     301      handle_quantity_change_by_button(e, $button) {
     302        const direction = $button.data('orderable-trigger');
     303        const quantity = parseInt($button.attr('data-orderable-quantity'));
     304        const siblingButtonName = 'increase-quantity' === direction ? 'decrease' : 'increase';
     305        const $siblingButton = $button.siblings(`.orderable-quantity-roller__button--${siblingButtonName}`);
     306        const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
     307        const newQuantity = 'increase-quantity' === direction ? quantity + 1 : Math.max(0, quantity - 1);
     308        const $parent = $button.parents('.orderable-product__actions-button');
     309        if (0 === newQuantity && $parent.length) {
     310          const $addToCartButton = $parent.find('button.orderable-button[data-orderable-trigger]');
     311          const $quantityRoller = $parent.find('.orderable-quantity-roller');
     312          if ($quantityRoller.length) {
     313            $addToCartButton.removeClass('orderable-button--product-in-the-cart');
     314            $quantityRoller.removeClass('orderable-quantity-roller--is-active');
     315          }
     316        }
     317        $button.attr('data-orderable-quantity', newQuantity);
     318        $siblingButton.attr('data-orderable-quantity', newQuantity);
     319        $quantityElement.attr('data-orderable-updating-quantity', newQuantity);
     320        $quantityElement.text(newQuantity);
     321        $quantityElement.attr('contenteditable', false);
     322      }
     323    }
     324  };
     325  $(document).ready(orderable_drawer.on_ready);
     326})(jQuery, document);
     327(function ($, document) {
     328  'use strict';
     329
     330  var orderable_products = {
     331    /**
     332     * On doc ready.
     333     */
     334    on_ready() {
     335      orderable_products.cache();
     336      orderable_products.watch();
     337    },
     338    /**
     339     * Cache.
     340     */
     341    cache() {
     342      orderable_products.vars = {
     343        classes: {
     344          clickable_product: 'orderable-product--add-to-cart ',
     345          add_to_order_button: 'orderable-product__add-to-order',
     346          product_messages: 'orderable-product__messages',
     347          product_price: 'orderable-product__actions-price',
     348          invalid_field: 'orderable-field--invalid',
     349          option_select_td: 'orderable-product__option-select',
     350          button_loading: 'orderable-button--loading',
     351          out_of_stock: 'orderable-button--out-of-stock'
     352        },
     353        parent_price: null,
     354        variable_product_types: ['variable', 'variable-subscription']
     355      };
     356      orderable_products.elements = {};
     357    },
     358    /**
     359     * Watch for trigger events.
     360     */
     361    watch() {
     362      $(document.body).on('orderable-drawer.opened', orderable_products.init_product_options);
     363      $(document.body).on('orderable-add-to-cart', orderable_products.click_add_to_order);
     364      $(document.body).on('orderable-product-options', orderable_products.click_add_to_order);
     365      $(document.body).on('orderable-view-product', orderable_products.view_product);
     366      $(document.body).on('mouseenter mouseleave', '.' + orderable_products.vars.classes.clickable_product, orderable_products.simulate_add_to_order_hover);
     367      $(document.body).on('orderable-edit-cart-item', orderable_products.edit_cart_item);
     368      $(document.body).on('orderable-update-cart-item', orderable_products.update_cart_item);
     369      $(document.body).on('orderable-show-cart', orderable_products.show_cart);
     370      $(document.body).on('orderable-add-to-cart-without-side-drawer', orderable_products.click_add_to_order);
     371      $(document.body).on('added_to_cart', orderable_products.remove_fragments);
     372      $(document.body).on('added_to_cart', orderable_products.remove_animation);
     373      $(document.body).on('added_to_cart', orderable_products.shake_floating_cart);
     374      $(document.body).on('removed_from_cart', orderable_products.hide_quantity_roller);
     375      $(document.body).on('wc_cart_button_updated', orderable_products.remove_view_cart_link);
     376    },
     377    /**
     378     * Simulate hover on add to order button.
     379     *
     380     * @param event
     381     */
     382    simulate_add_to_order_hover(event) {
     383      const $element = $(this),
     384        $button = $element.find('.' + orderable_products.vars.classes.add_to_order_button);
     385      $button.toggleClass('orderable-button--hover', 'mouseenter' === event.type);
     386    },
     387    /**
     388     * Add to order click event.
     389     *
     390     * This event accounts for button clicks or card clicks.
     391     * @param event
     392     * @param $element
     393     */
     394    click_add_to_order(event, $element) {
     395      // If undefined, it means it was triggered by a click
     396      // event and not the `orderable-add-to-cart` trigger.
     397      $element = typeof $element !== 'undefined' ? $element : $(this);
     398
     399      // The button is either the clicked element, or the
     400      // add to order button within the clicked element.
     401      const $button = $element.is('button') ? $element : $element.find('.' + orderable_products.vars.classes.add_to_order_button),
     402        action = $button.data('orderable-trigger'),
     403        product_id = $button.data('orderable-product-id'),
     404        variation_id = $button.data('orderable-variation-id'),
     405        attributes = $button.data('orderable-variation-attributes'),
     406        args = {
     407          action
     408        };
     409      if ($button.hasClass(orderable_products.vars.classes.button_loading) || $button.hasClass(orderable_products.vars.classes.out_of_stock)) {
     410        return;
     411      }
     412      $button.addClass(orderable_products.vars.classes.button_loading);
     413      switch (action) {
     414        case 'add-to-cart':
     415          orderable_products.add_to_cart({
     416            product_id,
     417            variation_id,
     418            attributes,
     419            thisbutton: $element
     420          }, function (response) {
     421            args.show_cart = true;
     422            args.response = response;
     423            $(document.body).trigger('orderable-drawer.open', args);
     424            $button.removeClass(orderable_products.vars.classes.button_loading);
     425            const $addToCartButtonOutsideDrawer = $('.orderable-product .orderable-product__actions-button button.orderable-product__add-to-order[data-orderable-product-id=' + product_id + ']');
     426            if ($addToCartButtonOutsideDrawer.siblings('.orderable-quantity-roller').length) {
     427              $addToCartButtonOutsideDrawer.addClass('orderable-button--product-in-the-cart');
     428            }
     429          });
     430          break;
     431        case 'add-to-cart-without-side-drawer':
     432          orderable_products.add_to_cart({
     433            product_id,
     434            variation_id,
     435            attributes
     436          }, function (response) {
     437            args.response = response;
     438            $button.addClass('orderable-button--product-in-the-cart');
     439            $button.removeClass(orderable_products.vars.classes.button_loading);
     440          });
     441          break;
     442        case 'product-options':
     443          orderable_products.get_product_options({
     444            product_id,
     445            focus: $button.data('orderable-focus')
     446          }, function (response) {
     447            args.html = response.html;
     448            $(document.body).trigger('orderable-drawer.open', args);
     449            $button.removeClass(orderable_products.vars.classes.button_loading);
     450          });
     451          break;
     452        default:
     453          break;
     454      }
     455    },
     456    /**
     457     * Show the cart.
     458     */
     459    show_cart() {
     460      $(document.body).trigger('orderable-drawer.open', {
     461        show_cart: true
     462      });
     463    },
     464    /**
     465     * View product.
     466     *
     467     * @param event
     468     * @param $element
     469     */
     470    view_product(event, $element) {
     471      const product_id = $element.data('orderable-product-id'),
     472        args = {
     473          action: 'product-options'
     474        };
     475      orderable_products.get_product_options({
     476        product_id,
     477        focus: $element.data('orderable-focus')
     478      }, function (response) {
     479        args.html = response.html;
     480        $(document.body).trigger('orderable-drawer.open', args);
     481      });
     482    },
     483    /**
     484     * Ajax add to cart.
     485     * @param args
     486     * @param callback
     487     */
     488    add_to_cart(args, callback) {
     489      if (typeof args.product_id === 'undefined') {
     490        return;
     491      }
     492      let data = {
     493        action: 'orderable_add_to_cart',
     494        product_id: args.product_id,
     495        variation_id: args.variation_id || false,
     496        attributes: args.attributes || false
     497      };
     498
     499      // Prepare addons data.
     500      if ($('.orderable-product-fields-group').length) {
     501        let inputs = jQuery('.orderable-product-fields-group :input').serializeArray();
     502        inputs = orderable_products.add_unchecked_checkbox_fields(inputs);
     503        const addons_data = orderable_products.convert_to_flat_object(inputs);
     504        if (!jQuery.isEmptyObject(addons_data)) {
     505          data = Object.assign(data, addons_data); // Merge objects.
     506        }
     507      }
     508      jQuery.post(orderable_vars.ajax_url, data, function (response) {
     509        if (!response) {
     510          return;
     511        }
     512
     513        // Trigger event so themes can refresh other areas.
     514        $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, args.thisbutton]);
     515        if (typeof callback === 'function') {
     516          callback(response);
     517        }
     518      });
     519    },
     520    /**
     521     * Edit cart item.
     522     *
     523     * @param event
     524     * @param $element
     525     */
     526    edit_cart_item(event, $element) {
     527      const cart_item_key = $element.data('orderable-cart-item-key');
     528      $element.addClass(orderable_products.vars.classes.button_loading);
     529      orderable_products.get_cart_item_options({
     530        cart_item_key
     531      }, function (response) {
     532        const args = {
     533          html: response.html,
     534          action: 'update-cart-item'
     535        };
     536        $(document.body).trigger('orderable-drawer.open', args);
     537        $element.removeClass(orderable_products.vars.classes.button_loading);
     538      });
     539    },
     540    /**
     541     * Update cart item.
     542     *
     543     * @param event
     544     * @param $element
     545     */
     546    update_cart_item(event, $element) {
     547      const cart_item_key = $element.data('orderable-cart-item-key');
     548      const product_id = $element.data('orderable-product-id');
     549      const variation_id = $element.data('orderable-variation-id');
     550      const attributes = $element.data('orderable-variation-attributes');
     551      $element.addClass(orderable_products.vars.classes.button_loading);
     552      orderable_products.update_cart_item_options({
     553        cart_item_key,
     554        product_id,
     555        variation_id,
     556        attributes
     557      }, function (response) {
     558        const args = {
     559          show_cart: true,
     560          response
     561        };
     562        $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, $element]);
     563        $(document.body).trigger('orderable-drawer.open', args);
     564        $element.removeClass(orderable_products.vars.classes.button_loading);
     565      });
     566    },
     567    /**
     568     * Convert [{name:x, value:y }] to {x:y} format.
     569     * @param inputs
     570     */
     571    convert_to_flat_object(inputs) {
     572      const data = {};
     573      inputs.forEach(function (input) {
     574        const is_array = '[]' === input.name.substr(-2) || Array.isArray(input.name);
     575        // If last 2 chars are '[]', remove them.
     576        const key = is_array ? input.name.substr(0, input.name.length - 2) : input.name;
     577        if (is_array) {
     578          data[key] = typeof data[key] === 'undefined' ? [] : data[key];
     579          data[key].push(input.value);
     580        } else {
     581          data[key] = input.value;
     582        }
     583      });
     584      return data;
     585    },
     586    /**
     587     * Get variable product options.
     588     *
     589     * @param args
     590     * @param callback
     591     */
     592    get_product_options(args, callback) {
     593      if (typeof args.product_id === 'undefined') {
     594        return;
     595      }
     596      args.action = 'orderable_get_product_options';
     597      jQuery.post(orderable_vars.ajax_url, args, function (response) {
     598        if (!response.success) {
     599          return;
     600        }
     601        if (typeof callback === 'function') {
     602          callback(response.data);
     603        }
     604      });
     605    },
     606    /**
     607     * Get variable product options.
     608     *
     609     * @param args
     610     * @param callback
     611     */
     612    get_cart_item_options(args, callback) {
     613      if (typeof args.cart_item_key === 'undefined') {
     614        return;
     615      }
     616      args.action = 'orderable_get_cart_item_options';
     617      jQuery.post(orderable_vars.ajax_url, args, function (response) {
     618        if (!response.success) {
     619          return;
     620        }
     621        if (typeof callback === 'function') {
     622          callback(response.data);
     623        }
     624      });
     625    },
     626    /**
     627     * Update variable product options.
     628     *
     629     * @param args
     630     * @param callback
     631     */
     632    update_cart_item_options(args, callback) {
     633      if (typeof args.cart_item_key === 'undefined') {
     634        return;
     635      }
     636      args.action = 'orderable_update_cart_item_options';
     637
     638      // Prepare addons data.
     639      if ($('.orderable-product-fields-group').length) {
     640        let inputs = jQuery('.orderable-product-fields-group :input').serializeArray();
     641        inputs = orderable_products.add_unchecked_checkbox_fields(inputs);
     642        const addons_data = orderable_products.convert_to_flat_object(inputs);
     643        if (!jQuery.isEmptyObject(addons_data)) {
     644          args = Object.assign(args, addons_data); // Merge objects.
     645        }
     646      }
     647      jQuery.post(orderable_vars.ajax_url, args, function (response) {
     648        if (!response) {
     649          return;
     650        }
     651        if (typeof callback === 'function') {
     652          callback(response);
     653        }
     654      });
     655    },
     656    /**
     657     * Init drawer product options.
     658     *
     659     * @param event
     660     * @param args
     661     */
     662    init_product_options(event, args) {
     663      if (typeof args.action === 'undefined' || 'product-options' !== args.action && 'update-cart-item' !== args.action) {
     664        return;
     665      }
     666      const selectors = '.orderable-drawer .orderable-product__options input, .orderable-drawer .orderable-product__options select, .orderable-product__options textarea';
     667      const $options = $(selectors);
     668      orderable_products.vars.parent_price = $('.orderable-drawer .orderable-product__actions-price').html();
     669      orderable_products.product_options_change($options);
     670      orderable_products.update_button_state();
     671      const debounced_update_button_state = orderable_products.debounce(orderable_products.update_button_state, 500);
     672      const debounced_product_options_change = orderable_products.debounce(orderable_products.product_options_change, 500);
     673      $(document).on('change keyup', selectors, function () {
     674        debounced_product_options_change($options);
     675        debounced_update_button_state();
     676      });
     677    },
     678    /**
     679     * On product options change.
     680     *
     681     * @param $options
     682     */
     683    product_options_change($options) {
     684      const $add_to_order_button = $('.orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item'),
     685        options_set = orderable_products.check_options($options),
     686        product_type = $add_to_order_button.data('orderable-product-type');
     687      if ('product-options' === $add_to_order_button.attr('data-orderable-trigger')) {
     688        $add_to_order_button.attr('data-orderable-trigger', 'add-to-cart');
     689      }
     690      $('.' + orderable_products.vars.classes.product_messages).html('');
     691      if (!orderable_products.vars.variable_product_types.includes(product_type)) {
     692        return;
     693      }
     694      if (!options_set) {
     695        orderable_products.clear_variation($add_to_order_button);
     696        return;
     697      }
     698      const variation = orderable_products.check_variation($options);
     699      orderable_products.set_variation($add_to_order_button, variation);
     700    },
     701    /**
     702     * Check if all product options are set.
     703     *
     704     * @param  $options
     705     * @return {boolean}
     706     */
     707    check_options($options) {
     708      if ($options.length <= 0) {
     709        return false;
     710      }
     711      let all_set = true;
     712      $options.each(function (index, option) {
     713        // Only check attribute fields.
     714        if (!$(option).hasClass('orderable-input--validate')) {
     715          return;
     716        }
     717        if ('' === $(option).val()) {
     718          $(option).addClass(orderable_products.vars.classes.invalid_field);
     719          all_set = false;
     720        } else {
     721          $(option).removeClass(orderable_products.vars.classes.invalid_field);
     722        }
     723      });
     724      return all_set;
     725    },
     726    /**
     727     * Check if variation has been selected.
     728     * @param $options
     729     */
     730    check_variation($options) {
     731      const $product = $options.closest('.orderable-drawer');
     732      let variations = $product.find('.orderable-product__variations').text();
     733      variations = variations ? JSON.parse(variations) : '';
     734      const selected_options = orderable_products.serialize_object($options),
     735        matching_variations = orderable_products.find_matching_variations(variations, selected_options);
     736      if (orderable_products.is_empty(matching_variations)) {
     737        return false;
     738      }
     739      const variation = matching_variations.shift();
     740      variation.attributes = selected_options;
     741      variation.attributes_json = JSON.stringify(selected_options);
     742      return typeof variation !== 'undefined' ? variation : false;
     743    },
     744    /**
     745     * Set variation for add to cart button.
     746     * @param $button
     747     * @param variation
     748     */
     749    set_variation($button, variation) {
     750      let variation_id = variation.variation_id || '',
     751        attributes = variation.attributes_json || '',
     752        price = variation.price_html || orderable_products.vars.parent_price,
     753        message = '';
     754      if (variation && '' !== variation.availability_html) {
     755        message = variation.availability_html;
     756      }
     757      if (variation && !variation.is_in_stock) {
     758        message = '<p>' + orderable_vars.i18n.out_of_stock + '</p>';
     759      }
     760      if (variation && !variation.is_purchasable) {
     761        message = '<p>' + orderable_vars.i18n.unavailable + '</p>';
     762      }
     763      if (false === variation) {
     764        message = '<p>' + orderable_vars.i18n.no_exist + '</p>';
     765      }
     766      if (variation && (!variation.is_purchasable || !variation.is_in_stock)) {
     767        variation_id = '';
     768        attributes = '';
     769      }
     770      if ('' !== message) {
     771        $('.' + orderable_products.vars.classes.product_messages).html(message);
     772      }
     773      $button.data('orderable-variation-id', variation_id);
     774      $button.data('orderable-variation-attributes', attributes);
     775      $('.orderable-drawer .orderable-product__actions-price').html(price);
     776      $button.trigger('orderable_variation_set', {
     777        variation,
     778        variation_id,
     779        attributes,
     780        price
     781      });
     782    },
     783    /**
     784     * Clear variation and disable add to order.
     785     *
     786     * @param $button
     787     */
     788    clear_variation($button) {
     789      orderable_products.set_variation($button, '');
     790      if (orderable_products.vars.parent_price) {
     791        $('.orderable-drawer .orderable-product__actions-price').html(orderable_products.vars.parent_price);
     792      }
     793    },
     794    /**
     795     * Find matching variations for attributes.
     796     * @param variations
     797     * @param attributes
     798     */
     799    find_matching_variations(variations, attributes) {
     800      const matching = [];
     801      for (let i = 0; i < variations.length; i++) {
     802        const variation = variations[i];
     803        if (orderable_products.is_matching_variation(variation.attributes, attributes)) {
     804          matching.push(variation);
     805        }
     806      }
     807      return matching;
     808    },
     809    /**
     810     * See if attributes match.
     811     * @param  variation_attributes
     812     * @param  attributes
     813     * @return {boolean}
     814     */
     815    is_matching_variation(variation_attributes, attributes) {
     816      let match = true;
     817      for (const attr_name in variation_attributes) {
     818        if (variation_attributes.hasOwnProperty(attr_name)) {
     819          const val1 = variation_attributes[attr_name];
     820          const val2 = attributes[attr_name];
     821          if (val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2) {
     822            match = false;
     823          }
     824        }
     825      }
     826      return match;
     827    },
     828    /**
     829     * Is value empty?
     830     *
     831     * @param  value
     832     * @return {boolean}
     833     */
     834    is_empty(value) {
     835      return typeof value === 'undefined' || false === value || value.length <= 0 || !value;
     836    },
     837    /**
     838     * Serialize into a key/value object.
     839     *
     840     * @param  $elements
     841     * @return {{}}
     842     */
     843    serialize_object: function objectifyForm($elements) {
     844      const serialized = $elements.serializeArray(),
     845        return_object = {};
     846      for (let i = 0; i < serialized.length; i++) {
     847        return_object[serialized[i].name] = serialized[i].value;
     848      }
     849      return return_object;
     850    },
     851    /**
     852     * Disable/Enable the 'Add to cart' button based on the presence of orderable-field--invalid class.
     853     */
     854    update_button_state() {
     855      // Add delay to ensure invalid class has been assigned to inputs.
     856      setTimeout(function () {
     857        let $button = $('.orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item'),
     858          invalid_fields_count = $('.orderable-drawer__html .' + orderable_products.vars.classes.invalid_field).length,
     859          product_type = $button.data('orderable-product-type'),
     860          has_variation_id = true;
     861        if ('variable' === product_type) {
     862          has_variation_id = '' !== $button.data('orderable-variation-id');
     863        }
     864        $button.prop('disabled', invalid_fields_count || !has_variation_id);
     865      }, 50);
     866    },
     867    /**
     868     * Debounce function.
     869     *
     870     * @param func      Function to debounce.
     871     * @param wait      Time to wait in milliseconds.
     872     * @param immediate Trigger the function on the leading edge, instead of the trailing.
     873     *
     874     * @return
     875     */
     876    debounce(func, wait, immediate) {
     877      let timeout;
     878      return function () {
     879        const context = this,
     880          args = arguments;
     881        const later = function () {
     882          timeout = null;
     883          if (!immediate) {
     884            func.apply(context, args);
     885          }
     886        };
     887        const callNow = immediate && !timeout;
     888        clearTimeout(timeout);
     889        timeout = setTimeout(later, wait);
     890        if (callNow) {
     891          func.apply(context, args);
     892        }
     893      };
     894    },
     895    /**
     896     * Remove the quantity roller fragments
     897     *
     898     * @param {Event}  e
     899     * @param {Object} fragments
     900     * @return void
     901     */
     902    remove_fragments(e, fragments) {
     903      if (!fragments || 'undefined' === typeof wc_cart_fragments_params || !wc_cart_fragments_params.fragment_name) {
     904        return;
     905      }
     906      const regex_quantity_roller = /\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-quantity-roller/;
     907      const regex_product_in_the_cart_counter = /\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-product__actions-counter/;
     908      for (const key in fragments) {
     909        if (!regex_quantity_roller.test(key) && !regex_product_in_the_cart_counter.test(key)) {
     910          continue;
     911        }
     912        fragments[key] = undefined;
     913      }
     914      sessionStorage.setItem(wc_cart_fragments_params.fragment_name, JSON.stringify(fragments));
     915    },
     916    /**
     917     * Remove animation.
     918     */
     919    remove_animation() {
     920      setTimeout(function () {
     921        $('.orderable-product__actions-counter').css('animation', '');
     922      }, 1000);
     923    },
     924    /**
     925     * Hide quantity roller element and show the Add to Cart button.
     926     *
     927     * @param {Event}   e
     928     * @param {Object}  fragments
     929     * @param {string}  cart_hash
     930     * @param {Element} $button
     931     * @return
     932     */
     933    hide_quantity_roller(e, fragments, cart_hash, $button) {
     934      const product_id = $button.attr('data-product_id') || $button.attr('data-orderable-product-id');
     935      if (!product_id) {
     936        return;
     937      }
     938      const $actions_button = $('.orderable-product[data-orderable-product-id=' + product_id + '] .orderable-product__actions-button');
     939      if (!$actions_button.length) {
     940        return;
     941      }
     942      const $quantity_roller = $actions_button.find('.orderable-quantity-roller');
     943      if ($quantity_roller.length) {
     944        $actions_button.find('button.orderable-product__add-to-order[data-orderable-trigger]').removeClass('orderable-button--product-in-the-cart');
     945        $quantity_roller.addClass('orderable-button--hide');
     946      }
     947    },
     948    /**
     949     * Add unchecked checkboxs to the list of inputs
     950     * sent to the request to add/update an item
     951     *
     952     * @param {Object} inputs
     953     * @return {Object}
     954     */
     955    add_unchecked_checkbox_fields(inputs) {
     956      jQuery('.orderable-product-fields-group :input[type="checkbox"]:not(:checked)').each(function (index, element) {
     957        inputs.push({
     958          name: element.getAttribute('name'),
     959          value: ''
     960        });
     961      });
     962      return inputs;
     963    },
     964    /**
     965     * Shake the floating cart button.
     966     *
     967     * @return void
     968     */
     969    shake_floating_cart() {
     970      $('.orderable-floating-cart__button').css('animation', 'wobble-hor-bottom .8s both');
     971    },
     972    /**
     973     * Remove the view cart link.
     974     *
     975     * @param event
     976     * @param $button
     977     */
     978    remove_view_cart_link(event, $button) {
     979      if (!$button?.hasClass('orderable-product__add-to-order')) {
     980        return;
     981      }
     982      $button?.siblings('.added_to_cart.wc-forward').remove();
     983    }
     984  };
     985  $(document).ready(orderable_products.on_ready);
     986})(jQuery, document);
     987(function ($, document) {
     988  'use strict';
     989
     990  var orderable_scrollbar = {
     991    /**
     992     * On doc ready.
     993     */
     994    on_ready() {
     995      orderable_scrollbar.cache();
     996      orderable_scrollbar.watch();
     997    },
     998    /**
     999     * Cache.
     1000     */
     1001    cache() {
     1002      orderable_scrollbar.vars = {
     1003        top: {}
     1004      };
     1005      orderable_scrollbar.elements = {};
     1006    },
     1007    /**
     1008     * Watch.
     1009     */
     1010    watch() {
     1011      $(document.body).on('orderable-drawer.opened', orderable_scrollbar.trigger);
     1012      $(document.body).on('orderable-tabs.changed', orderable_scrollbar.trigger);
     1013      $(document.body).on('orderable-accordion.toggled', orderable_scrollbar.trigger);
     1014      $(document.body).on('wc_fragments_loaded', orderable_scrollbar.trigger);
     1015    },
     1016    /**
     1017     * Init or retrigger scrollbars.
     1018     */
     1019    trigger() {
     1020      $('.orderable-sb-container').each(function (index, element) {
     1021        const $element = $(element),
     1022          scroll_id = $element.data('orderable-scroll-id');
     1023        if (!orderable_scrollbar.has_scrollbar($element)) {
     1024          $element.scrollBox({
     1025            containerClass: 'orderable-sb-container',
     1026            containerNoScrollClass: 'orderable-sb-container-noscroll',
     1027            contentClass: 'orderable-sb-content',
     1028            scrollbarContainerClass: 'orderable-sb-scrollbar-container',
     1029            scrollBarClass: 'orderable-sb-scrollbar'
     1030          });
     1031          const $content = $element.find('.orderable-sb-content');
     1032          if ($content.length > 0) {
     1033            $content.on('scroll.scrollBox', orderable_scrollbar.log_top_position);
     1034
     1035            // Set scroll position.
     1036            if (typeof orderable_scrollbar.vars.top[scroll_id] !== 'undefined') {
     1037              $content.scrollTop(orderable_scrollbar.vars.top[scroll_id]);
     1038            }
     1039          }
     1040          $(document.body).trigger('orderable-scrollbar.created', {
     1041            element: $element,
     1042            content: $content
     1043          });
     1044        }
     1045      });
     1046      $(window).trigger('resize.scrollBox');
     1047    },
     1048    /**
     1049     * Has scrollbar already?
     1050     *
     1051     * @param  $element
     1052     * @return {boolean}
     1053     */
     1054    has_scrollbar($element) {
     1055      return $element.find('.orderable-sb-content').length > 0;
     1056    },
     1057    /**
     1058     * Set scrolltop position.
     1059     *
     1060     * @param e
     1061     */
     1062    log_top_position(e) {
     1063      const $element = $(e.currentTarget),
     1064        $container = $element.closest('.orderable-sb-container'),
     1065        scroll_id = $container.data('orderable-scroll-id');
     1066      orderable_scrollbar.vars.top[scroll_id] = $(e.currentTarget).scrollTop();
     1067    }
     1068  };
     1069  $(document).ready(orderable_scrollbar.on_ready);
     1070})(jQuery, document);
     1071(function ($, document) {
     1072  'use strict';
     1073
     1074  var orderable_tabs = {
     1075    /**
     1076     * On doc ready.
     1077     */
     1078    on_ready() {
     1079      orderable_tabs.cache();
     1080      orderable_tabs.watch();
     1081      orderable_tabs.toggle_scroll();
     1082    },
     1083    /**
     1084     * On resize.
     1085     */
     1086    on_resize() {
     1087      if (typeof orderable_tabs.vars === 'undefined') {
     1088        orderable_tabs.cache();
     1089      }
     1090      orderable_tabs.toggle_scroll();
     1091    },
     1092    /**
     1093     * Cache.
     1094     */
     1095    cache() {
     1096      orderable_tabs.vars = {
     1097        classes: {
     1098          tabs: 'orderable-tabs',
     1099          tabs_list: 'orderable-tabs__list',
     1100          tab_items: 'orderable-tabs__item',
     1101          tab_item_active: 'orderable-tabs__item--active',
     1102          tab_links: 'orderable-tabs__link',
     1103          tab_arrow_right: 'orderable-tabs__arrow-right',
     1104          tab_arrow_left: 'orderable-tabs__arrow-left'
     1105        },
     1106        dragging: false
     1107      };
     1108      orderable_tabs.elements = {};
     1109    },
     1110    /**
     1111     * Watch.
     1112     */
     1113    watch() {
     1114      $('body').on('touchstart', function () {
     1115        orderable_tabs.vars.dragging = false;
     1116      }).on('touchmove', function () {
     1117        orderable_tabs.vars.dragging = true;
     1118      });
     1119      $(document.body).on('click mouseup touchend', '.' + orderable_tabs.vars.classes.tab_links, function (e) {
     1120        if (orderable_tabs.vars.dragging) {
     1121          return;
     1122        }
     1123        e.preventDefault();
     1124        const $link = $(this),
     1125          section_id = $link.attr('href'),
     1126          $tab = $link.closest('.' + orderable_tabs.vars.classes.tab_items),
     1127          $tabs = $link.closest('.' + orderable_tabs.vars.classes.tabs),
     1128          $tabs_list = $tabs.find('.' + orderable_tabs.vars.classes.tabs_list),
     1129          $tab_items = $tabs.find('.' + orderable_tabs.vars.classes.tab_items),
     1130          tabs_args = $tabs.data('orderable-tabs'),
     1131          $wrapper = $link.closest(tabs_args.wrapper),
     1132          $sections = $wrapper.find(tabs_args.sections),
     1133          $section = $wrapper.find(section_id);
     1134        $sections.hide();
     1135        $section.show();
     1136        $tab_items.removeClass(orderable_tabs.vars.classes.tab_item_active);
     1137        $tab.addClass(orderable_tabs.vars.classes.tab_item_active);
     1138        $tabs_list.animate({
     1139          scrollLeft: $tabs_list.scrollLeft() + $tab.position().left
     1140        });
     1141        $(document.body).trigger('orderable-tabs.changed', {
     1142          tab: $tab
     1143        });
     1144      });
     1145
     1146      /**
     1147       * Watch scroll position of tabs.
     1148       */
     1149      $('.' + orderable_tabs.vars.classes.tabs_list).on('scroll', function (e) {
     1150        const $list = $(this),
     1151          $wrapper = $list.parent('.' + orderable_tabs.vars.classes.tabs),
     1152          $arrow_right = $list.siblings('.' + orderable_tabs.vars.classes.tab_arrow_right),
     1153          $arrow_left = $list.siblings('.' + orderable_tabs.vars.classes.tab_arrow_left);
     1154        if ($list[0].scrollWidth <= $wrapper.width() + $list.scrollLeft()) {
     1155          $arrow_right.fadeOut();
     1156        } else {
     1157          $arrow_right.fadeIn();
     1158        }
     1159        if (0 >= $list.scrollLeft() - $arrow_left.width()) {
     1160          $arrow_left.fadeOut();
     1161        } else {
     1162          $arrow_left.fadeIn();
     1163        }
     1164      });
     1165
     1166      /**
     1167       * Stop animated scroll if user manually scrolls.
     1168       */
     1169      $('.' + orderable_tabs.vars.classes.tabs_list).on('wheel DOMMouseScroll mousewheel touchmove', function () {
     1170        $(this).stop();
     1171      });
     1172
     1173      /**
     1174       * Click tab arrow right.
     1175       */
     1176      $(document).on('click', '.' + orderable_tabs.vars.classes.tab_arrow_right, function (e) {
     1177        e.preventDefault();
     1178        const $arrow = $(this),
     1179          $wrapper = $arrow.parent(),
     1180          $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list);
     1181        $list.animate({
     1182          scrollLeft: $list.scrollLeft() + $wrapper.width() * 0.5
     1183        });
     1184      });
     1185
     1186      /**
     1187       * Click tab arrow left.
     1188       */
     1189      $(document).on('click', '.' + orderable_tabs.vars.classes.tab_arrow_left, function (e) {
     1190        e.preventDefault();
     1191        const $arrow = $(this),
     1192          $wrapper = $arrow.parent(),
     1193          $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list);
     1194        $list.animate({
     1195          scrollLeft: $list.scrollLeft() - $wrapper.width() * 0.5
     1196        });
     1197      });
     1198    },
     1199    /**
     1200     * Toggle scroll arrow.
     1201     */
     1202    toggle_scroll() {
     1203      $('.' + orderable_tabs.vars.classes.tabs).each(function (index, wrapper) {
     1204        const $tabs = $(this),
     1205          tabs_args = $tabs.data('orderable-tabs'),
     1206          $wrapper = $tabs.closest(tabs_args.wrapper),
     1207          $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list),
     1208          $arrow_right = $wrapper.find('.' + orderable_tabs.vars.classes.tab_arrow_right),
     1209          wrapper_width = $wrapper.outerWidth(),
     1210          list_width = $list[0].scrollWidth;
     1211        if (list_width > wrapper_width) {
     1212          $arrow_right.show();
     1213        } else {
     1214          $arrow_right.hide();
     1215        }
     1216      });
     1217    }
     1218  };
     1219  $(document).ready(orderable_tabs.on_ready);
     1220  $(window).on('resize', orderable_tabs.on_resize);
     1221})(jQuery, document);
     1222let orderable_timings = {}; // Make this global so pro modules can access it.
     1223
     1224(function ($, document) {
     1225  'use strict';
     1226
     1227  orderable_timings = {
     1228    /**
     1229     * On doc ready.
     1230     */
     1231    on_ready() {
     1232      orderable_timings.watch();
     1233    },
     1234    /**
     1235     * Restore current timings.
     1236     */
     1237    restore() {
     1238      const timings = orderable_timings.get_timings();
     1239      if (!timings || !timings.date) {
     1240        return;
     1241      }
     1242      const dateSelect = $('.orderable-order-timings__date');
     1243      if (dateSelect.find('option[value="' + timings.date + '"]').length > 0) {
     1244        dateSelect.val(timings.date);
     1245        dateSelect.change();
     1246      }
     1247      if (!timings.time) {
     1248        return;
     1249      }
     1250      const timeSelect = $('.orderable-order-timings__time');
     1251      if (timeSelect.find('option[value="' + timings.time + '"]').length > 0) {
     1252        timeSelect.val(timings.time);
     1253        timeSelect.change();
     1254      }
     1255    },
     1256    /**
     1257     * Watch for trigger events.
     1258     */
     1259    watch() {
     1260      $(document.body).on('wc_fragments_refreshed', function () {
     1261        orderable_timings.restore();
     1262      });
     1263      $(document.body).on('updated_checkout', function () {
     1264        orderable_timings.restore();
     1265      });
     1266      $(document.body).on('change', '.orderable-order-timings__date', function (event) {
     1267        const $date_field = $(this),
     1268          $selected = $date_field.find('option:selected'),
     1269          slots = $selected.data('orderable-slots'),
     1270          $time_field_wrap = $('.orderable-order-timings--time'),
     1271          $time_field = $('.orderable-order-timings__time'),
     1272          $first_option = $time_field.find('option').first(),
     1273          $asap_option = $time_field.find('option[value="asap"]').first();
     1274        const timings = orderable_timings.get_timings();
     1275        timings.date = $('.orderable-order-timings__date').val();
     1276        window.localStorage.setItem('orderable_timings', JSON.stringify(timings));
     1277        $time_field.html($first_option);
     1278        if ($asap_option) {
     1279          $time_field.append($asap_option);
     1280        }
     1281        if (!slots) {
     1282          $time_field.prop('disabled', true);
     1283          $time_field_wrap.hide();
     1284          return;
     1285        }
     1286        if ('all-day' === slots[0].value) {
     1287          $time_field_wrap.hide();
     1288          $time_field.prop('disabled', true);
     1289        } else {
     1290          $time_field.prop('disabled', false);
     1291          $time_field_wrap.show();
     1292          $.each(slots, function (index, slot) {
     1293            $time_field.append($('<option />').attr('value', slot.value).attr('data-orderable-time-slot-id', slot?.setting_row?.time_slot_id).text(slot.formatted));
     1294          });
     1295        }
     1296      });
     1297      $(document.body).on('change', '.orderable-order-timings__time', function (event) {
     1298        const timings = orderable_timings.get_timings();
     1299        timings.time = $('.orderable-order-timings__time').val();
     1300        window.localStorage.setItem('orderable_timings', JSON.stringify(timings));
     1301        $(this).siblings('input[name="orderable_order_time_slot_id"]').val($(this).find(':selected').attr('data-orderable-time-slot-id'));
     1302      });
     1303    },
     1304    get_timings() {
     1305      return JSON.parse(window.localStorage.getItem('orderable_timings')) || {};
     1306    }
     1307  };
     1308  $(document).ready(orderable_timings.on_ready);
     1309})(jQuery, document);
     1310(function ($, document) {
     1311  'use strict';
     1312
     1313  var orderable_triggers = {
     1314    /**
     1315     * On doc ready.
     1316     */
     1317    on_ready() {
     1318      orderable_triggers.watch();
     1319    },
     1320    /**
     1321     * Watch for trigger events.
     1322     */
     1323    watch() {
     1324      if ('undefined' !== typeof window.orderable_triggers_admin) {
     1325        return;
     1326      }
     1327      $(document.body).on('click', '[data-orderable-trigger]', orderable_triggers.trigger);
     1328    },
     1329    /**
     1330     * Fire trigger.
     1331     * @param e
     1332     */
     1333    trigger(e) {
     1334      // Prevent even bubbling up.
     1335      e.stopImmediatePropagation();
     1336      const $trigger_element = $(this),
     1337        trigger = $trigger_element.data('orderable-trigger');
     1338      if ($trigger_element.is('button') || $trigger_element.is('a')) {
     1339        e.preventDefault();
     1340      }
     1341      $(document.body).trigger('orderable-' + trigger, [$trigger_element]);
     1342    }
     1343  };
     1344  $(document).ready(orderable_triggers.on_ready);
     1345})(jQuery, document);
    21346/**
    31347 * jQiery scrollBar Plugin
     
    1771521  }
    1781522}(window, document);
    179 (function ($, document) {
    180   'use strict';
    181 
    182   var orderable_accordion = {
    183     /**
    184      * On doc ready.
    185      */
    186     on_ready() {
    187       orderable_accordion.cache();
    188       orderable_accordion.watch();
    189     },
    190     /**
    191      * Cache.
    192      */
    193     cache() {
    194       orderable_accordion.vars = {
    195         classes: {
    196           parent: 'orderable-accordion',
    197           link: 'orderable-accordion__item-link',
    198           content: 'orderable-accordion__item-content',
    199           link_active: 'orderable-accordion__item-link--active',
    200           content_active: 'orderable-accordion__item-content--active'
    201         }
    202       };
    203     },
    204     /**
    205      * Watch.
    206      */
    207     watch() {
    208       /**
    209        * When click accordion link.
    210        */
    211       $(document.body).on('click', '.' + orderable_accordion.vars.classes.link, function (e) {
    212         e.preventDefault();
    213         const $link = $(this),
    214           $parent = $link.closest('.' + orderable_accordion.vars.classes.parent),
    215           content_id = $link.attr('href'),
    216           $content = $(content_id),
    217           is_active = $link.hasClass(orderable_accordion.vars.classes.link_active);
    218         $parent.find('.' + orderable_accordion.vars.classes.link).removeClass(orderable_accordion.vars.classes.link_active);
    219         $parent.find('.' + orderable_accordion.vars.classes.content).removeClass(orderable_accordion.vars.classes.content_active);
    220         if (!is_active) {
    221           $link.addClass(orderable_accordion.vars.classes.link_active);
    222           $content.addClass(orderable_accordion.vars.classes.content_active);
    223         }
    224         $(document.body).trigger('orderable-accordion.toggled', {
    225           link: $link,
    226           content: $content
    227         });
    228       });
    229 
    230       /**
    231        * When drawer is opened.
    232        */
    233       $(document.body).on('orderable-scrollbar.created', function (e, args) {
    234         const $active_accordion = $('.orderable-drawer .' + orderable_accordion.vars.classes.link_active);
    235         if ($active_accordion.length <= 0) {
    236           return;
    237         }
    238         const $scroll_content = args.content,
    239           scroll_position = $scroll_content.scrollTop() - $scroll_content.offset().top + $active_accordion.offset().top;
    240         $scroll_content.scrollTop(scroll_position);
    241       });
    242     }
    243   };
    244   $(document).ready(orderable_accordion.on_ready);
    245 })(jQuery, document);
    246 (function ($, document) {
    247   'use strict';
    248 
    249   var orderable_drawer = {
    250     /**
    251      * Delays invoking function
    252      *
    253      * @param {Function} func    The function to debounce.
    254      * @param {number}   timeout The number of milliseconds to delay.
    255      * @return {Function} Returns the new debounced function.
    256      */
    257     debounce(func, timeout = 700) {
    258       let timer;
    259       return (...args) => {
    260         clearTimeout(timer);
    261         timer = setTimeout(() => {
    262           func.apply(this, args);
    263         }, timeout);
    264       };
    265     },
    266     /**
    267      * Allow only number for events like keypress
    268      *
    269      * @param {Event} event
    270      */
    271     allow_only_numbers(event) {
    272       const value = String.fromCharCode(event.which);
    273       if (!/^\d+$/.test(value)) {
    274         event.preventDefault();
    275       }
    276     },
    277     /**
    278      * Send a request to change the quantity.
    279      *
    280      * @param {Event} event
    281      */
    282     on_change_quantity(event) {
    283       const quantityElement = $(event.currentTarget);
    284       const product_id = quantityElement.data('orderable-product-id');
    285       const cart_item_key = quantityElement.data('orderable-cart-item-key');
    286       const quantity = parseInt(quantityElement.text());
    287       const data = {
    288         action: 'orderable_cart_quantity',
    289         cart_item_key,
    290         product_id,
    291         quantity
    292       };
    293       jQuery.post(orderable_vars.ajax_url, data, function (response) {
    294         if (!response) {
    295           return;
    296         }
    297         $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, quantityElement]);
    298         $(document.body).trigger('orderable-drawer.quantity-updated');
    299       });
    300     },
    301     /**
    302      * On doc ready.
    303      */
    304     on_ready() {
    305       orderable_drawer.cache();
    306       orderable_drawer.watch();
    307 
    308       /**
    309        * Handle manually changing the quantity of a product.
    310        */
    311       $(document.body).on('keypress', '.orderable-quantity-roller__quantity', orderable_drawer.allow_only_numbers);
    312       $('.orderable-drawer__cart, .orderable-product--add-to-cart, .orderable-products-list').on('input', '.orderable-quantity-roller__quantity', orderable_drawer.debounce(orderable_drawer.on_change_quantity));
    313       $(document.body).on('click', '.orderable-quantity-roller__quantity', function (event) {
    314         event.stopPropagation();
    315       });
    316 
    317       /**
    318        * We turn off the click event for .add_to_cart_button elements
    319        * to keep the AJAX behaviour only on Mini cart when the option
    320        * "Enable AJAX add to cart buttons on archives" is disabled.
    321        */
    322       if (orderable_vars && !orderable_vars.woocommerce_enable_ajax_add_to_cart) {
    323         $(document.body).off('click', '.add_to_cart_button');
    324       }
    325     },
    326     /**
    327      * Cache.
    328      */
    329     cache() {
    330       orderable_drawer.vars = {
    331         classes: {
    332           overlay: 'orderable-drawer-overlay',
    333           drawer: 'orderable-drawer',
    334           drawer_cart: 'orderable-drawer__cart',
    335           drawer_html: 'orderable-drawer__html',
    336           overlay_open: 'orderable-drawer-overlay--open',
    337           drawer_open: 'orderable-drawer--open',
    338           drawer_open_body: 'orderable-drawer-open'
    339         }
    340       };
    341       orderable_drawer.elements = {
    342         body: $('body'),
    343         overlay: $('.' + orderable_drawer.vars.classes.overlay),
    344         drawer: $('.' + orderable_drawer.vars.classes.drawer),
    345         drawer_cart: $('.' + orderable_drawer.vars.classes.drawer_cart),
    346         drawer_html: $('.' + orderable_drawer.vars.classes.drawer_html),
    347         floating_cart_button_class: '.orderable-floating-cart__button'
    348       };
    349     },
    350     /**
    351      * Watch for trigger events.
    352      */
    353     watch() {
    354       if (typeof orderable_drawer.elements.drawer === 'undefined') {
    355         return;
    356       }
    357       $(document.body).on('orderable-drawer.open', orderable_drawer.open);
    358       $(document.body).on('orderable-drawer.close', orderable_drawer.close);
    359       $(document.body).on('click', orderable_drawer.elements.floating_cart_button_class, function () {
    360         $(document.body).trigger('orderable-drawer.open', {
    361           show_cart: true
    362         });
    363       });
    364       $(document.body).on('orderable-increase-quantity', orderable_drawer.cart.handle_quantity_change_by_button);
    365       $(document.body).on('orderable-decrease-quantity', orderable_drawer.cart.handle_quantity_change_by_button);
    366       const updateQuantityRequest = orderable_drawer.debounce(orderable_drawer.cart.click_increase_decrease_quantity);
    367       $(document.body).on('orderable-increase-quantity', updateQuantityRequest);
    368       $(document.body).on('orderable-decrease-quantity', updateQuantityRequest);
    369       const drawer = document.querySelector('body:not( .rtl ) .orderable-drawer');
    370       const drawer_rtl = document.querySelector('body.rtl .orderable-drawer');
    371       if (drawer) {
    372         drawer.addEventListener('swiped-right', function (e) {
    373           orderable_drawer.close();
    374         });
    375       }
    376       if (drawer_rtl) {
    377         drawer_rtl.addEventListener('swiped-left', function (e) {
    378           orderable_drawer.close();
    379         });
    380       }
    381     },
    382     /**
    383      * Open the drawer.
    384      * @param event
    385      * @param args
    386      */
    387     open(event, args) {
    388       args.html = args.html || false;
    389       args.show_cart = args.show_cart || false;
    390       orderable_drawer.elements.drawer_html.hide();
    391       orderable_drawer.elements.drawer_cart.hide();
    392       if (args.html) {
    393         orderable_drawer.elements.drawer_html.html(args.html);
    394         orderable_drawer.elements.drawer_html.show();
    395       }
    396       if (args.show_cart) {
    397         // Empty drawer HTML before showing cart. Prevents options
    398         // interfering with subsequent cart additions.
    399         orderable_drawer.elements.drawer_html.html('');
    400         orderable_drawer.elements.drawer_cart.show();
    401       }
    402       orderable_drawer.elements.overlay.addClass(orderable_drawer.vars.classes.overlay_open);
    403       orderable_drawer.elements.drawer.addClass(orderable_drawer.vars.classes.drawer_open);
    404       orderable_drawer.elements.body.addClass(orderable_drawer.vars.classes.drawer_open_body);
    405       $(document.body).trigger('orderable-drawer.opened', args);
    406     },
    407     /**
    408      * Close the drawer.
    409      */
    410     close() {
    411       orderable_drawer.elements.overlay.removeClass(orderable_drawer.vars.classes.overlay_open);
    412       orderable_drawer.elements.drawer.removeClass(orderable_drawer.vars.classes.drawer_open);
    413       orderable_drawer.elements.body.removeClass(orderable_drawer.vars.classes.drawer_open_body);
    414       orderable_drawer.elements.drawer_html.html('');
    415       $(document.body).trigger('orderable-drawer.closed');
    416     },
    417     /**
    418      * Mini cart related functions.
    419      */
    420     cart: {
    421       /**
    422        * When increase qty is clicked.
    423        *
    424        * @param e
    425        * @param $button
    426        */
    427       click_increase_decrease_quantity(e, $button) {
    428         const direction = $button.data('orderable-trigger');
    429         const product_id = $button.attr('data-orderable-product-id'),
    430           cart_item_key = $button.attr('data-orderable-cart-item-key'),
    431           quantity = $button.attr('data-orderable-quantity');
    432         const siblingButtonName = 'increase-quantity' === direction ? 'decrease' : 'increase';
    433         const $siblingButton = $button.siblings(`.orderable-quantity-roller__button--${siblingButtonName}`);
    434         const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
    435         const data = {
    436           action: 'orderable_cart_quantity',
    437           cart_item_key,
    438           product_id,
    439           quantity
    440         };
    441         if (this.currentRequest) {
    442           this.currentRequest.abort();
    443           this.currentRequest = undefined;
    444         }
    445         $button.addClass('orderable-button--loading');
    446         $button.attr('disabled', true);
    447         $siblingButton.attr('disabled', true);
    448         $quantityElement.attr('contenteditable', false);
    449         this.currentRequest = jQuery.post(orderable_vars.ajax_url, data, function (response) {
    450           if (!response) {
    451             return;
    452           }
    453           const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
    454           if (response && response.fragments && response.fragments['.orderable-mini-cart__notices']) {
    455             $(document.body).trigger('orderable-drawer.open', {
    456               show_cart: true
    457             });
    458           }
    459           switch (data.quantity) {
    460             case '0':
    461               $(document.body).trigger('removed_from_cart', [response.fragments, response.cart_hash, $button]);
    462               break;
    463             case $quantityElement.attr('data-orderable-updating-quantity'):
    464               $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, $button]);
    465               $(document.body).trigger('orderable-drawer.quantity-updated');
    466               break;
    467             default:
    468               break;
    469           }
    470         }.bind(this)).always(function () {
    471           this.currentRequest = undefined;
    472           $button.removeClass('orderable-button--loading');
    473           $button.attr('disabled', false);
    474           $siblingButton.attr('disabled', false);
    475           $quantityElement.attr('contenteditable', true);
    476         }.bind(this));
    477       },
    478       handle_quantity_change_by_button(e, $button) {
    479         const direction = $button.data('orderable-trigger');
    480         const quantity = parseInt($button.attr('data-orderable-quantity'));
    481         const siblingButtonName = 'increase-quantity' === direction ? 'decrease' : 'increase';
    482         const $siblingButton = $button.siblings(`.orderable-quantity-roller__button--${siblingButtonName}`);
    483         const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
    484         const newQuantity = 'increase-quantity' === direction ? quantity + 1 : Math.max(0, quantity - 1);
    485         const $parent = $button.parents('.orderable-product__actions-button');
    486         if (0 === newQuantity && $parent.length) {
    487           const $addToCartButton = $parent.find('button.orderable-button[data-orderable-trigger]');
    488           const $quantityRoller = $parent.find('.orderable-quantity-roller');
    489           if ($quantityRoller.length) {
    490             $addToCartButton.removeClass('orderable-button--product-in-the-cart');
    491             $quantityRoller.removeClass('orderable-quantity-roller--is-active');
    492           }
    493         }
    494         $button.attr('data-orderable-quantity', newQuantity);
    495         $siblingButton.attr('data-orderable-quantity', newQuantity);
    496         $quantityElement.attr('data-orderable-updating-quantity', newQuantity);
    497         $quantityElement.text(newQuantity);
    498         $quantityElement.attr('contenteditable', false);
    499       }
    500     }
    501   };
    502   $(document).ready(orderable_drawer.on_ready);
    503 })(jQuery, document);
    504 (function ($, document) {
    505   'use strict';
    506 
    507   var orderable_products = {
    508     /**
    509      * On doc ready.
    510      */
    511     on_ready() {
    512       orderable_products.cache();
    513       orderable_products.watch();
    514     },
    515     /**
    516      * Cache.
    517      */
    518     cache() {
    519       orderable_products.vars = {
    520         classes: {
    521           clickable_product: 'orderable-product--add-to-cart ',
    522           add_to_order_button: 'orderable-product__add-to-order',
    523           product_messages: 'orderable-product__messages',
    524           product_price: 'orderable-product__actions-price',
    525           invalid_field: 'orderable-field--invalid',
    526           option_select_td: 'orderable-product__option-select',
    527           button_loading: 'orderable-button--loading',
    528           out_of_stock: 'orderable-button--out-of-stock'
    529         },
    530         parent_price: null,
    531         variable_product_types: ['variable', 'variable-subscription']
    532       };
    533       orderable_products.elements = {};
    534     },
    535     /**
    536      * Watch for trigger events.
    537      */
    538     watch() {
    539       $(document.body).on('orderable-drawer.opened', orderable_products.init_product_options);
    540       $(document.body).on('orderable-add-to-cart', orderable_products.click_add_to_order);
    541       $(document.body).on('orderable-product-options', orderable_products.click_add_to_order);
    542       $(document.body).on('orderable-view-product', orderable_products.view_product);
    543       $(document.body).on('mouseenter mouseleave', '.' + orderable_products.vars.classes.clickable_product, orderable_products.simulate_add_to_order_hover);
    544       $(document.body).on('orderable-edit-cart-item', orderable_products.edit_cart_item);
    545       $(document.body).on('orderable-update-cart-item', orderable_products.update_cart_item);
    546       $(document.body).on('orderable-show-cart', orderable_products.show_cart);
    547       $(document.body).on('orderable-add-to-cart-without-side-drawer', orderable_products.click_add_to_order);
    548       $(document.body).on('added_to_cart', orderable_products.remove_fragments);
    549       $(document.body).on('added_to_cart', orderable_products.remove_animation);
    550       $(document.body).on('added_to_cart', orderable_products.shake_floating_cart);
    551       $(document.body).on('removed_from_cart', orderable_products.hide_quantity_roller);
    552       $(document.body).on('wc_cart_button_updated', orderable_products.remove_view_cart_link);
    553     },
    554     /**
    555      * Simulate hover on add to order button.
    556      *
    557      * @param event
    558      */
    559     simulate_add_to_order_hover(event) {
    560       const $element = $(this),
    561         $button = $element.find('.' + orderable_products.vars.classes.add_to_order_button);
    562       $button.toggleClass('orderable-button--hover', 'mouseenter' === event.type);
    563     },
    564     /**
    565      * Add to order click event.
    566      *
    567      * This event accounts for button clicks or card clicks.
    568      * @param event
    569      * @param $element
    570      */
    571     click_add_to_order(event, $element) {
    572       // If undefined, it means it was triggered by a click
    573       // event and not the `orderable-add-to-cart` trigger.
    574       $element = typeof $element !== 'undefined' ? $element : $(this);
    575 
    576       // The button is either the clicked element, or the
    577       // add to order button within the clicked element.
    578       const $button = $element.is('button') ? $element : $element.find('.' + orderable_products.vars.classes.add_to_order_button),
    579         action = $button.data('orderable-trigger'),
    580         product_id = $button.data('orderable-product-id'),
    581         variation_id = $button.data('orderable-variation-id'),
    582         attributes = $button.data('orderable-variation-attributes'),
    583         args = {
    584           action
    585         };
    586       if ($button.hasClass(orderable_products.vars.classes.button_loading) || $button.hasClass(orderable_products.vars.classes.out_of_stock)) {
    587         return;
    588       }
    589       $button.addClass(orderable_products.vars.classes.button_loading);
    590       switch (action) {
    591         case 'add-to-cart':
    592           orderable_products.add_to_cart({
    593             product_id,
    594             variation_id,
    595             attributes,
    596             thisbutton: $element
    597           }, function (response) {
    598             args.show_cart = true;
    599             args.response = response;
    600             $(document.body).trigger('orderable-drawer.open', args);
    601             $button.removeClass(orderable_products.vars.classes.button_loading);
    602             const $addToCartButtonOutsideDrawer = $('.orderable-product .orderable-product__actions-button button.orderable-product__add-to-order[data-orderable-product-id=' + product_id + ']');
    603             if ($addToCartButtonOutsideDrawer.siblings('.orderable-quantity-roller').length) {
    604               $addToCartButtonOutsideDrawer.addClass('orderable-button--product-in-the-cart');
    605             }
    606           });
    607           break;
    608         case 'add-to-cart-without-side-drawer':
    609           orderable_products.add_to_cart({
    610             product_id,
    611             variation_id,
    612             attributes
    613           }, function (response) {
    614             args.response = response;
    615             $button.addClass('orderable-button--product-in-the-cart');
    616             $button.removeClass(orderable_products.vars.classes.button_loading);
    617           });
    618           break;
    619         case 'product-options':
    620           orderable_products.get_product_options({
    621             product_id,
    622             focus: $button.data('orderable-focus')
    623           }, function (response) {
    624             args.html = response.html;
    625             $(document.body).trigger('orderable-drawer.open', args);
    626             $button.removeClass(orderable_products.vars.classes.button_loading);
    627           });
    628           break;
    629         default:
    630           break;
    631       }
    632     },
    633     /**
    634      * Show the cart.
    635      */
    636     show_cart() {
    637       $(document.body).trigger('orderable-drawer.open', {
    638         show_cart: true
    639       });
    640     },
    641     /**
    642      * View product.
    643      *
    644      * @param event
    645      * @param $element
    646      */
    647     view_product(event, $element) {
    648       const product_id = $element.data('orderable-product-id'),
    649         args = {
    650           action: 'product-options'
    651         };
    652       orderable_products.get_product_options({
    653         product_id,
    654         focus: $element.data('orderable-focus')
    655       }, function (response) {
    656         args.html = response.html;
    657         $(document.body).trigger('orderable-drawer.open', args);
    658       });
    659     },
    660     /**
    661      * Ajax add to cart.
    662      * @param args
    663      * @param callback
    664      */
    665     add_to_cart(args, callback) {
    666       if (typeof args.product_id === 'undefined') {
    667         return;
    668       }
    669       let data = {
    670         action: 'orderable_add_to_cart',
    671         product_id: args.product_id,
    672         variation_id: args.variation_id || false,
    673         attributes: args.attributes || false
    674       };
    675 
    676       // Prepare addons data.
    677       if ($('.orderable-product-fields-group').length) {
    678         let inputs = jQuery('.orderable-product-fields-group :input').serializeArray();
    679         inputs = orderable_products.add_unchecked_checkbox_fields(inputs);
    680         const addons_data = orderable_products.convert_to_flat_object(inputs);
    681         if (!jQuery.isEmptyObject(addons_data)) {
    682           data = Object.assign(data, addons_data); // Merge objects.
    683         }
    684       }
    685       jQuery.post(orderable_vars.ajax_url, data, function (response) {
    686         if (!response) {
    687           return;
    688         }
    689 
    690         // Trigger event so themes can refresh other areas.
    691         $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, args.thisbutton]);
    692         if (typeof callback === 'function') {
    693           callback(response);
    694         }
    695       });
    696     },
    697     /**
    698      * Edit cart item.
    699      *
    700      * @param event
    701      * @param $element
    702      */
    703     edit_cart_item(event, $element) {
    704       const cart_item_key = $element.data('orderable-cart-item-key');
    705       $element.addClass(orderable_products.vars.classes.button_loading);
    706       orderable_products.get_cart_item_options({
    707         cart_item_key
    708       }, function (response) {
    709         const args = {
    710           html: response.html,
    711           action: 'update-cart-item'
    712         };
    713         $(document.body).trigger('orderable-drawer.open', args);
    714         $element.removeClass(orderable_products.vars.classes.button_loading);
    715       });
    716     },
    717     /**
    718      * Update cart item.
    719      *
    720      * @param event
    721      * @param $element
    722      */
    723     update_cart_item(event, $element) {
    724       const cart_item_key = $element.data('orderable-cart-item-key');
    725       const product_id = $element.data('orderable-product-id');
    726       const variation_id = $element.data('orderable-variation-id');
    727       const attributes = $element.data('orderable-variation-attributes');
    728       $element.addClass(orderable_products.vars.classes.button_loading);
    729       orderable_products.update_cart_item_options({
    730         cart_item_key,
    731         product_id,
    732         variation_id,
    733         attributes
    734       }, function (response) {
    735         const args = {
    736           show_cart: true,
    737           response
    738         };
    739         $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash]);
    740         $(document.body).trigger('orderable-drawer.open', args);
    741         $element.removeClass(orderable_products.vars.classes.button_loading);
    742       });
    743     },
    744     /**
    745      * Convert [{name:x, value:y }] to {x:y} format.
    746      * @param inputs
    747      */
    748     convert_to_flat_object(inputs) {
    749       const data = {};
    750       inputs.forEach(function (input) {
    751         const is_array = '[]' === input.name.substr(-2) || Array.isArray(input.name);
    752         // If last 2 chars are '[]', remove them.
    753         const key = is_array ? input.name.substr(0, input.name.length - 2) : input.name;
    754         if (is_array) {
    755           data[key] = typeof data[key] === 'undefined' ? [] : data[key];
    756           data[key].push(input.value);
    757         } else {
    758           data[key] = input.value;
    759         }
    760       });
    761       return data;
    762     },
    763     /**
    764      * Get variable product options.
    765      *
    766      * @param args
    767      * @param callback
    768      */
    769     get_product_options(args, callback) {
    770       if (typeof args.product_id === 'undefined') {
    771         return;
    772       }
    773       args.action = 'orderable_get_product_options';
    774       jQuery.post(orderable_vars.ajax_url, args, function (response) {
    775         if (!response.success) {
    776           return;
    777         }
    778         if (typeof callback === 'function') {
    779           callback(response.data);
    780         }
    781       });
    782     },
    783     /**
    784      * Get variable product options.
    785      *
    786      * @param args
    787      * @param callback
    788      */
    789     get_cart_item_options(args, callback) {
    790       if (typeof args.cart_item_key === 'undefined') {
    791         return;
    792       }
    793       args.action = 'orderable_get_cart_item_options';
    794       jQuery.post(orderable_vars.ajax_url, args, function (response) {
    795         if (!response.success) {
    796           return;
    797         }
    798         if (typeof callback === 'function') {
    799           callback(response.data);
    800         }
    801       });
    802     },
    803     /**
    804      * Update variable product options.
    805      *
    806      * @param args
    807      * @param callback
    808      */
    809     update_cart_item_options(args, callback) {
    810       if (typeof args.cart_item_key === 'undefined') {
    811         return;
    812       }
    813       args.action = 'orderable_update_cart_item_options';
    814 
    815       // Prepare addons data.
    816       if ($('.orderable-product-fields-group').length) {
    817         let inputs = jQuery('.orderable-product-fields-group :input').serializeArray();
    818         inputs = orderable_products.add_unchecked_checkbox_fields(inputs);
    819         const addons_data = orderable_products.convert_to_flat_object(inputs);
    820         if (!jQuery.isEmptyObject(addons_data)) {
    821           args = Object.assign(args, addons_data); // Merge objects.
    822         }
    823       }
    824       jQuery.post(orderable_vars.ajax_url, args, function (response) {
    825         if (!response) {
    826           return;
    827         }
    828         if (typeof callback === 'function') {
    829           callback(response);
    830         }
    831       });
    832     },
    833     /**
    834      * Init drawer product options.
    835      *
    836      * @param event
    837      * @param args
    838      */
    839     init_product_options(event, args) {
    840       if (typeof args.action === 'undefined' || 'product-options' !== args.action && 'update-cart-item' !== args.action) {
    841         return;
    842       }
    843       const selectors = '.orderable-drawer .orderable-product__options input, .orderable-drawer .orderable-product__options select, .orderable-product__options textarea';
    844       const $options = $(selectors);
    845       orderable_products.vars.parent_price = $('.orderable-drawer .orderable-product__actions-price').html();
    846       orderable_products.product_options_change($options);
    847       orderable_products.update_button_state();
    848       const debounced_update_button_state = orderable_products.debounce(orderable_products.update_button_state, 500);
    849       const debounced_product_options_change = orderable_products.debounce(orderable_products.product_options_change, 500);
    850       $(document).on('change keyup', selectors, function () {
    851         debounced_product_options_change($options);
    852         debounced_update_button_state();
    853       });
    854     },
    855     /**
    856      * On product options change.
    857      *
    858      * @param $options
    859      */
    860     product_options_change($options) {
    861       const $add_to_order_button = $('.orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item'),
    862         options_set = orderable_products.check_options($options),
    863         product_type = $add_to_order_button.data('orderable-product-type');
    864       if ('product-options' === $add_to_order_button.attr('data-orderable-trigger')) {
    865         $add_to_order_button.attr('data-orderable-trigger', 'add-to-cart');
    866       }
    867       $('.' + orderable_products.vars.classes.product_messages).html('');
    868       if (!orderable_products.vars.variable_product_types.includes(product_type)) {
    869         return;
    870       }
    871       if (!options_set) {
    872         orderable_products.clear_variation($add_to_order_button);
    873         return;
    874       }
    875       const variation = orderable_products.check_variation($options);
    876       orderable_products.set_variation($add_to_order_button, variation);
    877     },
    878     /**
    879      * Check if all product options are set.
    880      *
    881      * @param  $options
    882      * @return {boolean}
    883      */
    884     check_options($options) {
    885       if ($options.length <= 0) {
    886         return false;
    887       }
    888       let all_set = true;
    889       $options.each(function (index, option) {
    890         // Only check attribute fields.
    891         if (!$(option).hasClass('orderable-input--validate')) {
    892           return;
    893         }
    894         if ('' === $(option).val()) {
    895           $(option).addClass(orderable_products.vars.classes.invalid_field);
    896           all_set = false;
    897         } else {
    898           $(option).removeClass(orderable_products.vars.classes.invalid_field);
    899         }
    900       });
    901       return all_set;
    902     },
    903     /**
    904      * Check if variation has been selected.
    905      * @param $options
    906      */
    907     check_variation($options) {
    908       const $product = $options.closest('.orderable-drawer');
    909       let variations = $product.find('.orderable-product__variations').text();
    910       variations = variations ? JSON.parse(variations) : '';
    911       const selected_options = orderable_products.serialize_object($options),
    912         matching_variations = orderable_products.find_matching_variations(variations, selected_options);
    913       if (orderable_products.is_empty(matching_variations)) {
    914         return false;
    915       }
    916       const variation = matching_variations.shift();
    917       variation.attributes = selected_options;
    918       variation.attributes_json = JSON.stringify(selected_options);
    919       return typeof variation !== 'undefined' ? variation : false;
    920     },
    921     /**
    922      * Set variation for add to cart button.
    923      * @param $button
    924      * @param variation
    925      */
    926     set_variation($button, variation) {
    927       let variation_id = variation.variation_id || '',
    928         attributes = variation.attributes_json || '',
    929         price = variation.price_html || orderable_products.vars.parent_price,
    930         message = '';
    931       if (variation && '' !== variation.availability_html) {
    932         message = variation.availability_html;
    933       }
    934       if (variation && !variation.is_in_stock) {
    935         message = '<p>' + orderable_vars.i18n.out_of_stock + '</p>';
    936       }
    937       if (variation && !variation.is_purchasable) {
    938         message = '<p>' + orderable_vars.i18n.unavailable + '</p>';
    939       }
    940       if (false === variation) {
    941         message = '<p>' + orderable_vars.i18n.no_exist + '</p>';
    942       }
    943       if (variation && (!variation.is_purchasable || !variation.is_in_stock)) {
    944         variation_id = '';
    945         attributes = '';
    946       }
    947       if ('' !== message) {
    948         $('.' + orderable_products.vars.classes.product_messages).html(message);
    949       }
    950       $button.data('orderable-variation-id', variation_id);
    951       $button.data('orderable-variation-attributes', attributes);
    952       $('.orderable-drawer .orderable-product__actions-price').html(price);
    953       $button.trigger('orderable_variation_set', {
    954         variation,
    955         variation_id,
    956         attributes,
    957         price
    958       });
    959     },
    960     /**
    961      * Clear variation and disable add to order.
    962      *
    963      * @param $button
    964      */
    965     clear_variation($button) {
    966       orderable_products.set_variation($button, '');
    967       if (orderable_products.vars.parent_price) {
    968         $('.orderable-drawer .orderable-product__actions-price').html(orderable_products.vars.parent_price);
    969       }
    970     },
    971     /**
    972      * Find matching variations for attributes.
    973      * @param variations
    974      * @param attributes
    975      */
    976     find_matching_variations(variations, attributes) {
    977       const matching = [];
    978       for (let i = 0; i < variations.length; i++) {
    979         const variation = variations[i];
    980         if (orderable_products.is_matching_variation(variation.attributes, attributes)) {
    981           matching.push(variation);
    982         }
    983       }
    984       return matching;
    985     },
    986     /**
    987      * See if attributes match.
    988      * @param  variation_attributes
    989      * @param  attributes
    990      * @return {boolean}
    991      */
    992     is_matching_variation(variation_attributes, attributes) {
    993       let match = true;
    994       for (const attr_name in variation_attributes) {
    995         if (variation_attributes.hasOwnProperty(attr_name)) {
    996           const val1 = variation_attributes[attr_name];
    997           const val2 = attributes[attr_name];
    998           if (val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2) {
    999             match = false;
    1000           }
    1001         }
    1002       }
    1003       return match;
    1004     },
    1005     /**
    1006      * Is value empty?
    1007      *
    1008      * @param  value
    1009      * @return {boolean}
    1010      */
    1011     is_empty(value) {
    1012       return typeof value === 'undefined' || false === value || value.length <= 0 || !value;
    1013     },
    1014     /**
    1015      * Serialize into a key/value object.
    1016      *
    1017      * @param  $elements
    1018      * @return {{}}
    1019      */
    1020     serialize_object: function objectifyForm($elements) {
    1021       const serialized = $elements.serializeArray(),
    1022         return_object = {};
    1023       for (let i = 0; i < serialized.length; i++) {
    1024         return_object[serialized[i].name] = serialized[i].value;
    1025       }
    1026       return return_object;
    1027     },
    1028     /**
    1029      * Disable/Enable the 'Add to cart' button based on the presence of orderable-field--invalid class.
    1030      */
    1031     update_button_state() {
    1032       // Add delay to ensure invalid class has been assigned to inputs.
    1033       setTimeout(function () {
    1034         let $button = $('.orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item'),
    1035           invalid_fields_count = $('.orderable-drawer__html .' + orderable_products.vars.classes.invalid_field).length,
    1036           product_type = $button.data('orderable-product-type'),
    1037           has_variation_id = true;
    1038         if ('variable' === product_type) {
    1039           has_variation_id = '' !== $button.data('orderable-variation-id');
    1040         }
    1041         $button.prop('disabled', invalid_fields_count || !has_variation_id);
    1042       }, 50);
    1043     },
    1044     /**
    1045      * Debounce function.
    1046      *
    1047      * @param func      Function to debounce.
    1048      * @param wait      Time to wait in milliseconds.
    1049      * @param immediate Trigger the function on the leading edge, instead of the trailing.
    1050      *
    1051      * @return
    1052      */
    1053     debounce(func, wait, immediate) {
    1054       let timeout;
    1055       return function () {
    1056         const context = this,
    1057           args = arguments;
    1058         const later = function () {
    1059           timeout = null;
    1060           if (!immediate) {
    1061             func.apply(context, args);
    1062           }
    1063         };
    1064         const callNow = immediate && !timeout;
    1065         clearTimeout(timeout);
    1066         timeout = setTimeout(later, wait);
    1067         if (callNow) {
    1068           func.apply(context, args);
    1069         }
    1070       };
    1071     },
    1072     /**
    1073      * Remove the quantity roller fragments
    1074      *
    1075      * @param {Event}  e
    1076      * @param {Object} fragments
    1077      * @return void
    1078      */
    1079     remove_fragments(e, fragments) {
    1080       if (!fragments || 'undefined' === typeof wc_cart_fragments_params || !wc_cart_fragments_params.fragment_name) {
    1081         return;
    1082       }
    1083       const regex_quantity_roller = /\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-quantity-roller/;
    1084       const regex_product_in_the_cart_counter = /\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-product__actions-counter/;
    1085       for (const key in fragments) {
    1086         if (!regex_quantity_roller.test(key) && !regex_product_in_the_cart_counter.test(key)) {
    1087           continue;
    1088         }
    1089         fragments[key] = undefined;
    1090       }
    1091       sessionStorage.setItem(wc_cart_fragments_params.fragment_name, JSON.stringify(fragments));
    1092     },
    1093     /**
    1094      * Remove animation.
    1095      */
    1096     remove_animation() {
    1097       setTimeout(function () {
    1098         $('.orderable-product__actions-counter').css('animation', '');
    1099       }, 1000);
    1100     },
    1101     /**
    1102      * Hide quantity roller element and show the Add to Cart button.
    1103      *
    1104      * @param {Event}   e
    1105      * @param {Object}  fragments
    1106      * @param {string}  cart_hash
    1107      * @param {Element} $button
    1108      * @return
    1109      */
    1110     hide_quantity_roller(e, fragments, cart_hash, $button) {
    1111       const product_id = $button.attr('data-product_id') || $button.attr('data-orderable-product-id');
    1112       if (!product_id) {
    1113         return;
    1114       }
    1115       const $actions_button = $('.orderable-product[data-orderable-product-id=' + product_id + '] .orderable-product__actions-button');
    1116       if (!$actions_button.length) {
    1117         return;
    1118       }
    1119       const $quantity_roller = $actions_button.find('.orderable-quantity-roller');
    1120       if ($quantity_roller.length) {
    1121         $actions_button.find('button.orderable-product__add-to-order[data-orderable-trigger]').removeClass('orderable-button--product-in-the-cart');
    1122         $quantity_roller.addClass('orderable-button--hide');
    1123       }
    1124     },
    1125     /**
    1126      * Add unchecked checkboxs to the list of inputs
    1127      * sent to the request to add/update an item
    1128      *
    1129      * @param {Object} inputs
    1130      * @return {Object}
    1131      */
    1132     add_unchecked_checkbox_fields(inputs) {
    1133       jQuery('.orderable-product-fields-group :input[type="checkbox"]:not(:checked)').each(function (index, element) {
    1134         inputs.push({
    1135           name: element.getAttribute('name'),
    1136           value: ''
    1137         });
    1138       });
    1139       return inputs;
    1140     },
    1141     /**
    1142      * Shake the floating cart button.
    1143      *
    1144      * @return void
    1145      */
    1146     shake_floating_cart() {
    1147       $('.orderable-floating-cart__button').css('animation', 'wobble-hor-bottom .8s both');
    1148     },
    1149     /**
    1150      * Remove the view cart link.
    1151      *
    1152      * @param event
    1153      * @param $button
    1154      */
    1155     remove_view_cart_link(event, $button) {
    1156       if (!$button?.hasClass('orderable-product__add-to-order')) {
    1157         return;
    1158       }
    1159       $button?.siblings('.added_to_cart.wc-forward').remove();
    1160     }
    1161   };
    1162   $(document).ready(orderable_products.on_ready);
    1163 })(jQuery, document);
    1164 (function ($, document) {
    1165   'use strict';
    1166 
    1167   var orderable_scrollbar = {
    1168     /**
    1169      * On doc ready.
    1170      */
    1171     on_ready() {
    1172       orderable_scrollbar.cache();
    1173       orderable_scrollbar.watch();
    1174     },
    1175     /**
    1176      * Cache.
    1177      */
    1178     cache() {
    1179       orderable_scrollbar.vars = {
    1180         top: {}
    1181       };
    1182       orderable_scrollbar.elements = {};
    1183     },
    1184     /**
    1185      * Watch.
    1186      */
    1187     watch() {
    1188       $(document.body).on('orderable-drawer.opened', orderable_scrollbar.trigger);
    1189       $(document.body).on('orderable-tabs.changed', orderable_scrollbar.trigger);
    1190       $(document.body).on('orderable-accordion.toggled', orderable_scrollbar.trigger);
    1191       $(document.body).on('wc_fragments_loaded', orderable_scrollbar.trigger);
    1192     },
    1193     /**
    1194      * Init or retrigger scrollbars.
    1195      */
    1196     trigger() {
    1197       $('.orderable-sb-container').each(function (index, element) {
    1198         const $element = $(element),
    1199           scroll_id = $element.data('orderable-scroll-id');
    1200         if (!orderable_scrollbar.has_scrollbar($element)) {
    1201           $element.scrollBox({
    1202             containerClass: 'orderable-sb-container',
    1203             containerNoScrollClass: 'orderable-sb-container-noscroll',
    1204             contentClass: 'orderable-sb-content',
    1205             scrollbarContainerClass: 'orderable-sb-scrollbar-container',
    1206             scrollBarClass: 'orderable-sb-scrollbar'
    1207           });
    1208           const $content = $element.find('.orderable-sb-content');
    1209           if ($content.length > 0) {
    1210             $content.on('scroll.scrollBox', orderable_scrollbar.log_top_position);
    1211 
    1212             // Set scroll position.
    1213             if (typeof orderable_scrollbar.vars.top[scroll_id] !== 'undefined') {
    1214               $content.scrollTop(orderable_scrollbar.vars.top[scroll_id]);
    1215             }
    1216           }
    1217           $(document.body).trigger('orderable-scrollbar.created', {
    1218             element: $element,
    1219             content: $content
    1220           });
    1221         }
    1222       });
    1223       $(window).trigger('resize.scrollBox');
    1224     },
    1225     /**
    1226      * Has scrollbar already?
    1227      *
    1228      * @param  $element
    1229      * @return {boolean}
    1230      */
    1231     has_scrollbar($element) {
    1232       return $element.find('.orderable-sb-content').length > 0;
    1233     },
    1234     /**
    1235      * Set scrolltop position.
    1236      *
    1237      * @param e
    1238      */
    1239     log_top_position(e) {
    1240       const $element = $(e.currentTarget),
    1241         $container = $element.closest('.orderable-sb-container'),
    1242         scroll_id = $container.data('orderable-scroll-id');
    1243       orderable_scrollbar.vars.top[scroll_id] = $(e.currentTarget).scrollTop();
    1244     }
    1245   };
    1246   $(document).ready(orderable_scrollbar.on_ready);
    1247 })(jQuery, document);
    1248 (function ($, document) {
    1249   'use strict';
    1250 
    1251   var orderable_tabs = {
    1252     /**
    1253      * On doc ready.
    1254      */
    1255     on_ready() {
    1256       orderable_tabs.cache();
    1257       orderable_tabs.watch();
    1258       orderable_tabs.toggle_scroll();
    1259     },
    1260     /**
    1261      * On resize.
    1262      */
    1263     on_resize() {
    1264       orderable_tabs.toggle_scroll();
    1265     },
    1266     /**
    1267      * Cache.
    1268      */
    1269     cache() {
    1270       orderable_tabs.vars = {
    1271         classes: {
    1272           tabs: 'orderable-tabs',
    1273           tabs_list: 'orderable-tabs__list',
    1274           tab_items: 'orderable-tabs__item',
    1275           tab_item_active: 'orderable-tabs__item--active',
    1276           tab_links: 'orderable-tabs__link',
    1277           tab_arrow_right: 'orderable-tabs__arrow-right',
    1278           tab_arrow_left: 'orderable-tabs__arrow-left'
    1279         },
    1280         dragging: false
    1281       };
    1282       orderable_tabs.elements = {};
    1283     },
    1284     /**
    1285      * Watch.
    1286      */
    1287     watch() {
    1288       $('body').on('touchstart', function () {
    1289         orderable_tabs.vars.dragging = false;
    1290       }).on('touchmove', function () {
    1291         orderable_tabs.vars.dragging = true;
    1292       });
    1293       $(document.body).on('click mouseup touchend', '.' + orderable_tabs.vars.classes.tab_links, function (e) {
    1294         if (orderable_tabs.vars.dragging) {
    1295           return;
    1296         }
    1297         e.preventDefault();
    1298         const $link = $(this),
    1299           section_id = $link.attr('href'),
    1300           $tab = $link.closest('.' + orderable_tabs.vars.classes.tab_items),
    1301           $tabs = $link.closest('.' + orderable_tabs.vars.classes.tabs),
    1302           $tabs_list = $tabs.find('.' + orderable_tabs.vars.classes.tabs_list),
    1303           $tab_items = $tabs.find('.' + orderable_tabs.vars.classes.tab_items),
    1304           tabs_args = $tabs.data('orderable-tabs'),
    1305           $wrapper = $link.closest(tabs_args.wrapper),
    1306           $sections = $wrapper.find(tabs_args.sections),
    1307           $section = $wrapper.find(section_id);
    1308         $sections.hide();
    1309         $section.show();
    1310         $tab_items.removeClass(orderable_tabs.vars.classes.tab_item_active);
    1311         $tab.addClass(orderable_tabs.vars.classes.tab_item_active);
    1312         $tabs_list.animate({
    1313           scrollLeft: $tabs_list.scrollLeft() + $tab.position().left
    1314         });
    1315         $(document.body).trigger('orderable-tabs.changed', {
    1316           tab: $tab
    1317         });
    1318       });
    1319 
    1320       /**
    1321        * Watch scroll position of tabs.
    1322        */
    1323       $('.' + orderable_tabs.vars.classes.tabs_list).on('scroll', function (e) {
    1324         const $list = $(this),
    1325           $wrapper = $list.parent('.' + orderable_tabs.vars.classes.tabs),
    1326           $arrow_right = $list.siblings('.' + orderable_tabs.vars.classes.tab_arrow_right),
    1327           $arrow_left = $list.siblings('.' + orderable_tabs.vars.classes.tab_arrow_left);
    1328         if ($list[0].scrollWidth <= $wrapper.width() + $list.scrollLeft()) {
    1329           $arrow_right.fadeOut();
    1330         } else {
    1331           $arrow_right.fadeIn();
    1332         }
    1333         if (0 >= $list.scrollLeft() - $arrow_left.width()) {
    1334           $arrow_left.fadeOut();
    1335         } else {
    1336           $arrow_left.fadeIn();
    1337         }
    1338       });
    1339 
    1340       /**
    1341        * Stop animated scroll if user manually scrolls.
    1342        */
    1343       $('.' + orderable_tabs.vars.classes.tabs_list).on('wheel DOMMouseScroll mousewheel touchmove', function () {
    1344         $(this).stop();
    1345       });
    1346 
    1347       /**
    1348        * Click tab arrow right.
    1349        */
    1350       $(document).on('click', '.' + orderable_tabs.vars.classes.tab_arrow_right, function (e) {
    1351         e.preventDefault();
    1352         const $arrow = $(this),
    1353           $wrapper = $arrow.parent(),
    1354           $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list);
    1355         $list.animate({
    1356           scrollLeft: $list.scrollLeft() + $wrapper.width() * 0.5
    1357         });
    1358       });
    1359 
    1360       /**
    1361        * Click tab arrow left.
    1362        */
    1363       $(document).on('click', '.' + orderable_tabs.vars.classes.tab_arrow_left, function (e) {
    1364         e.preventDefault();
    1365         const $arrow = $(this),
    1366           $wrapper = $arrow.parent(),
    1367           $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list);
    1368         $list.animate({
    1369           scrollLeft: $list.scrollLeft() - $wrapper.width() * 0.5
    1370         });
    1371       });
    1372     },
    1373     /**
    1374      * Toggle scroll arrow.
    1375      */
    1376     toggle_scroll() {
    1377       $('.' + orderable_tabs.vars.classes.tabs).each(function (index, wrapper) {
    1378         const $tabs = $(this),
    1379           tabs_args = $tabs.data('orderable-tabs'),
    1380           $wrapper = $tabs.closest(tabs_args.wrapper),
    1381           $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list),
    1382           $arrow_right = $wrapper.find('.' + orderable_tabs.vars.classes.tab_arrow_right),
    1383           wrapper_width = $wrapper.outerWidth(),
    1384           list_width = $list[0].scrollWidth;
    1385         if (list_width > wrapper_width) {
    1386           $arrow_right.show();
    1387         } else {
    1388           $arrow_right.hide();
    1389         }
    1390       });
    1391     }
    1392   };
    1393   $(document).ready(orderable_tabs.on_ready);
    1394   $(window).on('resize', orderable_tabs.on_resize);
    1395 })(jQuery, document);
    1396 let orderable_timings = {}; // Make this global so pro modules can access it.
    1397 
    1398 (function ($, document) {
    1399   'use strict';
    1400 
    1401   orderable_timings = {
    1402     /**
    1403      * On doc ready.
    1404      */
    1405     on_ready() {
    1406       orderable_timings.watch();
    1407     },
    1408     /**
    1409      * Restore current timings.
    1410      */
    1411     restore() {
    1412       const timings = orderable_timings.get_timings();
    1413       if (!timings || !timings.date) {
    1414         return;
    1415       }
    1416       const dateSelect = $('.orderable-order-timings__date');
    1417       if (dateSelect.find('option[value="' + timings.date + '"]').length > 0) {
    1418         dateSelect.val(timings.date);
    1419         dateSelect.change();
    1420       }
    1421       if (!timings.time) {
    1422         return;
    1423       }
    1424       const timeSelect = $('.orderable-order-timings__time');
    1425       if (timeSelect.find('option[value="' + timings.time + '"]').length > 0) {
    1426         timeSelect.val(timings.time);
    1427         timeSelect.change();
    1428       }
    1429     },
    1430     /**
    1431      * Watch for trigger events.
    1432      */
    1433     watch() {
    1434       $(document.body).on('wc_fragments_refreshed', function () {
    1435         orderable_timings.restore();
    1436       });
    1437       $(document.body).on('updated_checkout', function () {
    1438         orderable_timings.restore();
    1439       });
    1440       $(document.body).on('change', '.orderable-order-timings__date', function (event) {
    1441         const $date_field = $(this),
    1442           $selected = $date_field.find('option:selected'),
    1443           slots = $selected.data('orderable-slots'),
    1444           $time_field_wrap = $('.orderable-order-timings--time'),
    1445           $time_field = $('.orderable-order-timings__time'),
    1446           $first_option = $time_field.find('option').first(),
    1447           $asap_option = $time_field.find('option[value="asap"]').first();
    1448         const timings = orderable_timings.get_timings();
    1449         timings.date = $('.orderable-order-timings__date').val();
    1450         window.localStorage.setItem('orderable_timings', JSON.stringify(timings));
    1451         $time_field.html($first_option);
    1452         if ($asap_option) {
    1453           $time_field.append($asap_option);
    1454         }
    1455         if (!slots) {
    1456           $time_field.prop('disabled', true);
    1457           $time_field_wrap.hide();
    1458           return;
    1459         }
    1460         if ('all-day' === slots[0].value) {
    1461           $time_field_wrap.hide();
    1462           $time_field.prop('disabled', true);
    1463         } else {
    1464           $time_field.prop('disabled', false);
    1465           $time_field_wrap.show();
    1466           $.each(slots, function (index, slot) {
    1467             $time_field.append($('<option />').attr('value', slot.value).attr('data-orderable-time-slot-id', slot?.setting_row?.time_slot_id).text(slot.formatted));
    1468           });
    1469         }
    1470       });
    1471       $(document.body).on('change', '.orderable-order-timings__time', function (event) {
    1472         const timings = orderable_timings.get_timings();
    1473         timings.time = $('.orderable-order-timings__time').val();
    1474         window.localStorage.setItem('orderable_timings', JSON.stringify(timings));
    1475         $(this).siblings('input[name="orderable_order_time_slot_id"]').val($(this).find(':selected').attr('data-orderable-time-slot-id'));
    1476       });
    1477     },
    1478     get_timings() {
    1479       return JSON.parse(window.localStorage.getItem('orderable_timings')) || {};
    1480     }
    1481   };
    1482   $(document).ready(orderable_timings.on_ready);
    1483 })(jQuery, document);
    1484 (function ($, document) {
    1485   'use strict';
    1486 
    1487   var orderable_triggers = {
    1488     /**
    1489      * On doc ready.
    1490      */
    1491     on_ready() {
    1492       orderable_triggers.watch();
    1493     },
    1494     /**
    1495      * Watch for trigger events.
    1496      */
    1497     watch() {
    1498       if ('undefined' !== typeof window.orderable_triggers_admin) {
    1499         return;
    1500       }
    1501       $(document.body).on('click', '[data-orderable-trigger]', orderable_triggers.trigger);
    1502     },
    1503     /**
    1504      * Fire trigger.
    1505      * @param e
    1506      */
    1507     trigger(e) {
    1508       // Prevent even bubbling up.
    1509       e.stopImmediatePropagation();
    1510       const $trigger_element = $(this),
    1511         trigger = $trigger_element.data('orderable-trigger');
    1512       if ($trigger_element.is('button') || $trigger_element.is('a')) {
    1513         e.preventDefault();
    1514       }
    1515       $(document.body).trigger('orderable-' + trigger, [$trigger_element]);
    1516     }
    1517   };
    1518   $(document).ready(orderable_triggers.on_ready);
    1519 })(jQuery, document);
  • orderable/tags/1.17.1/assets/frontend/js/main.min.js

    r3192586 r3237969  
    1 !function(o,e,s){"use strict";var n="scrollBox",r={containerClass:"sb-container",containerNoScrollClass:"sb-container-noscroll",contentClass:"sb-content",scrollbarContainerClass:"sb-scrollbar-container",scrollBarClass:"sb-scrollbar"};function t(e,t){this.element=e,this.settings=o.extend({},r,t),this._defaults=r,this._name=n,this.init()}o.extend(t.prototype,{init:function(){this.addScrollbar(),this.addEvents(),this.onResize()},addScrollbar:function(){o(this.element).addClass(this.settings.containerClass),this.wrapper=o("<div class='"+this.settings.contentClass+"' />"),this.wrapper.append(o(this.element).contents()),o(this.element).append(this.wrapper),this.scollbarContainer=o("<div class='"+this.settings.scrollbarContainerClass+"' />"),this.scrollBar=o("<div class='"+this.settings.scrollBarClass+"' />"),this.scollbarContainer.append(this.scrollBar),o(this.element).prepend(this.scollbarContainer)},addEvents:function(){this.wrapper.on("scroll."+n,o.proxy(this.onScroll,this)),o(e).on("resize."+n,o.proxy(this.onResize,this)),this.scrollBar.on("mousedown."+n,o.proxy(this.onMousedown,this)),this.scrollBar.on("touchstart."+n,o.proxy(this.onTouchstart,this))},onTouchstart:function(t){var r=this,a=(t.preventDefault(),r.scrollBar[0].offsetTop);o(s).on("touchmove."+n,function(e){e=e.touches[0].pageY-t.touches[0].pageY;r.scrollBar[0].style.top=Math.min(r.scollbarContainer[0].clientHeight-r.scrollBar[0].clientHeight,Math.max(0,a+e))+"px",r.wrapper[0].scrollTop=r.wrapper[0].scrollHeight*r.scrollBar[0].offsetTop/r.scollbarContainer[0].clientHeight}),o(s).on("touchend."+n,function(){o(s).off("touchmove."+n),o(s).off("touchend."+n)})},onMousedown:function(t){var r=this,a=(t.preventDefault(),r.scrollBar[0].offsetTop);o(s).on("mousemove."+n,function(e){e=e.pageY-t.pageY;r.scrollBar[0].style.top=Math.min(r.scollbarContainer[0].clientHeight-r.scrollBar[0].clientHeight,Math.max(0,a+e))+"px",r.wrapper[0].scrollTop=r.wrapper[0].scrollHeight*r.scrollBar[0].offsetTop/r.scollbarContainer[0].clientHeight}),o(s).on("mouseup."+n,function(){o(s).off("mousemove."+n),o(s).off("mouseup."+n)})},onResize:function(){this.wrapper.css("max-height",o(this.element).height());var e=this.wrapper[0].clientHeight;this.scrollBar.css("height",this.scollbarContainer[0].clientHeight*e/this.wrapper[0].scrollHeight+"px"),this.scollbarContainer[0].clientHeight<=this.scrollBar[0].clientHeight?o(this.element).addClass(this.settings.containerNoScrollClass):o(this.element).removeClass(this.settings.containerNoScrollClass),this.onScroll()},onScroll:function(){this.scrollBar.css("top",Math.min(this.scollbarContainer[0].clientHeight-this.scrollBar[0].clientHeight,this.scollbarContainer[0].clientHeight*this.wrapper[0].scrollTop/this.wrapper[0].scrollHeight)+"px")}}),o.fn[n]=function(e){return this.each(function(){o.data(this,"plugin_"+n)||o.data(this,"plugin_"+n,new t(this,e))})}}(jQuery,window,document),function(e,o){"use strict";"function"!=typeof e.CustomEvent&&(e.CustomEvent=function(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var r=o.createEvent("CustomEvent");return r.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),r},e.CustomEvent.prototype=e.Event.prototype),o.addEventListener("touchstart",function(e){"true"!==e.target.getAttribute("data-swipe-ignore")&&(c=e.target,l=Date.now(),s=e.touches[0].clientX,n=e.touches[0].clientY,d=i=0)},!1),o.addEventListener("touchmove",function(e){var t;s&&n&&(t=e.touches[0].clientX,e=e.touches[0].clientY,i=s-t,d=n-e)},!1),o.addEventListener("touchend",function(e){var t,r,a,o;c===e.target&&(o=parseInt(_(c,"data-swipe-threshold","20"),10),t=parseInt(_(c,"data-swipe-timeout","500"),10),r=Date.now()-l,a="",e=e.changedTouches||e.touches||[],Math.abs(i)>Math.abs(d)?Math.abs(i)>o&&r<t&&(a=0<i?"swiped-left":"swiped-right"):Math.abs(d)>o&&r<t&&(a=0<d?"swiped-up":"swiped-down"),""!==a&&(o={dir:a.replace(/swiped-/,""),touchType:(e[0]||{}).touchType||"direct",xStart:parseInt(s,10),xEnd:parseInt((e[0]||{}).clientX||-1,10),yStart:parseInt(n,10),yEnd:parseInt((e[0]||{}).clientY||-1,10)},c.dispatchEvent(new CustomEvent("swiped",{bubbles:!0,cancelable:!0,detail:o})),c.dispatchEvent(new CustomEvent(a,{bubbles:!0,cancelable:!0,detail:o}))),l=n=s=null)},!1);var s=null,n=null,i=null,d=null,l=null,c=null;function _(e,t,r){for(;e&&e!==o.documentElement;){var a=e.getAttribute(t);if(a)return a;e=e.parentNode}return r}}(window,document),function(o,s){"use strict";var n={on_ready(){n.cache(),n.watch()},cache(){n.vars={classes:{parent:"orderable-accordion",link:"orderable-accordion__item-link",content:"orderable-accordion__item-content",link_active:"orderable-accordion__item-link--active",content_active:"orderable-accordion__item-content--active"}}},watch(){o(s.body).on("click","."+n.vars.classes.link,function(e){e.preventDefault();var e=o(this),t=e.closest("."+n.vars.classes.parent),r=e.attr("href"),r=o(r),a=e.hasClass(n.vars.classes.link_active);t.find("."+n.vars.classes.link).removeClass(n.vars.classes.link_active),t.find("."+n.vars.classes.content).removeClass(n.vars.classes.content_active),a||(e.addClass(n.vars.classes.link_active),r.addClass(n.vars.classes.content_active)),o(s.body).trigger("orderable-accordion.toggled",{link:e,content:r})}),o(s.body).on("orderable-scrollbar.created",function(e,t){var r=o(".orderable-drawer ."+n.vars.classes.link_active);r.length<=0||(r=(t=t.content).scrollTop()-t.offset().top+r.offset().top,t.scrollTop(r))})}};o(s).ready(n.on_ready)}(jQuery,document),function(l,c){"use strict";var r={debounce(t,r=700){let a;return(...e)=>{clearTimeout(a),a=setTimeout(()=>{t.apply(this,e)},r)}},allow_only_numbers(e){var t=String.fromCharCode(e.which);/^\d+$/.test(t)||e.preventDefault()},on_change_quantity(e){const t=l(e.currentTarget);var e=t.data("orderable-product-id"),r=t.data("orderable-cart-item-key"),a=parseInt(t.text());jQuery.post(orderable_vars.ajax_url,{action:"orderable_cart_quantity",cart_item_key:r,product_id:e,quantity:a},function(e){e&&(l(c.body).trigger("added_to_cart",[e.fragments,e.cart_hash,t]),l(c.body).trigger("orderable-drawer.quantity-updated"))})},on_ready(){r.cache(),r.watch(),l(c.body).on("keypress",".orderable-quantity-roller__quantity",r.allow_only_numbers),l(".orderable-drawer__cart, .orderable-product--add-to-cart, .orderable-products-list").on("input",".orderable-quantity-roller__quantity",r.debounce(r.on_change_quantity)),l(c.body).on("click",".orderable-quantity-roller__quantity",function(e){e.stopPropagation()}),orderable_vars&&!orderable_vars.woocommerce_enable_ajax_add_to_cart&&l(c.body).off("click",".add_to_cart_button")},cache(){r.vars={classes:{overlay:"orderable-drawer-overlay",drawer:"orderable-drawer",drawer_cart:"orderable-drawer__cart",drawer_html:"orderable-drawer__html",overlay_open:"orderable-drawer-overlay--open",drawer_open:"orderable-drawer--open",drawer_open_body:"orderable-drawer-open"}},r.elements={body:l("body"),overlay:l("."+r.vars.classes.overlay),drawer:l("."+r.vars.classes.drawer),drawer_cart:l("."+r.vars.classes.drawer_cart),drawer_html:l("."+r.vars.classes.drawer_html),floating_cart_button_class:".orderable-floating-cart__button"}},watch(){var e,t;void 0!==r.elements.drawer&&(l(c.body).on("orderable-drawer.open",r.open),l(c.body).on("orderable-drawer.close",r.close),l(c.body).on("click",r.elements.floating_cart_button_class,function(){l(c.body).trigger("orderable-drawer.open",{show_cart:!0})}),l(c.body).on("orderable-increase-quantity",r.cart.handle_quantity_change_by_button),l(c.body).on("orderable-decrease-quantity",r.cart.handle_quantity_change_by_button),e=r.debounce(r.cart.click_increase_decrease_quantity),l(c.body).on("orderable-increase-quantity",e),l(c.body).on("orderable-decrease-quantity",e),e=c.querySelector("body:not( .rtl ) .orderable-drawer"),t=c.querySelector("body.rtl .orderable-drawer"),e&&e.addEventListener("swiped-right",function(e){r.close()}),t)&&t.addEventListener("swiped-left",function(e){r.close()})},open(e,t){t.html=t.html||!1,t.show_cart=t.show_cart||!1,r.elements.drawer_html.hide(),r.elements.drawer_cart.hide(),t.html&&(r.elements.drawer_html.html(t.html),r.elements.drawer_html.show()),t.show_cart&&(r.elements.drawer_html.html(""),r.elements.drawer_cart.show()),r.elements.overlay.addClass(r.vars.classes.overlay_open),r.elements.drawer.addClass(r.vars.classes.drawer_open),r.elements.body.addClass(r.vars.classes.drawer_open_body),l(c.body).trigger("orderable-drawer.opened",t)},close(){r.elements.overlay.removeClass(r.vars.classes.overlay_open),r.elements.drawer.removeClass(r.vars.classes.drawer_open),r.elements.body.removeClass(r.vars.classes.drawer_open_body),r.elements.drawer_html.html(""),l(c.body).trigger("orderable-drawer.closed")},cart:{click_increase_decrease_quantity(e,r){var t=r.data("orderable-trigger"),a=r.attr("data-orderable-product-id"),o=r.attr("data-orderable-cart-item-key"),s=r.attr("data-orderable-quantity");const n=r.siblings(".orderable-quantity-roller__button--"+("increase-quantity"===t?"decrease":"increase")),i=r.siblings(".orderable-quantity-roller__quantity"),d={action:"orderable_cart_quantity",cart_item_key:o,product_id:a,quantity:s};this.currentRequest&&(this.currentRequest.abort(),this.currentRequest=void 0),r.addClass("orderable-button--loading"),r.attr("disabled",!0),n.attr("disabled",!0),i.attr("contenteditable",!1),this.currentRequest=jQuery.post(orderable_vars.ajax_url,d,function(e){if(e){var t=r.siblings(".orderable-quantity-roller__quantity");switch(e&&e.fragments&&e.fragments[".orderable-mini-cart__notices"]&&l(c.body).trigger("orderable-drawer.open",{show_cart:!0}),d.quantity){case"0":l(c.body).trigger("removed_from_cart",[e.fragments,e.cart_hash,r]);break;case t.attr("data-orderable-updating-quantity"):l(c.body).trigger("added_to_cart",[e.fragments,e.cart_hash,r]),l(c.body).trigger("orderable-drawer.quantity-updated")}}}.bind(this)).always(function(){this.currentRequest=void 0,r.removeClass("orderable-button--loading"),r.attr("disabled",!1),n.attr("disabled",!1),i.attr("contenteditable",!0)}.bind(this))},handle_quantity_change_by_button(e,t){var r,a=t.data("orderable-trigger"),o=parseInt(t.attr("data-orderable-quantity")),s=t.siblings(".orderable-quantity-roller__button--"+("increase-quantity"===a?"decrease":"increase")),n=t.siblings(".orderable-quantity-roller__quantity"),a="increase-quantity"===a?o+1:Math.max(0,o-1),o=t.parents(".orderable-product__actions-button");0===a&&o.length&&(r=o.find("button.orderable-button[data-orderable-trigger]"),(o=o.find(".orderable-quantity-roller")).length)&&(r.removeClass("orderable-button--product-in-the-cart"),o.removeClass("orderable-quantity-roller--is-active")),t.attr("data-orderable-quantity",a),s.attr("data-orderable-quantity",a),n.attr("data-orderable-updating-quantity",a),n.text(a),n.attr("contenteditable",!1)}}};l(c).ready(r.on_ready)}(jQuery,document),function(d,l){"use strict";var c={on_ready(){c.cache(),c.watch()},cache(){c.vars={classes:{clickable_product:"orderable-product--add-to-cart ",add_to_order_button:"orderable-product__add-to-order",product_messages:"orderable-product__messages",product_price:"orderable-product__actions-price",invalid_field:"orderable-field--invalid",option_select_td:"orderable-product__option-select",button_loading:"orderable-button--loading",out_of_stock:"orderable-button--out-of-stock"},parent_price:null,variable_product_types:["variable","variable-subscription"]},c.elements={}},watch(){d(l.body).on("orderable-drawer.opened",c.init_product_options),d(l.body).on("orderable-add-to-cart",c.click_add_to_order),d(l.body).on("orderable-product-options",c.click_add_to_order),d(l.body).on("orderable-view-product",c.view_product),d(l.body).on("mouseenter mouseleave","."+c.vars.classes.clickable_product,c.simulate_add_to_order_hover),d(l.body).on("orderable-edit-cart-item",c.edit_cart_item),d(l.body).on("orderable-update-cart-item",c.update_cart_item),d(l.body).on("orderable-show-cart",c.show_cart),d(l.body).on("orderable-add-to-cart-without-side-drawer",c.click_add_to_order),d(l.body).on("added_to_cart",c.remove_fragments),d(l.body).on("added_to_cart",c.remove_animation),d(l.body).on("added_to_cart",c.shake_floating_cart),d(l.body).on("removed_from_cart",c.hide_quantity_roller),d(l.body).on("wc_cart_button_updated",c.remove_view_cart_link)},simulate_add_to_order_hover(e){d(this).find("."+c.vars.classes.add_to_order_button).toggleClass("orderable-button--hover","mouseenter"===e.type)},click_add_to_order(e,t){const r=(t=void 0!==t?t:d(this)).is("button")?t:t.find("."+c.vars.classes.add_to_order_button),a=r.data("orderable-trigger"),o=r.data("orderable-product-id"),s=r.data("orderable-variation-id"),n=r.data("orderable-variation-attributes"),i={action:a};if(!r.hasClass(c.vars.classes.button_loading)&&!r.hasClass(c.vars.classes.out_of_stock))switch(r.addClass(c.vars.classes.button_loading),a){case"add-to-cart":c.add_to_cart({product_id:o,variation_id:s,attributes:n,thisbutton:t},function(e){i.show_cart=!0,i.response=e,d(l.body).trigger("orderable-drawer.open",i),r.removeClass(c.vars.classes.button_loading);e=d(".orderable-product .orderable-product__actions-button button.orderable-product__add-to-order[data-orderable-product-id="+o+"]");e.siblings(".orderable-quantity-roller").length&&e.addClass("orderable-button--product-in-the-cart")});break;case"add-to-cart-without-side-drawer":c.add_to_cart({product_id:o,variation_id:s,attributes:n},function(e){i.response=e,r.addClass("orderable-button--product-in-the-cart"),r.removeClass(c.vars.classes.button_loading)});break;case"product-options":c.get_product_options({product_id:o,focus:r.data("orderable-focus")},function(e){i.html=e.html,d(l.body).trigger("orderable-drawer.open",i),r.removeClass(c.vars.classes.button_loading)})}},show_cart(){d(l.body).trigger("orderable-drawer.open",{show_cart:!0})},view_product(e,t){const r=t.data("orderable-product-id"),a={action:"product-options"};c.get_product_options({product_id:r,focus:t.data("orderable-focus")},function(e){a.html=e.html,d(l.body).trigger("orderable-drawer.open",a)})},add_to_cart(t,r){if(void 0!==t.product_id){let e={action:"orderable_add_to_cart",product_id:t.product_id,variation_id:t.variation_id||!1,attributes:t.attributes||!1};var a;d(".orderable-product-fields-group").length&&(a=jQuery(".orderable-product-fields-group :input").serializeArray(),a=c.add_unchecked_checkbox_fields(a),a=c.convert_to_flat_object(a),jQuery.isEmptyObject(a)||(e=Object.assign(e,a))),jQuery.post(orderable_vars.ajax_url,e,function(e){e&&(d(l.body).trigger("added_to_cart",[e.fragments,e.cart_hash,t.thisbutton]),"function"==typeof r)&&r(e)})}},edit_cart_item(e,t){var r=t.data("orderable-cart-item-key");t.addClass(c.vars.classes.button_loading),c.get_cart_item_options({cart_item_key:r},function(e){e={html:e.html,action:"update-cart-item"};d(l.body).trigger("orderable-drawer.open",e),t.removeClass(c.vars.classes.button_loading)})},update_cart_item(e,r){var t=r.data("orderable-cart-item-key"),a=r.data("orderable-product-id"),o=r.data("orderable-variation-id"),s=r.data("orderable-variation-attributes");r.addClass(c.vars.classes.button_loading),c.update_cart_item_options({cart_item_key:t,product_id:a,variation_id:o,attributes:s},function(e){var t={show_cart:!0,response:e};d(l.body).trigger("added_to_cart",[e.fragments,e.cart_hash]),d(l.body).trigger("orderable-drawer.open",t),r.removeClass(c.vars.classes.button_loading)})},convert_to_flat_object(e){const a={};return e.forEach(function(e){var t="[]"===e.name.substr(-2)||Array.isArray(e.name),r=t?e.name.substr(0,e.name.length-2):e.name;t?(a[r]=void 0===a[r]?[]:a[r],a[r].push(e.value)):a[r]=e.value}),a},get_product_options(e,t){void 0!==e.product_id&&(e.action="orderable_get_product_options",jQuery.post(orderable_vars.ajax_url,e,function(e){e.success&&"function"==typeof t&&t(e.data)}))},get_cart_item_options(e,t){void 0!==e.cart_item_key&&(e.action="orderable_get_cart_item_options",jQuery.post(orderable_vars.ajax_url,e,function(e){e.success&&"function"==typeof t&&t(e.data)}))},update_cart_item_options(e,t){var r;void 0!==e.cart_item_key&&(e.action="orderable_update_cart_item_options",d(".orderable-product-fields-group").length&&(r=jQuery(".orderable-product-fields-group :input").serializeArray(),r=c.add_unchecked_checkbox_fields(r),r=c.convert_to_flat_object(r),jQuery.isEmptyObject(r)||(e=Object.assign(e,r))),jQuery.post(orderable_vars.ajax_url,e,function(e){e&&"function"==typeof t&&t(e)}))},init_product_options(e,t){if(void 0!==t.action&&("product-options"===t.action||"update-cart-item"===t.action)){t=".orderable-drawer .orderable-product__options input, .orderable-drawer .orderable-product__options select, .orderable-product__options textarea";const r=d(t),a=(c.vars.parent_price=d(".orderable-drawer .orderable-product__actions-price").html(),c.product_options_change(r),c.update_button_state(),c.debounce(c.update_button_state,500)),o=c.debounce(c.product_options_change,500);d(l).on("change keyup",t,function(){o(r),a()})}},product_options_change(e){var t=d(".orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item"),r=c.check_options(e),a=t.data("orderable-product-type");"product-options"===t.attr("data-orderable-trigger")&&t.attr("data-orderable-trigger","add-to-cart"),d("."+c.vars.classes.product_messages).html(""),c.vars.variable_product_types.includes(a)&&(r?(a=c.check_variation(e),c.set_variation(t,a)):c.clear_variation(t))},check_options(e){if(e.length<=0)return!1;let r=!0;return e.each(function(e,t){d(t).hasClass("orderable-input--validate")&&(""===d(t).val()?(d(t).addClass(c.vars.classes.invalid_field),r=!1):d(t).removeClass(c.vars.classes.invalid_field))}),r},check_variation(e){var t=(t=e.closest(".orderable-drawer").find(".orderable-product__variations").text())?JSON.parse(t):"",e=c.serialize_object(e),t=c.find_matching_variations(t,e);return!c.is_empty(t)&&((t=t.shift()).attributes=e,t.attributes_json=JSON.stringify(e),void 0!==t)&&t},set_variation(e,t){let r=t.variation_id||"",a=t.attributes_json||"",o=t.price_html||c.vars.parent_price,s="";t&&""!==t.availability_html&&(s=t.availability_html),t&&!t.is_in_stock&&(s="<p>"+orderable_vars.i18n.out_of_stock+"</p>"),t&&!t.is_purchasable&&(s="<p>"+orderable_vars.i18n.unavailable+"</p>"),!1===t&&(s="<p>"+orderable_vars.i18n.no_exist+"</p>"),!t||t.is_purchasable&&t.is_in_stock||(r="",a=""),""!==s&&d("."+c.vars.classes.product_messages).html(s),e.data("orderable-variation-id",r),e.data("orderable-variation-attributes",a),d(".orderable-drawer .orderable-product__actions-price").html(o),e.trigger("orderable_variation_set",{variation:t,variation_id:r,attributes:a,price:o})},clear_variation(e){c.set_variation(e,""),c.vars.parent_price&&d(".orderable-drawer .orderable-product__actions-price").html(c.vars.parent_price)},find_matching_variations(t,r){var a=[];for(let e=0;e<t.length;e++){var o=t[e];c.is_matching_variation(o.attributes,r)&&a.push(o)}return a},is_matching_variation(e,t){let r=!0;for(const s in e){var a,o;e.hasOwnProperty(s)&&(a=e[s],o=t[s],void 0!==a)&&void 0!==o&&0!==a.length&&0!==o.length&&a!==o&&(r=!1)}return r},is_empty(e){return void 0===e||!1===e||e.length<=0||!e},serialize_object:function(e){var t=e.serializeArray(),r={};for(let e=0;e<t.length;e++)r[t[e].name]=t[e].value;return r},update_button_state(){setTimeout(function(){let e=d(".orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item"),t=d(".orderable-drawer__html ."+c.vars.classes.invalid_field).length,r=e.data("orderable-product-type"),a=!0;"variable"===r&&(a=""!==e.data("orderable-variation-id")),e.prop("disabled",t||!a)},50)},debounce(a,o,s){let n;return function(){const e=this,t=arguments;var r=s&&!n;clearTimeout(n),n=setTimeout(function(){n=null,s||a.apply(e,t)},o),r&&a.apply(e,t)}},remove_fragments(e,t){if(t&&"undefined"!=typeof wc_cart_fragments_params&&wc_cart_fragments_params.fragment_name){var r=/\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-quantity-roller/,a=/\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-product__actions-counter/;for(const o in t)(r.test(o)||a.test(o))&&(t[o]=void 0);sessionStorage.setItem(wc_cart_fragments_params.fragment_name,JSON.stringify(t))}},remove_animation(){setTimeout(function(){d(".orderable-product__actions-counter").css("animation","")},1e3)},hide_quantity_roller(e,t,r,a){var o,a=a.attr("data-product_id")||a.attr("data-orderable-product-id");a&&(a=d(".orderable-product[data-orderable-product-id="+a+"] .orderable-product__actions-button")).length&&(o=a.find(".orderable-quantity-roller")).length&&(a.find("button.orderable-product__add-to-order[data-orderable-trigger]").removeClass("orderable-button--product-in-the-cart"),o.addClass("orderable-button--hide"))},add_unchecked_checkbox_fields(r){return jQuery('.orderable-product-fields-group :input[type="checkbox"]:not(:checked)').each(function(e,t){r.push({name:t.getAttribute("name"),value:""})}),r},shake_floating_cart(){d(".orderable-floating-cart__button").css("animation","wobble-hor-bottom .8s both")},remove_view_cart_link(e,t){t?.hasClass("orderable-product__add-to-order")&&t?.siblings(".added_to_cart.wc-forward").remove()}};d(l).ready(c.on_ready)}(jQuery,document),function(o,s){"use strict";var n={on_ready(){n.cache(),n.watch()},cache(){n.vars={top:{}},n.elements={}},watch(){o(s.body).on("orderable-drawer.opened",n.trigger),o(s.body).on("orderable-tabs.changed",n.trigger),o(s.body).on("orderable-accordion.toggled",n.trigger),o(s.body).on("wc_fragments_loaded",n.trigger)},trigger(){o(".orderable-sb-container").each(function(e,t){var r,t=o(t),a=t.data("orderable-scroll-id");n.has_scrollbar(t)||(t.scrollBox({containerClass:"orderable-sb-container",containerNoScrollClass:"orderable-sb-container-noscroll",contentClass:"orderable-sb-content",scrollbarContainerClass:"orderable-sb-scrollbar-container",scrollBarClass:"orderable-sb-scrollbar"}),0<(r=t.find(".orderable-sb-content")).length&&(r.on("scroll.scrollBox",n.log_top_position),void 0!==n.vars.top[a])&&r.scrollTop(n.vars.top[a]),o(s.body).trigger("orderable-scrollbar.created",{element:t,content:r}))}),o(window).trigger("resize.scrollBox")},has_scrollbar(e){return 0<e.find(".orderable-sb-content").length},log_top_position(e){var t=o(e.currentTarget).closest(".orderable-sb-container").data("orderable-scroll-id");n.vars.top[t]=o(e.currentTarget).scrollTop()}};o(s).ready(n.on_ready)}(jQuery,document),function(n,i){"use strict";var d={on_ready(){d.cache(),d.watch(),d.toggle_scroll()},on_resize(){d.toggle_scroll()},cache(){d.vars={classes:{tabs:"orderable-tabs",tabs_list:"orderable-tabs__list",tab_items:"orderable-tabs__item",tab_item_active:"orderable-tabs__item--active",tab_links:"orderable-tabs__link",tab_arrow_right:"orderable-tabs__arrow-right",tab_arrow_left:"orderable-tabs__arrow-left"},dragging:!1},d.elements={}},watch(){n("body").on("touchstart",function(){d.vars.dragging=!1}).on("touchmove",function(){d.vars.dragging=!0}),n(i.body).on("click mouseup touchend","."+d.vars.classes.tab_links,function(e){var t,r,a,o,s;d.vars.dragging||(e.preventDefault(),t=(e=n(this)).attr("href"),r=e.closest("."+d.vars.classes.tab_items),a=(s=e.closest("."+d.vars.classes.tabs)).find("."+d.vars.classes.tabs_list),o=s.find("."+d.vars.classes.tab_items),s=s.data("orderable-tabs"),s=(e=e.closest(s.wrapper)).find(s.sections),e=e.find(t),s.hide(),e.show(),o.removeClass(d.vars.classes.tab_item_active),r.addClass(d.vars.classes.tab_item_active),a.animate({scrollLeft:a.scrollLeft()+r.position().left}),n(i.body).trigger("orderable-tabs.changed",{tab:r}))}),n("."+d.vars.classes.tabs_list).on("scroll",function(e){var t=n(this),r=t.parent("."+d.vars.classes.tabs),a=t.siblings("."+d.vars.classes.tab_arrow_right),o=t.siblings("."+d.vars.classes.tab_arrow_left);t[0].scrollWidth<=r.width()+t.scrollLeft()?a.fadeOut():a.fadeIn(),t.scrollLeft()-o.width()<=0?o.fadeOut():o.fadeIn()}),n("."+d.vars.classes.tabs_list).on("wheel DOMMouseScroll mousewheel touchmove",function(){n(this).stop()}),n(i).on("click","."+d.vars.classes.tab_arrow_right,function(e){e.preventDefault();var e=n(this).parent(),t=e.find("."+d.vars.classes.tabs_list);t.animate({scrollLeft:t.scrollLeft()+.5*e.width()})}),n(i).on("click","."+d.vars.classes.tab_arrow_left,function(e){e.preventDefault();var e=n(this).parent(),t=e.find("."+d.vars.classes.tabs_list);t.animate({scrollLeft:t.scrollLeft()-.5*e.width()})})},toggle_scroll(){n("."+d.vars.classes.tabs).each(function(e,t){var r=n(this),a=r.data("orderable-tabs"),r=r.closest(a.wrapper),a=r.find("."+d.vars.classes.tabs_list),o=r.find("."+d.vars.classes.tab_arrow_right);r.outerWidth()<a[0].scrollWidth?o.show():o.hide()})}};n(i).ready(d.on_ready),n(window).on("resize",d.on_resize)}(jQuery,document);let orderable_timings={};!function(l,e){"use strict";orderable_timings={on_ready(){orderable_timings.watch()},restore(){var e,t=orderable_timings.get_timings();t&&t.date&&(0<(e=l(".orderable-order-timings__date")).find('option[value="'+t.date+'"]').length&&(e.val(t.date),e.change()),t.time)&&0<(e=l(".orderable-order-timings__time")).find('option[value="'+t.time+'"]').length&&(e.val(t.time),e.change())},watch(){l(e.body).on("wc_fragments_refreshed",function(){orderable_timings.restore()}),l(e.body).on("updated_checkout",function(){orderable_timings.restore()}),l(e.body).on("change",".orderable-order-timings__date",function(e){const t=l(this),r=t.find("option:selected"),a=r.data("orderable-slots"),o=l(".orderable-order-timings--time"),s=l(".orderable-order-timings__time"),n=s.find("option").first(),i=s.find('option[value="asap"]').first();var d=orderable_timings.get_timings();d.date=l(".orderable-order-timings__date").val(),window.localStorage.setItem("orderable_timings",JSON.stringify(d)),s.html(n),i&&s.append(i),a?"all-day"===a[0].value?(o.hide(),s.prop("disabled",!0)):(s.prop("disabled",!1),o.show(),l.each(a,function(e,t){s.append(l("<option />").attr("value",t.value).attr("data-orderable-time-slot-id",t?.setting_row?.time_slot_id).text(t.formatted))})):(s.prop("disabled",!0),o.hide())}),l(e.body).on("change",".orderable-order-timings__time",function(e){var t=orderable_timings.get_timings();t.time=l(".orderable-order-timings__time").val(),window.localStorage.setItem("orderable_timings",JSON.stringify(t)),l(this).siblings('input[name="orderable_order_time_slot_id"]').val(l(this).find(":selected").attr("data-orderable-time-slot-id"))})},get_timings(){return JSON.parse(window.localStorage.getItem("orderable_timings"))||{}}},l(e).ready(orderable_timings.on_ready)}(jQuery,document),function(a,o){"use strict";var e={on_ready(){e.watch()},watch(){void 0===window.orderable_triggers_admin&&a(o.body).on("click","[data-orderable-trigger]",e.trigger)},trigger(e){e.stopImmediatePropagation();var t=a(this),r=t.data("orderable-trigger");(t.is("button")||t.is("a"))&&e.preventDefault(),a(o.body).trigger("orderable-"+r,[t])}};a(o).ready(e.on_ready)}(jQuery,document);
     1((o,s)=>{var i={on_ready(){i.cache(),i.watch()},cache(){i.vars={classes:{parent:"orderable-accordion",link:"orderable-accordion__item-link",content:"orderable-accordion__item-content",link_active:"orderable-accordion__item-link--active",content_active:"orderable-accordion__item-content--active"}}},watch(){o(s.body).on("click","."+i.vars.classes.link,function(e){e.preventDefault();var e=o(this),t=e.closest("."+i.vars.classes.parent),r=e.attr("href"),r=o(r),a=e.hasClass(i.vars.classes.link_active);t.find("."+i.vars.classes.link).removeClass(i.vars.classes.link_active),t.find("."+i.vars.classes.content).removeClass(i.vars.classes.content_active),a||(e.addClass(i.vars.classes.link_active),r.addClass(i.vars.classes.content_active)),o(s.body).trigger("orderable-accordion.toggled",{link:e,content:r})}),o(s.body).on("orderable-scrollbar.created",function(e,t){var r=o(".orderable-drawer ."+i.vars.classes.link_active);r.length<=0||(r=(t=t.content).scrollTop()-t.offset().top+r.offset().top,t.scrollTop(r))})}};o(s).ready(i.on_ready)})(jQuery,document),((l,c)=>{var r={debounce(t,r=700){let a;return(...e)=>{clearTimeout(a),a=setTimeout(()=>{t.apply(this,e)},r)}},allow_only_numbers(e){var t=String.fromCharCode(e.which);/^\d+$/.test(t)||e.preventDefault()},on_change_quantity(e){let t=l(e.currentTarget);var e=t.data("orderable-product-id"),r=t.data("orderable-cart-item-key"),a=parseInt(t.text());jQuery.post(orderable_vars.ajax_url,{action:"orderable_cart_quantity",cart_item_key:r,product_id:e,quantity:a},function(e){e&&(l(c.body).trigger("added_to_cart",[e.fragments,e.cart_hash,t]),l(c.body).trigger("orderable-drawer.quantity-updated"))})},on_ready(){r.cache(),r.watch(),l(c.body).on("keypress",".orderable-quantity-roller__quantity",r.allow_only_numbers),l(".orderable-drawer__cart, .orderable-product--add-to-cart, .orderable-products-list").on("input",".orderable-quantity-roller__quantity",r.debounce(r.on_change_quantity)),l(c.body).on("click",".orderable-quantity-roller__quantity",function(e){e.stopPropagation()}),orderable_vars&&!orderable_vars.woocommerce_enable_ajax_add_to_cart&&l(c.body).off("click",".add_to_cart_button")},cache(){r.vars={classes:{overlay:"orderable-drawer-overlay",drawer:"orderable-drawer",drawer_cart:"orderable-drawer__cart",drawer_html:"orderable-drawer__html",overlay_open:"orderable-drawer-overlay--open",drawer_open:"orderable-drawer--open",drawer_open_body:"orderable-drawer-open"}},r.elements={body:l("body"),overlay:l("."+r.vars.classes.overlay),drawer:l("."+r.vars.classes.drawer),drawer_cart:l("."+r.vars.classes.drawer_cart),drawer_html:l("."+r.vars.classes.drawer_html),floating_cart_button_class:".orderable-floating-cart__button"}},watch(){var e,t;void 0!==r.elements.drawer&&(l(c.body).on("orderable-drawer.open",r.open),l(c.body).on("orderable-drawer.close",r.close),l(c.body).on("click",r.elements.floating_cart_button_class,function(){l(c.body).trigger("orderable-drawer.open",{show_cart:!0})}),l(c.body).on("orderable-increase-quantity",r.cart.handle_quantity_change_by_button),l(c.body).on("orderable-decrease-quantity",r.cart.handle_quantity_change_by_button),e=r.debounce(r.cart.click_increase_decrease_quantity),l(c.body).on("orderable-increase-quantity",e),l(c.body).on("orderable-decrease-quantity",e),e=c.querySelector("body:not( .rtl ) .orderable-drawer"),t=c.querySelector("body.rtl .orderable-drawer"),e&&e.addEventListener("swiped-right",function(e){r.close()}),t)&&t.addEventListener("swiped-left",function(e){r.close()})},open(e,t){t.html=t.html||!1,t.show_cart=t.show_cart||!1,r.elements.drawer_html.hide(),r.elements.drawer_cart.hide(),t.html&&(r.elements.drawer_html.html(t.html),r.elements.drawer_html.show()),t.show_cart&&(r.elements.drawer_html.html(""),r.elements.drawer_cart.show()),r.elements.overlay.addClass(r.vars.classes.overlay_open),r.elements.drawer.addClass(r.vars.classes.drawer_open),r.elements.body.addClass(r.vars.classes.drawer_open_body),l(c.body).trigger("orderable-drawer.opened",t)},close(){r.elements.overlay.removeClass(r.vars.classes.overlay_open),r.elements.drawer.removeClass(r.vars.classes.drawer_open),r.elements.body.removeClass(r.vars.classes.drawer_open_body),r.elements.drawer_html.html(""),l(c.body).trigger("orderable-drawer.closed")},cart:{click_increase_decrease_quantity(e,r){var t=r.data("orderable-trigger"),a=r.attr("data-orderable-product-id"),o=r.attr("data-orderable-cart-item-key"),s=r.attr("data-orderable-quantity");let i=r.siblings(".orderable-quantity-roller__button--"+("increase-quantity"===t?"decrease":"increase")),n=r.siblings(".orderable-quantity-roller__quantity"),d={action:"orderable_cart_quantity",cart_item_key:o,product_id:a,quantity:s};this.currentRequest&&(this.currentRequest.abort(),this.currentRequest=void 0),r.addClass("orderable-button--loading"),r.attr("disabled",!0),i.attr("disabled",!0),n.attr("contenteditable",!1),this.currentRequest=jQuery.post(orderable_vars.ajax_url,d,function(e){if(e){var t=r.siblings(".orderable-quantity-roller__quantity");switch(e&&e.fragments&&e.fragments[".orderable-mini-cart__notices"]&&l(c.body).trigger("orderable-drawer.open",{show_cart:!0}),d.quantity){case"0":l(c.body).trigger("removed_from_cart",[e.fragments,e.cart_hash,r]);break;case t.attr("data-orderable-updating-quantity"):l(c.body).trigger("added_to_cart",[e.fragments,e.cart_hash,r]),l(c.body).trigger("orderable-drawer.quantity-updated")}}}.bind(this)).always(function(){this.currentRequest=void 0,r.removeClass("orderable-button--loading"),r.attr("disabled",!1),i.attr("disabled",!1),n.attr("contenteditable",!0)}.bind(this))},handle_quantity_change_by_button(e,t){var r,a=t.data("orderable-trigger"),o=parseInt(t.attr("data-orderable-quantity")),s=t.siblings(".orderable-quantity-roller__button--"+("increase-quantity"===a?"decrease":"increase")),i=t.siblings(".orderable-quantity-roller__quantity"),a="increase-quantity"===a?o+1:Math.max(0,o-1),o=t.parents(".orderable-product__actions-button");0===a&&o.length&&(r=o.find("button.orderable-button[data-orderable-trigger]"),(o=o.find(".orderable-quantity-roller")).length)&&(r.removeClass("orderable-button--product-in-the-cart"),o.removeClass("orderable-quantity-roller--is-active")),t.attr("data-orderable-quantity",a),s.attr("data-orderable-quantity",a),i.attr("data-orderable-updating-quantity",a),i.text(a),i.attr("contenteditable",!1)}}};l(c).ready(r.on_ready)})(jQuery,document),((d,l)=>{var c={on_ready(){c.cache(),c.watch()},cache(){c.vars={classes:{clickable_product:"orderable-product--add-to-cart ",add_to_order_button:"orderable-product__add-to-order",product_messages:"orderable-product__messages",product_price:"orderable-product__actions-price",invalid_field:"orderable-field--invalid",option_select_td:"orderable-product__option-select",button_loading:"orderable-button--loading",out_of_stock:"orderable-button--out-of-stock"},parent_price:null,variable_product_types:["variable","variable-subscription"]},c.elements={}},watch(){d(l.body).on("orderable-drawer.opened",c.init_product_options),d(l.body).on("orderable-add-to-cart",c.click_add_to_order),d(l.body).on("orderable-product-options",c.click_add_to_order),d(l.body).on("orderable-view-product",c.view_product),d(l.body).on("mouseenter mouseleave","."+c.vars.classes.clickable_product,c.simulate_add_to_order_hover),d(l.body).on("orderable-edit-cart-item",c.edit_cart_item),d(l.body).on("orderable-update-cart-item",c.update_cart_item),d(l.body).on("orderable-show-cart",c.show_cart),d(l.body).on("orderable-add-to-cart-without-side-drawer",c.click_add_to_order),d(l.body).on("added_to_cart",c.remove_fragments),d(l.body).on("added_to_cart",c.remove_animation),d(l.body).on("added_to_cart",c.shake_floating_cart),d(l.body).on("removed_from_cart",c.hide_quantity_roller),d(l.body).on("wc_cart_button_updated",c.remove_view_cart_link)},simulate_add_to_order_hover(e){d(this).find("."+c.vars.classes.add_to_order_button).toggleClass("orderable-button--hover","mouseenter"===e.type)},click_add_to_order(e,t){let r=(t=void 0!==t?t:d(this)).is("button")?t:t.find("."+c.vars.classes.add_to_order_button),a=r.data("orderable-trigger"),o=r.data("orderable-product-id"),s=r.data("orderable-variation-id"),i=r.data("orderable-variation-attributes"),n={action:a};if(!r.hasClass(c.vars.classes.button_loading)&&!r.hasClass(c.vars.classes.out_of_stock))switch(r.addClass(c.vars.classes.button_loading),a){case"add-to-cart":c.add_to_cart({product_id:o,variation_id:s,attributes:i,thisbutton:t},function(e){n.show_cart=!0,n.response=e,d(l.body).trigger("orderable-drawer.open",n),r.removeClass(c.vars.classes.button_loading);e=d(".orderable-product .orderable-product__actions-button button.orderable-product__add-to-order[data-orderable-product-id="+o+"]");e.siblings(".orderable-quantity-roller").length&&e.addClass("orderable-button--product-in-the-cart")});break;case"add-to-cart-without-side-drawer":c.add_to_cart({product_id:o,variation_id:s,attributes:i},function(e){n.response=e,r.addClass("orderable-button--product-in-the-cart"),r.removeClass(c.vars.classes.button_loading)});break;case"product-options":c.get_product_options({product_id:o,focus:r.data("orderable-focus")},function(e){n.html=e.html,d(l.body).trigger("orderable-drawer.open",n),r.removeClass(c.vars.classes.button_loading)})}},show_cart(){d(l.body).trigger("orderable-drawer.open",{show_cart:!0})},view_product(e,t){let r=t.data("orderable-product-id"),a={action:"product-options"};c.get_product_options({product_id:r,focus:t.data("orderable-focus")},function(e){a.html=e.html,d(l.body).trigger("orderable-drawer.open",a)})},add_to_cart(t,r){if(void 0!==t.product_id){let e={action:"orderable_add_to_cart",product_id:t.product_id,variation_id:t.variation_id||!1,attributes:t.attributes||!1};var a;d(".orderable-product-fields-group").length&&(a=jQuery(".orderable-product-fields-group :input").serializeArray(),a=c.add_unchecked_checkbox_fields(a),a=c.convert_to_flat_object(a),jQuery.isEmptyObject(a)||(e=Object.assign(e,a))),jQuery.post(orderable_vars.ajax_url,e,function(e){e&&(d(l.body).trigger("added_to_cart",[e.fragments,e.cart_hash,t.thisbutton]),"function"==typeof r)&&r(e)})}},edit_cart_item(e,t){var r=t.data("orderable-cart-item-key");t.addClass(c.vars.classes.button_loading),c.get_cart_item_options({cart_item_key:r},function(e){e={html:e.html,action:"update-cart-item"};d(l.body).trigger("orderable-drawer.open",e),t.removeClass(c.vars.classes.button_loading)})},update_cart_item(e,r){var t=r.data("orderable-cart-item-key"),a=r.data("orderable-product-id"),o=r.data("orderable-variation-id"),s=r.data("orderable-variation-attributes");r.addClass(c.vars.classes.button_loading),c.update_cart_item_options({cart_item_key:t,product_id:a,variation_id:o,attributes:s},function(e){var t={show_cart:!0,response:e};d(l.body).trigger("added_to_cart",[e.fragments,e.cart_hash,r]),d(l.body).trigger("orderable-drawer.open",t),r.removeClass(c.vars.classes.button_loading)})},convert_to_flat_object(e){let a={};return e.forEach(function(e){var t="[]"===e.name.substr(-2)||Array.isArray(e.name),r=t?e.name.substr(0,e.name.length-2):e.name;t?(a[r]=void 0===a[r]?[]:a[r],a[r].push(e.value)):a[r]=e.value}),a},get_product_options(e,t){void 0!==e.product_id&&(e.action="orderable_get_product_options",jQuery.post(orderable_vars.ajax_url,e,function(e){e.success&&"function"==typeof t&&t(e.data)}))},get_cart_item_options(e,t){void 0!==e.cart_item_key&&(e.action="orderable_get_cart_item_options",jQuery.post(orderable_vars.ajax_url,e,function(e){e.success&&"function"==typeof t&&t(e.data)}))},update_cart_item_options(e,t){var r;void 0!==e.cart_item_key&&(e.action="orderable_update_cart_item_options",d(".orderable-product-fields-group").length&&(r=jQuery(".orderable-product-fields-group :input").serializeArray(),r=c.add_unchecked_checkbox_fields(r),r=c.convert_to_flat_object(r),jQuery.isEmptyObject(r)||(e=Object.assign(e,r))),jQuery.post(orderable_vars.ajax_url,e,function(e){e&&"function"==typeof t&&t(e)}))},init_product_options(e,a){if(void 0!==a.action&&("product-options"===a.action||"update-cart-item"===a.action)){a=".orderable-drawer .orderable-product__options input, .orderable-drawer .orderable-product__options select, .orderable-product__options textarea";let e=d(a),t=(c.vars.parent_price=d(".orderable-drawer .orderable-product__actions-price").html(),c.product_options_change(e),c.update_button_state(),c.debounce(c.update_button_state,500)),r=c.debounce(c.product_options_change,500);d(l).on("change keyup",a,function(){r(e),t()})}},product_options_change(e){var t=d(".orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item"),r=c.check_options(e),a=t.data("orderable-product-type");"product-options"===t.attr("data-orderable-trigger")&&t.attr("data-orderable-trigger","add-to-cart"),d("."+c.vars.classes.product_messages).html(""),c.vars.variable_product_types.includes(a)&&(r?(a=c.check_variation(e),c.set_variation(t,a)):c.clear_variation(t))},check_options(e){if(e.length<=0)return!1;let r=!0;return e.each(function(e,t){d(t).hasClass("orderable-input--validate")&&(""===d(t).val()?(d(t).addClass(c.vars.classes.invalid_field),r=!1):d(t).removeClass(c.vars.classes.invalid_field))}),r},check_variation(e){var t=(t=e.closest(".orderable-drawer").find(".orderable-product__variations").text())?JSON.parse(t):"",e=c.serialize_object(e),t=c.find_matching_variations(t,e);return!c.is_empty(t)&&((t=t.shift()).attributes=e,t.attributes_json=JSON.stringify(e),void 0!==t)&&t},set_variation(e,t){let r=t.variation_id||"",a=t.attributes_json||"",o=t.price_html||c.vars.parent_price,s="";t&&""!==t.availability_html&&(s=t.availability_html),t&&!t.is_in_stock&&(s="<p>"+orderable_vars.i18n.out_of_stock+"</p>"),t&&!t.is_purchasable&&(s="<p>"+orderable_vars.i18n.unavailable+"</p>"),!1===t&&(s="<p>"+orderable_vars.i18n.no_exist+"</p>"),!t||t.is_purchasable&&t.is_in_stock||(r="",a=""),""!==s&&d("."+c.vars.classes.product_messages).html(s),e.data("orderable-variation-id",r),e.data("orderable-variation-attributes",a),d(".orderable-drawer .orderable-product__actions-price").html(o),e.trigger("orderable_variation_set",{variation:t,variation_id:r,attributes:a,price:o})},clear_variation(e){c.set_variation(e,""),c.vars.parent_price&&d(".orderable-drawer .orderable-product__actions-price").html(c.vars.parent_price)},find_matching_variations(t,r){var a=[];for(let e=0;e<t.length;e++){var o=t[e];c.is_matching_variation(o.attributes,r)&&a.push(o)}return a},is_matching_variation(e,t){let r=!0;for(var a in e){var o;e.hasOwnProperty(a)&&(o=e[a],a=t[a],void 0!==o)&&void 0!==a&&0!==o.length&&0!==a.length&&o!==a&&(r=!1)}return r},is_empty(e){return void 0===e||!1===e||e.length<=0||!e},serialize_object:function(e){var t=e.serializeArray(),r={};for(let e=0;e<t.length;e++)r[t[e].name]=t[e].value;return r},update_button_state(){setTimeout(function(){let e=d(".orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item"),t=d(".orderable-drawer__html ."+c.vars.classes.invalid_field).length,r=e.data("orderable-product-type"),a=!0;"variable"===r&&(a=""!==e.data("orderable-variation-id")),e.prop("disabled",t||!a)},50)},debounce(a,o,s){let i;return function(){let e=this,t=arguments;var r=s&&!i;clearTimeout(i),i=setTimeout(function(){i=null,s||a.apply(e,t)},o),r&&a.apply(e,t)}},remove_fragments(e,t){if(t&&"undefined"!=typeof wc_cart_fragments_params&&wc_cart_fragments_params.fragment_name){var r,a=/\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-quantity-roller/,o=/\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-product__actions-counter/;for(r in t)(a.test(r)||o.test(r))&&(t[r]=void 0);sessionStorage.setItem(wc_cart_fragments_params.fragment_name,JSON.stringify(t))}},remove_animation(){setTimeout(function(){d(".orderable-product__actions-counter").css("animation","")},1e3)},hide_quantity_roller(e,t,r,a){var o,a=a.attr("data-product_id")||a.attr("data-orderable-product-id");a&&(a=d(".orderable-product[data-orderable-product-id="+a+"] .orderable-product__actions-button")).length&&(o=a.find(".orderable-quantity-roller")).length&&(a.find("button.orderable-product__add-to-order[data-orderable-trigger]").removeClass("orderable-button--product-in-the-cart"),o.addClass("orderable-button--hide"))},add_unchecked_checkbox_fields(r){return jQuery('.orderable-product-fields-group :input[type="checkbox"]:not(:checked)').each(function(e,t){r.push({name:t.getAttribute("name"),value:""})}),r},shake_floating_cart(){d(".orderable-floating-cart__button").css("animation","wobble-hor-bottom .8s both")},remove_view_cart_link(e,t){t?.hasClass("orderable-product__add-to-order")&&t?.siblings(".added_to_cart.wc-forward").remove()}};d(l).ready(c.on_ready)})(jQuery,document),((o,s)=>{var i={on_ready(){i.cache(),i.watch()},cache(){i.vars={top:{}},i.elements={}},watch(){o(s.body).on("orderable-drawer.opened",i.trigger),o(s.body).on("orderable-tabs.changed",i.trigger),o(s.body).on("orderable-accordion.toggled",i.trigger),o(s.body).on("wc_fragments_loaded",i.trigger)},trigger(){o(".orderable-sb-container").each(function(e,t){var r,t=o(t),a=t.data("orderable-scroll-id");i.has_scrollbar(t)||(t.scrollBox({containerClass:"orderable-sb-container",containerNoScrollClass:"orderable-sb-container-noscroll",contentClass:"orderable-sb-content",scrollbarContainerClass:"orderable-sb-scrollbar-container",scrollBarClass:"orderable-sb-scrollbar"}),0<(r=t.find(".orderable-sb-content")).length&&(r.on("scroll.scrollBox",i.log_top_position),void 0!==i.vars.top[a])&&r.scrollTop(i.vars.top[a]),o(s.body).trigger("orderable-scrollbar.created",{element:t,content:r}))}),o(window).trigger("resize.scrollBox")},has_scrollbar(e){return 0<e.find(".orderable-sb-content").length},log_top_position(e){var t=o(e.currentTarget).closest(".orderable-sb-container").data("orderable-scroll-id");i.vars.top[t]=o(e.currentTarget).scrollTop()}};o(s).ready(i.on_ready)})(jQuery,document),((i,n)=>{var d={on_ready(){d.cache(),d.watch(),d.toggle_scroll()},on_resize(){void 0===d.vars&&d.cache(),d.toggle_scroll()},cache(){d.vars={classes:{tabs:"orderable-tabs",tabs_list:"orderable-tabs__list",tab_items:"orderable-tabs__item",tab_item_active:"orderable-tabs__item--active",tab_links:"orderable-tabs__link",tab_arrow_right:"orderable-tabs__arrow-right",tab_arrow_left:"orderable-tabs__arrow-left"},dragging:!1},d.elements={}},watch(){i("body").on("touchstart",function(){d.vars.dragging=!1}).on("touchmove",function(){d.vars.dragging=!0}),i(n.body).on("click mouseup touchend","."+d.vars.classes.tab_links,function(e){var t,r,a,o,s;d.vars.dragging||(e.preventDefault(),t=(e=i(this)).attr("href"),r=e.closest("."+d.vars.classes.tab_items),a=(s=e.closest("."+d.vars.classes.tabs)).find("."+d.vars.classes.tabs_list),o=s.find("."+d.vars.classes.tab_items),s=s.data("orderable-tabs"),s=(e=e.closest(s.wrapper)).find(s.sections),e=e.find(t),s.hide(),e.show(),o.removeClass(d.vars.classes.tab_item_active),r.addClass(d.vars.classes.tab_item_active),a.animate({scrollLeft:a.scrollLeft()+r.position().left}),i(n.body).trigger("orderable-tabs.changed",{tab:r}))}),i("."+d.vars.classes.tabs_list).on("scroll",function(e){var t=i(this),r=t.parent("."+d.vars.classes.tabs),a=t.siblings("."+d.vars.classes.tab_arrow_right),o=t.siblings("."+d.vars.classes.tab_arrow_left);t[0].scrollWidth<=r.width()+t.scrollLeft()?a.fadeOut():a.fadeIn(),t.scrollLeft()-o.width()<=0?o.fadeOut():o.fadeIn()}),i("."+d.vars.classes.tabs_list).on("wheel DOMMouseScroll mousewheel touchmove",function(){i(this).stop()}),i(n).on("click","."+d.vars.classes.tab_arrow_right,function(e){e.preventDefault();var e=i(this).parent(),t=e.find("."+d.vars.classes.tabs_list);t.animate({scrollLeft:t.scrollLeft()+.5*e.width()})}),i(n).on("click","."+d.vars.classes.tab_arrow_left,function(e){e.preventDefault();var e=i(this).parent(),t=e.find("."+d.vars.classes.tabs_list);t.animate({scrollLeft:t.scrollLeft()-.5*e.width()})})},toggle_scroll(){i("."+d.vars.classes.tabs).each(function(e,t){var r=i(this),a=r.data("orderable-tabs"),r=r.closest(a.wrapper),a=r.find("."+d.vars.classes.tabs_list),o=r.find("."+d.vars.classes.tab_arrow_right);r.outerWidth()<a[0].scrollWidth?o.show():o.hide()})}};i(n).ready(d.on_ready),i(window).on("resize",d.on_resize)})(jQuery,document);let orderable_timings={};((l,e)=>{orderable_timings={on_ready(){orderable_timings.watch()},restore(){var e,t=orderable_timings.get_timings();t&&t.date&&(0<(e=l(".orderable-order-timings__date")).find('option[value="'+t.date+'"]').length&&(e.val(t.date),e.change()),t.time)&&0<(e=l(".orderable-order-timings__time")).find('option[value="'+t.time+'"]').length&&(e.val(t.time),e.change())},watch(){l(e.body).on("wc_fragments_refreshed",function(){orderable_timings.restore()}),l(e.body).on("updated_checkout",function(){orderable_timings.restore()}),l(e.body).on("change",".orderable-order-timings__date",function(e){let t=l(this),r=t.find("option:selected"),a=r.data("orderable-slots"),o=l(".orderable-order-timings--time"),s=l(".orderable-order-timings__time"),i=s.find("option").first(),n=s.find('option[value="asap"]').first();var d=orderable_timings.get_timings();d.date=l(".orderable-order-timings__date").val(),window.localStorage.setItem("orderable_timings",JSON.stringify(d)),s.html(i),n&&s.append(n),a?"all-day"===a[0].value?(o.hide(),s.prop("disabled",!0)):(s.prop("disabled",!1),o.show(),l.each(a,function(e,t){s.append(l("<option />").attr("value",t.value).attr("data-orderable-time-slot-id",t?.setting_row?.time_slot_id).text(t.formatted))})):(s.prop("disabled",!0),o.hide())}),l(e.body).on("change",".orderable-order-timings__time",function(e){var t=orderable_timings.get_timings();t.time=l(".orderable-order-timings__time").val(),window.localStorage.setItem("orderable_timings",JSON.stringify(t)),l(this).siblings('input[name="orderable_order_time_slot_id"]').val(l(this).find(":selected").attr("data-orderable-time-slot-id"))})},get_timings(){return JSON.parse(window.localStorage.getItem("orderable_timings"))||{}}},l(e).ready(orderable_timings.on_ready)})(jQuery,document),((a,o)=>{var e={on_ready(){e.watch()},watch(){void 0===window.orderable_triggers_admin&&a(o.body).on("click","[data-orderable-trigger]",e.trigger)},trigger(e){e.stopImmediatePropagation();var t=a(this),r=t.data("orderable-trigger");(t.is("button")||t.is("a"))&&e.preventDefault(),a(o.body).trigger("orderable-"+r,[t])}};a(o).ready(e.on_ready)})(jQuery,document),((o,e,s)=>{var i="scrollBox",r={containerClass:"sb-container",containerNoScrollClass:"sb-container-noscroll",contentClass:"sb-content",scrollbarContainerClass:"sb-scrollbar-container",scrollBarClass:"sb-scrollbar"};function t(e,t){this.element=e,this.settings=o.extend({},r,t),this._defaults=r,this._name=i,this.init()}o.extend(t.prototype,{init:function(){this.addScrollbar(),this.addEvents(),this.onResize()},addScrollbar:function(){o(this.element).addClass(this.settings.containerClass),this.wrapper=o("<div class='"+this.settings.contentClass+"' />"),this.wrapper.append(o(this.element).contents()),o(this.element).append(this.wrapper),this.scollbarContainer=o("<div class='"+this.settings.scrollbarContainerClass+"' />"),this.scrollBar=o("<div class='"+this.settings.scrollBarClass+"' />"),this.scollbarContainer.append(this.scrollBar),o(this.element).prepend(this.scollbarContainer)},addEvents:function(){this.wrapper.on("scroll."+i,o.proxy(this.onScroll,this)),o(e).on("resize."+i,o.proxy(this.onResize,this)),this.scrollBar.on("mousedown."+i,o.proxy(this.onMousedown,this)),this.scrollBar.on("touchstart."+i,o.proxy(this.onTouchstart,this))},onTouchstart:function(t){var r=this,a=(t.preventDefault(),r.scrollBar[0].offsetTop);o(s).on("touchmove."+i,function(e){e=e.touches[0].pageY-t.touches[0].pageY;r.scrollBar[0].style.top=Math.min(r.scollbarContainer[0].clientHeight-r.scrollBar[0].clientHeight,Math.max(0,a+e))+"px",r.wrapper[0].scrollTop=r.wrapper[0].scrollHeight*r.scrollBar[0].offsetTop/r.scollbarContainer[0].clientHeight}),o(s).on("touchend."+i,function(){o(s).off("touchmove."+i),o(s).off("touchend."+i)})},onMousedown:function(t){var r=this,a=(t.preventDefault(),r.scrollBar[0].offsetTop);o(s).on("mousemove."+i,function(e){e=e.pageY-t.pageY;r.scrollBar[0].style.top=Math.min(r.scollbarContainer[0].clientHeight-r.scrollBar[0].clientHeight,Math.max(0,a+e))+"px",r.wrapper[0].scrollTop=r.wrapper[0].scrollHeight*r.scrollBar[0].offsetTop/r.scollbarContainer[0].clientHeight}),o(s).on("mouseup."+i,function(){o(s).off("mousemove."+i),o(s).off("mouseup."+i)})},onResize:function(){this.wrapper.css("max-height",o(this.element).height());var e=this.wrapper[0].clientHeight;this.scrollBar.css("height",this.scollbarContainer[0].clientHeight*e/this.wrapper[0].scrollHeight+"px"),this.scollbarContainer[0].clientHeight<=this.scrollBar[0].clientHeight?o(this.element).addClass(this.settings.containerNoScrollClass):o(this.element).removeClass(this.settings.containerNoScrollClass),this.onScroll()},onScroll:function(){this.scrollBar.css("top",Math.min(this.scollbarContainer[0].clientHeight-this.scrollBar[0].clientHeight,this.scollbarContainer[0].clientHeight*this.wrapper[0].scrollTop/this.wrapper[0].scrollHeight)+"px")}}),o.fn[i]=function(e){return this.each(function(){o.data(this,"plugin_"+i)||o.data(this,"plugin_"+i,new t(this,e))})}})(jQuery,window,document),((e,o)=>{"function"!=typeof e.CustomEvent&&(e.CustomEvent=function(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var r=o.createEvent("CustomEvent");return r.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),r},e.CustomEvent.prototype=e.Event.prototype),o.addEventListener("touchstart",function(e){"true"!==e.target.getAttribute("data-swipe-ignore")&&(c=e.target,l=Date.now(),s=e.touches[0].clientX,i=e.touches[0].clientY,d=n=0)},!1),o.addEventListener("touchmove",function(e){var t;s&&i&&(t=e.touches[0].clientX,e=e.touches[0].clientY,n=s-t,d=i-e)},!1),o.addEventListener("touchend",function(e){var t,r,a,o;c===e.target&&(o=parseInt(_(c,"data-swipe-threshold","20"),10),t=parseInt(_(c,"data-swipe-timeout","500"),10),r=Date.now()-l,a="",e=e.changedTouches||e.touches||[],Math.abs(n)>Math.abs(d)?Math.abs(n)>o&&r<t&&(a=0<n?"swiped-left":"swiped-right"):Math.abs(d)>o&&r<t&&(a=0<d?"swiped-up":"swiped-down"),""!==a&&(o={dir:a.replace(/swiped-/,""),touchType:(e[0]||{}).touchType||"direct",xStart:parseInt(s,10),xEnd:parseInt((e[0]||{}).clientX||-1,10),yStart:parseInt(i,10),yEnd:parseInt((e[0]||{}).clientY||-1,10)},c.dispatchEvent(new CustomEvent("swiped",{bubbles:!0,cancelable:!0,detail:o})),c.dispatchEvent(new CustomEvent(a,{bubbles:!0,cancelable:!0,detail:o}))),l=i=s=null)},!1);var s=null,i=null,n=null,d=null,l=null,c=null;function _(e,t,r){for(;e&&e!==o.documentElement;){var a=e.getAttribute(t);if(a)return a;e=e.parentNode}return r}})(window,document);
  • orderable/tags/1.17.1/docs/filters.json

    r3192586 r3237969  
    270270            "type": "filter",
    271271            "doc": {
     272                "description": "",
     273                "long_description": "",
     274                "tags": [],
     275                "long_description_html": ""
     276            },
     277            "args": 2
     278        },
     279        {
     280            "name": "orderable_get_accordion_data",
     281            "file": "inc/class-products.php",
     282            "type": "filter",
     283            "doc": {
     284                "description": "",
     285                "long_description": "",
     286                "tags": [],
     287                "long_description_html": ""
     288            },
     289            "args": 2
     290        },
     291        {
     292            "name": "orderable_get_accordion_data",
     293            "file": "inc/class-products.php",
     294            "type": "filter",
     295            "doc": {
    272296                "description": "Filter product accordion data.",
    273297                "long_description": "",
     
    288312                        ],
    289313                        "variable": "$product"
     314                    },
     315                    {
     316                        "name": "since",
     317                        "content": "1.0.0"
    290318                    }
    291319                ],
  • orderable/tags/1.17.1/languages/orderable.pot

    r3192586 r3237969  
    1 # Copyright (C) 2024 orderable
     1# Copyright (C) 2025 orderable
    22# This file is distributed under the same license as the orderable package.
    33msgid ""
     
    77"Content-Type: text/plain; charset=UTF-8\n"
    88"Content-Transfer-Encoding: 8bit\n"
    9 "POT-Creation-Date: 2024-11-19 18:56+0000\n"
     9"POT-Creation-Date: 2025-02-10 13:33+0000\n"
    1010"X-Poedit-Basepath: ..\n"
    1111"X-Poedit-KeywordsList: __;_e;_ex:1,2c;_n:1,2;_n_noop:1,2;_nx:1,2,4c;_nx_noop:1,2,3c;_x:1,2c;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c\n"
  • orderable/tags/1.17.1/orderable.php

    r3192586 r3237969  
    44 * Author URI: https://orderable.com
    55 * Description: Take local online ordering to a whole new level with Orderable.
    6  * Version: 1.17.0
     6 * Version: 1.17.1
    77 * Author: Orderable
    88 * Text Domain: orderable
    99 * WC requires at least: 5.4.0
    10  * WC tested up to: 9.4
     10 * WC tested up to: 9.6
    1111 */
    1212
     
    2020     * @var string Plugin version.
    2121     */
    22     public static $version = '1.17.0';
     22    public static $version = '1.17.1';
    2323
    2424    /**
  • orderable/tags/1.17.1/readme.txt

    r3192586 r3237969  
    55Tested up to: 6.7
    66Requires PHP: 5.6
    7 Stable tag: 1.17.0
     7Stable tag: 1.17.1
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    186186
    187187== Changelog ==
     188**v1.17.1** (10 Feb 2025)
     189[fix] Compatibility issue with Xstore theme
     190
    188191**v1.17.0** (19 Nov 2024)
    189192[fix] Compatibility with Flux Checkout for WooCommerce plugin
  • orderable/trunk/assets/frontend/js/main.js

    r3192586 r3237969  
    11
     2(function ($, document) {
     3  'use strict';
     4
     5  var orderable_accordion = {
     6    /**
     7     * On doc ready.
     8     */
     9    on_ready() {
     10      orderable_accordion.cache();
     11      orderable_accordion.watch();
     12    },
     13    /**
     14     * Cache.
     15     */
     16    cache() {
     17      orderable_accordion.vars = {
     18        classes: {
     19          parent: 'orderable-accordion',
     20          link: 'orderable-accordion__item-link',
     21          content: 'orderable-accordion__item-content',
     22          link_active: 'orderable-accordion__item-link--active',
     23          content_active: 'orderable-accordion__item-content--active'
     24        }
     25      };
     26    },
     27    /**
     28     * Watch.
     29     */
     30    watch() {
     31      /**
     32       * When click accordion link.
     33       */
     34      $(document.body).on('click', '.' + orderable_accordion.vars.classes.link, function (e) {
     35        e.preventDefault();
     36        const $link = $(this),
     37          $parent = $link.closest('.' + orderable_accordion.vars.classes.parent),
     38          content_id = $link.attr('href'),
     39          $content = $(content_id),
     40          is_active = $link.hasClass(orderable_accordion.vars.classes.link_active);
     41        $parent.find('.' + orderable_accordion.vars.classes.link).removeClass(orderable_accordion.vars.classes.link_active);
     42        $parent.find('.' + orderable_accordion.vars.classes.content).removeClass(orderable_accordion.vars.classes.content_active);
     43        if (!is_active) {
     44          $link.addClass(orderable_accordion.vars.classes.link_active);
     45          $content.addClass(orderable_accordion.vars.classes.content_active);
     46        }
     47        $(document.body).trigger('orderable-accordion.toggled', {
     48          link: $link,
     49          content: $content
     50        });
     51      });
     52
     53      /**
     54       * When drawer is opened.
     55       */
     56      $(document.body).on('orderable-scrollbar.created', function (e, args) {
     57        const $active_accordion = $('.orderable-drawer .' + orderable_accordion.vars.classes.link_active);
     58        if ($active_accordion.length <= 0) {
     59          return;
     60        }
     61        const $scroll_content = args.content,
     62          scroll_position = $scroll_content.scrollTop() - $scroll_content.offset().top + $active_accordion.offset().top;
     63        $scroll_content.scrollTop(scroll_position);
     64      });
     65    }
     66  };
     67  $(document).ready(orderable_accordion.on_ready);
     68})(jQuery, document);
     69(function ($, document) {
     70  'use strict';
     71
     72  var orderable_drawer = {
     73    /**
     74     * Delays invoking function
     75     *
     76     * @param {Function} func    The function to debounce.
     77     * @param {number}   timeout The number of milliseconds to delay.
     78     * @return {Function} Returns the new debounced function.
     79     */
     80    debounce(func, timeout = 700) {
     81      let timer;
     82      return (...args) => {
     83        clearTimeout(timer);
     84        timer = setTimeout(() => {
     85          func.apply(this, args);
     86        }, timeout);
     87      };
     88    },
     89    /**
     90     * Allow only number for events like keypress
     91     *
     92     * @param {Event} event
     93     */
     94    allow_only_numbers(event) {
     95      const value = String.fromCharCode(event.which);
     96      if (!/^\d+$/.test(value)) {
     97        event.preventDefault();
     98      }
     99    },
     100    /**
     101     * Send a request to change the quantity.
     102     *
     103     * @param {Event} event
     104     */
     105    on_change_quantity(event) {
     106      const quantityElement = $(event.currentTarget);
     107      const product_id = quantityElement.data('orderable-product-id');
     108      const cart_item_key = quantityElement.data('orderable-cart-item-key');
     109      const quantity = parseInt(quantityElement.text());
     110      const data = {
     111        action: 'orderable_cart_quantity',
     112        cart_item_key,
     113        product_id,
     114        quantity
     115      };
     116      jQuery.post(orderable_vars.ajax_url, data, function (response) {
     117        if (!response) {
     118          return;
     119        }
     120        $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, quantityElement]);
     121        $(document.body).trigger('orderable-drawer.quantity-updated');
     122      });
     123    },
     124    /**
     125     * On doc ready.
     126     */
     127    on_ready() {
     128      orderable_drawer.cache();
     129      orderable_drawer.watch();
     130
     131      /**
     132       * Handle manually changing the quantity of a product.
     133       */
     134      $(document.body).on('keypress', '.orderable-quantity-roller__quantity', orderable_drawer.allow_only_numbers);
     135      $('.orderable-drawer__cart, .orderable-product--add-to-cart, .orderable-products-list').on('input', '.orderable-quantity-roller__quantity', orderable_drawer.debounce(orderable_drawer.on_change_quantity));
     136      $(document.body).on('click', '.orderable-quantity-roller__quantity', function (event) {
     137        event.stopPropagation();
     138      });
     139
     140      /**
     141       * We turn off the click event for .add_to_cart_button elements
     142       * to keep the AJAX behaviour only on Mini cart when the option
     143       * "Enable AJAX add to cart buttons on archives" is disabled.
     144       */
     145      if (orderable_vars && !orderable_vars.woocommerce_enable_ajax_add_to_cart) {
     146        $(document.body).off('click', '.add_to_cart_button');
     147      }
     148    },
     149    /**
     150     * Cache.
     151     */
     152    cache() {
     153      orderable_drawer.vars = {
     154        classes: {
     155          overlay: 'orderable-drawer-overlay',
     156          drawer: 'orderable-drawer',
     157          drawer_cart: 'orderable-drawer__cart',
     158          drawer_html: 'orderable-drawer__html',
     159          overlay_open: 'orderable-drawer-overlay--open',
     160          drawer_open: 'orderable-drawer--open',
     161          drawer_open_body: 'orderable-drawer-open'
     162        }
     163      };
     164      orderable_drawer.elements = {
     165        body: $('body'),
     166        overlay: $('.' + orderable_drawer.vars.classes.overlay),
     167        drawer: $('.' + orderable_drawer.vars.classes.drawer),
     168        drawer_cart: $('.' + orderable_drawer.vars.classes.drawer_cart),
     169        drawer_html: $('.' + orderable_drawer.vars.classes.drawer_html),
     170        floating_cart_button_class: '.orderable-floating-cart__button'
     171      };
     172    },
     173    /**
     174     * Watch for trigger events.
     175     */
     176    watch() {
     177      if (typeof orderable_drawer.elements.drawer === 'undefined') {
     178        return;
     179      }
     180      $(document.body).on('orderable-drawer.open', orderable_drawer.open);
     181      $(document.body).on('orderable-drawer.close', orderable_drawer.close);
     182      $(document.body).on('click', orderable_drawer.elements.floating_cart_button_class, function () {
     183        $(document.body).trigger('orderable-drawer.open', {
     184          show_cart: true
     185        });
     186      });
     187      $(document.body).on('orderable-increase-quantity', orderable_drawer.cart.handle_quantity_change_by_button);
     188      $(document.body).on('orderable-decrease-quantity', orderable_drawer.cart.handle_quantity_change_by_button);
     189      const updateQuantityRequest = orderable_drawer.debounce(orderable_drawer.cart.click_increase_decrease_quantity);
     190      $(document.body).on('orderable-increase-quantity', updateQuantityRequest);
     191      $(document.body).on('orderable-decrease-quantity', updateQuantityRequest);
     192      const drawer = document.querySelector('body:not( .rtl ) .orderable-drawer');
     193      const drawer_rtl = document.querySelector('body.rtl .orderable-drawer');
     194      if (drawer) {
     195        drawer.addEventListener('swiped-right', function (e) {
     196          orderable_drawer.close();
     197        });
     198      }
     199      if (drawer_rtl) {
     200        drawer_rtl.addEventListener('swiped-left', function (e) {
     201          orderable_drawer.close();
     202        });
     203      }
     204    },
     205    /**
     206     * Open the drawer.
     207     * @param event
     208     * @param args
     209     */
     210    open(event, args) {
     211      args.html = args.html || false;
     212      args.show_cart = args.show_cart || false;
     213      orderable_drawer.elements.drawer_html.hide();
     214      orderable_drawer.elements.drawer_cart.hide();
     215      if (args.html) {
     216        orderable_drawer.elements.drawer_html.html(args.html);
     217        orderable_drawer.elements.drawer_html.show();
     218      }
     219      if (args.show_cart) {
     220        // Empty drawer HTML before showing cart. Prevents options
     221        // interfering with subsequent cart additions.
     222        orderable_drawer.elements.drawer_html.html('');
     223        orderable_drawer.elements.drawer_cart.show();
     224      }
     225      orderable_drawer.elements.overlay.addClass(orderable_drawer.vars.classes.overlay_open);
     226      orderable_drawer.elements.drawer.addClass(orderable_drawer.vars.classes.drawer_open);
     227      orderable_drawer.elements.body.addClass(orderable_drawer.vars.classes.drawer_open_body);
     228      $(document.body).trigger('orderable-drawer.opened', args);
     229    },
     230    /**
     231     * Close the drawer.
     232     */
     233    close() {
     234      orderable_drawer.elements.overlay.removeClass(orderable_drawer.vars.classes.overlay_open);
     235      orderable_drawer.elements.drawer.removeClass(orderable_drawer.vars.classes.drawer_open);
     236      orderable_drawer.elements.body.removeClass(orderable_drawer.vars.classes.drawer_open_body);
     237      orderable_drawer.elements.drawer_html.html('');
     238      $(document.body).trigger('orderable-drawer.closed');
     239    },
     240    /**
     241     * Mini cart related functions.
     242     */
     243    cart: {
     244      /**
     245       * When increase qty is clicked.
     246       *
     247       * @param e
     248       * @param $button
     249       */
     250      click_increase_decrease_quantity(e, $button) {
     251        const direction = $button.data('orderable-trigger');
     252        const product_id = $button.attr('data-orderable-product-id'),
     253          cart_item_key = $button.attr('data-orderable-cart-item-key'),
     254          quantity = $button.attr('data-orderable-quantity');
     255        const siblingButtonName = 'increase-quantity' === direction ? 'decrease' : 'increase';
     256        const $siblingButton = $button.siblings(`.orderable-quantity-roller__button--${siblingButtonName}`);
     257        const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
     258        const data = {
     259          action: 'orderable_cart_quantity',
     260          cart_item_key,
     261          product_id,
     262          quantity
     263        };
     264        if (this.currentRequest) {
     265          this.currentRequest.abort();
     266          this.currentRequest = undefined;
     267        }
     268        $button.addClass('orderable-button--loading');
     269        $button.attr('disabled', true);
     270        $siblingButton.attr('disabled', true);
     271        $quantityElement.attr('contenteditable', false);
     272        this.currentRequest = jQuery.post(orderable_vars.ajax_url, data, function (response) {
     273          if (!response) {
     274            return;
     275          }
     276          const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
     277          if (response && response.fragments && response.fragments['.orderable-mini-cart__notices']) {
     278            $(document.body).trigger('orderable-drawer.open', {
     279              show_cart: true
     280            });
     281          }
     282          switch (data.quantity) {
     283            case '0':
     284              $(document.body).trigger('removed_from_cart', [response.fragments, response.cart_hash, $button]);
     285              break;
     286            case $quantityElement.attr('data-orderable-updating-quantity'):
     287              $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, $button]);
     288              $(document.body).trigger('orderable-drawer.quantity-updated');
     289              break;
     290            default:
     291              break;
     292          }
     293        }.bind(this)).always(function () {
     294          this.currentRequest = undefined;
     295          $button.removeClass('orderable-button--loading');
     296          $button.attr('disabled', false);
     297          $siblingButton.attr('disabled', false);
     298          $quantityElement.attr('contenteditable', true);
     299        }.bind(this));
     300      },
     301      handle_quantity_change_by_button(e, $button) {
     302        const direction = $button.data('orderable-trigger');
     303        const quantity = parseInt($button.attr('data-orderable-quantity'));
     304        const siblingButtonName = 'increase-quantity' === direction ? 'decrease' : 'increase';
     305        const $siblingButton = $button.siblings(`.orderable-quantity-roller__button--${siblingButtonName}`);
     306        const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
     307        const newQuantity = 'increase-quantity' === direction ? quantity + 1 : Math.max(0, quantity - 1);
     308        const $parent = $button.parents('.orderable-product__actions-button');
     309        if (0 === newQuantity && $parent.length) {
     310          const $addToCartButton = $parent.find('button.orderable-button[data-orderable-trigger]');
     311          const $quantityRoller = $parent.find('.orderable-quantity-roller');
     312          if ($quantityRoller.length) {
     313            $addToCartButton.removeClass('orderable-button--product-in-the-cart');
     314            $quantityRoller.removeClass('orderable-quantity-roller--is-active');
     315          }
     316        }
     317        $button.attr('data-orderable-quantity', newQuantity);
     318        $siblingButton.attr('data-orderable-quantity', newQuantity);
     319        $quantityElement.attr('data-orderable-updating-quantity', newQuantity);
     320        $quantityElement.text(newQuantity);
     321        $quantityElement.attr('contenteditable', false);
     322      }
     323    }
     324  };
     325  $(document).ready(orderable_drawer.on_ready);
     326})(jQuery, document);
     327(function ($, document) {
     328  'use strict';
     329
     330  var orderable_products = {
     331    /**
     332     * On doc ready.
     333     */
     334    on_ready() {
     335      orderable_products.cache();
     336      orderable_products.watch();
     337    },
     338    /**
     339     * Cache.
     340     */
     341    cache() {
     342      orderable_products.vars = {
     343        classes: {
     344          clickable_product: 'orderable-product--add-to-cart ',
     345          add_to_order_button: 'orderable-product__add-to-order',
     346          product_messages: 'orderable-product__messages',
     347          product_price: 'orderable-product__actions-price',
     348          invalid_field: 'orderable-field--invalid',
     349          option_select_td: 'orderable-product__option-select',
     350          button_loading: 'orderable-button--loading',
     351          out_of_stock: 'orderable-button--out-of-stock'
     352        },
     353        parent_price: null,
     354        variable_product_types: ['variable', 'variable-subscription']
     355      };
     356      orderable_products.elements = {};
     357    },
     358    /**
     359     * Watch for trigger events.
     360     */
     361    watch() {
     362      $(document.body).on('orderable-drawer.opened', orderable_products.init_product_options);
     363      $(document.body).on('orderable-add-to-cart', orderable_products.click_add_to_order);
     364      $(document.body).on('orderable-product-options', orderable_products.click_add_to_order);
     365      $(document.body).on('orderable-view-product', orderable_products.view_product);
     366      $(document.body).on('mouseenter mouseleave', '.' + orderable_products.vars.classes.clickable_product, orderable_products.simulate_add_to_order_hover);
     367      $(document.body).on('orderable-edit-cart-item', orderable_products.edit_cart_item);
     368      $(document.body).on('orderable-update-cart-item', orderable_products.update_cart_item);
     369      $(document.body).on('orderable-show-cart', orderable_products.show_cart);
     370      $(document.body).on('orderable-add-to-cart-without-side-drawer', orderable_products.click_add_to_order);
     371      $(document.body).on('added_to_cart', orderable_products.remove_fragments);
     372      $(document.body).on('added_to_cart', orderable_products.remove_animation);
     373      $(document.body).on('added_to_cart', orderable_products.shake_floating_cart);
     374      $(document.body).on('removed_from_cart', orderable_products.hide_quantity_roller);
     375      $(document.body).on('wc_cart_button_updated', orderable_products.remove_view_cart_link);
     376    },
     377    /**
     378     * Simulate hover on add to order button.
     379     *
     380     * @param event
     381     */
     382    simulate_add_to_order_hover(event) {
     383      const $element = $(this),
     384        $button = $element.find('.' + orderable_products.vars.classes.add_to_order_button);
     385      $button.toggleClass('orderable-button--hover', 'mouseenter' === event.type);
     386    },
     387    /**
     388     * Add to order click event.
     389     *
     390     * This event accounts for button clicks or card clicks.
     391     * @param event
     392     * @param $element
     393     */
     394    click_add_to_order(event, $element) {
     395      // If undefined, it means it was triggered by a click
     396      // event and not the `orderable-add-to-cart` trigger.
     397      $element = typeof $element !== 'undefined' ? $element : $(this);
     398
     399      // The button is either the clicked element, or the
     400      // add to order button within the clicked element.
     401      const $button = $element.is('button') ? $element : $element.find('.' + orderable_products.vars.classes.add_to_order_button),
     402        action = $button.data('orderable-trigger'),
     403        product_id = $button.data('orderable-product-id'),
     404        variation_id = $button.data('orderable-variation-id'),
     405        attributes = $button.data('orderable-variation-attributes'),
     406        args = {
     407          action
     408        };
     409      if ($button.hasClass(orderable_products.vars.classes.button_loading) || $button.hasClass(orderable_products.vars.classes.out_of_stock)) {
     410        return;
     411      }
     412      $button.addClass(orderable_products.vars.classes.button_loading);
     413      switch (action) {
     414        case 'add-to-cart':
     415          orderable_products.add_to_cart({
     416            product_id,
     417            variation_id,
     418            attributes,
     419            thisbutton: $element
     420          }, function (response) {
     421            args.show_cart = true;
     422            args.response = response;
     423            $(document.body).trigger('orderable-drawer.open', args);
     424            $button.removeClass(orderable_products.vars.classes.button_loading);
     425            const $addToCartButtonOutsideDrawer = $('.orderable-product .orderable-product__actions-button button.orderable-product__add-to-order[data-orderable-product-id=' + product_id + ']');
     426            if ($addToCartButtonOutsideDrawer.siblings('.orderable-quantity-roller').length) {
     427              $addToCartButtonOutsideDrawer.addClass('orderable-button--product-in-the-cart');
     428            }
     429          });
     430          break;
     431        case 'add-to-cart-without-side-drawer':
     432          orderable_products.add_to_cart({
     433            product_id,
     434            variation_id,
     435            attributes
     436          }, function (response) {
     437            args.response = response;
     438            $button.addClass('orderable-button--product-in-the-cart');
     439            $button.removeClass(orderable_products.vars.classes.button_loading);
     440          });
     441          break;
     442        case 'product-options':
     443          orderable_products.get_product_options({
     444            product_id,
     445            focus: $button.data('orderable-focus')
     446          }, function (response) {
     447            args.html = response.html;
     448            $(document.body).trigger('orderable-drawer.open', args);
     449            $button.removeClass(orderable_products.vars.classes.button_loading);
     450          });
     451          break;
     452        default:
     453          break;
     454      }
     455    },
     456    /**
     457     * Show the cart.
     458     */
     459    show_cart() {
     460      $(document.body).trigger('orderable-drawer.open', {
     461        show_cart: true
     462      });
     463    },
     464    /**
     465     * View product.
     466     *
     467     * @param event
     468     * @param $element
     469     */
     470    view_product(event, $element) {
     471      const product_id = $element.data('orderable-product-id'),
     472        args = {
     473          action: 'product-options'
     474        };
     475      orderable_products.get_product_options({
     476        product_id,
     477        focus: $element.data('orderable-focus')
     478      }, function (response) {
     479        args.html = response.html;
     480        $(document.body).trigger('orderable-drawer.open', args);
     481      });
     482    },
     483    /**
     484     * Ajax add to cart.
     485     * @param args
     486     * @param callback
     487     */
     488    add_to_cart(args, callback) {
     489      if (typeof args.product_id === 'undefined') {
     490        return;
     491      }
     492      let data = {
     493        action: 'orderable_add_to_cart',
     494        product_id: args.product_id,
     495        variation_id: args.variation_id || false,
     496        attributes: args.attributes || false
     497      };
     498
     499      // Prepare addons data.
     500      if ($('.orderable-product-fields-group').length) {
     501        let inputs = jQuery('.orderable-product-fields-group :input').serializeArray();
     502        inputs = orderable_products.add_unchecked_checkbox_fields(inputs);
     503        const addons_data = orderable_products.convert_to_flat_object(inputs);
     504        if (!jQuery.isEmptyObject(addons_data)) {
     505          data = Object.assign(data, addons_data); // Merge objects.
     506        }
     507      }
     508      jQuery.post(orderable_vars.ajax_url, data, function (response) {
     509        if (!response) {
     510          return;
     511        }
     512
     513        // Trigger event so themes can refresh other areas.
     514        $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, args.thisbutton]);
     515        if (typeof callback === 'function') {
     516          callback(response);
     517        }
     518      });
     519    },
     520    /**
     521     * Edit cart item.
     522     *
     523     * @param event
     524     * @param $element
     525     */
     526    edit_cart_item(event, $element) {
     527      const cart_item_key = $element.data('orderable-cart-item-key');
     528      $element.addClass(orderable_products.vars.classes.button_loading);
     529      orderable_products.get_cart_item_options({
     530        cart_item_key
     531      }, function (response) {
     532        const args = {
     533          html: response.html,
     534          action: 'update-cart-item'
     535        };
     536        $(document.body).trigger('orderable-drawer.open', args);
     537        $element.removeClass(orderable_products.vars.classes.button_loading);
     538      });
     539    },
     540    /**
     541     * Update cart item.
     542     *
     543     * @param event
     544     * @param $element
     545     */
     546    update_cart_item(event, $element) {
     547      const cart_item_key = $element.data('orderable-cart-item-key');
     548      const product_id = $element.data('orderable-product-id');
     549      const variation_id = $element.data('orderable-variation-id');
     550      const attributes = $element.data('orderable-variation-attributes');
     551      $element.addClass(orderable_products.vars.classes.button_loading);
     552      orderable_products.update_cart_item_options({
     553        cart_item_key,
     554        product_id,
     555        variation_id,
     556        attributes
     557      }, function (response) {
     558        const args = {
     559          show_cart: true,
     560          response
     561        };
     562        $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, $element]);
     563        $(document.body).trigger('orderable-drawer.open', args);
     564        $element.removeClass(orderable_products.vars.classes.button_loading);
     565      });
     566    },
     567    /**
     568     * Convert [{name:x, value:y }] to {x:y} format.
     569     * @param inputs
     570     */
     571    convert_to_flat_object(inputs) {
     572      const data = {};
     573      inputs.forEach(function (input) {
     574        const is_array = '[]' === input.name.substr(-2) || Array.isArray(input.name);
     575        // If last 2 chars are '[]', remove them.
     576        const key = is_array ? input.name.substr(0, input.name.length - 2) : input.name;
     577        if (is_array) {
     578          data[key] = typeof data[key] === 'undefined' ? [] : data[key];
     579          data[key].push(input.value);
     580        } else {
     581          data[key] = input.value;
     582        }
     583      });
     584      return data;
     585    },
     586    /**
     587     * Get variable product options.
     588     *
     589     * @param args
     590     * @param callback
     591     */
     592    get_product_options(args, callback) {
     593      if (typeof args.product_id === 'undefined') {
     594        return;
     595      }
     596      args.action = 'orderable_get_product_options';
     597      jQuery.post(orderable_vars.ajax_url, args, function (response) {
     598        if (!response.success) {
     599          return;
     600        }
     601        if (typeof callback === 'function') {
     602          callback(response.data);
     603        }
     604      });
     605    },
     606    /**
     607     * Get variable product options.
     608     *
     609     * @param args
     610     * @param callback
     611     */
     612    get_cart_item_options(args, callback) {
     613      if (typeof args.cart_item_key === 'undefined') {
     614        return;
     615      }
     616      args.action = 'orderable_get_cart_item_options';
     617      jQuery.post(orderable_vars.ajax_url, args, function (response) {
     618        if (!response.success) {
     619          return;
     620        }
     621        if (typeof callback === 'function') {
     622          callback(response.data);
     623        }
     624      });
     625    },
     626    /**
     627     * Update variable product options.
     628     *
     629     * @param args
     630     * @param callback
     631     */
     632    update_cart_item_options(args, callback) {
     633      if (typeof args.cart_item_key === 'undefined') {
     634        return;
     635      }
     636      args.action = 'orderable_update_cart_item_options';
     637
     638      // Prepare addons data.
     639      if ($('.orderable-product-fields-group').length) {
     640        let inputs = jQuery('.orderable-product-fields-group :input').serializeArray();
     641        inputs = orderable_products.add_unchecked_checkbox_fields(inputs);
     642        const addons_data = orderable_products.convert_to_flat_object(inputs);
     643        if (!jQuery.isEmptyObject(addons_data)) {
     644          args = Object.assign(args, addons_data); // Merge objects.
     645        }
     646      }
     647      jQuery.post(orderable_vars.ajax_url, args, function (response) {
     648        if (!response) {
     649          return;
     650        }
     651        if (typeof callback === 'function') {
     652          callback(response);
     653        }
     654      });
     655    },
     656    /**
     657     * Init drawer product options.
     658     *
     659     * @param event
     660     * @param args
     661     */
     662    init_product_options(event, args) {
     663      if (typeof args.action === 'undefined' || 'product-options' !== args.action && 'update-cart-item' !== args.action) {
     664        return;
     665      }
     666      const selectors = '.orderable-drawer .orderable-product__options input, .orderable-drawer .orderable-product__options select, .orderable-product__options textarea';
     667      const $options = $(selectors);
     668      orderable_products.vars.parent_price = $('.orderable-drawer .orderable-product__actions-price').html();
     669      orderable_products.product_options_change($options);
     670      orderable_products.update_button_state();
     671      const debounced_update_button_state = orderable_products.debounce(orderable_products.update_button_state, 500);
     672      const debounced_product_options_change = orderable_products.debounce(orderable_products.product_options_change, 500);
     673      $(document).on('change keyup', selectors, function () {
     674        debounced_product_options_change($options);
     675        debounced_update_button_state();
     676      });
     677    },
     678    /**
     679     * On product options change.
     680     *
     681     * @param $options
     682     */
     683    product_options_change($options) {
     684      const $add_to_order_button = $('.orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item'),
     685        options_set = orderable_products.check_options($options),
     686        product_type = $add_to_order_button.data('orderable-product-type');
     687      if ('product-options' === $add_to_order_button.attr('data-orderable-trigger')) {
     688        $add_to_order_button.attr('data-orderable-trigger', 'add-to-cart');
     689      }
     690      $('.' + orderable_products.vars.classes.product_messages).html('');
     691      if (!orderable_products.vars.variable_product_types.includes(product_type)) {
     692        return;
     693      }
     694      if (!options_set) {
     695        orderable_products.clear_variation($add_to_order_button);
     696        return;
     697      }
     698      const variation = orderable_products.check_variation($options);
     699      orderable_products.set_variation($add_to_order_button, variation);
     700    },
     701    /**
     702     * Check if all product options are set.
     703     *
     704     * @param  $options
     705     * @return {boolean}
     706     */
     707    check_options($options) {
     708      if ($options.length <= 0) {
     709        return false;
     710      }
     711      let all_set = true;
     712      $options.each(function (index, option) {
     713        // Only check attribute fields.
     714        if (!$(option).hasClass('orderable-input--validate')) {
     715          return;
     716        }
     717        if ('' === $(option).val()) {
     718          $(option).addClass(orderable_products.vars.classes.invalid_field);
     719          all_set = false;
     720        } else {
     721          $(option).removeClass(orderable_products.vars.classes.invalid_field);
     722        }
     723      });
     724      return all_set;
     725    },
     726    /**
     727     * Check if variation has been selected.
     728     * @param $options
     729     */
     730    check_variation($options) {
     731      const $product = $options.closest('.orderable-drawer');
     732      let variations = $product.find('.orderable-product__variations').text();
     733      variations = variations ? JSON.parse(variations) : '';
     734      const selected_options = orderable_products.serialize_object($options),
     735        matching_variations = orderable_products.find_matching_variations(variations, selected_options);
     736      if (orderable_products.is_empty(matching_variations)) {
     737        return false;
     738      }
     739      const variation = matching_variations.shift();
     740      variation.attributes = selected_options;
     741      variation.attributes_json = JSON.stringify(selected_options);
     742      return typeof variation !== 'undefined' ? variation : false;
     743    },
     744    /**
     745     * Set variation for add to cart button.
     746     * @param $button
     747     * @param variation
     748     */
     749    set_variation($button, variation) {
     750      let variation_id = variation.variation_id || '',
     751        attributes = variation.attributes_json || '',
     752        price = variation.price_html || orderable_products.vars.parent_price,
     753        message = '';
     754      if (variation && '' !== variation.availability_html) {
     755        message = variation.availability_html;
     756      }
     757      if (variation && !variation.is_in_stock) {
     758        message = '<p>' + orderable_vars.i18n.out_of_stock + '</p>';
     759      }
     760      if (variation && !variation.is_purchasable) {
     761        message = '<p>' + orderable_vars.i18n.unavailable + '</p>';
     762      }
     763      if (false === variation) {
     764        message = '<p>' + orderable_vars.i18n.no_exist + '</p>';
     765      }
     766      if (variation && (!variation.is_purchasable || !variation.is_in_stock)) {
     767        variation_id = '';
     768        attributes = '';
     769      }
     770      if ('' !== message) {
     771        $('.' + orderable_products.vars.classes.product_messages).html(message);
     772      }
     773      $button.data('orderable-variation-id', variation_id);
     774      $button.data('orderable-variation-attributes', attributes);
     775      $('.orderable-drawer .orderable-product__actions-price').html(price);
     776      $button.trigger('orderable_variation_set', {
     777        variation,
     778        variation_id,
     779        attributes,
     780        price
     781      });
     782    },
     783    /**
     784     * Clear variation and disable add to order.
     785     *
     786     * @param $button
     787     */
     788    clear_variation($button) {
     789      orderable_products.set_variation($button, '');
     790      if (orderable_products.vars.parent_price) {
     791        $('.orderable-drawer .orderable-product__actions-price').html(orderable_products.vars.parent_price);
     792      }
     793    },
     794    /**
     795     * Find matching variations for attributes.
     796     * @param variations
     797     * @param attributes
     798     */
     799    find_matching_variations(variations, attributes) {
     800      const matching = [];
     801      for (let i = 0; i < variations.length; i++) {
     802        const variation = variations[i];
     803        if (orderable_products.is_matching_variation(variation.attributes, attributes)) {
     804          matching.push(variation);
     805        }
     806      }
     807      return matching;
     808    },
     809    /**
     810     * See if attributes match.
     811     * @param  variation_attributes
     812     * @param  attributes
     813     * @return {boolean}
     814     */
     815    is_matching_variation(variation_attributes, attributes) {
     816      let match = true;
     817      for (const attr_name in variation_attributes) {
     818        if (variation_attributes.hasOwnProperty(attr_name)) {
     819          const val1 = variation_attributes[attr_name];
     820          const val2 = attributes[attr_name];
     821          if (val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2) {
     822            match = false;
     823          }
     824        }
     825      }
     826      return match;
     827    },
     828    /**
     829     * Is value empty?
     830     *
     831     * @param  value
     832     * @return {boolean}
     833     */
     834    is_empty(value) {
     835      return typeof value === 'undefined' || false === value || value.length <= 0 || !value;
     836    },
     837    /**
     838     * Serialize into a key/value object.
     839     *
     840     * @param  $elements
     841     * @return {{}}
     842     */
     843    serialize_object: function objectifyForm($elements) {
     844      const serialized = $elements.serializeArray(),
     845        return_object = {};
     846      for (let i = 0; i < serialized.length; i++) {
     847        return_object[serialized[i].name] = serialized[i].value;
     848      }
     849      return return_object;
     850    },
     851    /**
     852     * Disable/Enable the 'Add to cart' button based on the presence of orderable-field--invalid class.
     853     */
     854    update_button_state() {
     855      // Add delay to ensure invalid class has been assigned to inputs.
     856      setTimeout(function () {
     857        let $button = $('.orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item'),
     858          invalid_fields_count = $('.orderable-drawer__html .' + orderable_products.vars.classes.invalid_field).length,
     859          product_type = $button.data('orderable-product-type'),
     860          has_variation_id = true;
     861        if ('variable' === product_type) {
     862          has_variation_id = '' !== $button.data('orderable-variation-id');
     863        }
     864        $button.prop('disabled', invalid_fields_count || !has_variation_id);
     865      }, 50);
     866    },
     867    /**
     868     * Debounce function.
     869     *
     870     * @param func      Function to debounce.
     871     * @param wait      Time to wait in milliseconds.
     872     * @param immediate Trigger the function on the leading edge, instead of the trailing.
     873     *
     874     * @return
     875     */
     876    debounce(func, wait, immediate) {
     877      let timeout;
     878      return function () {
     879        const context = this,
     880          args = arguments;
     881        const later = function () {
     882          timeout = null;
     883          if (!immediate) {
     884            func.apply(context, args);
     885          }
     886        };
     887        const callNow = immediate && !timeout;
     888        clearTimeout(timeout);
     889        timeout = setTimeout(later, wait);
     890        if (callNow) {
     891          func.apply(context, args);
     892        }
     893      };
     894    },
     895    /**
     896     * Remove the quantity roller fragments
     897     *
     898     * @param {Event}  e
     899     * @param {Object} fragments
     900     * @return void
     901     */
     902    remove_fragments(e, fragments) {
     903      if (!fragments || 'undefined' === typeof wc_cart_fragments_params || !wc_cart_fragments_params.fragment_name) {
     904        return;
     905      }
     906      const regex_quantity_roller = /\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-quantity-roller/;
     907      const regex_product_in_the_cart_counter = /\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-product__actions-counter/;
     908      for (const key in fragments) {
     909        if (!regex_quantity_roller.test(key) && !regex_product_in_the_cart_counter.test(key)) {
     910          continue;
     911        }
     912        fragments[key] = undefined;
     913      }
     914      sessionStorage.setItem(wc_cart_fragments_params.fragment_name, JSON.stringify(fragments));
     915    },
     916    /**
     917     * Remove animation.
     918     */
     919    remove_animation() {
     920      setTimeout(function () {
     921        $('.orderable-product__actions-counter').css('animation', '');
     922      }, 1000);
     923    },
     924    /**
     925     * Hide quantity roller element and show the Add to Cart button.
     926     *
     927     * @param {Event}   e
     928     * @param {Object}  fragments
     929     * @param {string}  cart_hash
     930     * @param {Element} $button
     931     * @return
     932     */
     933    hide_quantity_roller(e, fragments, cart_hash, $button) {
     934      const product_id = $button.attr('data-product_id') || $button.attr('data-orderable-product-id');
     935      if (!product_id) {
     936        return;
     937      }
     938      const $actions_button = $('.orderable-product[data-orderable-product-id=' + product_id + '] .orderable-product__actions-button');
     939      if (!$actions_button.length) {
     940        return;
     941      }
     942      const $quantity_roller = $actions_button.find('.orderable-quantity-roller');
     943      if ($quantity_roller.length) {
     944        $actions_button.find('button.orderable-product__add-to-order[data-orderable-trigger]').removeClass('orderable-button--product-in-the-cart');
     945        $quantity_roller.addClass('orderable-button--hide');
     946      }
     947    },
     948    /**
     949     * Add unchecked checkboxs to the list of inputs
     950     * sent to the request to add/update an item
     951     *
     952     * @param {Object} inputs
     953     * @return {Object}
     954     */
     955    add_unchecked_checkbox_fields(inputs) {
     956      jQuery('.orderable-product-fields-group :input[type="checkbox"]:not(:checked)').each(function (index, element) {
     957        inputs.push({
     958          name: element.getAttribute('name'),
     959          value: ''
     960        });
     961      });
     962      return inputs;
     963    },
     964    /**
     965     * Shake the floating cart button.
     966     *
     967     * @return void
     968     */
     969    shake_floating_cart() {
     970      $('.orderable-floating-cart__button').css('animation', 'wobble-hor-bottom .8s both');
     971    },
     972    /**
     973     * Remove the view cart link.
     974     *
     975     * @param event
     976     * @param $button
     977     */
     978    remove_view_cart_link(event, $button) {
     979      if (!$button?.hasClass('orderable-product__add-to-order')) {
     980        return;
     981      }
     982      $button?.siblings('.added_to_cart.wc-forward').remove();
     983    }
     984  };
     985  $(document).ready(orderable_products.on_ready);
     986})(jQuery, document);
     987(function ($, document) {
     988  'use strict';
     989
     990  var orderable_scrollbar = {
     991    /**
     992     * On doc ready.
     993     */
     994    on_ready() {
     995      orderable_scrollbar.cache();
     996      orderable_scrollbar.watch();
     997    },
     998    /**
     999     * Cache.
     1000     */
     1001    cache() {
     1002      orderable_scrollbar.vars = {
     1003        top: {}
     1004      };
     1005      orderable_scrollbar.elements = {};
     1006    },
     1007    /**
     1008     * Watch.
     1009     */
     1010    watch() {
     1011      $(document.body).on('orderable-drawer.opened', orderable_scrollbar.trigger);
     1012      $(document.body).on('orderable-tabs.changed', orderable_scrollbar.trigger);
     1013      $(document.body).on('orderable-accordion.toggled', orderable_scrollbar.trigger);
     1014      $(document.body).on('wc_fragments_loaded', orderable_scrollbar.trigger);
     1015    },
     1016    /**
     1017     * Init or retrigger scrollbars.
     1018     */
     1019    trigger() {
     1020      $('.orderable-sb-container').each(function (index, element) {
     1021        const $element = $(element),
     1022          scroll_id = $element.data('orderable-scroll-id');
     1023        if (!orderable_scrollbar.has_scrollbar($element)) {
     1024          $element.scrollBox({
     1025            containerClass: 'orderable-sb-container',
     1026            containerNoScrollClass: 'orderable-sb-container-noscroll',
     1027            contentClass: 'orderable-sb-content',
     1028            scrollbarContainerClass: 'orderable-sb-scrollbar-container',
     1029            scrollBarClass: 'orderable-sb-scrollbar'
     1030          });
     1031          const $content = $element.find('.orderable-sb-content');
     1032          if ($content.length > 0) {
     1033            $content.on('scroll.scrollBox', orderable_scrollbar.log_top_position);
     1034
     1035            // Set scroll position.
     1036            if (typeof orderable_scrollbar.vars.top[scroll_id] !== 'undefined') {
     1037              $content.scrollTop(orderable_scrollbar.vars.top[scroll_id]);
     1038            }
     1039          }
     1040          $(document.body).trigger('orderable-scrollbar.created', {
     1041            element: $element,
     1042            content: $content
     1043          });
     1044        }
     1045      });
     1046      $(window).trigger('resize.scrollBox');
     1047    },
     1048    /**
     1049     * Has scrollbar already?
     1050     *
     1051     * @param  $element
     1052     * @return {boolean}
     1053     */
     1054    has_scrollbar($element) {
     1055      return $element.find('.orderable-sb-content').length > 0;
     1056    },
     1057    /**
     1058     * Set scrolltop position.
     1059     *
     1060     * @param e
     1061     */
     1062    log_top_position(e) {
     1063      const $element = $(e.currentTarget),
     1064        $container = $element.closest('.orderable-sb-container'),
     1065        scroll_id = $container.data('orderable-scroll-id');
     1066      orderable_scrollbar.vars.top[scroll_id] = $(e.currentTarget).scrollTop();
     1067    }
     1068  };
     1069  $(document).ready(orderable_scrollbar.on_ready);
     1070})(jQuery, document);
     1071(function ($, document) {
     1072  'use strict';
     1073
     1074  var orderable_tabs = {
     1075    /**
     1076     * On doc ready.
     1077     */
     1078    on_ready() {
     1079      orderable_tabs.cache();
     1080      orderable_tabs.watch();
     1081      orderable_tabs.toggle_scroll();
     1082    },
     1083    /**
     1084     * On resize.
     1085     */
     1086    on_resize() {
     1087      if (typeof orderable_tabs.vars === 'undefined') {
     1088        orderable_tabs.cache();
     1089      }
     1090      orderable_tabs.toggle_scroll();
     1091    },
     1092    /**
     1093     * Cache.
     1094     */
     1095    cache() {
     1096      orderable_tabs.vars = {
     1097        classes: {
     1098          tabs: 'orderable-tabs',
     1099          tabs_list: 'orderable-tabs__list',
     1100          tab_items: 'orderable-tabs__item',
     1101          tab_item_active: 'orderable-tabs__item--active',
     1102          tab_links: 'orderable-tabs__link',
     1103          tab_arrow_right: 'orderable-tabs__arrow-right',
     1104          tab_arrow_left: 'orderable-tabs__arrow-left'
     1105        },
     1106        dragging: false
     1107      };
     1108      orderable_tabs.elements = {};
     1109    },
     1110    /**
     1111     * Watch.
     1112     */
     1113    watch() {
     1114      $('body').on('touchstart', function () {
     1115        orderable_tabs.vars.dragging = false;
     1116      }).on('touchmove', function () {
     1117        orderable_tabs.vars.dragging = true;
     1118      });
     1119      $(document.body).on('click mouseup touchend', '.' + orderable_tabs.vars.classes.tab_links, function (e) {
     1120        if (orderable_tabs.vars.dragging) {
     1121          return;
     1122        }
     1123        e.preventDefault();
     1124        const $link = $(this),
     1125          section_id = $link.attr('href'),
     1126          $tab = $link.closest('.' + orderable_tabs.vars.classes.tab_items),
     1127          $tabs = $link.closest('.' + orderable_tabs.vars.classes.tabs),
     1128          $tabs_list = $tabs.find('.' + orderable_tabs.vars.classes.tabs_list),
     1129          $tab_items = $tabs.find('.' + orderable_tabs.vars.classes.tab_items),
     1130          tabs_args = $tabs.data('orderable-tabs'),
     1131          $wrapper = $link.closest(tabs_args.wrapper),
     1132          $sections = $wrapper.find(tabs_args.sections),
     1133          $section = $wrapper.find(section_id);
     1134        $sections.hide();
     1135        $section.show();
     1136        $tab_items.removeClass(orderable_tabs.vars.classes.tab_item_active);
     1137        $tab.addClass(orderable_tabs.vars.classes.tab_item_active);
     1138        $tabs_list.animate({
     1139          scrollLeft: $tabs_list.scrollLeft() + $tab.position().left
     1140        });
     1141        $(document.body).trigger('orderable-tabs.changed', {
     1142          tab: $tab
     1143        });
     1144      });
     1145
     1146      /**
     1147       * Watch scroll position of tabs.
     1148       */
     1149      $('.' + orderable_tabs.vars.classes.tabs_list).on('scroll', function (e) {
     1150        const $list = $(this),
     1151          $wrapper = $list.parent('.' + orderable_tabs.vars.classes.tabs),
     1152          $arrow_right = $list.siblings('.' + orderable_tabs.vars.classes.tab_arrow_right),
     1153          $arrow_left = $list.siblings('.' + orderable_tabs.vars.classes.tab_arrow_left);
     1154        if ($list[0].scrollWidth <= $wrapper.width() + $list.scrollLeft()) {
     1155          $arrow_right.fadeOut();
     1156        } else {
     1157          $arrow_right.fadeIn();
     1158        }
     1159        if (0 >= $list.scrollLeft() - $arrow_left.width()) {
     1160          $arrow_left.fadeOut();
     1161        } else {
     1162          $arrow_left.fadeIn();
     1163        }
     1164      });
     1165
     1166      /**
     1167       * Stop animated scroll if user manually scrolls.
     1168       */
     1169      $('.' + orderable_tabs.vars.classes.tabs_list).on('wheel DOMMouseScroll mousewheel touchmove', function () {
     1170        $(this).stop();
     1171      });
     1172
     1173      /**
     1174       * Click tab arrow right.
     1175       */
     1176      $(document).on('click', '.' + orderable_tabs.vars.classes.tab_arrow_right, function (e) {
     1177        e.preventDefault();
     1178        const $arrow = $(this),
     1179          $wrapper = $arrow.parent(),
     1180          $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list);
     1181        $list.animate({
     1182          scrollLeft: $list.scrollLeft() + $wrapper.width() * 0.5
     1183        });
     1184      });
     1185
     1186      /**
     1187       * Click tab arrow left.
     1188       */
     1189      $(document).on('click', '.' + orderable_tabs.vars.classes.tab_arrow_left, function (e) {
     1190        e.preventDefault();
     1191        const $arrow = $(this),
     1192          $wrapper = $arrow.parent(),
     1193          $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list);
     1194        $list.animate({
     1195          scrollLeft: $list.scrollLeft() - $wrapper.width() * 0.5
     1196        });
     1197      });
     1198    },
     1199    /**
     1200     * Toggle scroll arrow.
     1201     */
     1202    toggle_scroll() {
     1203      $('.' + orderable_tabs.vars.classes.tabs).each(function (index, wrapper) {
     1204        const $tabs = $(this),
     1205          tabs_args = $tabs.data('orderable-tabs'),
     1206          $wrapper = $tabs.closest(tabs_args.wrapper),
     1207          $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list),
     1208          $arrow_right = $wrapper.find('.' + orderable_tabs.vars.classes.tab_arrow_right),
     1209          wrapper_width = $wrapper.outerWidth(),
     1210          list_width = $list[0].scrollWidth;
     1211        if (list_width > wrapper_width) {
     1212          $arrow_right.show();
     1213        } else {
     1214          $arrow_right.hide();
     1215        }
     1216      });
     1217    }
     1218  };
     1219  $(document).ready(orderable_tabs.on_ready);
     1220  $(window).on('resize', orderable_tabs.on_resize);
     1221})(jQuery, document);
     1222let orderable_timings = {}; // Make this global so pro modules can access it.
     1223
     1224(function ($, document) {
     1225  'use strict';
     1226
     1227  orderable_timings = {
     1228    /**
     1229     * On doc ready.
     1230     */
     1231    on_ready() {
     1232      orderable_timings.watch();
     1233    },
     1234    /**
     1235     * Restore current timings.
     1236     */
     1237    restore() {
     1238      const timings = orderable_timings.get_timings();
     1239      if (!timings || !timings.date) {
     1240        return;
     1241      }
     1242      const dateSelect = $('.orderable-order-timings__date');
     1243      if (dateSelect.find('option[value="' + timings.date + '"]').length > 0) {
     1244        dateSelect.val(timings.date);
     1245        dateSelect.change();
     1246      }
     1247      if (!timings.time) {
     1248        return;
     1249      }
     1250      const timeSelect = $('.orderable-order-timings__time');
     1251      if (timeSelect.find('option[value="' + timings.time + '"]').length > 0) {
     1252        timeSelect.val(timings.time);
     1253        timeSelect.change();
     1254      }
     1255    },
     1256    /**
     1257     * Watch for trigger events.
     1258     */
     1259    watch() {
     1260      $(document.body).on('wc_fragments_refreshed', function () {
     1261        orderable_timings.restore();
     1262      });
     1263      $(document.body).on('updated_checkout', function () {
     1264        orderable_timings.restore();
     1265      });
     1266      $(document.body).on('change', '.orderable-order-timings__date', function (event) {
     1267        const $date_field = $(this),
     1268          $selected = $date_field.find('option:selected'),
     1269          slots = $selected.data('orderable-slots'),
     1270          $time_field_wrap = $('.orderable-order-timings--time'),
     1271          $time_field = $('.orderable-order-timings__time'),
     1272          $first_option = $time_field.find('option').first(),
     1273          $asap_option = $time_field.find('option[value="asap"]').first();
     1274        const timings = orderable_timings.get_timings();
     1275        timings.date = $('.orderable-order-timings__date').val();
     1276        window.localStorage.setItem('orderable_timings', JSON.stringify(timings));
     1277        $time_field.html($first_option);
     1278        if ($asap_option) {
     1279          $time_field.append($asap_option);
     1280        }
     1281        if (!slots) {
     1282          $time_field.prop('disabled', true);
     1283          $time_field_wrap.hide();
     1284          return;
     1285        }
     1286        if ('all-day' === slots[0].value) {
     1287          $time_field_wrap.hide();
     1288          $time_field.prop('disabled', true);
     1289        } else {
     1290          $time_field.prop('disabled', false);
     1291          $time_field_wrap.show();
     1292          $.each(slots, function (index, slot) {
     1293            $time_field.append($('<option />').attr('value', slot.value).attr('data-orderable-time-slot-id', slot?.setting_row?.time_slot_id).text(slot.formatted));
     1294          });
     1295        }
     1296      });
     1297      $(document.body).on('change', '.orderable-order-timings__time', function (event) {
     1298        const timings = orderable_timings.get_timings();
     1299        timings.time = $('.orderable-order-timings__time').val();
     1300        window.localStorage.setItem('orderable_timings', JSON.stringify(timings));
     1301        $(this).siblings('input[name="orderable_order_time_slot_id"]').val($(this).find(':selected').attr('data-orderable-time-slot-id'));
     1302      });
     1303    },
     1304    get_timings() {
     1305      return JSON.parse(window.localStorage.getItem('orderable_timings')) || {};
     1306    }
     1307  };
     1308  $(document).ready(orderable_timings.on_ready);
     1309})(jQuery, document);
     1310(function ($, document) {
     1311  'use strict';
     1312
     1313  var orderable_triggers = {
     1314    /**
     1315     * On doc ready.
     1316     */
     1317    on_ready() {
     1318      orderable_triggers.watch();
     1319    },
     1320    /**
     1321     * Watch for trigger events.
     1322     */
     1323    watch() {
     1324      if ('undefined' !== typeof window.orderable_triggers_admin) {
     1325        return;
     1326      }
     1327      $(document.body).on('click', '[data-orderable-trigger]', orderable_triggers.trigger);
     1328    },
     1329    /**
     1330     * Fire trigger.
     1331     * @param e
     1332     */
     1333    trigger(e) {
     1334      // Prevent even bubbling up.
     1335      e.stopImmediatePropagation();
     1336      const $trigger_element = $(this),
     1337        trigger = $trigger_element.data('orderable-trigger');
     1338      if ($trigger_element.is('button') || $trigger_element.is('a')) {
     1339        e.preventDefault();
     1340      }
     1341      $(document.body).trigger('orderable-' + trigger, [$trigger_element]);
     1342    }
     1343  };
     1344  $(document).ready(orderable_triggers.on_ready);
     1345})(jQuery, document);
    21346/**
    31347 * jQiery scrollBar Plugin
     
    1771521  }
    1781522}(window, document);
    179 (function ($, document) {
    180   'use strict';
    181 
    182   var orderable_accordion = {
    183     /**
    184      * On doc ready.
    185      */
    186     on_ready() {
    187       orderable_accordion.cache();
    188       orderable_accordion.watch();
    189     },
    190     /**
    191      * Cache.
    192      */
    193     cache() {
    194       orderable_accordion.vars = {
    195         classes: {
    196           parent: 'orderable-accordion',
    197           link: 'orderable-accordion__item-link',
    198           content: 'orderable-accordion__item-content',
    199           link_active: 'orderable-accordion__item-link--active',
    200           content_active: 'orderable-accordion__item-content--active'
    201         }
    202       };
    203     },
    204     /**
    205      * Watch.
    206      */
    207     watch() {
    208       /**
    209        * When click accordion link.
    210        */
    211       $(document.body).on('click', '.' + orderable_accordion.vars.classes.link, function (e) {
    212         e.preventDefault();
    213         const $link = $(this),
    214           $parent = $link.closest('.' + orderable_accordion.vars.classes.parent),
    215           content_id = $link.attr('href'),
    216           $content = $(content_id),
    217           is_active = $link.hasClass(orderable_accordion.vars.classes.link_active);
    218         $parent.find('.' + orderable_accordion.vars.classes.link).removeClass(orderable_accordion.vars.classes.link_active);
    219         $parent.find('.' + orderable_accordion.vars.classes.content).removeClass(orderable_accordion.vars.classes.content_active);
    220         if (!is_active) {
    221           $link.addClass(orderable_accordion.vars.classes.link_active);
    222           $content.addClass(orderable_accordion.vars.classes.content_active);
    223         }
    224         $(document.body).trigger('orderable-accordion.toggled', {
    225           link: $link,
    226           content: $content
    227         });
    228       });
    229 
    230       /**
    231        * When drawer is opened.
    232        */
    233       $(document.body).on('orderable-scrollbar.created', function (e, args) {
    234         const $active_accordion = $('.orderable-drawer .' + orderable_accordion.vars.classes.link_active);
    235         if ($active_accordion.length <= 0) {
    236           return;
    237         }
    238         const $scroll_content = args.content,
    239           scroll_position = $scroll_content.scrollTop() - $scroll_content.offset().top + $active_accordion.offset().top;
    240         $scroll_content.scrollTop(scroll_position);
    241       });
    242     }
    243   };
    244   $(document).ready(orderable_accordion.on_ready);
    245 })(jQuery, document);
    246 (function ($, document) {
    247   'use strict';
    248 
    249   var orderable_drawer = {
    250     /**
    251      * Delays invoking function
    252      *
    253      * @param {Function} func    The function to debounce.
    254      * @param {number}   timeout The number of milliseconds to delay.
    255      * @return {Function} Returns the new debounced function.
    256      */
    257     debounce(func, timeout = 700) {
    258       let timer;
    259       return (...args) => {
    260         clearTimeout(timer);
    261         timer = setTimeout(() => {
    262           func.apply(this, args);
    263         }, timeout);
    264       };
    265     },
    266     /**
    267      * Allow only number for events like keypress
    268      *
    269      * @param {Event} event
    270      */
    271     allow_only_numbers(event) {
    272       const value = String.fromCharCode(event.which);
    273       if (!/^\d+$/.test(value)) {
    274         event.preventDefault();
    275       }
    276     },
    277     /**
    278      * Send a request to change the quantity.
    279      *
    280      * @param {Event} event
    281      */
    282     on_change_quantity(event) {
    283       const quantityElement = $(event.currentTarget);
    284       const product_id = quantityElement.data('orderable-product-id');
    285       const cart_item_key = quantityElement.data('orderable-cart-item-key');
    286       const quantity = parseInt(quantityElement.text());
    287       const data = {
    288         action: 'orderable_cart_quantity',
    289         cart_item_key,
    290         product_id,
    291         quantity
    292       };
    293       jQuery.post(orderable_vars.ajax_url, data, function (response) {
    294         if (!response) {
    295           return;
    296         }
    297         $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, quantityElement]);
    298         $(document.body).trigger('orderable-drawer.quantity-updated');
    299       });
    300     },
    301     /**
    302      * On doc ready.
    303      */
    304     on_ready() {
    305       orderable_drawer.cache();
    306       orderable_drawer.watch();
    307 
    308       /**
    309        * Handle manually changing the quantity of a product.
    310        */
    311       $(document.body).on('keypress', '.orderable-quantity-roller__quantity', orderable_drawer.allow_only_numbers);
    312       $('.orderable-drawer__cart, .orderable-product--add-to-cart, .orderable-products-list').on('input', '.orderable-quantity-roller__quantity', orderable_drawer.debounce(orderable_drawer.on_change_quantity));
    313       $(document.body).on('click', '.orderable-quantity-roller__quantity', function (event) {
    314         event.stopPropagation();
    315       });
    316 
    317       /**
    318        * We turn off the click event for .add_to_cart_button elements
    319        * to keep the AJAX behaviour only on Mini cart when the option
    320        * "Enable AJAX add to cart buttons on archives" is disabled.
    321        */
    322       if (orderable_vars && !orderable_vars.woocommerce_enable_ajax_add_to_cart) {
    323         $(document.body).off('click', '.add_to_cart_button');
    324       }
    325     },
    326     /**
    327      * Cache.
    328      */
    329     cache() {
    330       orderable_drawer.vars = {
    331         classes: {
    332           overlay: 'orderable-drawer-overlay',
    333           drawer: 'orderable-drawer',
    334           drawer_cart: 'orderable-drawer__cart',
    335           drawer_html: 'orderable-drawer__html',
    336           overlay_open: 'orderable-drawer-overlay--open',
    337           drawer_open: 'orderable-drawer--open',
    338           drawer_open_body: 'orderable-drawer-open'
    339         }
    340       };
    341       orderable_drawer.elements = {
    342         body: $('body'),
    343         overlay: $('.' + orderable_drawer.vars.classes.overlay),
    344         drawer: $('.' + orderable_drawer.vars.classes.drawer),
    345         drawer_cart: $('.' + orderable_drawer.vars.classes.drawer_cart),
    346         drawer_html: $('.' + orderable_drawer.vars.classes.drawer_html),
    347         floating_cart_button_class: '.orderable-floating-cart__button'
    348       };
    349     },
    350     /**
    351      * Watch for trigger events.
    352      */
    353     watch() {
    354       if (typeof orderable_drawer.elements.drawer === 'undefined') {
    355         return;
    356       }
    357       $(document.body).on('orderable-drawer.open', orderable_drawer.open);
    358       $(document.body).on('orderable-drawer.close', orderable_drawer.close);
    359       $(document.body).on('click', orderable_drawer.elements.floating_cart_button_class, function () {
    360         $(document.body).trigger('orderable-drawer.open', {
    361           show_cart: true
    362         });
    363       });
    364       $(document.body).on('orderable-increase-quantity', orderable_drawer.cart.handle_quantity_change_by_button);
    365       $(document.body).on('orderable-decrease-quantity', orderable_drawer.cart.handle_quantity_change_by_button);
    366       const updateQuantityRequest = orderable_drawer.debounce(orderable_drawer.cart.click_increase_decrease_quantity);
    367       $(document.body).on('orderable-increase-quantity', updateQuantityRequest);
    368       $(document.body).on('orderable-decrease-quantity', updateQuantityRequest);
    369       const drawer = document.querySelector('body:not( .rtl ) .orderable-drawer');
    370       const drawer_rtl = document.querySelector('body.rtl .orderable-drawer');
    371       if (drawer) {
    372         drawer.addEventListener('swiped-right', function (e) {
    373           orderable_drawer.close();
    374         });
    375       }
    376       if (drawer_rtl) {
    377         drawer_rtl.addEventListener('swiped-left', function (e) {
    378           orderable_drawer.close();
    379         });
    380       }
    381     },
    382     /**
    383      * Open the drawer.
    384      * @param event
    385      * @param args
    386      */
    387     open(event, args) {
    388       args.html = args.html || false;
    389       args.show_cart = args.show_cart || false;
    390       orderable_drawer.elements.drawer_html.hide();
    391       orderable_drawer.elements.drawer_cart.hide();
    392       if (args.html) {
    393         orderable_drawer.elements.drawer_html.html(args.html);
    394         orderable_drawer.elements.drawer_html.show();
    395       }
    396       if (args.show_cart) {
    397         // Empty drawer HTML before showing cart. Prevents options
    398         // interfering with subsequent cart additions.
    399         orderable_drawer.elements.drawer_html.html('');
    400         orderable_drawer.elements.drawer_cart.show();
    401       }
    402       orderable_drawer.elements.overlay.addClass(orderable_drawer.vars.classes.overlay_open);
    403       orderable_drawer.elements.drawer.addClass(orderable_drawer.vars.classes.drawer_open);
    404       orderable_drawer.elements.body.addClass(orderable_drawer.vars.classes.drawer_open_body);
    405       $(document.body).trigger('orderable-drawer.opened', args);
    406     },
    407     /**
    408      * Close the drawer.
    409      */
    410     close() {
    411       orderable_drawer.elements.overlay.removeClass(orderable_drawer.vars.classes.overlay_open);
    412       orderable_drawer.elements.drawer.removeClass(orderable_drawer.vars.classes.drawer_open);
    413       orderable_drawer.elements.body.removeClass(orderable_drawer.vars.classes.drawer_open_body);
    414       orderable_drawer.elements.drawer_html.html('');
    415       $(document.body).trigger('orderable-drawer.closed');
    416     },
    417     /**
    418      * Mini cart related functions.
    419      */
    420     cart: {
    421       /**
    422        * When increase qty is clicked.
    423        *
    424        * @param e
    425        * @param $button
    426        */
    427       click_increase_decrease_quantity(e, $button) {
    428         const direction = $button.data('orderable-trigger');
    429         const product_id = $button.attr('data-orderable-product-id'),
    430           cart_item_key = $button.attr('data-orderable-cart-item-key'),
    431           quantity = $button.attr('data-orderable-quantity');
    432         const siblingButtonName = 'increase-quantity' === direction ? 'decrease' : 'increase';
    433         const $siblingButton = $button.siblings(`.orderable-quantity-roller__button--${siblingButtonName}`);
    434         const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
    435         const data = {
    436           action: 'orderable_cart_quantity',
    437           cart_item_key,
    438           product_id,
    439           quantity
    440         };
    441         if (this.currentRequest) {
    442           this.currentRequest.abort();
    443           this.currentRequest = undefined;
    444         }
    445         $button.addClass('orderable-button--loading');
    446         $button.attr('disabled', true);
    447         $siblingButton.attr('disabled', true);
    448         $quantityElement.attr('contenteditable', false);
    449         this.currentRequest = jQuery.post(orderable_vars.ajax_url, data, function (response) {
    450           if (!response) {
    451             return;
    452           }
    453           const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
    454           if (response && response.fragments && response.fragments['.orderable-mini-cart__notices']) {
    455             $(document.body).trigger('orderable-drawer.open', {
    456               show_cart: true
    457             });
    458           }
    459           switch (data.quantity) {
    460             case '0':
    461               $(document.body).trigger('removed_from_cart', [response.fragments, response.cart_hash, $button]);
    462               break;
    463             case $quantityElement.attr('data-orderable-updating-quantity'):
    464               $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, $button]);
    465               $(document.body).trigger('orderable-drawer.quantity-updated');
    466               break;
    467             default:
    468               break;
    469           }
    470         }.bind(this)).always(function () {
    471           this.currentRequest = undefined;
    472           $button.removeClass('orderable-button--loading');
    473           $button.attr('disabled', false);
    474           $siblingButton.attr('disabled', false);
    475           $quantityElement.attr('contenteditable', true);
    476         }.bind(this));
    477       },
    478       handle_quantity_change_by_button(e, $button) {
    479         const direction = $button.data('orderable-trigger');
    480         const quantity = parseInt($button.attr('data-orderable-quantity'));
    481         const siblingButtonName = 'increase-quantity' === direction ? 'decrease' : 'increase';
    482         const $siblingButton = $button.siblings(`.orderable-quantity-roller__button--${siblingButtonName}`);
    483         const $quantityElement = $button.siblings('.orderable-quantity-roller__quantity');
    484         const newQuantity = 'increase-quantity' === direction ? quantity + 1 : Math.max(0, quantity - 1);
    485         const $parent = $button.parents('.orderable-product__actions-button');
    486         if (0 === newQuantity && $parent.length) {
    487           const $addToCartButton = $parent.find('button.orderable-button[data-orderable-trigger]');
    488           const $quantityRoller = $parent.find('.orderable-quantity-roller');
    489           if ($quantityRoller.length) {
    490             $addToCartButton.removeClass('orderable-button--product-in-the-cart');
    491             $quantityRoller.removeClass('orderable-quantity-roller--is-active');
    492           }
    493         }
    494         $button.attr('data-orderable-quantity', newQuantity);
    495         $siblingButton.attr('data-orderable-quantity', newQuantity);
    496         $quantityElement.attr('data-orderable-updating-quantity', newQuantity);
    497         $quantityElement.text(newQuantity);
    498         $quantityElement.attr('contenteditable', false);
    499       }
    500     }
    501   };
    502   $(document).ready(orderable_drawer.on_ready);
    503 })(jQuery, document);
    504 (function ($, document) {
    505   'use strict';
    506 
    507   var orderable_products = {
    508     /**
    509      * On doc ready.
    510      */
    511     on_ready() {
    512       orderable_products.cache();
    513       orderable_products.watch();
    514     },
    515     /**
    516      * Cache.
    517      */
    518     cache() {
    519       orderable_products.vars = {
    520         classes: {
    521           clickable_product: 'orderable-product--add-to-cart ',
    522           add_to_order_button: 'orderable-product__add-to-order',
    523           product_messages: 'orderable-product__messages',
    524           product_price: 'orderable-product__actions-price',
    525           invalid_field: 'orderable-field--invalid',
    526           option_select_td: 'orderable-product__option-select',
    527           button_loading: 'orderable-button--loading',
    528           out_of_stock: 'orderable-button--out-of-stock'
    529         },
    530         parent_price: null,
    531         variable_product_types: ['variable', 'variable-subscription']
    532       };
    533       orderable_products.elements = {};
    534     },
    535     /**
    536      * Watch for trigger events.
    537      */
    538     watch() {
    539       $(document.body).on('orderable-drawer.opened', orderable_products.init_product_options);
    540       $(document.body).on('orderable-add-to-cart', orderable_products.click_add_to_order);
    541       $(document.body).on('orderable-product-options', orderable_products.click_add_to_order);
    542       $(document.body).on('orderable-view-product', orderable_products.view_product);
    543       $(document.body).on('mouseenter mouseleave', '.' + orderable_products.vars.classes.clickable_product, orderable_products.simulate_add_to_order_hover);
    544       $(document.body).on('orderable-edit-cart-item', orderable_products.edit_cart_item);
    545       $(document.body).on('orderable-update-cart-item', orderable_products.update_cart_item);
    546       $(document.body).on('orderable-show-cart', orderable_products.show_cart);
    547       $(document.body).on('orderable-add-to-cart-without-side-drawer', orderable_products.click_add_to_order);
    548       $(document.body).on('added_to_cart', orderable_products.remove_fragments);
    549       $(document.body).on('added_to_cart', orderable_products.remove_animation);
    550       $(document.body).on('added_to_cart', orderable_products.shake_floating_cart);
    551       $(document.body).on('removed_from_cart', orderable_products.hide_quantity_roller);
    552       $(document.body).on('wc_cart_button_updated', orderable_products.remove_view_cart_link);
    553     },
    554     /**
    555      * Simulate hover on add to order button.
    556      *
    557      * @param event
    558      */
    559     simulate_add_to_order_hover(event) {
    560       const $element = $(this),
    561         $button = $element.find('.' + orderable_products.vars.classes.add_to_order_button);
    562       $button.toggleClass('orderable-button--hover', 'mouseenter' === event.type);
    563     },
    564     /**
    565      * Add to order click event.
    566      *
    567      * This event accounts for button clicks or card clicks.
    568      * @param event
    569      * @param $element
    570      */
    571     click_add_to_order(event, $element) {
    572       // If undefined, it means it was triggered by a click
    573       // event and not the `orderable-add-to-cart` trigger.
    574       $element = typeof $element !== 'undefined' ? $element : $(this);
    575 
    576       // The button is either the clicked element, or the
    577       // add to order button within the clicked element.
    578       const $button = $element.is('button') ? $element : $element.find('.' + orderable_products.vars.classes.add_to_order_button),
    579         action = $button.data('orderable-trigger'),
    580         product_id = $button.data('orderable-product-id'),
    581         variation_id = $button.data('orderable-variation-id'),
    582         attributes = $button.data('orderable-variation-attributes'),
    583         args = {
    584           action
    585         };
    586       if ($button.hasClass(orderable_products.vars.classes.button_loading) || $button.hasClass(orderable_products.vars.classes.out_of_stock)) {
    587         return;
    588       }
    589       $button.addClass(orderable_products.vars.classes.button_loading);
    590       switch (action) {
    591         case 'add-to-cart':
    592           orderable_products.add_to_cart({
    593             product_id,
    594             variation_id,
    595             attributes,
    596             thisbutton: $element
    597           }, function (response) {
    598             args.show_cart = true;
    599             args.response = response;
    600             $(document.body).trigger('orderable-drawer.open', args);
    601             $button.removeClass(orderable_products.vars.classes.button_loading);
    602             const $addToCartButtonOutsideDrawer = $('.orderable-product .orderable-product__actions-button button.orderable-product__add-to-order[data-orderable-product-id=' + product_id + ']');
    603             if ($addToCartButtonOutsideDrawer.siblings('.orderable-quantity-roller').length) {
    604               $addToCartButtonOutsideDrawer.addClass('orderable-button--product-in-the-cart');
    605             }
    606           });
    607           break;
    608         case 'add-to-cart-without-side-drawer':
    609           orderable_products.add_to_cart({
    610             product_id,
    611             variation_id,
    612             attributes
    613           }, function (response) {
    614             args.response = response;
    615             $button.addClass('orderable-button--product-in-the-cart');
    616             $button.removeClass(orderable_products.vars.classes.button_loading);
    617           });
    618           break;
    619         case 'product-options':
    620           orderable_products.get_product_options({
    621             product_id,
    622             focus: $button.data('orderable-focus')
    623           }, function (response) {
    624             args.html = response.html;
    625             $(document.body).trigger('orderable-drawer.open', args);
    626             $button.removeClass(orderable_products.vars.classes.button_loading);
    627           });
    628           break;
    629         default:
    630           break;
    631       }
    632     },
    633     /**
    634      * Show the cart.
    635      */
    636     show_cart() {
    637       $(document.body).trigger('orderable-drawer.open', {
    638         show_cart: true
    639       });
    640     },
    641     /**
    642      * View product.
    643      *
    644      * @param event
    645      * @param $element
    646      */
    647     view_product(event, $element) {
    648       const product_id = $element.data('orderable-product-id'),
    649         args = {
    650           action: 'product-options'
    651         };
    652       orderable_products.get_product_options({
    653         product_id,
    654         focus: $element.data('orderable-focus')
    655       }, function (response) {
    656         args.html = response.html;
    657         $(document.body).trigger('orderable-drawer.open', args);
    658       });
    659     },
    660     /**
    661      * Ajax add to cart.
    662      * @param args
    663      * @param callback
    664      */
    665     add_to_cart(args, callback) {
    666       if (typeof args.product_id === 'undefined') {
    667         return;
    668       }
    669       let data = {
    670         action: 'orderable_add_to_cart',
    671         product_id: args.product_id,
    672         variation_id: args.variation_id || false,
    673         attributes: args.attributes || false
    674       };
    675 
    676       // Prepare addons data.
    677       if ($('.orderable-product-fields-group').length) {
    678         let inputs = jQuery('.orderable-product-fields-group :input').serializeArray();
    679         inputs = orderable_products.add_unchecked_checkbox_fields(inputs);
    680         const addons_data = orderable_products.convert_to_flat_object(inputs);
    681         if (!jQuery.isEmptyObject(addons_data)) {
    682           data = Object.assign(data, addons_data); // Merge objects.
    683         }
    684       }
    685       jQuery.post(orderable_vars.ajax_url, data, function (response) {
    686         if (!response) {
    687           return;
    688         }
    689 
    690         // Trigger event so themes can refresh other areas.
    691         $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, args.thisbutton]);
    692         if (typeof callback === 'function') {
    693           callback(response);
    694         }
    695       });
    696     },
    697     /**
    698      * Edit cart item.
    699      *
    700      * @param event
    701      * @param $element
    702      */
    703     edit_cart_item(event, $element) {
    704       const cart_item_key = $element.data('orderable-cart-item-key');
    705       $element.addClass(orderable_products.vars.classes.button_loading);
    706       orderable_products.get_cart_item_options({
    707         cart_item_key
    708       }, function (response) {
    709         const args = {
    710           html: response.html,
    711           action: 'update-cart-item'
    712         };
    713         $(document.body).trigger('orderable-drawer.open', args);
    714         $element.removeClass(orderable_products.vars.classes.button_loading);
    715       });
    716     },
    717     /**
    718      * Update cart item.
    719      *
    720      * @param event
    721      * @param $element
    722      */
    723     update_cart_item(event, $element) {
    724       const cart_item_key = $element.data('orderable-cart-item-key');
    725       const product_id = $element.data('orderable-product-id');
    726       const variation_id = $element.data('orderable-variation-id');
    727       const attributes = $element.data('orderable-variation-attributes');
    728       $element.addClass(orderable_products.vars.classes.button_loading);
    729       orderable_products.update_cart_item_options({
    730         cart_item_key,
    731         product_id,
    732         variation_id,
    733         attributes
    734       }, function (response) {
    735         const args = {
    736           show_cart: true,
    737           response
    738         };
    739         $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash]);
    740         $(document.body).trigger('orderable-drawer.open', args);
    741         $element.removeClass(orderable_products.vars.classes.button_loading);
    742       });
    743     },
    744     /**
    745      * Convert [{name:x, value:y }] to {x:y} format.
    746      * @param inputs
    747      */
    748     convert_to_flat_object(inputs) {
    749       const data = {};
    750       inputs.forEach(function (input) {
    751         const is_array = '[]' === input.name.substr(-2) || Array.isArray(input.name);
    752         // If last 2 chars are '[]', remove them.
    753         const key = is_array ? input.name.substr(0, input.name.length - 2) : input.name;
    754         if (is_array) {
    755           data[key] = typeof data[key] === 'undefined' ? [] : data[key];
    756           data[key].push(input.value);
    757         } else {
    758           data[key] = input.value;
    759         }
    760       });
    761       return data;
    762     },
    763     /**
    764      * Get variable product options.
    765      *
    766      * @param args
    767      * @param callback
    768      */
    769     get_product_options(args, callback) {
    770       if (typeof args.product_id === 'undefined') {
    771         return;
    772       }
    773       args.action = 'orderable_get_product_options';
    774       jQuery.post(orderable_vars.ajax_url, args, function (response) {
    775         if (!response.success) {
    776           return;
    777         }
    778         if (typeof callback === 'function') {
    779           callback(response.data);
    780         }
    781       });
    782     },
    783     /**
    784      * Get variable product options.
    785      *
    786      * @param args
    787      * @param callback
    788      */
    789     get_cart_item_options(args, callback) {
    790       if (typeof args.cart_item_key === 'undefined') {
    791         return;
    792       }
    793       args.action = 'orderable_get_cart_item_options';
    794       jQuery.post(orderable_vars.ajax_url, args, function (response) {
    795         if (!response.success) {
    796           return;
    797         }
    798         if (typeof callback === 'function') {
    799           callback(response.data);
    800         }
    801       });
    802     },
    803     /**
    804      * Update variable product options.
    805      *
    806      * @param args
    807      * @param callback
    808      */
    809     update_cart_item_options(args, callback) {
    810       if (typeof args.cart_item_key === 'undefined') {
    811         return;
    812       }
    813       args.action = 'orderable_update_cart_item_options';
    814 
    815       // Prepare addons data.
    816       if ($('.orderable-product-fields-group').length) {
    817         let inputs = jQuery('.orderable-product-fields-group :input').serializeArray();
    818         inputs = orderable_products.add_unchecked_checkbox_fields(inputs);
    819         const addons_data = orderable_products.convert_to_flat_object(inputs);
    820         if (!jQuery.isEmptyObject(addons_data)) {
    821           args = Object.assign(args, addons_data); // Merge objects.
    822         }
    823       }
    824       jQuery.post(orderable_vars.ajax_url, args, function (response) {
    825         if (!response) {
    826           return;
    827         }
    828         if (typeof callback === 'function') {
    829           callback(response);
    830         }
    831       });
    832     },
    833     /**
    834      * Init drawer product options.
    835      *
    836      * @param event
    837      * @param args
    838      */
    839     init_product_options(event, args) {
    840       if (typeof args.action === 'undefined' || 'product-options' !== args.action && 'update-cart-item' !== args.action) {
    841         return;
    842       }
    843       const selectors = '.orderable-drawer .orderable-product__options input, .orderable-drawer .orderable-product__options select, .orderable-product__options textarea';
    844       const $options = $(selectors);
    845       orderable_products.vars.parent_price = $('.orderable-drawer .orderable-product__actions-price').html();
    846       orderable_products.product_options_change($options);
    847       orderable_products.update_button_state();
    848       const debounced_update_button_state = orderable_products.debounce(orderable_products.update_button_state, 500);
    849       const debounced_product_options_change = orderable_products.debounce(orderable_products.product_options_change, 500);
    850       $(document).on('change keyup', selectors, function () {
    851         debounced_product_options_change($options);
    852         debounced_update_button_state();
    853       });
    854     },
    855     /**
    856      * On product options change.
    857      *
    858      * @param $options
    859      */
    860     product_options_change($options) {
    861       const $add_to_order_button = $('.orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item'),
    862         options_set = orderable_products.check_options($options),
    863         product_type = $add_to_order_button.data('orderable-product-type');
    864       if ('product-options' === $add_to_order_button.attr('data-orderable-trigger')) {
    865         $add_to_order_button.attr('data-orderable-trigger', 'add-to-cart');
    866       }
    867       $('.' + orderable_products.vars.classes.product_messages).html('');
    868       if (!orderable_products.vars.variable_product_types.includes(product_type)) {
    869         return;
    870       }
    871       if (!options_set) {
    872         orderable_products.clear_variation($add_to_order_button);
    873         return;
    874       }
    875       const variation = orderable_products.check_variation($options);
    876       orderable_products.set_variation($add_to_order_button, variation);
    877     },
    878     /**
    879      * Check if all product options are set.
    880      *
    881      * @param  $options
    882      * @return {boolean}
    883      */
    884     check_options($options) {
    885       if ($options.length <= 0) {
    886         return false;
    887       }
    888       let all_set = true;
    889       $options.each(function (index, option) {
    890         // Only check attribute fields.
    891         if (!$(option).hasClass('orderable-input--validate')) {
    892           return;
    893         }
    894         if ('' === $(option).val()) {
    895           $(option).addClass(orderable_products.vars.classes.invalid_field);
    896           all_set = false;
    897         } else {
    898           $(option).removeClass(orderable_products.vars.classes.invalid_field);
    899         }
    900       });
    901       return all_set;
    902     },
    903     /**
    904      * Check if variation has been selected.
    905      * @param $options
    906      */
    907     check_variation($options) {
    908       const $product = $options.closest('.orderable-drawer');
    909       let variations = $product.find('.orderable-product__variations').text();
    910       variations = variations ? JSON.parse(variations) : '';
    911       const selected_options = orderable_products.serialize_object($options),
    912         matching_variations = orderable_products.find_matching_variations(variations, selected_options);
    913       if (orderable_products.is_empty(matching_variations)) {
    914         return false;
    915       }
    916       const variation = matching_variations.shift();
    917       variation.attributes = selected_options;
    918       variation.attributes_json = JSON.stringify(selected_options);
    919       return typeof variation !== 'undefined' ? variation : false;
    920     },
    921     /**
    922      * Set variation for add to cart button.
    923      * @param $button
    924      * @param variation
    925      */
    926     set_variation($button, variation) {
    927       let variation_id = variation.variation_id || '',
    928         attributes = variation.attributes_json || '',
    929         price = variation.price_html || orderable_products.vars.parent_price,
    930         message = '';
    931       if (variation && '' !== variation.availability_html) {
    932         message = variation.availability_html;
    933       }
    934       if (variation && !variation.is_in_stock) {
    935         message = '<p>' + orderable_vars.i18n.out_of_stock + '</p>';
    936       }
    937       if (variation && !variation.is_purchasable) {
    938         message = '<p>' + orderable_vars.i18n.unavailable + '</p>';
    939       }
    940       if (false === variation) {
    941         message = '<p>' + orderable_vars.i18n.no_exist + '</p>';
    942       }
    943       if (variation && (!variation.is_purchasable || !variation.is_in_stock)) {
    944         variation_id = '';
    945         attributes = '';
    946       }
    947       if ('' !== message) {
    948         $('.' + orderable_products.vars.classes.product_messages).html(message);
    949       }
    950       $button.data('orderable-variation-id', variation_id);
    951       $button.data('orderable-variation-attributes', attributes);
    952       $('.orderable-drawer .orderable-product__actions-price').html(price);
    953       $button.trigger('orderable_variation_set', {
    954         variation,
    955         variation_id,
    956         attributes,
    957         price
    958       });
    959     },
    960     /**
    961      * Clear variation and disable add to order.
    962      *
    963      * @param $button
    964      */
    965     clear_variation($button) {
    966       orderable_products.set_variation($button, '');
    967       if (orderable_products.vars.parent_price) {
    968         $('.orderable-drawer .orderable-product__actions-price').html(orderable_products.vars.parent_price);
    969       }
    970     },
    971     /**
    972      * Find matching variations for attributes.
    973      * @param variations
    974      * @param attributes
    975      */
    976     find_matching_variations(variations, attributes) {
    977       const matching = [];
    978       for (let i = 0; i < variations.length; i++) {
    979         const variation = variations[i];
    980         if (orderable_products.is_matching_variation(variation.attributes, attributes)) {
    981           matching.push(variation);
    982         }
    983       }
    984       return matching;
    985     },
    986     /**
    987      * See if attributes match.
    988      * @param  variation_attributes
    989      * @param  attributes
    990      * @return {boolean}
    991      */
    992     is_matching_variation(variation_attributes, attributes) {
    993       let match = true;
    994       for (const attr_name in variation_attributes) {
    995         if (variation_attributes.hasOwnProperty(attr_name)) {
    996           const val1 = variation_attributes[attr_name];
    997           const val2 = attributes[attr_name];
    998           if (val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2) {
    999             match = false;
    1000           }
    1001         }
    1002       }
    1003       return match;
    1004     },
    1005     /**
    1006      * Is value empty?
    1007      *
    1008      * @param  value
    1009      * @return {boolean}
    1010      */
    1011     is_empty(value) {
    1012       return typeof value === 'undefined' || false === value || value.length <= 0 || !value;
    1013     },
    1014     /**
    1015      * Serialize into a key/value object.
    1016      *
    1017      * @param  $elements
    1018      * @return {{}}
    1019      */
    1020     serialize_object: function objectifyForm($elements) {
    1021       const serialized = $elements.serializeArray(),
    1022         return_object = {};
    1023       for (let i = 0; i < serialized.length; i++) {
    1024         return_object[serialized[i].name] = serialized[i].value;
    1025       }
    1026       return return_object;
    1027     },
    1028     /**
    1029      * Disable/Enable the 'Add to cart' button based on the presence of orderable-field--invalid class.
    1030      */
    1031     update_button_state() {
    1032       // Add delay to ensure invalid class has been assigned to inputs.
    1033       setTimeout(function () {
    1034         let $button = $('.orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item'),
    1035           invalid_fields_count = $('.orderable-drawer__html .' + orderable_products.vars.classes.invalid_field).length,
    1036           product_type = $button.data('orderable-product-type'),
    1037           has_variation_id = true;
    1038         if ('variable' === product_type) {
    1039           has_variation_id = '' !== $button.data('orderable-variation-id');
    1040         }
    1041         $button.prop('disabled', invalid_fields_count || !has_variation_id);
    1042       }, 50);
    1043     },
    1044     /**
    1045      * Debounce function.
    1046      *
    1047      * @param func      Function to debounce.
    1048      * @param wait      Time to wait in milliseconds.
    1049      * @param immediate Trigger the function on the leading edge, instead of the trailing.
    1050      *
    1051      * @return
    1052      */
    1053     debounce(func, wait, immediate) {
    1054       let timeout;
    1055       return function () {
    1056         const context = this,
    1057           args = arguments;
    1058         const later = function () {
    1059           timeout = null;
    1060           if (!immediate) {
    1061             func.apply(context, args);
    1062           }
    1063         };
    1064         const callNow = immediate && !timeout;
    1065         clearTimeout(timeout);
    1066         timeout = setTimeout(later, wait);
    1067         if (callNow) {
    1068           func.apply(context, args);
    1069         }
    1070       };
    1071     },
    1072     /**
    1073      * Remove the quantity roller fragments
    1074      *
    1075      * @param {Event}  e
    1076      * @param {Object} fragments
    1077      * @return void
    1078      */
    1079     remove_fragments(e, fragments) {
    1080       if (!fragments || 'undefined' === typeof wc_cart_fragments_params || !wc_cart_fragments_params.fragment_name) {
    1081         return;
    1082       }
    1083       const regex_quantity_roller = /\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-quantity-roller/;
    1084       const regex_product_in_the_cart_counter = /\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-product__actions-counter/;
    1085       for (const key in fragments) {
    1086         if (!regex_quantity_roller.test(key) && !regex_product_in_the_cart_counter.test(key)) {
    1087           continue;
    1088         }
    1089         fragments[key] = undefined;
    1090       }
    1091       sessionStorage.setItem(wc_cart_fragments_params.fragment_name, JSON.stringify(fragments));
    1092     },
    1093     /**
    1094      * Remove animation.
    1095      */
    1096     remove_animation() {
    1097       setTimeout(function () {
    1098         $('.orderable-product__actions-counter').css('animation', '');
    1099       }, 1000);
    1100     },
    1101     /**
    1102      * Hide quantity roller element and show the Add to Cart button.
    1103      *
    1104      * @param {Event}   e
    1105      * @param {Object}  fragments
    1106      * @param {string}  cart_hash
    1107      * @param {Element} $button
    1108      * @return
    1109      */
    1110     hide_quantity_roller(e, fragments, cart_hash, $button) {
    1111       const product_id = $button.attr('data-product_id') || $button.attr('data-orderable-product-id');
    1112       if (!product_id) {
    1113         return;
    1114       }
    1115       const $actions_button = $('.orderable-product[data-orderable-product-id=' + product_id + '] .orderable-product__actions-button');
    1116       if (!$actions_button.length) {
    1117         return;
    1118       }
    1119       const $quantity_roller = $actions_button.find('.orderable-quantity-roller');
    1120       if ($quantity_roller.length) {
    1121         $actions_button.find('button.orderable-product__add-to-order[data-orderable-trigger]').removeClass('orderable-button--product-in-the-cart');
    1122         $quantity_roller.addClass('orderable-button--hide');
    1123       }
    1124     },
    1125     /**
    1126      * Add unchecked checkboxs to the list of inputs
    1127      * sent to the request to add/update an item
    1128      *
    1129      * @param {Object} inputs
    1130      * @return {Object}
    1131      */
    1132     add_unchecked_checkbox_fields(inputs) {
    1133       jQuery('.orderable-product-fields-group :input[type="checkbox"]:not(:checked)').each(function (index, element) {
    1134         inputs.push({
    1135           name: element.getAttribute('name'),
    1136           value: ''
    1137         });
    1138       });
    1139       return inputs;
    1140     },
    1141     /**
    1142      * Shake the floating cart button.
    1143      *
    1144      * @return void
    1145      */
    1146     shake_floating_cart() {
    1147       $('.orderable-floating-cart__button').css('animation', 'wobble-hor-bottom .8s both');
    1148     },
    1149     /**
    1150      * Remove the view cart link.
    1151      *
    1152      * @param event
    1153      * @param $button
    1154      */
    1155     remove_view_cart_link(event, $button) {
    1156       if (!$button?.hasClass('orderable-product__add-to-order')) {
    1157         return;
    1158       }
    1159       $button?.siblings('.added_to_cart.wc-forward').remove();
    1160     }
    1161   };
    1162   $(document).ready(orderable_products.on_ready);
    1163 })(jQuery, document);
    1164 (function ($, document) {
    1165   'use strict';
    1166 
    1167   var orderable_scrollbar = {
    1168     /**
    1169      * On doc ready.
    1170      */
    1171     on_ready() {
    1172       orderable_scrollbar.cache();
    1173       orderable_scrollbar.watch();
    1174     },
    1175     /**
    1176      * Cache.
    1177      */
    1178     cache() {
    1179       orderable_scrollbar.vars = {
    1180         top: {}
    1181       };
    1182       orderable_scrollbar.elements = {};
    1183     },
    1184     /**
    1185      * Watch.
    1186      */
    1187     watch() {
    1188       $(document.body).on('orderable-drawer.opened', orderable_scrollbar.trigger);
    1189       $(document.body).on('orderable-tabs.changed', orderable_scrollbar.trigger);
    1190       $(document.body).on('orderable-accordion.toggled', orderable_scrollbar.trigger);
    1191       $(document.body).on('wc_fragments_loaded', orderable_scrollbar.trigger);
    1192     },
    1193     /**
    1194      * Init or retrigger scrollbars.
    1195      */
    1196     trigger() {
    1197       $('.orderable-sb-container').each(function (index, element) {
    1198         const $element = $(element),
    1199           scroll_id = $element.data('orderable-scroll-id');
    1200         if (!orderable_scrollbar.has_scrollbar($element)) {
    1201           $element.scrollBox({
    1202             containerClass: 'orderable-sb-container',
    1203             containerNoScrollClass: 'orderable-sb-container-noscroll',
    1204             contentClass: 'orderable-sb-content',
    1205             scrollbarContainerClass: 'orderable-sb-scrollbar-container',
    1206             scrollBarClass: 'orderable-sb-scrollbar'
    1207           });
    1208           const $content = $element.find('.orderable-sb-content');
    1209           if ($content.length > 0) {
    1210             $content.on('scroll.scrollBox', orderable_scrollbar.log_top_position);
    1211 
    1212             // Set scroll position.
    1213             if (typeof orderable_scrollbar.vars.top[scroll_id] !== 'undefined') {
    1214               $content.scrollTop(orderable_scrollbar.vars.top[scroll_id]);
    1215             }
    1216           }
    1217           $(document.body).trigger('orderable-scrollbar.created', {
    1218             element: $element,
    1219             content: $content
    1220           });
    1221         }
    1222       });
    1223       $(window).trigger('resize.scrollBox');
    1224     },
    1225     /**
    1226      * Has scrollbar already?
    1227      *
    1228      * @param  $element
    1229      * @return {boolean}
    1230      */
    1231     has_scrollbar($element) {
    1232       return $element.find('.orderable-sb-content').length > 0;
    1233     },
    1234     /**
    1235      * Set scrolltop position.
    1236      *
    1237      * @param e
    1238      */
    1239     log_top_position(e) {
    1240       const $element = $(e.currentTarget),
    1241         $container = $element.closest('.orderable-sb-container'),
    1242         scroll_id = $container.data('orderable-scroll-id');
    1243       orderable_scrollbar.vars.top[scroll_id] = $(e.currentTarget).scrollTop();
    1244     }
    1245   };
    1246   $(document).ready(orderable_scrollbar.on_ready);
    1247 })(jQuery, document);
    1248 (function ($, document) {
    1249   'use strict';
    1250 
    1251   var orderable_tabs = {
    1252     /**
    1253      * On doc ready.
    1254      */
    1255     on_ready() {
    1256       orderable_tabs.cache();
    1257       orderable_tabs.watch();
    1258       orderable_tabs.toggle_scroll();
    1259     },
    1260     /**
    1261      * On resize.
    1262      */
    1263     on_resize() {
    1264       orderable_tabs.toggle_scroll();
    1265     },
    1266     /**
    1267      * Cache.
    1268      */
    1269     cache() {
    1270       orderable_tabs.vars = {
    1271         classes: {
    1272           tabs: 'orderable-tabs',
    1273           tabs_list: 'orderable-tabs__list',
    1274           tab_items: 'orderable-tabs__item',
    1275           tab_item_active: 'orderable-tabs__item--active',
    1276           tab_links: 'orderable-tabs__link',
    1277           tab_arrow_right: 'orderable-tabs__arrow-right',
    1278           tab_arrow_left: 'orderable-tabs__arrow-left'
    1279         },
    1280         dragging: false
    1281       };
    1282       orderable_tabs.elements = {};
    1283     },
    1284     /**
    1285      * Watch.
    1286      */
    1287     watch() {
    1288       $('body').on('touchstart', function () {
    1289         orderable_tabs.vars.dragging = false;
    1290       }).on('touchmove', function () {
    1291         orderable_tabs.vars.dragging = true;
    1292       });
    1293       $(document.body).on('click mouseup touchend', '.' + orderable_tabs.vars.classes.tab_links, function (e) {
    1294         if (orderable_tabs.vars.dragging) {
    1295           return;
    1296         }
    1297         e.preventDefault();
    1298         const $link = $(this),
    1299           section_id = $link.attr('href'),
    1300           $tab = $link.closest('.' + orderable_tabs.vars.classes.tab_items),
    1301           $tabs = $link.closest('.' + orderable_tabs.vars.classes.tabs),
    1302           $tabs_list = $tabs.find('.' + orderable_tabs.vars.classes.tabs_list),
    1303           $tab_items = $tabs.find('.' + orderable_tabs.vars.classes.tab_items),
    1304           tabs_args = $tabs.data('orderable-tabs'),
    1305           $wrapper = $link.closest(tabs_args.wrapper),
    1306           $sections = $wrapper.find(tabs_args.sections),
    1307           $section = $wrapper.find(section_id);
    1308         $sections.hide();
    1309         $section.show();
    1310         $tab_items.removeClass(orderable_tabs.vars.classes.tab_item_active);
    1311         $tab.addClass(orderable_tabs.vars.classes.tab_item_active);
    1312         $tabs_list.animate({
    1313           scrollLeft: $tabs_list.scrollLeft() + $tab.position().left
    1314         });
    1315         $(document.body).trigger('orderable-tabs.changed', {
    1316           tab: $tab
    1317         });
    1318       });
    1319 
    1320       /**
    1321        * Watch scroll position of tabs.
    1322        */
    1323       $('.' + orderable_tabs.vars.classes.tabs_list).on('scroll', function (e) {
    1324         const $list = $(this),
    1325           $wrapper = $list.parent('.' + orderable_tabs.vars.classes.tabs),
    1326           $arrow_right = $list.siblings('.' + orderable_tabs.vars.classes.tab_arrow_right),
    1327           $arrow_left = $list.siblings('.' + orderable_tabs.vars.classes.tab_arrow_left);
    1328         if ($list[0].scrollWidth <= $wrapper.width() + $list.scrollLeft()) {
    1329           $arrow_right.fadeOut();
    1330         } else {
    1331           $arrow_right.fadeIn();
    1332         }
    1333         if (0 >= $list.scrollLeft() - $arrow_left.width()) {
    1334           $arrow_left.fadeOut();
    1335         } else {
    1336           $arrow_left.fadeIn();
    1337         }
    1338       });
    1339 
    1340       /**
    1341        * Stop animated scroll if user manually scrolls.
    1342        */
    1343       $('.' + orderable_tabs.vars.classes.tabs_list).on('wheel DOMMouseScroll mousewheel touchmove', function () {
    1344         $(this).stop();
    1345       });
    1346 
    1347       /**
    1348        * Click tab arrow right.
    1349        */
    1350       $(document).on('click', '.' + orderable_tabs.vars.classes.tab_arrow_right, function (e) {
    1351         e.preventDefault();
    1352         const $arrow = $(this),
    1353           $wrapper = $arrow.parent(),
    1354           $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list);
    1355         $list.animate({
    1356           scrollLeft: $list.scrollLeft() + $wrapper.width() * 0.5
    1357         });
    1358       });
    1359 
    1360       /**
    1361        * Click tab arrow left.
    1362        */
    1363       $(document).on('click', '.' + orderable_tabs.vars.classes.tab_arrow_left, function (e) {
    1364         e.preventDefault();
    1365         const $arrow = $(this),
    1366           $wrapper = $arrow.parent(),
    1367           $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list);
    1368         $list.animate({
    1369           scrollLeft: $list.scrollLeft() - $wrapper.width() * 0.5
    1370         });
    1371       });
    1372     },
    1373     /**
    1374      * Toggle scroll arrow.
    1375      */
    1376     toggle_scroll() {
    1377       $('.' + orderable_tabs.vars.classes.tabs).each(function (index, wrapper) {
    1378         const $tabs = $(this),
    1379           tabs_args = $tabs.data('orderable-tabs'),
    1380           $wrapper = $tabs.closest(tabs_args.wrapper),
    1381           $list = $wrapper.find('.' + orderable_tabs.vars.classes.tabs_list),
    1382           $arrow_right = $wrapper.find('.' + orderable_tabs.vars.classes.tab_arrow_right),
    1383           wrapper_width = $wrapper.outerWidth(),
    1384           list_width = $list[0].scrollWidth;
    1385         if (list_width > wrapper_width) {
    1386           $arrow_right.show();
    1387         } else {
    1388           $arrow_right.hide();
    1389         }
    1390       });
    1391     }
    1392   };
    1393   $(document).ready(orderable_tabs.on_ready);
    1394   $(window).on('resize', orderable_tabs.on_resize);
    1395 })(jQuery, document);
    1396 let orderable_timings = {}; // Make this global so pro modules can access it.
    1397 
    1398 (function ($, document) {
    1399   'use strict';
    1400 
    1401   orderable_timings = {
    1402     /**
    1403      * On doc ready.
    1404      */
    1405     on_ready() {
    1406       orderable_timings.watch();
    1407     },
    1408     /**
    1409      * Restore current timings.
    1410      */
    1411     restore() {
    1412       const timings = orderable_timings.get_timings();
    1413       if (!timings || !timings.date) {
    1414         return;
    1415       }
    1416       const dateSelect = $('.orderable-order-timings__date');
    1417       if (dateSelect.find('option[value="' + timings.date + '"]').length > 0) {
    1418         dateSelect.val(timings.date);
    1419         dateSelect.change();
    1420       }
    1421       if (!timings.time) {
    1422         return;
    1423       }
    1424       const timeSelect = $('.orderable-order-timings__time');
    1425       if (timeSelect.find('option[value="' + timings.time + '"]').length > 0) {
    1426         timeSelect.val(timings.time);
    1427         timeSelect.change();
    1428       }
    1429     },
    1430     /**
    1431      * Watch for trigger events.
    1432      */
    1433     watch() {
    1434       $(document.body).on('wc_fragments_refreshed', function () {
    1435         orderable_timings.restore();
    1436       });
    1437       $(document.body).on('updated_checkout', function () {
    1438         orderable_timings.restore();
    1439       });
    1440       $(document.body).on('change', '.orderable-order-timings__date', function (event) {
    1441         const $date_field = $(this),
    1442           $selected = $date_field.find('option:selected'),
    1443           slots = $selected.data('orderable-slots'),
    1444           $time_field_wrap = $('.orderable-order-timings--time'),
    1445           $time_field = $('.orderable-order-timings__time'),
    1446           $first_option = $time_field.find('option').first(),
    1447           $asap_option = $time_field.find('option[value="asap"]').first();
    1448         const timings = orderable_timings.get_timings();
    1449         timings.date = $('.orderable-order-timings__date').val();
    1450         window.localStorage.setItem('orderable_timings', JSON.stringify(timings));
    1451         $time_field.html($first_option);
    1452         if ($asap_option) {
    1453           $time_field.append($asap_option);
    1454         }
    1455         if (!slots) {
    1456           $time_field.prop('disabled', true);
    1457           $time_field_wrap.hide();
    1458           return;
    1459         }
    1460         if ('all-day' === slots[0].value) {
    1461           $time_field_wrap.hide();
    1462           $time_field.prop('disabled', true);
    1463         } else {
    1464           $time_field.prop('disabled', false);
    1465           $time_field_wrap.show();
    1466           $.each(slots, function (index, slot) {
    1467             $time_field.append($('<option />').attr('value', slot.value).attr('data-orderable-time-slot-id', slot?.setting_row?.time_slot_id).text(slot.formatted));
    1468           });
    1469         }
    1470       });
    1471       $(document.body).on('change', '.orderable-order-timings__time', function (event) {
    1472         const timings = orderable_timings.get_timings();
    1473         timings.time = $('.orderable-order-timings__time').val();
    1474         window.localStorage.setItem('orderable_timings', JSON.stringify(timings));
    1475         $(this).siblings('input[name="orderable_order_time_slot_id"]').val($(this).find(':selected').attr('data-orderable-time-slot-id'));
    1476       });
    1477     },
    1478     get_timings() {
    1479       return JSON.parse(window.localStorage.getItem('orderable_timings')) || {};
    1480     }
    1481   };
    1482   $(document).ready(orderable_timings.on_ready);
    1483 })(jQuery, document);
    1484 (function ($, document) {
    1485   'use strict';
    1486 
    1487   var orderable_triggers = {
    1488     /**
    1489      * On doc ready.
    1490      */
    1491     on_ready() {
    1492       orderable_triggers.watch();
    1493     },
    1494     /**
    1495      * Watch for trigger events.
    1496      */
    1497     watch() {
    1498       if ('undefined' !== typeof window.orderable_triggers_admin) {
    1499         return;
    1500       }
    1501       $(document.body).on('click', '[data-orderable-trigger]', orderable_triggers.trigger);
    1502     },
    1503     /**
    1504      * Fire trigger.
    1505      * @param e
    1506      */
    1507     trigger(e) {
    1508       // Prevent even bubbling up.
    1509       e.stopImmediatePropagation();
    1510       const $trigger_element = $(this),
    1511         trigger = $trigger_element.data('orderable-trigger');
    1512       if ($trigger_element.is('button') || $trigger_element.is('a')) {
    1513         e.preventDefault();
    1514       }
    1515       $(document.body).trigger('orderable-' + trigger, [$trigger_element]);
    1516     }
    1517   };
    1518   $(document).ready(orderable_triggers.on_ready);
    1519 })(jQuery, document);
  • orderable/trunk/assets/frontend/js/main.min.js

    r3192586 r3237969  
    1 !function(o,e,s){"use strict";var n="scrollBox",r={containerClass:"sb-container",containerNoScrollClass:"sb-container-noscroll",contentClass:"sb-content",scrollbarContainerClass:"sb-scrollbar-container",scrollBarClass:"sb-scrollbar"};function t(e,t){this.element=e,this.settings=o.extend({},r,t),this._defaults=r,this._name=n,this.init()}o.extend(t.prototype,{init:function(){this.addScrollbar(),this.addEvents(),this.onResize()},addScrollbar:function(){o(this.element).addClass(this.settings.containerClass),this.wrapper=o("<div class='"+this.settings.contentClass+"' />"),this.wrapper.append(o(this.element).contents()),o(this.element).append(this.wrapper),this.scollbarContainer=o("<div class='"+this.settings.scrollbarContainerClass+"' />"),this.scrollBar=o("<div class='"+this.settings.scrollBarClass+"' />"),this.scollbarContainer.append(this.scrollBar),o(this.element).prepend(this.scollbarContainer)},addEvents:function(){this.wrapper.on("scroll."+n,o.proxy(this.onScroll,this)),o(e).on("resize."+n,o.proxy(this.onResize,this)),this.scrollBar.on("mousedown."+n,o.proxy(this.onMousedown,this)),this.scrollBar.on("touchstart."+n,o.proxy(this.onTouchstart,this))},onTouchstart:function(t){var r=this,a=(t.preventDefault(),r.scrollBar[0].offsetTop);o(s).on("touchmove."+n,function(e){e=e.touches[0].pageY-t.touches[0].pageY;r.scrollBar[0].style.top=Math.min(r.scollbarContainer[0].clientHeight-r.scrollBar[0].clientHeight,Math.max(0,a+e))+"px",r.wrapper[0].scrollTop=r.wrapper[0].scrollHeight*r.scrollBar[0].offsetTop/r.scollbarContainer[0].clientHeight}),o(s).on("touchend."+n,function(){o(s).off("touchmove."+n),o(s).off("touchend."+n)})},onMousedown:function(t){var r=this,a=(t.preventDefault(),r.scrollBar[0].offsetTop);o(s).on("mousemove."+n,function(e){e=e.pageY-t.pageY;r.scrollBar[0].style.top=Math.min(r.scollbarContainer[0].clientHeight-r.scrollBar[0].clientHeight,Math.max(0,a+e))+"px",r.wrapper[0].scrollTop=r.wrapper[0].scrollHeight*r.scrollBar[0].offsetTop/r.scollbarContainer[0].clientHeight}),o(s).on("mouseup."+n,function(){o(s).off("mousemove."+n),o(s).off("mouseup."+n)})},onResize:function(){this.wrapper.css("max-height",o(this.element).height());var e=this.wrapper[0].clientHeight;this.scrollBar.css("height",this.scollbarContainer[0].clientHeight*e/this.wrapper[0].scrollHeight+"px"),this.scollbarContainer[0].clientHeight<=this.scrollBar[0].clientHeight?o(this.element).addClass(this.settings.containerNoScrollClass):o(this.element).removeClass(this.settings.containerNoScrollClass),this.onScroll()},onScroll:function(){this.scrollBar.css("top",Math.min(this.scollbarContainer[0].clientHeight-this.scrollBar[0].clientHeight,this.scollbarContainer[0].clientHeight*this.wrapper[0].scrollTop/this.wrapper[0].scrollHeight)+"px")}}),o.fn[n]=function(e){return this.each(function(){o.data(this,"plugin_"+n)||o.data(this,"plugin_"+n,new t(this,e))})}}(jQuery,window,document),function(e,o){"use strict";"function"!=typeof e.CustomEvent&&(e.CustomEvent=function(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var r=o.createEvent("CustomEvent");return r.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),r},e.CustomEvent.prototype=e.Event.prototype),o.addEventListener("touchstart",function(e){"true"!==e.target.getAttribute("data-swipe-ignore")&&(c=e.target,l=Date.now(),s=e.touches[0].clientX,n=e.touches[0].clientY,d=i=0)},!1),o.addEventListener("touchmove",function(e){var t;s&&n&&(t=e.touches[0].clientX,e=e.touches[0].clientY,i=s-t,d=n-e)},!1),o.addEventListener("touchend",function(e){var t,r,a,o;c===e.target&&(o=parseInt(_(c,"data-swipe-threshold","20"),10),t=parseInt(_(c,"data-swipe-timeout","500"),10),r=Date.now()-l,a="",e=e.changedTouches||e.touches||[],Math.abs(i)>Math.abs(d)?Math.abs(i)>o&&r<t&&(a=0<i?"swiped-left":"swiped-right"):Math.abs(d)>o&&r<t&&(a=0<d?"swiped-up":"swiped-down"),""!==a&&(o={dir:a.replace(/swiped-/,""),touchType:(e[0]||{}).touchType||"direct",xStart:parseInt(s,10),xEnd:parseInt((e[0]||{}).clientX||-1,10),yStart:parseInt(n,10),yEnd:parseInt((e[0]||{}).clientY||-1,10)},c.dispatchEvent(new CustomEvent("swiped",{bubbles:!0,cancelable:!0,detail:o})),c.dispatchEvent(new CustomEvent(a,{bubbles:!0,cancelable:!0,detail:o}))),l=n=s=null)},!1);var s=null,n=null,i=null,d=null,l=null,c=null;function _(e,t,r){for(;e&&e!==o.documentElement;){var a=e.getAttribute(t);if(a)return a;e=e.parentNode}return r}}(window,document),function(o,s){"use strict";var n={on_ready(){n.cache(),n.watch()},cache(){n.vars={classes:{parent:"orderable-accordion",link:"orderable-accordion__item-link",content:"orderable-accordion__item-content",link_active:"orderable-accordion__item-link--active",content_active:"orderable-accordion__item-content--active"}}},watch(){o(s.body).on("click","."+n.vars.classes.link,function(e){e.preventDefault();var e=o(this),t=e.closest("."+n.vars.classes.parent),r=e.attr("href"),r=o(r),a=e.hasClass(n.vars.classes.link_active);t.find("."+n.vars.classes.link).removeClass(n.vars.classes.link_active),t.find("."+n.vars.classes.content).removeClass(n.vars.classes.content_active),a||(e.addClass(n.vars.classes.link_active),r.addClass(n.vars.classes.content_active)),o(s.body).trigger("orderable-accordion.toggled",{link:e,content:r})}),o(s.body).on("orderable-scrollbar.created",function(e,t){var r=o(".orderable-drawer ."+n.vars.classes.link_active);r.length<=0||(r=(t=t.content).scrollTop()-t.offset().top+r.offset().top,t.scrollTop(r))})}};o(s).ready(n.on_ready)}(jQuery,document),function(l,c){"use strict";var r={debounce(t,r=700){let a;return(...e)=>{clearTimeout(a),a=setTimeout(()=>{t.apply(this,e)},r)}},allow_only_numbers(e){var t=String.fromCharCode(e.which);/^\d+$/.test(t)||e.preventDefault()},on_change_quantity(e){const t=l(e.currentTarget);var e=t.data("orderable-product-id"),r=t.data("orderable-cart-item-key"),a=parseInt(t.text());jQuery.post(orderable_vars.ajax_url,{action:"orderable_cart_quantity",cart_item_key:r,product_id:e,quantity:a},function(e){e&&(l(c.body).trigger("added_to_cart",[e.fragments,e.cart_hash,t]),l(c.body).trigger("orderable-drawer.quantity-updated"))})},on_ready(){r.cache(),r.watch(),l(c.body).on("keypress",".orderable-quantity-roller__quantity",r.allow_only_numbers),l(".orderable-drawer__cart, .orderable-product--add-to-cart, .orderable-products-list").on("input",".orderable-quantity-roller__quantity",r.debounce(r.on_change_quantity)),l(c.body).on("click",".orderable-quantity-roller__quantity",function(e){e.stopPropagation()}),orderable_vars&&!orderable_vars.woocommerce_enable_ajax_add_to_cart&&l(c.body).off("click",".add_to_cart_button")},cache(){r.vars={classes:{overlay:"orderable-drawer-overlay",drawer:"orderable-drawer",drawer_cart:"orderable-drawer__cart",drawer_html:"orderable-drawer__html",overlay_open:"orderable-drawer-overlay--open",drawer_open:"orderable-drawer--open",drawer_open_body:"orderable-drawer-open"}},r.elements={body:l("body"),overlay:l("."+r.vars.classes.overlay),drawer:l("."+r.vars.classes.drawer),drawer_cart:l("."+r.vars.classes.drawer_cart),drawer_html:l("."+r.vars.classes.drawer_html),floating_cart_button_class:".orderable-floating-cart__button"}},watch(){var e,t;void 0!==r.elements.drawer&&(l(c.body).on("orderable-drawer.open",r.open),l(c.body).on("orderable-drawer.close",r.close),l(c.body).on("click",r.elements.floating_cart_button_class,function(){l(c.body).trigger("orderable-drawer.open",{show_cart:!0})}),l(c.body).on("orderable-increase-quantity",r.cart.handle_quantity_change_by_button),l(c.body).on("orderable-decrease-quantity",r.cart.handle_quantity_change_by_button),e=r.debounce(r.cart.click_increase_decrease_quantity),l(c.body).on("orderable-increase-quantity",e),l(c.body).on("orderable-decrease-quantity",e),e=c.querySelector("body:not( .rtl ) .orderable-drawer"),t=c.querySelector("body.rtl .orderable-drawer"),e&&e.addEventListener("swiped-right",function(e){r.close()}),t)&&t.addEventListener("swiped-left",function(e){r.close()})},open(e,t){t.html=t.html||!1,t.show_cart=t.show_cart||!1,r.elements.drawer_html.hide(),r.elements.drawer_cart.hide(),t.html&&(r.elements.drawer_html.html(t.html),r.elements.drawer_html.show()),t.show_cart&&(r.elements.drawer_html.html(""),r.elements.drawer_cart.show()),r.elements.overlay.addClass(r.vars.classes.overlay_open),r.elements.drawer.addClass(r.vars.classes.drawer_open),r.elements.body.addClass(r.vars.classes.drawer_open_body),l(c.body).trigger("orderable-drawer.opened",t)},close(){r.elements.overlay.removeClass(r.vars.classes.overlay_open),r.elements.drawer.removeClass(r.vars.classes.drawer_open),r.elements.body.removeClass(r.vars.classes.drawer_open_body),r.elements.drawer_html.html(""),l(c.body).trigger("orderable-drawer.closed")},cart:{click_increase_decrease_quantity(e,r){var t=r.data("orderable-trigger"),a=r.attr("data-orderable-product-id"),o=r.attr("data-orderable-cart-item-key"),s=r.attr("data-orderable-quantity");const n=r.siblings(".orderable-quantity-roller__button--"+("increase-quantity"===t?"decrease":"increase")),i=r.siblings(".orderable-quantity-roller__quantity"),d={action:"orderable_cart_quantity",cart_item_key:o,product_id:a,quantity:s};this.currentRequest&&(this.currentRequest.abort(),this.currentRequest=void 0),r.addClass("orderable-button--loading"),r.attr("disabled",!0),n.attr("disabled",!0),i.attr("contenteditable",!1),this.currentRequest=jQuery.post(orderable_vars.ajax_url,d,function(e){if(e){var t=r.siblings(".orderable-quantity-roller__quantity");switch(e&&e.fragments&&e.fragments[".orderable-mini-cart__notices"]&&l(c.body).trigger("orderable-drawer.open",{show_cart:!0}),d.quantity){case"0":l(c.body).trigger("removed_from_cart",[e.fragments,e.cart_hash,r]);break;case t.attr("data-orderable-updating-quantity"):l(c.body).trigger("added_to_cart",[e.fragments,e.cart_hash,r]),l(c.body).trigger("orderable-drawer.quantity-updated")}}}.bind(this)).always(function(){this.currentRequest=void 0,r.removeClass("orderable-button--loading"),r.attr("disabled",!1),n.attr("disabled",!1),i.attr("contenteditable",!0)}.bind(this))},handle_quantity_change_by_button(e,t){var r,a=t.data("orderable-trigger"),o=parseInt(t.attr("data-orderable-quantity")),s=t.siblings(".orderable-quantity-roller__button--"+("increase-quantity"===a?"decrease":"increase")),n=t.siblings(".orderable-quantity-roller__quantity"),a="increase-quantity"===a?o+1:Math.max(0,o-1),o=t.parents(".orderable-product__actions-button");0===a&&o.length&&(r=o.find("button.orderable-button[data-orderable-trigger]"),(o=o.find(".orderable-quantity-roller")).length)&&(r.removeClass("orderable-button--product-in-the-cart"),o.removeClass("orderable-quantity-roller--is-active")),t.attr("data-orderable-quantity",a),s.attr("data-orderable-quantity",a),n.attr("data-orderable-updating-quantity",a),n.text(a),n.attr("contenteditable",!1)}}};l(c).ready(r.on_ready)}(jQuery,document),function(d,l){"use strict";var c={on_ready(){c.cache(),c.watch()},cache(){c.vars={classes:{clickable_product:"orderable-product--add-to-cart ",add_to_order_button:"orderable-product__add-to-order",product_messages:"orderable-product__messages",product_price:"orderable-product__actions-price",invalid_field:"orderable-field--invalid",option_select_td:"orderable-product__option-select",button_loading:"orderable-button--loading",out_of_stock:"orderable-button--out-of-stock"},parent_price:null,variable_product_types:["variable","variable-subscription"]},c.elements={}},watch(){d(l.body).on("orderable-drawer.opened",c.init_product_options),d(l.body).on("orderable-add-to-cart",c.click_add_to_order),d(l.body).on("orderable-product-options",c.click_add_to_order),d(l.body).on("orderable-view-product",c.view_product),d(l.body).on("mouseenter mouseleave","."+c.vars.classes.clickable_product,c.simulate_add_to_order_hover),d(l.body).on("orderable-edit-cart-item",c.edit_cart_item),d(l.body).on("orderable-update-cart-item",c.update_cart_item),d(l.body).on("orderable-show-cart",c.show_cart),d(l.body).on("orderable-add-to-cart-without-side-drawer",c.click_add_to_order),d(l.body).on("added_to_cart",c.remove_fragments),d(l.body).on("added_to_cart",c.remove_animation),d(l.body).on("added_to_cart",c.shake_floating_cart),d(l.body).on("removed_from_cart",c.hide_quantity_roller),d(l.body).on("wc_cart_button_updated",c.remove_view_cart_link)},simulate_add_to_order_hover(e){d(this).find("."+c.vars.classes.add_to_order_button).toggleClass("orderable-button--hover","mouseenter"===e.type)},click_add_to_order(e,t){const r=(t=void 0!==t?t:d(this)).is("button")?t:t.find("."+c.vars.classes.add_to_order_button),a=r.data("orderable-trigger"),o=r.data("orderable-product-id"),s=r.data("orderable-variation-id"),n=r.data("orderable-variation-attributes"),i={action:a};if(!r.hasClass(c.vars.classes.button_loading)&&!r.hasClass(c.vars.classes.out_of_stock))switch(r.addClass(c.vars.classes.button_loading),a){case"add-to-cart":c.add_to_cart({product_id:o,variation_id:s,attributes:n,thisbutton:t},function(e){i.show_cart=!0,i.response=e,d(l.body).trigger("orderable-drawer.open",i),r.removeClass(c.vars.classes.button_loading);e=d(".orderable-product .orderable-product__actions-button button.orderable-product__add-to-order[data-orderable-product-id="+o+"]");e.siblings(".orderable-quantity-roller").length&&e.addClass("orderable-button--product-in-the-cart")});break;case"add-to-cart-without-side-drawer":c.add_to_cart({product_id:o,variation_id:s,attributes:n},function(e){i.response=e,r.addClass("orderable-button--product-in-the-cart"),r.removeClass(c.vars.classes.button_loading)});break;case"product-options":c.get_product_options({product_id:o,focus:r.data("orderable-focus")},function(e){i.html=e.html,d(l.body).trigger("orderable-drawer.open",i),r.removeClass(c.vars.classes.button_loading)})}},show_cart(){d(l.body).trigger("orderable-drawer.open",{show_cart:!0})},view_product(e,t){const r=t.data("orderable-product-id"),a={action:"product-options"};c.get_product_options({product_id:r,focus:t.data("orderable-focus")},function(e){a.html=e.html,d(l.body).trigger("orderable-drawer.open",a)})},add_to_cart(t,r){if(void 0!==t.product_id){let e={action:"orderable_add_to_cart",product_id:t.product_id,variation_id:t.variation_id||!1,attributes:t.attributes||!1};var a;d(".orderable-product-fields-group").length&&(a=jQuery(".orderable-product-fields-group :input").serializeArray(),a=c.add_unchecked_checkbox_fields(a),a=c.convert_to_flat_object(a),jQuery.isEmptyObject(a)||(e=Object.assign(e,a))),jQuery.post(orderable_vars.ajax_url,e,function(e){e&&(d(l.body).trigger("added_to_cart",[e.fragments,e.cart_hash,t.thisbutton]),"function"==typeof r)&&r(e)})}},edit_cart_item(e,t){var r=t.data("orderable-cart-item-key");t.addClass(c.vars.classes.button_loading),c.get_cart_item_options({cart_item_key:r},function(e){e={html:e.html,action:"update-cart-item"};d(l.body).trigger("orderable-drawer.open",e),t.removeClass(c.vars.classes.button_loading)})},update_cart_item(e,r){var t=r.data("orderable-cart-item-key"),a=r.data("orderable-product-id"),o=r.data("orderable-variation-id"),s=r.data("orderable-variation-attributes");r.addClass(c.vars.classes.button_loading),c.update_cart_item_options({cart_item_key:t,product_id:a,variation_id:o,attributes:s},function(e){var t={show_cart:!0,response:e};d(l.body).trigger("added_to_cart",[e.fragments,e.cart_hash]),d(l.body).trigger("orderable-drawer.open",t),r.removeClass(c.vars.classes.button_loading)})},convert_to_flat_object(e){const a={};return e.forEach(function(e){var t="[]"===e.name.substr(-2)||Array.isArray(e.name),r=t?e.name.substr(0,e.name.length-2):e.name;t?(a[r]=void 0===a[r]?[]:a[r],a[r].push(e.value)):a[r]=e.value}),a},get_product_options(e,t){void 0!==e.product_id&&(e.action="orderable_get_product_options",jQuery.post(orderable_vars.ajax_url,e,function(e){e.success&&"function"==typeof t&&t(e.data)}))},get_cart_item_options(e,t){void 0!==e.cart_item_key&&(e.action="orderable_get_cart_item_options",jQuery.post(orderable_vars.ajax_url,e,function(e){e.success&&"function"==typeof t&&t(e.data)}))},update_cart_item_options(e,t){var r;void 0!==e.cart_item_key&&(e.action="orderable_update_cart_item_options",d(".orderable-product-fields-group").length&&(r=jQuery(".orderable-product-fields-group :input").serializeArray(),r=c.add_unchecked_checkbox_fields(r),r=c.convert_to_flat_object(r),jQuery.isEmptyObject(r)||(e=Object.assign(e,r))),jQuery.post(orderable_vars.ajax_url,e,function(e){e&&"function"==typeof t&&t(e)}))},init_product_options(e,t){if(void 0!==t.action&&("product-options"===t.action||"update-cart-item"===t.action)){t=".orderable-drawer .orderable-product__options input, .orderable-drawer .orderable-product__options select, .orderable-product__options textarea";const r=d(t),a=(c.vars.parent_price=d(".orderable-drawer .orderable-product__actions-price").html(),c.product_options_change(r),c.update_button_state(),c.debounce(c.update_button_state,500)),o=c.debounce(c.product_options_change,500);d(l).on("change keyup",t,function(){o(r),a()})}},product_options_change(e){var t=d(".orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item"),r=c.check_options(e),a=t.data("orderable-product-type");"product-options"===t.attr("data-orderable-trigger")&&t.attr("data-orderable-trigger","add-to-cart"),d("."+c.vars.classes.product_messages).html(""),c.vars.variable_product_types.includes(a)&&(r?(a=c.check_variation(e),c.set_variation(t,a)):c.clear_variation(t))},check_options(e){if(e.length<=0)return!1;let r=!0;return e.each(function(e,t){d(t).hasClass("orderable-input--validate")&&(""===d(t).val()?(d(t).addClass(c.vars.classes.invalid_field),r=!1):d(t).removeClass(c.vars.classes.invalid_field))}),r},check_variation(e){var t=(t=e.closest(".orderable-drawer").find(".orderable-product__variations").text())?JSON.parse(t):"",e=c.serialize_object(e),t=c.find_matching_variations(t,e);return!c.is_empty(t)&&((t=t.shift()).attributes=e,t.attributes_json=JSON.stringify(e),void 0!==t)&&t},set_variation(e,t){let r=t.variation_id||"",a=t.attributes_json||"",o=t.price_html||c.vars.parent_price,s="";t&&""!==t.availability_html&&(s=t.availability_html),t&&!t.is_in_stock&&(s="<p>"+orderable_vars.i18n.out_of_stock+"</p>"),t&&!t.is_purchasable&&(s="<p>"+orderable_vars.i18n.unavailable+"</p>"),!1===t&&(s="<p>"+orderable_vars.i18n.no_exist+"</p>"),!t||t.is_purchasable&&t.is_in_stock||(r="",a=""),""!==s&&d("."+c.vars.classes.product_messages).html(s),e.data("orderable-variation-id",r),e.data("orderable-variation-attributes",a),d(".orderable-drawer .orderable-product__actions-price").html(o),e.trigger("orderable_variation_set",{variation:t,variation_id:r,attributes:a,price:o})},clear_variation(e){c.set_variation(e,""),c.vars.parent_price&&d(".orderable-drawer .orderable-product__actions-price").html(c.vars.parent_price)},find_matching_variations(t,r){var a=[];for(let e=0;e<t.length;e++){var o=t[e];c.is_matching_variation(o.attributes,r)&&a.push(o)}return a},is_matching_variation(e,t){let r=!0;for(const s in e){var a,o;e.hasOwnProperty(s)&&(a=e[s],o=t[s],void 0!==a)&&void 0!==o&&0!==a.length&&0!==o.length&&a!==o&&(r=!1)}return r},is_empty(e){return void 0===e||!1===e||e.length<=0||!e},serialize_object:function(e){var t=e.serializeArray(),r={};for(let e=0;e<t.length;e++)r[t[e].name]=t[e].value;return r},update_button_state(){setTimeout(function(){let e=d(".orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item"),t=d(".orderable-drawer__html ."+c.vars.classes.invalid_field).length,r=e.data("orderable-product-type"),a=!0;"variable"===r&&(a=""!==e.data("orderable-variation-id")),e.prop("disabled",t||!a)},50)},debounce(a,o,s){let n;return function(){const e=this,t=arguments;var r=s&&!n;clearTimeout(n),n=setTimeout(function(){n=null,s||a.apply(e,t)},o),r&&a.apply(e,t)}},remove_fragments(e,t){if(t&&"undefined"!=typeof wc_cart_fragments_params&&wc_cart_fragments_params.fragment_name){var r=/\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-quantity-roller/,a=/\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-product__actions-counter/;for(const o in t)(r.test(o)||a.test(o))&&(t[o]=void 0);sessionStorage.setItem(wc_cart_fragments_params.fragment_name,JSON.stringify(t))}},remove_animation(){setTimeout(function(){d(".orderable-product__actions-counter").css("animation","")},1e3)},hide_quantity_roller(e,t,r,a){var o,a=a.attr("data-product_id")||a.attr("data-orderable-product-id");a&&(a=d(".orderable-product[data-orderable-product-id="+a+"] .orderable-product__actions-button")).length&&(o=a.find(".orderable-quantity-roller")).length&&(a.find("button.orderable-product__add-to-order[data-orderable-trigger]").removeClass("orderable-button--product-in-the-cart"),o.addClass("orderable-button--hide"))},add_unchecked_checkbox_fields(r){return jQuery('.orderable-product-fields-group :input[type="checkbox"]:not(:checked)').each(function(e,t){r.push({name:t.getAttribute("name"),value:""})}),r},shake_floating_cart(){d(".orderable-floating-cart__button").css("animation","wobble-hor-bottom .8s both")},remove_view_cart_link(e,t){t?.hasClass("orderable-product__add-to-order")&&t?.siblings(".added_to_cart.wc-forward").remove()}};d(l).ready(c.on_ready)}(jQuery,document),function(o,s){"use strict";var n={on_ready(){n.cache(),n.watch()},cache(){n.vars={top:{}},n.elements={}},watch(){o(s.body).on("orderable-drawer.opened",n.trigger),o(s.body).on("orderable-tabs.changed",n.trigger),o(s.body).on("orderable-accordion.toggled",n.trigger),o(s.body).on("wc_fragments_loaded",n.trigger)},trigger(){o(".orderable-sb-container").each(function(e,t){var r,t=o(t),a=t.data("orderable-scroll-id");n.has_scrollbar(t)||(t.scrollBox({containerClass:"orderable-sb-container",containerNoScrollClass:"orderable-sb-container-noscroll",contentClass:"orderable-sb-content",scrollbarContainerClass:"orderable-sb-scrollbar-container",scrollBarClass:"orderable-sb-scrollbar"}),0<(r=t.find(".orderable-sb-content")).length&&(r.on("scroll.scrollBox",n.log_top_position),void 0!==n.vars.top[a])&&r.scrollTop(n.vars.top[a]),o(s.body).trigger("orderable-scrollbar.created",{element:t,content:r}))}),o(window).trigger("resize.scrollBox")},has_scrollbar(e){return 0<e.find(".orderable-sb-content").length},log_top_position(e){var t=o(e.currentTarget).closest(".orderable-sb-container").data("orderable-scroll-id");n.vars.top[t]=o(e.currentTarget).scrollTop()}};o(s).ready(n.on_ready)}(jQuery,document),function(n,i){"use strict";var d={on_ready(){d.cache(),d.watch(),d.toggle_scroll()},on_resize(){d.toggle_scroll()},cache(){d.vars={classes:{tabs:"orderable-tabs",tabs_list:"orderable-tabs__list",tab_items:"orderable-tabs__item",tab_item_active:"orderable-tabs__item--active",tab_links:"orderable-tabs__link",tab_arrow_right:"orderable-tabs__arrow-right",tab_arrow_left:"orderable-tabs__arrow-left"},dragging:!1},d.elements={}},watch(){n("body").on("touchstart",function(){d.vars.dragging=!1}).on("touchmove",function(){d.vars.dragging=!0}),n(i.body).on("click mouseup touchend","."+d.vars.classes.tab_links,function(e){var t,r,a,o,s;d.vars.dragging||(e.preventDefault(),t=(e=n(this)).attr("href"),r=e.closest("."+d.vars.classes.tab_items),a=(s=e.closest("."+d.vars.classes.tabs)).find("."+d.vars.classes.tabs_list),o=s.find("."+d.vars.classes.tab_items),s=s.data("orderable-tabs"),s=(e=e.closest(s.wrapper)).find(s.sections),e=e.find(t),s.hide(),e.show(),o.removeClass(d.vars.classes.tab_item_active),r.addClass(d.vars.classes.tab_item_active),a.animate({scrollLeft:a.scrollLeft()+r.position().left}),n(i.body).trigger("orderable-tabs.changed",{tab:r}))}),n("."+d.vars.classes.tabs_list).on("scroll",function(e){var t=n(this),r=t.parent("."+d.vars.classes.tabs),a=t.siblings("."+d.vars.classes.tab_arrow_right),o=t.siblings("."+d.vars.classes.tab_arrow_left);t[0].scrollWidth<=r.width()+t.scrollLeft()?a.fadeOut():a.fadeIn(),t.scrollLeft()-o.width()<=0?o.fadeOut():o.fadeIn()}),n("."+d.vars.classes.tabs_list).on("wheel DOMMouseScroll mousewheel touchmove",function(){n(this).stop()}),n(i).on("click","."+d.vars.classes.tab_arrow_right,function(e){e.preventDefault();var e=n(this).parent(),t=e.find("."+d.vars.classes.tabs_list);t.animate({scrollLeft:t.scrollLeft()+.5*e.width()})}),n(i).on("click","."+d.vars.classes.tab_arrow_left,function(e){e.preventDefault();var e=n(this).parent(),t=e.find("."+d.vars.classes.tabs_list);t.animate({scrollLeft:t.scrollLeft()-.5*e.width()})})},toggle_scroll(){n("."+d.vars.classes.tabs).each(function(e,t){var r=n(this),a=r.data("orderable-tabs"),r=r.closest(a.wrapper),a=r.find("."+d.vars.classes.tabs_list),o=r.find("."+d.vars.classes.tab_arrow_right);r.outerWidth()<a[0].scrollWidth?o.show():o.hide()})}};n(i).ready(d.on_ready),n(window).on("resize",d.on_resize)}(jQuery,document);let orderable_timings={};!function(l,e){"use strict";orderable_timings={on_ready(){orderable_timings.watch()},restore(){var e,t=orderable_timings.get_timings();t&&t.date&&(0<(e=l(".orderable-order-timings__date")).find('option[value="'+t.date+'"]').length&&(e.val(t.date),e.change()),t.time)&&0<(e=l(".orderable-order-timings__time")).find('option[value="'+t.time+'"]').length&&(e.val(t.time),e.change())},watch(){l(e.body).on("wc_fragments_refreshed",function(){orderable_timings.restore()}),l(e.body).on("updated_checkout",function(){orderable_timings.restore()}),l(e.body).on("change",".orderable-order-timings__date",function(e){const t=l(this),r=t.find("option:selected"),a=r.data("orderable-slots"),o=l(".orderable-order-timings--time"),s=l(".orderable-order-timings__time"),n=s.find("option").first(),i=s.find('option[value="asap"]').first();var d=orderable_timings.get_timings();d.date=l(".orderable-order-timings__date").val(),window.localStorage.setItem("orderable_timings",JSON.stringify(d)),s.html(n),i&&s.append(i),a?"all-day"===a[0].value?(o.hide(),s.prop("disabled",!0)):(s.prop("disabled",!1),o.show(),l.each(a,function(e,t){s.append(l("<option />").attr("value",t.value).attr("data-orderable-time-slot-id",t?.setting_row?.time_slot_id).text(t.formatted))})):(s.prop("disabled",!0),o.hide())}),l(e.body).on("change",".orderable-order-timings__time",function(e){var t=orderable_timings.get_timings();t.time=l(".orderable-order-timings__time").val(),window.localStorage.setItem("orderable_timings",JSON.stringify(t)),l(this).siblings('input[name="orderable_order_time_slot_id"]').val(l(this).find(":selected").attr("data-orderable-time-slot-id"))})},get_timings(){return JSON.parse(window.localStorage.getItem("orderable_timings"))||{}}},l(e).ready(orderable_timings.on_ready)}(jQuery,document),function(a,o){"use strict";var e={on_ready(){e.watch()},watch(){void 0===window.orderable_triggers_admin&&a(o.body).on("click","[data-orderable-trigger]",e.trigger)},trigger(e){e.stopImmediatePropagation();var t=a(this),r=t.data("orderable-trigger");(t.is("button")||t.is("a"))&&e.preventDefault(),a(o.body).trigger("orderable-"+r,[t])}};a(o).ready(e.on_ready)}(jQuery,document);
     1((o,s)=>{var i={on_ready(){i.cache(),i.watch()},cache(){i.vars={classes:{parent:"orderable-accordion",link:"orderable-accordion__item-link",content:"orderable-accordion__item-content",link_active:"orderable-accordion__item-link--active",content_active:"orderable-accordion__item-content--active"}}},watch(){o(s.body).on("click","."+i.vars.classes.link,function(e){e.preventDefault();var e=o(this),t=e.closest("."+i.vars.classes.parent),r=e.attr("href"),r=o(r),a=e.hasClass(i.vars.classes.link_active);t.find("."+i.vars.classes.link).removeClass(i.vars.classes.link_active),t.find("."+i.vars.classes.content).removeClass(i.vars.classes.content_active),a||(e.addClass(i.vars.classes.link_active),r.addClass(i.vars.classes.content_active)),o(s.body).trigger("orderable-accordion.toggled",{link:e,content:r})}),o(s.body).on("orderable-scrollbar.created",function(e,t){var r=o(".orderable-drawer ."+i.vars.classes.link_active);r.length<=0||(r=(t=t.content).scrollTop()-t.offset().top+r.offset().top,t.scrollTop(r))})}};o(s).ready(i.on_ready)})(jQuery,document),((l,c)=>{var r={debounce(t,r=700){let a;return(...e)=>{clearTimeout(a),a=setTimeout(()=>{t.apply(this,e)},r)}},allow_only_numbers(e){var t=String.fromCharCode(e.which);/^\d+$/.test(t)||e.preventDefault()},on_change_quantity(e){let t=l(e.currentTarget);var e=t.data("orderable-product-id"),r=t.data("orderable-cart-item-key"),a=parseInt(t.text());jQuery.post(orderable_vars.ajax_url,{action:"orderable_cart_quantity",cart_item_key:r,product_id:e,quantity:a},function(e){e&&(l(c.body).trigger("added_to_cart",[e.fragments,e.cart_hash,t]),l(c.body).trigger("orderable-drawer.quantity-updated"))})},on_ready(){r.cache(),r.watch(),l(c.body).on("keypress",".orderable-quantity-roller__quantity",r.allow_only_numbers),l(".orderable-drawer__cart, .orderable-product--add-to-cart, .orderable-products-list").on("input",".orderable-quantity-roller__quantity",r.debounce(r.on_change_quantity)),l(c.body).on("click",".orderable-quantity-roller__quantity",function(e){e.stopPropagation()}),orderable_vars&&!orderable_vars.woocommerce_enable_ajax_add_to_cart&&l(c.body).off("click",".add_to_cart_button")},cache(){r.vars={classes:{overlay:"orderable-drawer-overlay",drawer:"orderable-drawer",drawer_cart:"orderable-drawer__cart",drawer_html:"orderable-drawer__html",overlay_open:"orderable-drawer-overlay--open",drawer_open:"orderable-drawer--open",drawer_open_body:"orderable-drawer-open"}},r.elements={body:l("body"),overlay:l("."+r.vars.classes.overlay),drawer:l("."+r.vars.classes.drawer),drawer_cart:l("."+r.vars.classes.drawer_cart),drawer_html:l("."+r.vars.classes.drawer_html),floating_cart_button_class:".orderable-floating-cart__button"}},watch(){var e,t;void 0!==r.elements.drawer&&(l(c.body).on("orderable-drawer.open",r.open),l(c.body).on("orderable-drawer.close",r.close),l(c.body).on("click",r.elements.floating_cart_button_class,function(){l(c.body).trigger("orderable-drawer.open",{show_cart:!0})}),l(c.body).on("orderable-increase-quantity",r.cart.handle_quantity_change_by_button),l(c.body).on("orderable-decrease-quantity",r.cart.handle_quantity_change_by_button),e=r.debounce(r.cart.click_increase_decrease_quantity),l(c.body).on("orderable-increase-quantity",e),l(c.body).on("orderable-decrease-quantity",e),e=c.querySelector("body:not( .rtl ) .orderable-drawer"),t=c.querySelector("body.rtl .orderable-drawer"),e&&e.addEventListener("swiped-right",function(e){r.close()}),t)&&t.addEventListener("swiped-left",function(e){r.close()})},open(e,t){t.html=t.html||!1,t.show_cart=t.show_cart||!1,r.elements.drawer_html.hide(),r.elements.drawer_cart.hide(),t.html&&(r.elements.drawer_html.html(t.html),r.elements.drawer_html.show()),t.show_cart&&(r.elements.drawer_html.html(""),r.elements.drawer_cart.show()),r.elements.overlay.addClass(r.vars.classes.overlay_open),r.elements.drawer.addClass(r.vars.classes.drawer_open),r.elements.body.addClass(r.vars.classes.drawer_open_body),l(c.body).trigger("orderable-drawer.opened",t)},close(){r.elements.overlay.removeClass(r.vars.classes.overlay_open),r.elements.drawer.removeClass(r.vars.classes.drawer_open),r.elements.body.removeClass(r.vars.classes.drawer_open_body),r.elements.drawer_html.html(""),l(c.body).trigger("orderable-drawer.closed")},cart:{click_increase_decrease_quantity(e,r){var t=r.data("orderable-trigger"),a=r.attr("data-orderable-product-id"),o=r.attr("data-orderable-cart-item-key"),s=r.attr("data-orderable-quantity");let i=r.siblings(".orderable-quantity-roller__button--"+("increase-quantity"===t?"decrease":"increase")),n=r.siblings(".orderable-quantity-roller__quantity"),d={action:"orderable_cart_quantity",cart_item_key:o,product_id:a,quantity:s};this.currentRequest&&(this.currentRequest.abort(),this.currentRequest=void 0),r.addClass("orderable-button--loading"),r.attr("disabled",!0),i.attr("disabled",!0),n.attr("contenteditable",!1),this.currentRequest=jQuery.post(orderable_vars.ajax_url,d,function(e){if(e){var t=r.siblings(".orderable-quantity-roller__quantity");switch(e&&e.fragments&&e.fragments[".orderable-mini-cart__notices"]&&l(c.body).trigger("orderable-drawer.open",{show_cart:!0}),d.quantity){case"0":l(c.body).trigger("removed_from_cart",[e.fragments,e.cart_hash,r]);break;case t.attr("data-orderable-updating-quantity"):l(c.body).trigger("added_to_cart",[e.fragments,e.cart_hash,r]),l(c.body).trigger("orderable-drawer.quantity-updated")}}}.bind(this)).always(function(){this.currentRequest=void 0,r.removeClass("orderable-button--loading"),r.attr("disabled",!1),i.attr("disabled",!1),n.attr("contenteditable",!0)}.bind(this))},handle_quantity_change_by_button(e,t){var r,a=t.data("orderable-trigger"),o=parseInt(t.attr("data-orderable-quantity")),s=t.siblings(".orderable-quantity-roller__button--"+("increase-quantity"===a?"decrease":"increase")),i=t.siblings(".orderable-quantity-roller__quantity"),a="increase-quantity"===a?o+1:Math.max(0,o-1),o=t.parents(".orderable-product__actions-button");0===a&&o.length&&(r=o.find("button.orderable-button[data-orderable-trigger]"),(o=o.find(".orderable-quantity-roller")).length)&&(r.removeClass("orderable-button--product-in-the-cart"),o.removeClass("orderable-quantity-roller--is-active")),t.attr("data-orderable-quantity",a),s.attr("data-orderable-quantity",a),i.attr("data-orderable-updating-quantity",a),i.text(a),i.attr("contenteditable",!1)}}};l(c).ready(r.on_ready)})(jQuery,document),((d,l)=>{var c={on_ready(){c.cache(),c.watch()},cache(){c.vars={classes:{clickable_product:"orderable-product--add-to-cart ",add_to_order_button:"orderable-product__add-to-order",product_messages:"orderable-product__messages",product_price:"orderable-product__actions-price",invalid_field:"orderable-field--invalid",option_select_td:"orderable-product__option-select",button_loading:"orderable-button--loading",out_of_stock:"orderable-button--out-of-stock"},parent_price:null,variable_product_types:["variable","variable-subscription"]},c.elements={}},watch(){d(l.body).on("orderable-drawer.opened",c.init_product_options),d(l.body).on("orderable-add-to-cart",c.click_add_to_order),d(l.body).on("orderable-product-options",c.click_add_to_order),d(l.body).on("orderable-view-product",c.view_product),d(l.body).on("mouseenter mouseleave","."+c.vars.classes.clickable_product,c.simulate_add_to_order_hover),d(l.body).on("orderable-edit-cart-item",c.edit_cart_item),d(l.body).on("orderable-update-cart-item",c.update_cart_item),d(l.body).on("orderable-show-cart",c.show_cart),d(l.body).on("orderable-add-to-cart-without-side-drawer",c.click_add_to_order),d(l.body).on("added_to_cart",c.remove_fragments),d(l.body).on("added_to_cart",c.remove_animation),d(l.body).on("added_to_cart",c.shake_floating_cart),d(l.body).on("removed_from_cart",c.hide_quantity_roller),d(l.body).on("wc_cart_button_updated",c.remove_view_cart_link)},simulate_add_to_order_hover(e){d(this).find("."+c.vars.classes.add_to_order_button).toggleClass("orderable-button--hover","mouseenter"===e.type)},click_add_to_order(e,t){let r=(t=void 0!==t?t:d(this)).is("button")?t:t.find("."+c.vars.classes.add_to_order_button),a=r.data("orderable-trigger"),o=r.data("orderable-product-id"),s=r.data("orderable-variation-id"),i=r.data("orderable-variation-attributes"),n={action:a};if(!r.hasClass(c.vars.classes.button_loading)&&!r.hasClass(c.vars.classes.out_of_stock))switch(r.addClass(c.vars.classes.button_loading),a){case"add-to-cart":c.add_to_cart({product_id:o,variation_id:s,attributes:i,thisbutton:t},function(e){n.show_cart=!0,n.response=e,d(l.body).trigger("orderable-drawer.open",n),r.removeClass(c.vars.classes.button_loading);e=d(".orderable-product .orderable-product__actions-button button.orderable-product__add-to-order[data-orderable-product-id="+o+"]");e.siblings(".orderable-quantity-roller").length&&e.addClass("orderable-button--product-in-the-cart")});break;case"add-to-cart-without-side-drawer":c.add_to_cart({product_id:o,variation_id:s,attributes:i},function(e){n.response=e,r.addClass("orderable-button--product-in-the-cart"),r.removeClass(c.vars.classes.button_loading)});break;case"product-options":c.get_product_options({product_id:o,focus:r.data("orderable-focus")},function(e){n.html=e.html,d(l.body).trigger("orderable-drawer.open",n),r.removeClass(c.vars.classes.button_loading)})}},show_cart(){d(l.body).trigger("orderable-drawer.open",{show_cart:!0})},view_product(e,t){let r=t.data("orderable-product-id"),a={action:"product-options"};c.get_product_options({product_id:r,focus:t.data("orderable-focus")},function(e){a.html=e.html,d(l.body).trigger("orderable-drawer.open",a)})},add_to_cart(t,r){if(void 0!==t.product_id){let e={action:"orderable_add_to_cart",product_id:t.product_id,variation_id:t.variation_id||!1,attributes:t.attributes||!1};var a;d(".orderable-product-fields-group").length&&(a=jQuery(".orderable-product-fields-group :input").serializeArray(),a=c.add_unchecked_checkbox_fields(a),a=c.convert_to_flat_object(a),jQuery.isEmptyObject(a)||(e=Object.assign(e,a))),jQuery.post(orderable_vars.ajax_url,e,function(e){e&&(d(l.body).trigger("added_to_cart",[e.fragments,e.cart_hash,t.thisbutton]),"function"==typeof r)&&r(e)})}},edit_cart_item(e,t){var r=t.data("orderable-cart-item-key");t.addClass(c.vars.classes.button_loading),c.get_cart_item_options({cart_item_key:r},function(e){e={html:e.html,action:"update-cart-item"};d(l.body).trigger("orderable-drawer.open",e),t.removeClass(c.vars.classes.button_loading)})},update_cart_item(e,r){var t=r.data("orderable-cart-item-key"),a=r.data("orderable-product-id"),o=r.data("orderable-variation-id"),s=r.data("orderable-variation-attributes");r.addClass(c.vars.classes.button_loading),c.update_cart_item_options({cart_item_key:t,product_id:a,variation_id:o,attributes:s},function(e){var t={show_cart:!0,response:e};d(l.body).trigger("added_to_cart",[e.fragments,e.cart_hash,r]),d(l.body).trigger("orderable-drawer.open",t),r.removeClass(c.vars.classes.button_loading)})},convert_to_flat_object(e){let a={};return e.forEach(function(e){var t="[]"===e.name.substr(-2)||Array.isArray(e.name),r=t?e.name.substr(0,e.name.length-2):e.name;t?(a[r]=void 0===a[r]?[]:a[r],a[r].push(e.value)):a[r]=e.value}),a},get_product_options(e,t){void 0!==e.product_id&&(e.action="orderable_get_product_options",jQuery.post(orderable_vars.ajax_url,e,function(e){e.success&&"function"==typeof t&&t(e.data)}))},get_cart_item_options(e,t){void 0!==e.cart_item_key&&(e.action="orderable_get_cart_item_options",jQuery.post(orderable_vars.ajax_url,e,function(e){e.success&&"function"==typeof t&&t(e.data)}))},update_cart_item_options(e,t){var r;void 0!==e.cart_item_key&&(e.action="orderable_update_cart_item_options",d(".orderable-product-fields-group").length&&(r=jQuery(".orderable-product-fields-group :input").serializeArray(),r=c.add_unchecked_checkbox_fields(r),r=c.convert_to_flat_object(r),jQuery.isEmptyObject(r)||(e=Object.assign(e,r))),jQuery.post(orderable_vars.ajax_url,e,function(e){e&&"function"==typeof t&&t(e)}))},init_product_options(e,a){if(void 0!==a.action&&("product-options"===a.action||"update-cart-item"===a.action)){a=".orderable-drawer .orderable-product__options input, .orderable-drawer .orderable-product__options select, .orderable-product__options textarea";let e=d(a),t=(c.vars.parent_price=d(".orderable-drawer .orderable-product__actions-price").html(),c.product_options_change(e),c.update_button_state(),c.debounce(c.update_button_state,500)),r=c.debounce(c.product_options_change,500);d(l).on("change keyup",a,function(){r(e),t()})}},product_options_change(e){var t=d(".orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item"),r=c.check_options(e),a=t.data("orderable-product-type");"product-options"===t.attr("data-orderable-trigger")&&t.attr("data-orderable-trigger","add-to-cart"),d("."+c.vars.classes.product_messages).html(""),c.vars.variable_product_types.includes(a)&&(r?(a=c.check_variation(e),c.set_variation(t,a)):c.clear_variation(t))},check_options(e){if(e.length<=0)return!1;let r=!0;return e.each(function(e,t){d(t).hasClass("orderable-input--validate")&&(""===d(t).val()?(d(t).addClass(c.vars.classes.invalid_field),r=!1):d(t).removeClass(c.vars.classes.invalid_field))}),r},check_variation(e){var t=(t=e.closest(".orderable-drawer").find(".orderable-product__variations").text())?JSON.parse(t):"",e=c.serialize_object(e),t=c.find_matching_variations(t,e);return!c.is_empty(t)&&((t=t.shift()).attributes=e,t.attributes_json=JSON.stringify(e),void 0!==t)&&t},set_variation(e,t){let r=t.variation_id||"",a=t.attributes_json||"",o=t.price_html||c.vars.parent_price,s="";t&&""!==t.availability_html&&(s=t.availability_html),t&&!t.is_in_stock&&(s="<p>"+orderable_vars.i18n.out_of_stock+"</p>"),t&&!t.is_purchasable&&(s="<p>"+orderable_vars.i18n.unavailable+"</p>"),!1===t&&(s="<p>"+orderable_vars.i18n.no_exist+"</p>"),!t||t.is_purchasable&&t.is_in_stock||(r="",a=""),""!==s&&d("."+c.vars.classes.product_messages).html(s),e.data("orderable-variation-id",r),e.data("orderable-variation-attributes",a),d(".orderable-drawer .orderable-product__actions-price").html(o),e.trigger("orderable_variation_set",{variation:t,variation_id:r,attributes:a,price:o})},clear_variation(e){c.set_variation(e,""),c.vars.parent_price&&d(".orderable-drawer .orderable-product__actions-price").html(c.vars.parent_price)},find_matching_variations(t,r){var a=[];for(let e=0;e<t.length;e++){var o=t[e];c.is_matching_variation(o.attributes,r)&&a.push(o)}return a},is_matching_variation(e,t){let r=!0;for(var a in e){var o;e.hasOwnProperty(a)&&(o=e[a],a=t[a],void 0!==o)&&void 0!==a&&0!==o.length&&0!==a.length&&o!==a&&(r=!1)}return r},is_empty(e){return void 0===e||!1===e||e.length<=0||!e},serialize_object:function(e){var t=e.serializeArray(),r={};for(let e=0;e<t.length;e++)r[t[e].name]=t[e].value;return r},update_button_state(){setTimeout(function(){let e=d(".orderable-drawer .orderable-product__add-to-order, .orderable-drawer .orderable-product__update-cart-item"),t=d(".orderable-drawer__html ."+c.vars.classes.invalid_field).length,r=e.data("orderable-product-type"),a=!0;"variable"===r&&(a=""!==e.data("orderable-variation-id")),e.prop("disabled",t||!a)},50)},debounce(a,o,s){let i;return function(){let e=this,t=arguments;var r=s&&!i;clearTimeout(i),i=setTimeout(function(){i=null,s||a.apply(e,t)},o),r&&a.apply(e,t)}},remove_fragments(e,t){if(t&&"undefined"!=typeof wc_cart_fragments_params&&wc_cart_fragments_params.fragment_name){var r,a=/\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-quantity-roller/,o=/\.orderable-product\[data-orderable-product-id='[1-9][0-9]*'\] \.orderable-product__actions-button \.orderable-product__actions-counter/;for(r in t)(a.test(r)||o.test(r))&&(t[r]=void 0);sessionStorage.setItem(wc_cart_fragments_params.fragment_name,JSON.stringify(t))}},remove_animation(){setTimeout(function(){d(".orderable-product__actions-counter").css("animation","")},1e3)},hide_quantity_roller(e,t,r,a){var o,a=a.attr("data-product_id")||a.attr("data-orderable-product-id");a&&(a=d(".orderable-product[data-orderable-product-id="+a+"] .orderable-product__actions-button")).length&&(o=a.find(".orderable-quantity-roller")).length&&(a.find("button.orderable-product__add-to-order[data-orderable-trigger]").removeClass("orderable-button--product-in-the-cart"),o.addClass("orderable-button--hide"))},add_unchecked_checkbox_fields(r){return jQuery('.orderable-product-fields-group :input[type="checkbox"]:not(:checked)').each(function(e,t){r.push({name:t.getAttribute("name"),value:""})}),r},shake_floating_cart(){d(".orderable-floating-cart__button").css("animation","wobble-hor-bottom .8s both")},remove_view_cart_link(e,t){t?.hasClass("orderable-product__add-to-order")&&t?.siblings(".added_to_cart.wc-forward").remove()}};d(l).ready(c.on_ready)})(jQuery,document),((o,s)=>{var i={on_ready(){i.cache(),i.watch()},cache(){i.vars={top:{}},i.elements={}},watch(){o(s.body).on("orderable-drawer.opened",i.trigger),o(s.body).on("orderable-tabs.changed",i.trigger),o(s.body).on("orderable-accordion.toggled",i.trigger),o(s.body).on("wc_fragments_loaded",i.trigger)},trigger(){o(".orderable-sb-container").each(function(e,t){var r,t=o(t),a=t.data("orderable-scroll-id");i.has_scrollbar(t)||(t.scrollBox({containerClass:"orderable-sb-container",containerNoScrollClass:"orderable-sb-container-noscroll",contentClass:"orderable-sb-content",scrollbarContainerClass:"orderable-sb-scrollbar-container",scrollBarClass:"orderable-sb-scrollbar"}),0<(r=t.find(".orderable-sb-content")).length&&(r.on("scroll.scrollBox",i.log_top_position),void 0!==i.vars.top[a])&&r.scrollTop(i.vars.top[a]),o(s.body).trigger("orderable-scrollbar.created",{element:t,content:r}))}),o(window).trigger("resize.scrollBox")},has_scrollbar(e){return 0<e.find(".orderable-sb-content").length},log_top_position(e){var t=o(e.currentTarget).closest(".orderable-sb-container").data("orderable-scroll-id");i.vars.top[t]=o(e.currentTarget).scrollTop()}};o(s).ready(i.on_ready)})(jQuery,document),((i,n)=>{var d={on_ready(){d.cache(),d.watch(),d.toggle_scroll()},on_resize(){void 0===d.vars&&d.cache(),d.toggle_scroll()},cache(){d.vars={classes:{tabs:"orderable-tabs",tabs_list:"orderable-tabs__list",tab_items:"orderable-tabs__item",tab_item_active:"orderable-tabs__item--active",tab_links:"orderable-tabs__link",tab_arrow_right:"orderable-tabs__arrow-right",tab_arrow_left:"orderable-tabs__arrow-left"},dragging:!1},d.elements={}},watch(){i("body").on("touchstart",function(){d.vars.dragging=!1}).on("touchmove",function(){d.vars.dragging=!0}),i(n.body).on("click mouseup touchend","."+d.vars.classes.tab_links,function(e){var t,r,a,o,s;d.vars.dragging||(e.preventDefault(),t=(e=i(this)).attr("href"),r=e.closest("."+d.vars.classes.tab_items),a=(s=e.closest("."+d.vars.classes.tabs)).find("."+d.vars.classes.tabs_list),o=s.find("."+d.vars.classes.tab_items),s=s.data("orderable-tabs"),s=(e=e.closest(s.wrapper)).find(s.sections),e=e.find(t),s.hide(),e.show(),o.removeClass(d.vars.classes.tab_item_active),r.addClass(d.vars.classes.tab_item_active),a.animate({scrollLeft:a.scrollLeft()+r.position().left}),i(n.body).trigger("orderable-tabs.changed",{tab:r}))}),i("."+d.vars.classes.tabs_list).on("scroll",function(e){var t=i(this),r=t.parent("."+d.vars.classes.tabs),a=t.siblings("."+d.vars.classes.tab_arrow_right),o=t.siblings("."+d.vars.classes.tab_arrow_left);t[0].scrollWidth<=r.width()+t.scrollLeft()?a.fadeOut():a.fadeIn(),t.scrollLeft()-o.width()<=0?o.fadeOut():o.fadeIn()}),i("."+d.vars.classes.tabs_list).on("wheel DOMMouseScroll mousewheel touchmove",function(){i(this).stop()}),i(n).on("click","."+d.vars.classes.tab_arrow_right,function(e){e.preventDefault();var e=i(this).parent(),t=e.find("."+d.vars.classes.tabs_list);t.animate({scrollLeft:t.scrollLeft()+.5*e.width()})}),i(n).on("click","."+d.vars.classes.tab_arrow_left,function(e){e.preventDefault();var e=i(this).parent(),t=e.find("."+d.vars.classes.tabs_list);t.animate({scrollLeft:t.scrollLeft()-.5*e.width()})})},toggle_scroll(){i("."+d.vars.classes.tabs).each(function(e,t){var r=i(this),a=r.data("orderable-tabs"),r=r.closest(a.wrapper),a=r.find("."+d.vars.classes.tabs_list),o=r.find("."+d.vars.classes.tab_arrow_right);r.outerWidth()<a[0].scrollWidth?o.show():o.hide()})}};i(n).ready(d.on_ready),i(window).on("resize",d.on_resize)})(jQuery,document);let orderable_timings={};((l,e)=>{orderable_timings={on_ready(){orderable_timings.watch()},restore(){var e,t=orderable_timings.get_timings();t&&t.date&&(0<(e=l(".orderable-order-timings__date")).find('option[value="'+t.date+'"]').length&&(e.val(t.date),e.change()),t.time)&&0<(e=l(".orderable-order-timings__time")).find('option[value="'+t.time+'"]').length&&(e.val(t.time),e.change())},watch(){l(e.body).on("wc_fragments_refreshed",function(){orderable_timings.restore()}),l(e.body).on("updated_checkout",function(){orderable_timings.restore()}),l(e.body).on("change",".orderable-order-timings__date",function(e){let t=l(this),r=t.find("option:selected"),a=r.data("orderable-slots"),o=l(".orderable-order-timings--time"),s=l(".orderable-order-timings__time"),i=s.find("option").first(),n=s.find('option[value="asap"]').first();var d=orderable_timings.get_timings();d.date=l(".orderable-order-timings__date").val(),window.localStorage.setItem("orderable_timings",JSON.stringify(d)),s.html(i),n&&s.append(n),a?"all-day"===a[0].value?(o.hide(),s.prop("disabled",!0)):(s.prop("disabled",!1),o.show(),l.each(a,function(e,t){s.append(l("<option />").attr("value",t.value).attr("data-orderable-time-slot-id",t?.setting_row?.time_slot_id).text(t.formatted))})):(s.prop("disabled",!0),o.hide())}),l(e.body).on("change",".orderable-order-timings__time",function(e){var t=orderable_timings.get_timings();t.time=l(".orderable-order-timings__time").val(),window.localStorage.setItem("orderable_timings",JSON.stringify(t)),l(this).siblings('input[name="orderable_order_time_slot_id"]').val(l(this).find(":selected").attr("data-orderable-time-slot-id"))})},get_timings(){return JSON.parse(window.localStorage.getItem("orderable_timings"))||{}}},l(e).ready(orderable_timings.on_ready)})(jQuery,document),((a,o)=>{var e={on_ready(){e.watch()},watch(){void 0===window.orderable_triggers_admin&&a(o.body).on("click","[data-orderable-trigger]",e.trigger)},trigger(e){e.stopImmediatePropagation();var t=a(this),r=t.data("orderable-trigger");(t.is("button")||t.is("a"))&&e.preventDefault(),a(o.body).trigger("orderable-"+r,[t])}};a(o).ready(e.on_ready)})(jQuery,document),((o,e,s)=>{var i="scrollBox",r={containerClass:"sb-container",containerNoScrollClass:"sb-container-noscroll",contentClass:"sb-content",scrollbarContainerClass:"sb-scrollbar-container",scrollBarClass:"sb-scrollbar"};function t(e,t){this.element=e,this.settings=o.extend({},r,t),this._defaults=r,this._name=i,this.init()}o.extend(t.prototype,{init:function(){this.addScrollbar(),this.addEvents(),this.onResize()},addScrollbar:function(){o(this.element).addClass(this.settings.containerClass),this.wrapper=o("<div class='"+this.settings.contentClass+"' />"),this.wrapper.append(o(this.element).contents()),o(this.element).append(this.wrapper),this.scollbarContainer=o("<div class='"+this.settings.scrollbarContainerClass+"' />"),this.scrollBar=o("<div class='"+this.settings.scrollBarClass+"' />"),this.scollbarContainer.append(this.scrollBar),o(this.element).prepend(this.scollbarContainer)},addEvents:function(){this.wrapper.on("scroll."+i,o.proxy(this.onScroll,this)),o(e).on("resize."+i,o.proxy(this.onResize,this)),this.scrollBar.on("mousedown."+i,o.proxy(this.onMousedown,this)),this.scrollBar.on("touchstart."+i,o.proxy(this.onTouchstart,this))},onTouchstart:function(t){var r=this,a=(t.preventDefault(),r.scrollBar[0].offsetTop);o(s).on("touchmove."+i,function(e){e=e.touches[0].pageY-t.touches[0].pageY;r.scrollBar[0].style.top=Math.min(r.scollbarContainer[0].clientHeight-r.scrollBar[0].clientHeight,Math.max(0,a+e))+"px",r.wrapper[0].scrollTop=r.wrapper[0].scrollHeight*r.scrollBar[0].offsetTop/r.scollbarContainer[0].clientHeight}),o(s).on("touchend."+i,function(){o(s).off("touchmove."+i),o(s).off("touchend."+i)})},onMousedown:function(t){var r=this,a=(t.preventDefault(),r.scrollBar[0].offsetTop);o(s).on("mousemove."+i,function(e){e=e.pageY-t.pageY;r.scrollBar[0].style.top=Math.min(r.scollbarContainer[0].clientHeight-r.scrollBar[0].clientHeight,Math.max(0,a+e))+"px",r.wrapper[0].scrollTop=r.wrapper[0].scrollHeight*r.scrollBar[0].offsetTop/r.scollbarContainer[0].clientHeight}),o(s).on("mouseup."+i,function(){o(s).off("mousemove."+i),o(s).off("mouseup."+i)})},onResize:function(){this.wrapper.css("max-height",o(this.element).height());var e=this.wrapper[0].clientHeight;this.scrollBar.css("height",this.scollbarContainer[0].clientHeight*e/this.wrapper[0].scrollHeight+"px"),this.scollbarContainer[0].clientHeight<=this.scrollBar[0].clientHeight?o(this.element).addClass(this.settings.containerNoScrollClass):o(this.element).removeClass(this.settings.containerNoScrollClass),this.onScroll()},onScroll:function(){this.scrollBar.css("top",Math.min(this.scollbarContainer[0].clientHeight-this.scrollBar[0].clientHeight,this.scollbarContainer[0].clientHeight*this.wrapper[0].scrollTop/this.wrapper[0].scrollHeight)+"px")}}),o.fn[i]=function(e){return this.each(function(){o.data(this,"plugin_"+i)||o.data(this,"plugin_"+i,new t(this,e))})}})(jQuery,window,document),((e,o)=>{"function"!=typeof e.CustomEvent&&(e.CustomEvent=function(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var r=o.createEvent("CustomEvent");return r.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),r},e.CustomEvent.prototype=e.Event.prototype),o.addEventListener("touchstart",function(e){"true"!==e.target.getAttribute("data-swipe-ignore")&&(c=e.target,l=Date.now(),s=e.touches[0].clientX,i=e.touches[0].clientY,d=n=0)},!1),o.addEventListener("touchmove",function(e){var t;s&&i&&(t=e.touches[0].clientX,e=e.touches[0].clientY,n=s-t,d=i-e)},!1),o.addEventListener("touchend",function(e){var t,r,a,o;c===e.target&&(o=parseInt(_(c,"data-swipe-threshold","20"),10),t=parseInt(_(c,"data-swipe-timeout","500"),10),r=Date.now()-l,a="",e=e.changedTouches||e.touches||[],Math.abs(n)>Math.abs(d)?Math.abs(n)>o&&r<t&&(a=0<n?"swiped-left":"swiped-right"):Math.abs(d)>o&&r<t&&(a=0<d?"swiped-up":"swiped-down"),""!==a&&(o={dir:a.replace(/swiped-/,""),touchType:(e[0]||{}).touchType||"direct",xStart:parseInt(s,10),xEnd:parseInt((e[0]||{}).clientX||-1,10),yStart:parseInt(i,10),yEnd:parseInt((e[0]||{}).clientY||-1,10)},c.dispatchEvent(new CustomEvent("swiped",{bubbles:!0,cancelable:!0,detail:o})),c.dispatchEvent(new CustomEvent(a,{bubbles:!0,cancelable:!0,detail:o}))),l=i=s=null)},!1);var s=null,i=null,n=null,d=null,l=null,c=null;function _(e,t,r){for(;e&&e!==o.documentElement;){var a=e.getAttribute(t);if(a)return a;e=e.parentNode}return r}})(window,document);
  • orderable/trunk/docs/filters.json

    r3192586 r3237969  
    270270            "type": "filter",
    271271            "doc": {
     272                "description": "",
     273                "long_description": "",
     274                "tags": [],
     275                "long_description_html": ""
     276            },
     277            "args": 2
     278        },
     279        {
     280            "name": "orderable_get_accordion_data",
     281            "file": "inc/class-products.php",
     282            "type": "filter",
     283            "doc": {
     284                "description": "",
     285                "long_description": "",
     286                "tags": [],
     287                "long_description_html": ""
     288            },
     289            "args": 2
     290        },
     291        {
     292            "name": "orderable_get_accordion_data",
     293            "file": "inc/class-products.php",
     294            "type": "filter",
     295            "doc": {
    272296                "description": "Filter product accordion data.",
    273297                "long_description": "",
     
    288312                        ],
    289313                        "variable": "$product"
     314                    },
     315                    {
     316                        "name": "since",
     317                        "content": "1.0.0"
    290318                    }
    291319                ],
  • orderable/trunk/languages/orderable.pot

    r3192586 r3237969  
    1 # Copyright (C) 2024 orderable
     1# Copyright (C) 2025 orderable
    22# This file is distributed under the same license as the orderable package.
    33msgid ""
     
    77"Content-Type: text/plain; charset=UTF-8\n"
    88"Content-Transfer-Encoding: 8bit\n"
    9 "POT-Creation-Date: 2024-11-19 18:56+0000\n"
     9"POT-Creation-Date: 2025-02-10 13:33+0000\n"
    1010"X-Poedit-Basepath: ..\n"
    1111"X-Poedit-KeywordsList: __;_e;_ex:1,2c;_n:1,2;_n_noop:1,2;_nx:1,2,4c;_nx_noop:1,2,3c;_x:1,2c;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c\n"
  • orderable/trunk/orderable.php

    r3192586 r3237969  
    44 * Author URI: https://orderable.com
    55 * Description: Take local online ordering to a whole new level with Orderable.
    6  * Version: 1.17.0
     6 * Version: 1.17.1
    77 * Author: Orderable
    88 * Text Domain: orderable
    99 * WC requires at least: 5.4.0
    10  * WC tested up to: 9.4
     10 * WC tested up to: 9.6
    1111 */
    1212
     
    2020     * @var string Plugin version.
    2121     */
    22     public static $version = '1.17.0';
     22    public static $version = '1.17.1';
    2323
    2424    /**
  • orderable/trunk/readme.txt

    r3192586 r3237969  
    55Tested up to: 6.7
    66Requires PHP: 5.6
    7 Stable tag: 1.17.0
     7Stable tag: 1.17.1
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    186186
    187187== Changelog ==
     188**v1.17.1** (10 Feb 2025)
     189[fix] Compatibility issue with Xstore theme
     190
    188191**v1.17.0** (19 Nov 2024)
    189192[fix] Compatibility with Flux Checkout for WooCommerce plugin
Note: See TracChangeset for help on using the changeset viewer.