PluginProbe
Orderable – Restaurant & Food Ordering System / 0.2.0
Orderable – Restaurant & Food Ordering System v0.2.0
0.1.4 0.1.5 0.2.0 1.0.0 1.1.0 1.1.1 1.10.0 1.10.1 1.11.0 1.12.0 1.12.1 1.12.2 1.13.0 1.14.0 1.15.0 1.16.0 1.17.0 1.17.1 1.18.0 1.19.0 1.19.1 1.19.2 1.2.0 1.20.0 1.20.1 All 44 releases
orderable / assets / frontend / js / main.js

main.js in Orderable – Restaurant & Food Ordering System 0.2.0, at assets/frontend/js/main.js

1,013 lines 28.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1
2 /**
3 * jQiery scrollBar Plugin
4 * @author Falk Müller (www-falk-m.de)
5 * Thankts to https://codepen.io/IliaSky/pen/obowmv
6 */
7 ;( function( $, window, document ) {
8
9 "use strict";
10
11 var pluginName = "scrollBox",
12 defaults = {
13 containerClass: "sb-container",
14 containerNoScrollClass: "sb-container-noscroll",
15 contentClass: "sb-content",
16 scrollbarContainerClass: "sb-scrollbar-container",
17 scrollBarClass: "sb-scrollbar"
18
19 };
20
21 // plugin constructor
22 function Plugin ( element, options ) {
23 this.element = element;
24
25 this.settings = $.extend( {}, defaults, options );
26 this._defaults = defaults;
27 this._name = pluginName;
28 this.init();
29
30 }
31
32 // Avoid Plugin.prototype conflicts
33 $.extend( Plugin.prototype, {
34 init: function() {
35
36 this.addScrollbar();
37 this.addEvents();
38 this.onResize();
39 },
40 addScrollbar: function() {
41 $( this.element ).addClass(this.settings.containerClass);
42 this.wrapper = $("<div class='" + this.settings.contentClass + "' />");
43 this.wrapper.append($( this.element ).contents());
44 $( this.element ).append( this.wrapper );
45
46 this.scollbarContainer = $("<div class='" + this.settings.scrollbarContainerClass + "' />");
47 this.scrollBar = $("<div class='" + this.settings.scrollBarClass + "' />");
48 this.scollbarContainer.append(this.scrollBar);
49 $( this.element ).prepend(this.scollbarContainer);
50 },
51 addEvents: function(){
52
53 this.wrapper.on("scroll." + pluginName, $.proxy(this.onScroll, this) );
54 $(window).on("resize." + pluginName, $.proxy(this.onResize, this) );
55
56 this.scrollBar.on('mousedown.' + pluginName, $.proxy(this.onMousedown, this));
57 this.scrollBar.on('touchstart.' + pluginName, $.proxy(this.onTouchstart, this));
58 },
59
60 onTouchstart: function(ev){
61 var me = this;
62
63 ev.preventDefault();
64 var y = me.scrollBar[0].offsetTop;
65
66 var onMove = function(end){
67 var delta = end.touches[0].pageY - ev.touches[0].pageY;
68 me.scrollBar[0].style.top = Math.min(me.scollbarContainer[0].clientHeight - me.scrollBar[0].clientHeight, Math.max(0, y + delta)) + 'px';
69 me.wrapper[0].scrollTop = (me.wrapper[0].scrollHeight * me.scrollBar[0].offsetTop / me.scollbarContainer[0].clientHeight);
70 };
71
72 $(document).on("touchmove." + pluginName, onMove);
73 $(document).on("touchend." + pluginName, function(){
74 $(document).off("touchmove." + pluginName);
75 $(document).off("touchend." + pluginName);
76 });
77 },
78
79 onMousedown: function(ev){
80 var me = this;
81
82 ev.preventDefault();
83 var y = me.scrollBar[0].offsetTop;
84
85 var onMove = function(end){
86 var delta = end.pageY - ev.pageY;
87 me.scrollBar[0].style.top = Math.min(me.scollbarContainer[0].clientHeight - me.scrollBar[0].clientHeight, Math.max(0, y + delta)) + 'px';
88 me.wrapper[0].scrollTop = (me.wrapper[0].scrollHeight * me.scrollBar[0].offsetTop / me.scollbarContainer[0].clientHeight);
89 };
90
91 $(document).on("mousemove." + pluginName, onMove);
92 $(document).on("mouseup." + pluginName, function(){
93 $(document).off("mousemove." + pluginName);
94 $(document).off("mouseup." + pluginName);
95 });
96 },
97
98 onResize: function(){
99
100 this.wrapper.css("max-height", $(this.element).height());
101
102 var wrapper_client_height = this.wrapper[0].clientHeight;
103
104 this.scrollBar.css("height", this.scollbarContainer[0].clientHeight * wrapper_client_height / this.wrapper[0].scrollHeight + "px");
105 if(this.scollbarContainer[0].clientHeight <= this.scrollBar[0].clientHeight){
106 $( this.element ).addClass(this.settings.containerNoScrollClass);
107 } else {
108 $( this.element ).removeClass(this.settings.containerNoScrollClass);
109 }
110
111 this.onScroll();
112 },
113
114 onScroll: function(){
115
116 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");
117
118 }
119 } );
120
121 // A really lightweight plugin wrapper around the constructor,
122 // preventing against multiple instantiations
123 $.fn[pluginName] = function( options ) {
124 return this.each( function() {
125 if ( !$.data( this, "plugin_" + pluginName ) ) {
126 $.data( this, "plugin_" +
127 pluginName, new Plugin( this, options ) );
128 }
129 } );
130 };
131
132 } )( jQuery, window, document );
133 (function( $, document ) {
134 "use strict";
135
136 var orderable_drawer = {
137 /**
138 * On doc ready.
139 */
140 on_ready: function() {
141 orderable_drawer.cache();
142 orderable_drawer.watch();
143 },
144
145 /**
146 * Cache.
147 */
148 cache: function() {
149 orderable_drawer.vars = {
150 classes: {
151 overlay: 'orderable-drawer-overlay',
152 drawer: 'orderable-drawer',
153 drawer_cart: 'orderable-drawer__cart',
154 drawer_html: 'orderable-drawer__html',
155 overlay_open: 'orderable-drawer-overlay--open',
156 drawer_open: 'orderable-drawer--open',
157 drawer_open_body: 'orderable-drawer-open'
158 }
159 };
160
161 orderable_drawer.elements = {
162 body: $( 'body' ),
163 overlay: $( '.' + orderable_drawer.vars.classes.overlay ),
164 drawer: $( '.' + orderable_drawer.vars.classes.drawer ),
165 drawer_cart: $( '.' + orderable_drawer.vars.classes.drawer_cart ),
166 drawer_html: $( '.' + orderable_drawer.vars.classes.drawer_html ),
167 floating_cart_button_class: '.orderable-floating-cart__button'
168 };
169 },
170
171 /**
172 * Watch for trigger events.
173 */
174 watch: function() {
175 if ( typeof orderable_drawer.elements.drawer === 'undefined' ) {
176 return;
177 }
178
179 $( document.body ).on( 'orderable-drawer.open', orderable_drawer.open );
180 $( document.body ).on( 'orderable-drawer.close', orderable_drawer.close );
181
182 $( document.body ).on( 'click', orderable_drawer.elements.floating_cart_button_class, function() {
183 $( document.body ).trigger( 'orderable-drawer.open', { show_cart: true } );
184 } );
185
186 $( document.body ).on( 'orderable-increase-quantity', orderable_drawer.cart.click_increase_decrease_quantity );
187 $( document.body ).on( 'orderable-decrease-quantity', orderable_drawer.cart.click_increase_decrease_quantity );
188 },
189
190 /**
191 * Open the drawer.
192 */
193 open: function( event, args ) {
194 args.html = args.html || false;
195 args.show_cart = args.show_cart || false;
196
197 orderable_drawer.elements.drawer_html.hide();
198 orderable_drawer.elements.drawer_cart.hide();
199
200 if ( args.html ) {
201 orderable_drawer.elements.drawer_html.html( args.html );
202 orderable_drawer.elements.drawer_html.show();
203 }
204
205 if ( args.show_cart ) {
206 // Empty drawer HTML before showing cart. Prevents options
207 // interfering with subsequent cart additions.
208 orderable_drawer.elements.drawer_html.html( '' );
209 orderable_drawer.elements.drawer_cart.show();
210 }
211
212 orderable_drawer.elements.overlay.addClass( orderable_drawer.vars.classes.overlay_open );
213 orderable_drawer.elements.drawer.addClass( orderable_drawer.vars.classes.drawer_open );
214 orderable_drawer.elements.body.addClass( orderable_drawer.vars.classes.drawer_open_body );
215
216 $( document.body ).trigger( 'orderable-drawer.opened', args );
217 },
218
219 /**
220 * Close the drawer.
221 */
222 close: function() {
223 orderable_drawer.elements.overlay.removeClass( orderable_drawer.vars.classes.overlay_open );
224 orderable_drawer.elements.drawer.removeClass( orderable_drawer.vars.classes.drawer_open );
225 orderable_drawer.elements.body.removeClass( orderable_drawer.vars.classes.drawer_open_body );
226
227 orderable_drawer.elements.drawer_html.html( '' );
228
229 $( document.body ).trigger( 'orderable-drawer.closed' );
230 },
231
232 /**
233 * Mini cart related functions.
234 */
235 cart: {
236 /**
237 * When increase qty is clicked.
238 *
239 * @param e
240 * @param $button
241 */
242 click_increase_decrease_quantity: function( e, $button ) {
243 var product_id = $button.data( 'orderable-product-id' ),
244 cart_item_key = $button.data( 'orderable-cart-item-key' ),
245 direction = $button.data( 'orderable-trigger' ),
246 quantity = parseInt( $button.data( 'orderable-quantity' ) );
247
248 var data = {
249 'action': 'orderable_cart_quantity',
250 cart_item_key,
251 product_id,
252 'quantity': 'increase-quantity' === direction ? quantity + 1 : quantity - 1
253 };
254
255 jQuery.post(
256 wc_add_to_cart_params.ajax_url,
257 data,
258 function( response ) {
259 if ( ! response ) {
260 return;
261 }
262
263 $( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $button ] );
264 $( document.body ).trigger( 'orderable-drawer.quantity-updated' );
265 }
266 );
267 }
268 }
269 };
270
271 $( document ).ready( orderable_drawer.on_ready );
272 }( jQuery, document ));
273 (function( $, document ) {
274 "use strict";
275
276 var orderable_layouts = {
277 /**
278 * On doc ready.
279 */
280 on_ready: function() {
281 orderable_layouts.cache();
282 orderable_layouts.watch();
283 },
284
285 /**
286 * Cache.
287 */
288 cache: function() {
289 orderable_layouts.vars = {
290 classes: {
291 main: 'orderable-main',
292 tabs: 'orderable-tabs',
293 tab_items: 'orderable-tabs__item',
294 tab_item_active: 'orderable-tabs__item--active',
295 tab_links: 'orderable-tabs__link',
296 sections: 'orderable-main__group',
297 },
298 };
299
300 orderable_layouts.elements = {};
301 },
302
303 /**
304 * Watch.
305 */
306 watch: function() {
307 $( document.body ).on( 'click mouseup touchend', '.' + orderable_layouts.vars.classes.tab_links, function( e ) {
308 e.preventDefault();
309
310 var $link = $( this ),
311 section_id = $link.attr( 'href' ),
312 $tab = $link.closest( '.' + orderable_layouts.vars.classes.tab_items ),
313 $tabs = $link.closest( '.' + orderable_layouts.vars.classes.tabs ),
314 $tab_items = $tabs.find( '.' + orderable_layouts.vars.classes.tab_items ),
315 $main = $link.closest( '.' + orderable_layouts.vars.classes.main ),
316 $sections = $main.find( '.' + orderable_layouts.vars.classes.sections ),
317 $section = $main.find( section_id );
318
319 $sections.hide();
320 $section.show();
321
322 $tab_items.removeClass( orderable_layouts.vars.classes.tab_item_active );
323 $tab.addClass( orderable_layouts.vars.classes.tab_item_active );
324 } );
325 },
326 };
327
328 $( document ).ready( orderable_layouts.on_ready );
329 }( jQuery, document ));
330 (function( $, document ) {
331 "use strict";
332
333 var orderable_products = {
334 /**
335 * On doc ready.
336 */
337 on_ready: function() {
338 orderable_products.cache();
339 orderable_products.watch();
340 },
341
342 /**
343 * Cache.
344 */
345 cache: function() {
346 orderable_products.vars = {
347 classes: {
348 clickable_product: 'orderable-product--clickable',
349 add_to_order_button: 'orderable-product__add-to-order',
350 product_messages: 'orderable-product__messages',
351 product_price: 'orderable-product__actions-price',
352 invalid_field: 'orderable-field--invalid',
353 option_select_td: 'orderable-product__option-select',
354 button_loading: 'orderable-button--loading',
355 out_of_stock: 'orderable-button--out-of-stock'
356 },
357 parent_price: null
358 };
359
360 orderable_products.elements = {};
361 },
362
363 /**
364 * Watch for trigger events.
365 */
366 watch: function() {
367 $( document.body ).on( 'orderable-drawer.opened', orderable_products.init_product_options );
368 $( document.body ).on( 'orderable-add-to-cart', orderable_products.click_add_to_order );
369 $( document.body ).on( 'orderable-product-options', orderable_products.click_add_to_order );
370 $( document.body ).on( 'mouseenter mouseleave', '.' + orderable_products.vars.classes.clickable_product, orderable_products.simulate_add_to_order_hover );
371 $( document.body ).on( 'click', '.' + orderable_products.vars.classes.clickable_product, orderable_products.click_add_to_order );
372 },
373
374 /**
375 * Simulate hover on add to order button.
376 *
377 * @param event
378 */
379 simulate_add_to_order_hover: function( event ) {
380 var $element = $( this ),
381 $button = $element.find( '.' + orderable_products.vars.classes.add_to_order_button );
382
383 $button.toggleClass( 'orderable-button--hover', 'mouseenter' === event.type );
384 },
385
386 /**
387 * Add to order click event.
388 *
389 * This event accounts for button clicks or card clicks.
390 */
391 click_add_to_order: function( event, $element ) {
392 // If undefined, it means it was triggered by a click
393 // event and not the `orderable-add-to-cart` trigger.
394 $element = typeof $element !== 'undefined' ? $element : $( this );
395
396 // The button is either the clicked element, or the
397 // add to order button within the clicked element.
398 var $button = $element.is( 'button' ) ? $element : $element.find( '.' + orderable_products.vars.classes.add_to_order_button ),
399 action = $button.data( 'orderable-trigger' ),
400 product_id = $button.data( 'orderable-product-id' ),
401 variation_id = $button.data( 'orderable-variation-id' ),
402 attributes = $button.data( 'orderable-variation-attributes' ),
403 args = { action: action };
404
405 if ( $button.hasClass( orderable_products.vars.classes.button_loading ) || $button.hasClass( orderable_products.vars.classes.out_of_stock ) ) {
406 return;
407 }
408
409 $button.addClass( orderable_products.vars.classes.button_loading );
410
411 if ( 'add-to-cart' === action ) {
412 orderable_products.add_to_cart(
413 {
414 'product_id': product_id,
415 'variation_id': variation_id,
416 'attributes': attributes
417 },
418 function( response ) {
419 args.show_cart = true;
420 args.response = response;
421
422 $( document.body ).trigger( 'orderable-drawer.open', args );
423 $button.removeClass( orderable_products.vars.classes.button_loading );
424 }
425 );
426 } else if ( 'product-options' === action ) {
427 orderable_products.get_product_options(
428 {
429 'product_id': product_id
430 },
431 function( response ) {
432 args.html = response.html;
433
434 $( document.body ).trigger( 'orderable-drawer.open', args );
435 $button.removeClass( orderable_products.vars.classes.button_loading );
436 }
437 );
438 }
439 },
440
441 /**
442 * Ajax add to cart.
443 */
444 add_to_cart: function( args, callback ) {
445 if ( typeof args.product_id === 'undefined' ) {
446 return;
447 }
448
449 var data = {
450 'action': 'orderable_add_to_cart',
451 'product_id': args.product_id,
452 'variation_id': args.variation_id || false,
453 'attributes': args.attributes || false
454 };
455
456 // Prepare addons data.
457 if ( $( '.orderable-product-fields-group' ).length ) {
458 var inputs = jQuery( '.orderable-product-fields-group :input' ).serializeArray();
459 var addons_data = orderable_products.convert_to_flat_object( inputs );
460 if ( ! jQuery.isEmptyObject( addons_data ) ) {
461 data = Object.assign( data, addons_data ); // Merge objects.
462 }
463 }
464
465 jQuery.post(
466 wc_add_to_cart_params.ajax_url,
467 data,
468 function( response ) {
469 if ( !response ) {
470 return;
471 }
472
473 // Trigger event so themes can refresh other areas.
474 $( document.body ).trigger( 'added_to_cart', [
475 response.fragments,
476 response.cart_hash
477 ] );
478
479 if ( typeof callback === 'function' ) {
480 callback( response );
481 }
482 }
483 );
484 },
485
486 /**
487 * Convert [{name:x, value:y }] to {x:y} format.
488 */
489 convert_to_flat_object: function ( inputs ) {
490 var data = {};
491 inputs.forEach( function ( input ) {
492 var is_array = '[]' === input.name.substr( -2 ) || Array.isArray( input.name );
493 // If last 2 chars are '[]', remove them.
494 var key = is_array ? input.name.substr( 0, input.name.length - 2 ) : input.name;
495
496 if ( is_array ) {
497 data[ key ] = typeof data[ key ] === 'undefined' ? [] : data[ key ];
498 data[ key ].push( input.value );
499 } else {
500 data[ key ] = input.value;
501 }
502 } );
503
504 return data;
505 },
506
507 /**
508 * Get variable product options.
509 *
510 * @param args
511 * @param callback
512 */
513 get_product_options: function( args, callback ) {
514 if ( typeof args.product_id === 'undefined' ) {
515 return;
516 }
517
518 args.action = 'orderable_get_product_options';
519
520 jQuery.post(
521 wc_add_to_cart_params.ajax_url,
522 args,
523 function( response ) {
524 if ( !response.success ) {
525 return;
526 }
527
528 if ( typeof callback === 'function' ) {
529 callback( response.data );
530 }
531 }
532 );
533 },
534
535 /**
536 * Init drawer product options.
537 *
538 * @param event
539 * @param args
540 */
541 init_product_options: function( event, args ) {
542 if ( typeof args.action === 'undefined' || 'product-options' !== args.action ) {
543 return;
544 }
545
546 var $options = $( '.orderable-drawer .orderable-product__options input, .orderable-drawer .orderable-product__options select' );
547
548 orderable_products.vars.parent_price = $( '.orderable-drawer .orderable-product__actions-price' ).html();
549
550 orderable_products.product_options_change( $options );
551 orderable_products.update_button_state();
552
553 $options.on( 'change', function() {
554 orderable_products.product_options_change( $options );
555 orderable_products.update_button_state();
556 } );
557 },
558
559 /**
560 * On product options change.
561 *
562 * @param $options
563 */
564 product_options_change: function( $options ) {
565 var $add_to_order_button = $( '.orderable-drawer .orderable-product__add-to-order' ),
566 options_set = orderable_products.check_options( $options ),
567 product_type = $add_to_order_button.data( 'orderable-product-type' );
568
569 $add_to_order_button.attr( 'data-orderable-trigger', 'add-to-cart' );
570 $( '.' + orderable_products.vars.classes.product_messages ).html( '' );
571
572 if ( 'variable' !== product_type ) {
573 return;
574 }
575
576 if ( !options_set ) {
577 orderable_products.clear_variation( $add_to_order_button );
578 return;
579 }
580
581 var variation = orderable_products.check_variation( $options );
582
583 orderable_products.set_variation( $add_to_order_button, variation );
584 },
585
586 /**
587 * Check if all product options are set.
588 *
589 * @param $options
590 * @returns {boolean}
591 */
592 check_options: function( $options ) {
593 if ( $options.length <= 0 ) {
594 return false;
595 }
596
597 var all_set = true;
598
599 $options.each( function( index, option ) {
600 if ( '' === $( option ).val() ) {
601 $( option ).addClass( orderable_products.vars.classes.invalid_field );
602 all_set = false;
603 } else {
604 $( option ).removeClass( orderable_products.vars.classes.invalid_field );
605 }
606 } );
607
608 return all_set;
609 },
610
611 /**
612 * Check if variation has been selected.
613 */
614 check_variation: function( $options ) {
615 var $product = $options.closest( '.orderable-drawer' ),
616 variations = $.parseJSON( $product.find( '.orderable-product__variations' ).text() ),
617 selected_options = orderable_products.serialize_object( $options ),
618 matching_variations = orderable_products.find_matching_variations( variations, selected_options );
619
620 if ( orderable_products.is_empty( matching_variations ) ) {
621 return false;
622 }
623
624 var variation = matching_variations.shift();
625
626 variation.attributes = selected_options;
627 variation.attributes_json = JSON.stringify( selected_options );
628
629 return typeof variation !== 'undefined' ? variation : false;
630 },
631
632 /**
633 * Set variation for add to cart button.
634 */
635 set_variation: function( $button, variation ) {
636 var variation_id = variation.variation_id || '',
637 attributes = variation.attributes_json || '',
638 price = variation.price_html || orderable_products.vars.parent_price,
639 message = '';
640
641 if ( variation && '' !== variation.availability_html ) {
642 message = variation.availability_html;
643 }
644
645 if ( variation && !variation.is_in_stock ) {
646 message = '<p>' + orderable_vars.i18n.out_of_stock + '</p>';
647 }
648
649 if ( variation && !variation.is_purchasable ) {
650 message = '<p>' + orderable_vars.i18n.unavailable + '</p>';
651 }
652
653 if ( false === variation ) {
654 message = '<p>' + orderable_vars.i18n.no_exist + '</p>';
655 }
656
657 if ( variation && (!variation.is_purchasable || !variation.is_in_stock) ) {
658 variation_id = '';
659 attributes = '';
660 }
661
662 if ( '' !== message ) {
663 $( '.' + orderable_products.vars.classes.product_messages ).html( message );
664 }
665
666 $button.data( 'orderable-variation-id', variation_id );
667 $button.data( 'orderable-variation-attributes', attributes );
668 $( '.orderable-drawer .orderable-product__actions-price' ).html( price );
669
670 $button.trigger( 'orderable_variation_set', {
671 variation: variation,
672 variation_id: variation_id,
673 attributes: attributes,
674 price: price
675 } );
676 },
677
678 /**
679 * Clear variation and disable add to order.
680 *
681 * @param $button
682 */
683 clear_variation: function( $button ) {
684 orderable_products.set_variation( $button, '' );
685
686 if ( orderable_products.vars.parent_price ) {
687 $( '.orderable-drawer .orderable-product__actions-price' ).html( orderable_products.vars.parent_price );
688 }
689 },
690
691 /**
692 * Find matching variations for attributes.
693 */
694 find_matching_variations: function( variations, attributes ) {
695 var matching = [];
696
697 for ( var i = 0; i < variations.length; i ++ ) {
698 var variation = variations[ i ];
699
700 if ( orderable_products.is_matching_variation( variation.attributes, attributes ) ) {
701 matching.push( variation );
702 }
703 }
704
705 return matching;
706 },
707
708 /**
709 * See if attributes match.
710 * @return {Boolean}
711 */
712 is_matching_variation: function( variation_attributes, attributes ) {
713 var match = true;
714
715 for ( var attr_name in variation_attributes ) {
716 if ( variation_attributes.hasOwnProperty( attr_name ) ) {
717 var val1 = variation_attributes[ attr_name ];
718 var val2 = attributes[ attr_name ];
719 if ( val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2 ) {
720 match = false;
721 }
722 }
723 }
724
725 return match;
726 },
727
728 /**
729 * Is value empty?
730 *
731 * @param value
732 * @returns {boolean}
733 */
734 is_empty: function( value ) {
735 return typeof value === 'undefined' || false === value || value.length <= 0 || !value;
736 },
737
738 /**
739 * Serialize into a key/value object.
740 *
741 * @param $elements
742 * @returns {{}}
743 */
744 serialize_object: function objectifyForm( $elements ) {
745 var serialized = $elements.serializeArray(),
746 return_object = {};
747
748 for ( var i = 0; i < serialized.length; i ++ ) {
749 return_object[ serialized[ i ].name ] = serialized[ i ].value;
750 }
751 return return_object;
752 },
753
754 /**
755 * Disable/Enable the 'Add to cart' button based on the presence of orderable-field--invalid class.
756 */
757 update_button_state: function () {
758 // Add delay to ensure invalid class has been assigned to inputs.
759 setTimeout( function () {
760 var $button = $( '.orderable-drawer .orderable-product__add-to-order' ),
761 invalid_fields_count = $( '.orderable-drawer__html .' + orderable_products.vars.classes.invalid_field ).length,
762 product_type = $button.data( 'orderable-product-type' ),
763 has_variation_id = true;
764
765 if ( 'variable' === product_type ) {
766 has_variation_id = '' !== $button.data( 'orderable-variation-id' );
767 }
768
769 $button.prop( 'disabled', invalid_fields_count || ! has_variation_id );
770 }, 50 );
771 }
772 };
773
774 $( document ).ready( orderable_products.on_ready );
775 }( jQuery, document ));
776 (function( $, document ) {
777 "use strict";
778
779 var orderable_scrollbar = {
780 /**
781 * On doc ready.
782 */
783 on_ready: function() {
784 orderable_scrollbar.cache();
785 orderable_scrollbar.watch();
786 },
787
788 /**
789 * Cache.
790 */
791 cache: function() {
792 orderable_scrollbar.vars = {
793 top: {},
794 };
795 orderable_scrollbar.elements = {};
796 },
797
798 /**
799 * Watch.
800 */
801 watch: function() {
802 $( document.body ).on( 'orderable-drawer.opened', orderable_scrollbar.trigger );
803 $( document.body ).on( 'wc_fragments_loaded', orderable_scrollbar.trigger );
804 },
805
806 /**
807 * Init or retrigger scrollbars.
808 */
809 trigger: function() {
810 $( '.orderable-sb-container' ).each( function( index, element ) {
811 var $element = $( element ),
812 scroll_id = $element.data( 'orderable-scroll-id' );
813
814 if ( ! orderable_scrollbar.has_scrollbar( $element ) ) {
815 $element.scrollBox( {
816 containerClass: "orderable-sb-container",
817 containerNoScrollClass: "orderable-sb-container-noscroll",
818 contentClass: "orderable-sb-content",
819 scrollbarContainerClass: "orderable-sb-scrollbar-container",
820 scrollBarClass: "orderable-sb-scrollbar"
821 } );
822
823 var $content = $element.find( '.orderable-sb-content' );
824
825 if ( $content.length > 0 ) {
826 $content.on( 'scroll.scrollBox', orderable_scrollbar.log_top_position );
827
828 // Set scroll position.
829 if ( typeof orderable_scrollbar.vars.top[ scroll_id ] !== 'undefined' ) {
830 $content.scrollTop( orderable_scrollbar.vars.top[ scroll_id ] );
831 }
832 }
833 }
834 } );
835
836 $( window ).trigger( 'resize.scrollBox' );
837 },
838
839 /**
840 * Has scrollbar already?
841 *
842 * @param $element
843 * @return {boolean}
844 */
845 has_scrollbar: function( $element ) {
846 return $element.find( '.orderable-sb-content' ).length > 0;
847 },
848
849 /**
850 * Set scrolltop position.
851 *
852 * @param e
853 */
854 log_top_position: function( e ) {
855 var $element = $( e.currentTarget ),
856 $container = $element.closest( '.orderable-sb-container' ),
857 scroll_id = $container.data( 'orderable-scroll-id' );
858
859 orderable_scrollbar.vars.top[ scroll_id ] = $( e.currentTarget ).scrollTop();
860 }
861 };
862
863 $( document ).ready( orderable_scrollbar.on_ready );
864 }( jQuery, document ));
865 (function( $, document ) {
866 "use strict";
867
868 var orderable_services = {
869 /**
870 * On doc ready.
871 */
872 on_ready: function() {
873 orderable_services.watch();
874 },
875
876 /**
877 * Watch for trigger events.
878 */
879 watch: function() {
880 $( document.body ).on( 'orderable-show-lookup-services', function( event, $button ) {
881 var $parent = $button.closest( '.orderable-services-selector' ),
882 $lookup = $parent.find( '.orderable-services-selector__lookup' );
883
884 $button.hide();
885 $lookup.show();
886 } );
887
888 $( document.body ).on( 'orderable-lookup-services', function( event, $button ) {
889 var $parent = $button.closest( '.orderable-services-selector' ),
890 $message = $parent.find( '.orderable-services-selector__lookup-message' ),
891 $change = $parent.find( '.orderable-services-selector__selected-change' ),
892 city = $parent.find( '.orderable-services-selector__lookup-city' ).val(),
893 postcode = $parent.find( '.orderable-services-selector__lookup-postcode' ).val(),
894 service = $button.data( 'orderable-service' );
895
896 var data = {
897 'action': 'orderable_lookup_service',
898 'postcode': postcode,
899 'city': city,
900 'service': service
901 };
902
903 jQuery.post(
904 wc_add_to_cart_params.ajax_url,
905 data,
906 function( response ) {
907 if ( !response.success ) {
908 $message.html( '<p>' + response.data.message + '</p>' );
909 return;
910 }
911
912 $message.html( '' );
913 $change.show();
914
915 if ( typeof response.data.fragments !== 'undefined' ) {
916 $.each( response.data.fragments, function( fragment_selector, fragment_html ) {
917 $( fragment_selector ).html( fragment_html );
918 } );
919 }
920
921 console.log( response );
922 }
923 );
924 } );
925 }
926 };
927
928 $( document ).ready( orderable_services.on_ready );
929 }( jQuery, document ));
930 (function( $, document ) {
931 "use strict";
932
933 var orderable_timings = {
934 /**
935 * On doc ready.
936 */
937 on_ready: function() {
938 orderable_timings.watch();
939 },
940
941 /**
942 * Watch for trigger events.
943 */
944 watch: function() {
945 $( document.body ).on( 'change', '.orderable-order-timings__date', function( event ) {
946 var $date_field = $( this ),
947 $selected = $date_field.find( 'option:selected' ),
948 slots = $selected.data( 'orderable-slots' ),
949 $time_field_wrap = $( '.orderable-order-timings--time' ),
950 $time_field = $( '.orderable-order-timings__time' ),
951 $first_option = $time_field.find( 'option' ).first(),
952 $asap_option = $time_field.find( 'option[value="asap"]' );
953
954 $time_field.html( $first_option );
955
956 if ( $asap_option ) {
957 $time_field.append( $asap_option );
958 }
959
960 if ( ! slots ) {
961 $time_field.prop( 'disabled', true );
962 $time_field_wrap.hide();
963 return;
964 }
965
966 if ( 'all-day' === slots[ 0 ].value ) {
967 $time_field_wrap.hide();
968 $time_field.prop( 'disabled', true );
969 } else {
970 $time_field.prop( 'disabled', false );
971 $time_field_wrap.show();
972
973 $.each( slots, function( index, slot ) {
974 $time_field.append( $( '<option />' ).attr( 'value', slot.value ).text( slot.formatted ) );
975 } );
976 }
977 } );
978 }
979 };
980
981 $( document ).ready( orderable_timings.on_ready );
982 }( jQuery, document ));
983 (function( $, document ) {
984 "use strict";
985
986 var orderable_triggers = {
987 /**
988 * On doc ready.
989 */
990 on_ready: function() {
991 orderable_triggers.watch();
992 },
993
994 /**
995 * Watch for trigger events.
996 */
997 watch: function() {
998 $( document.body ).on( 'click', '[data-orderable-trigger]', orderable_triggers.trigger );
999 },
1000
1001 /**
1002 * Fire trigger.
1003 */
1004 trigger: function() {
1005 var $trigger_element = $( this ),
1006 trigger = $trigger_element.data( 'orderable-trigger' );
1007
1008 $( document.body ).trigger( 'orderable-' + trigger, [ $trigger_element ] );
1009 }
1010 };
1011
1012 $( document ).ready( orderable_triggers.on_ready );
1013 }( jQuery, document ));