PageSourceSearch

https://www.portopong.com/s/files/1/0020/4752/t/5/assets/theme_2.js

js portopong.com collected 2026-10-08 12:37:49 UTC 57,575 bytes, 2,020 lines download raw bytes

1window.theme = window.theme || {};
2
3/* ================ SLATE ================ */
4window.theme = window.theme || {};
5
6theme.Sections = function Sections() {
7  this.constructors = {};
8  this.instances = [];
9
10  $(document)
11    .on('shopify:section:load', this._onSectionLoad.bind(this))
12    .on('shopify:section:unload', this._onSectionUnload.bind(this))
13    .on('shopify:section:select', this._onSelect.bind(this))
14    .on('shopify:section:deselect', this._onDeselect.bind(this))
15    .on('shopify:block:select', this._onBlockSelect.bind(this))
16    .on('shopify:block:deselect', this._onBlockDeselect.bind(this));
17};
18
19theme.Sections.prototype = _.assignIn({}, theme.Sections.prototype, {
20  _createInstance: function(container, constructor) {
21    var $container = $(container);
22    var id = $container.attr('data-section-id');
23    var type = $container.attr('data-section-type');
24
25    constructor = constructor || this.constructors[type];
26
27    if (_.isUndefined(constructor)) {
28      return;
29    }
30
31    var instance = _.assignIn(new constructor(container), {
32      id: id,
33      type: type,
34      container: container
35    });
36
37    this.instances.push(instance);
38  },
39
40  _onSectionLoad: function(evt) {
41    var container = $('[data-section-id]', evt.target)[0];
42    if (container) {
43      this._createInstance(container);
44    }
45  },
46
47  _onSectionUnload: function(evt) {
48    this.instances = _.filter(this.instances, function(instance) {
49      var isEventInstance = instance.id === evt.detail.sectionId;
50
51      if (isEventInstance) {
52        if (_.isFunction(instance.onUnload)) {
53          instance.onUnload(evt);
54        }
55      }
56
57      return !isEventInstance;
58    });
59  },
60
61  _onSelect: function(evt) {
62    // eslint-disable-next-line no-shadow
63    var instance = _.find(this.instances, function(instance) {
64      return instance.id === evt.detail.sectionId;
65    });
66
67    if (!_.isUndefined(instance) && _.isFunction(instance.onSelect)) {
68      instance.onSelect(evt);
69    }
70  },
71
72  _onDeselect: function(evt) {
73    // eslint-disable-next-line no-shadow
74    var instance = _.find(this.instances, function(instance) {
75      return instance.id === evt.detail.sectionId;
76    });
77
78    if (!_.isUndefined(instance) && _.isFunction(instance.onDeselect)) {
79      instance.onDeselect(evt);
80    }
81  },
82
83  _onBlockSelect: function(evt) {
84    // eslint-disable-next-line no-shadow
85    var instance = _.find(this.instances, function(instance) {
86      return instance.id === evt.detail.sectionId;
87    });
88
89    if (!_.isUndefined(instance) && _.isFunction(instance.onBlockSelect)) {
90      instance.onBlockSelect(evt);
91    }
92  },
93
94  _onBlockDeselect: function(evt) {
95    // eslint-disable-next-line no-shadow
96    var instance = _.find(this.instances, function(instance) {
97      return instance.id === evt.detail.sectionId;
98    });
99
100    if (!_.isUndefined(instance) && _.isFunction(instance.onBlockDeselect)) {
101      instance.onBlockDeselect(evt);
102    }
103  },
104
105  register: function(type, constructor) {
106    this.constructors[type] = constructor;
107
108    $('[data-section-type=' + type + ']').each(
109      function(index, container) {
110        this._createInstance(container, constructor);
111      }.bind(this)
112    );
113  }
114});
115
116
117/* ================ MODULES ================ */
118/*============================================================================
119  Money Format
120  - Shopify.format money is defined in option_selection.js.
121    If that file is not included, it is redefined here.
122==============================================================================*/
123if (typeof Shopify === 'undefined') {
124  Shopify = {};
125}
126if (!Shopify.formatMoney) {
127  Shopify.formatMoney = function(cents, format) {
128    var value = '',
129      placeholderRegex = /\{\{\s*(\w+)\s*\}\}/,
130      formatString = format || this.money_format;
131
132    if (typeof cents === 'string') {
133      cents = cents.replace('.', '');
134    }
135
136    function defaultOption(opt, def) {
137      return typeof opt === 'undefined' ? def : opt;
138    }
139
140    function formatWithDelimiters(number, precision, thousands, decimal) {
141      precision = defaultOption(precision, 2);
142      thousands = defaultOption(thousands, ',');
143      decimal = defaultOption(decimal, '.');
144
145      if (isNaN(number) || number === null) {
146        return 0;
147      }
148
149      number = (number / 100.0).toFixed(precision);
150
151      var parts = number.split('.'),
152        dollars = parts[0].replace(
153          /(\d)(?=(\d\d\d)+(?!\d))/g,
154          '$1' + thousands
155        ),
156        cents = parts[1] ? decimal + parts[1] : '';
157
158      return dollars + cents;
159    }
160
161    switch (formatString.match(placeholderRegex)[1]) {
162      case 'amount':
163        value = formatWithDelimiters(cents, 2);
164        break;
165      case 'amount_no_decimals':
166        value = formatWithDelimiters(cents, 0);
167        break;
168      case 'amount_with_comma_separator':
169        value = formatWithDelimiters(cents, 2, '.', ',');
170        break;
171      case 'amount_no_decimals_with_comma_separator':
172        value = formatWithDelimiters(cents, 0, '.', ',');
173        break;
174    }
175
176    return formatString.replace(placeholderRegex, value);
177  };
178}
179
180// Timber functions
181window.timber = window.timber || {};
182
183timber.cacheSelectors = function() {
184  timber.cache = {
185    // General
186    $window: $(window),
187    $html: $('html'),
188    $body: $('body'),
189
190    // Navigation
191    $navigation: $('#AccessibleNav'),
192    $navBar: $('.nav-bar'),
193    $mobileSubNavToggle: $('.mobile-nav__toggle'),
194    $header: $('.site-header'),
195    $mobileMenuButton: $('#menu-opener'),
196
197    // Collection Pages
198    $changeView: $('.change-view'),
199
200    // Product Page
201    $productImage: $('#ProductPhotoImg'),
202    $thumbImages: $('#ProductThumbs').find('a.product-single__thumbnail'),
203
204    // Cart Page
205    $cartSection: $('#CartSection'),
206    cartNoCookies: 'cart--no-cookies',
207
208    // Customer Pages
209    $recoverPasswordLink: $('#RecoverPassword'),
210    $hideRecoverPasswordLink: $('#HideRecoverPasswordLink'),
211    $recoverPasswordForm: $('#RecoverPasswordForm'),
212    $customerLoginForm: $('#CustomerLoginForm'),
213    $passwordResetSuccess: $('#ResetSuccess')
214  };
215};
216
217timber.init = function() {
218  timber.cacheSelectors();
219  timber.drawersInit();
220  timber.cartInit();
221  timber.mobileNavToggle();
222  timber.productImageSwitch();
223  timber.collectionViews();
224  timber.loginForms();
225};
226
227timber.openDrawerMenu = function() {
228  var $allLinks = $('button, a', timber.cache.$navBar);
229
230  timber.cache.$body.addClass('opened-drawer');
231  timber.cache.$navBar.addClass('opened').attr('aria-hidden', 'false');
232  timber.cache.$mobileMenuButton
233    .attr('aria-expanded', 'true')
234    .addClass('opened');
235
236  // Set focus on drawer
237  timber.trapFocus({
238    $container: timber.cache.$navBar,
239    namespace: 'drawer_focus'
240  });
241
242  // Reset tabindex
243  $allLinks.attr('tabindex', '');
244
245  // Escape key closes menu
246  timber.cache.$html.on('keyup.drawerMenu', function(evt) {
247    if (evt.keyCode === 27) {
248      timber.closeDrawerMenu();
249    }
250  });
251};
252
253timber.closeDrawerMenu = function() {
254  var $allLinks = $('button, a', timber.cache.$navBar);
255
256  timber.cache.$body.removeClass('opened-drawer');
257
258  timber.cache.$navBar.removeClass('opened').attr('aria-hidden', 'true');
259
260  timber.cache.$mobileMenuButton
261    .attr('aria-expanded', 'false')
262    .removeClass('opened');
263
264  // Remove focus on drawer
265  timber.removeTrapFocus({
266    $container: timber.cache.$navBar,
267    namespace: 'drawer_focus'
268  });
269
270  // Reset tabindex
271  $allLinks.attr('tabindex', '-1');
272
273  timber.cache.$html.off('keyup.drawerMenu');
274};
275
276timber.drawersInit = function() {
277  timber.LeftDrawer = new timber.Drawers('NavDrawer', 'left');
278  timber.RightDrawer = new timber.Drawers('CartDrawer', 'right', {
279    onDrawerOpen: theme.settings.ajax_cart_enable
280  });
281};
282
283timber.cartInit = function() {
284  if (!timber.cookiesEnabled()) {
285    timber.cache.$cartSection.addClass(timber.cache.cartNoCookies);
286  }
287};
288
289timber.cookiesEnabled = function() {
290  var cookieEnabled = navigator.cookieEnabled;
291
292  if (!cookieEnabled) {
293    document.cookie = 'testcookie';
294    cookieEnabled = document.cookie.indexOf('testcookie') !== -1;
295  }
296  return cookieEnabled;
297};
298
299timber.mobileNavToggle = function() {
300  timber.cache.$mobileSubNavToggle.on('click', function() {
301    $(this)
302      .parent()
303      .toggleClass('mobile-nav--expanded');
304  });
305};
306
307/**
308 * Traps the focus in a particular container
309 *
310* @param {object} options - Options to be used
311* @param {jQuery} options.$container - Container to trap focus within
312* @param {jQuery} options.$elementToFocus - Element to be focused when focus leaves container
313* @param {string} options.namespace - Namespace used for new focus event handler
314*/
315timber.trapFocus = function(options) {
316  var eventName = options.namespace
317    ? 'focusin.' + options.namespace
318    : 'focusin';
319
320  if (!options.$elementToFocus) {
321    options.$elementToFocus = options.$container;
322    options.$container.attr('tabindex', '-1');
323  }
324
325  options.$elementToFocus.focus();
326
327  $(document).on(eventName, function(evt) {
328    if (
329      options.$container[0] !== evt.target &&
330      !options.$container.has(evt.target).length
331    ) {
332      options.$container.focus();
333    }
334  });
335};
336
337/**
338 * Removes the trap of focus in a particular container
339 *
340 * @param {object} options - Options to be used
341 * @param {jQuery} options.$container - Container to trap focus within
342 * @param {string} options.namespace - Namespace used for new focus event handler
343 */
344timber.removeTrapFocus = function(options) {
345  var eventName = options.namespace
346    ? 'focusin.' + options.namespace
347    : 'focusin';
348
349  if (options.$container && options.$container.length) {
350    options.$container.removeAttr('tabindex');
351  }
352
353  $(document).off(eventName);
354};
355
356timber.getHash = function() {
357  return window.location.hash;
358};
359
360timber.updateHash = function(hash) {
361  window.location.hash = '#' + hash;
362  $('#' + hash)
363    .attr('tabindex', -1)
364    .focus();
365};
366
367timber.productPage = function(options) {
368  var moneyFormat = options.money_format,
369    variant = options.variant;
370
371  // Selectors
372  var $productImage = $('#ProductPhotoImg'),
373    $addToCart = $('#AddToCart'),
374    $productPrice = $('#ProductPrice'),
375    $comparePrice = $('#ComparePrice'),
376    $quantityElements = $('.quantity-selector, label + .js-qty'),
377    $addToCartText = $('#AddToCartText');
378
379  if (variant) {
380    // Update variant image, if one is set
381    if (variant.featured_image) {
382      var newImg = variant.featured_image,
383        el = $productImage[0];
384      Shopify.Image.switchImage(newImg, el, timber.switchImage);
385    }
386
387    // Select a valid variant if available
388    if (variant.available) {
389      // Available, enable the submit button, change text, show quantity elements
390      $addToCart.removeClass('disabled').prop('disabled', false);
391      $addToCartText.html(theme.strings.add_to_cart);
392      $quantityElements.show();
393    } else {
394      // Sold out, disable the submit button, change text, hide quantity elements
395      $addToCart.addClass('disabled').prop('disabled', true);
396      $addToCartText.html(theme.strings.sold_out);
397      $quantityElements.hide();
398    }
399
400    // Regardless of stock, update the product price
401    $productPrice.html(Shopify.formatMoney(variant.price, moneyFormat));
402
403    // Also update and show the product's compare price if necessary
404    if (variant.compare_at_price > variant.price) {
405      $comparePrice
406        .html(Shopify.formatMoney(variant.compare_at_price, moneyFormat))
407        .show();
408    } else {
409      $comparePrice.hide();
410    }
411  } else {
412    // The variant doesn't exist, disable submit button.
413    // This may be an error or notice that a specific variant is not available.
414    // To only show available variants, implement linked product options:
415    //   - http://docs.shopify.com/manual/configuration/store-customization/advanced-navigation/linked-product-options
416    $addToCart.addClass('disabled').prop('disabled', true);
417    $addToCartText.html(theme.strings.unavailable);
418    $quantityElements.hide();
419  }
420};
421
422timber.productImageSwitch = function() {
423  if (timber.cache.$thumbImages.length) {
424    // Switch the main image with one of the thumbnails
425    // Note: this does not change the variant selected, just the image
426    timber.cache.$thumbImages.on('click', function(evt) {
427      evt.preventDefault();
428      var newImage = $(this).attr('href');
429      timber.switchImage(newImage, null, timber.cache.$productImage);
430    });
431  }
432};
433
434timber.switchImage = function(src, imgObject, el) {
435  // Make sure element is a jquery object
436  var $el = $(el);
437  $el.attr('src', src);
438};
439
440timber.collectionViews = function() {
441  if (timber.cache.$changeView.length) {
442    timber.cache.$changeView.on('click', function() {
443      var view = $(this).data('view'),
444        url = document.URL,
445        hasParams = url.indexOf('?') > -1;
446
447      if (hasParams) {
448        window.location = replaceUrlParam(url, 'view', view);
449      } else {
450        window.location = url + '?view=' + view;
451      }
452    });
453  }
454};
455
456timber.loginForms = function() {
457  function showRecoverPasswordForm() {
458    timber.cache.$recoverPasswordForm.show();
459    timber.cache.$customerLoginForm.hide();
460  }
461
462  function hideRecoverPasswordForm() {
463    timber.cache.$recoverPasswordForm.hide();
464    timber.cache.$customerLoginForm.show();
465  }
466
467  timber.cache.$recoverPasswordLink.on('click', function(evt) {
468    evt.preventDefault();
469    showRecoverPasswordForm();
470  });
471
472  timber.cache.$hideRecoverPasswordLink.on('click', function(evt) {
473    evt.preventDefault();
474    hideRecoverPasswordForm();
475  });
476
477  // Allow deep linking to recover password form
478  if (timber.getHash() === '#recover') {
479    showRecoverPasswordForm();
480  }
481};
482
483timber.resetPasswordSuccess = function() {
484  timber.cache.$passwordResetSuccess.show();
485};
486
487/*============================================================================
488  Drawer modules
489  - Docs http://shopify.github.io/Timber/#drawers
490==============================================================================*/
491timber.Drawers = (function() {
492  var Drawer = function(id, position, options) {
493    var defaults = {
494      close: '.js-drawer-close',
495      open: '.js-drawer-open-' + position,
496      openClass: 'js-drawer-open',
497      dirOpenClass: 'js-drawer-open-' + position
498    };
499
500    this.nodes = {
501      $parent: $('body, html'),
502      $page: $('#PageContainer'),
503      $moved: $('.is-moved-by-drawer')
504    };
505
506    this.config = $.extend(defaults, options);
507    this.position = position;
508
509    this.$drawer = $('#' + id);
510
511    if (!this.$drawer.length) {
512      return false;
513    }
514
515    this.drawerIsOpen = false;
516    this.init();
517  };
518
519  Drawer.prototype.init = function() {
520    $(this.config.open).on('click', $.proxy(this.open, this));
521    this.$drawer.find(this.config.close).on('click', $.proxy(this.close, this));
522  };
523
524  Drawer.prototype.open = function(evt) {
525    // Keep track if drawer was opened from a click, or called by another function
526    var externalCall = false;
527
528    // Prevent following href if link is clicked
529    if (evt) {
530      evt.preventDefault();
531    } else {
532      externalCall = true;
533    }
534
535    // Without this, the drawer opens, the click event bubbles up to $nodes.page
536    // which closes the drawer.
537    if (evt && evt.stopPropagation) {
538      evt.stopPropagation();
539      // save the source of the click, we'll focus to this on close
540      this.$activeSource = $(evt.currentTarget);
541    }
542
543    if (this.drawerIsOpen && !externalCall) {
544      return this.close();
545    }
546
547    // Add is-transitioning class to moved elements on open so drawer can have
548    // transition for close animation
549    this.nodes.$moved.addClass('is-transitioning');
550    this.$drawer.prepareTransition();
551
552    this.nodes.$parent.addClass(
553      this.config.openClass + ' ' + this.config.dirOpenClass
554    );
555    this.drawerIsOpen = true;
556
557    // Set focus on drawer
558    this.trapFocus(this.$drawer, 'drawer_focus');
559
560    // Run function when draw opens if set
561    if (
562      this.config.onDrawerOpen &&
563      typeof this.config.onDrawerOpen === 'function'
564    ) {
565      if (!externalCall) {
566        this.config.onDrawerOpen();
567      }
568    }
569
570    if (this.$activeSource && this.$activeSource.attr('aria-expanded')) {
571      this.$activeSource.attr('aria-expanded', 'true');
572    }
573
574    // Lock scrolling on mobile
575    this.nodes.$page.on('touchmove.drawer', function() {
576      return false;
577    });
578
579    this.nodes.$page.on(
580      'click.drawer',
581      $.proxy(function() {
582        this.close();
583        return false;
584      }, this)
585    );
586  };
587
588  Drawer.prototype.close = function() {
589    if (!this.drawerIsOpen) {
590      // don't close a closed drawer
591      return;
592    }
593
594    // deselect any focused form elements
595    $(document.activeElement).trigger('blur');
596
597    // Ensure closing transition is applied to moved elements, like the nav
598    this.nodes.$moved.prepareTransition({ disableExisting: true });
599    this.$drawer.prepareTransition({ disableExisting: true });
600
601    this.nodes.$parent.removeClass(
602      this.config.dirOpenClass + ' ' + this.config.openClass
603    );
604
605    this.drawerIsOpen = false;
606
607    // Remove focus on drawer
608    this.removeTrapFocus(this.$drawer, 'drawer_focus');
609
610    this.nodes.$page.off('.drawer');
611  };
612
613  Drawer.prototype.trapFocus = function($container, eventNamespace) {
614    var eventName = eventNamespace ? 'focusin.' + eventNamespace : 'focusin';
615
616    $container.attr('tabindex', '-1');
617
618    $container.focus();
619
620    $(document).on(eventName, function(evt) {
621      if ($container[0] !== evt.target && !$container.has(evt.target).length) {
622        $container.focus();
623      }
624    });
625  };
626
627  Drawer.prototype.removeTrapFocus = function($container, eventNamespace) {
628    var eventName = eventNamespace ? 'focusin.' + eventNamespace : 'focusin';
629
630    $container.removeAttr('tabindex');
631    $(document).off(eventName);
632  };
633
634  return Drawer;
635})();
636
637// Initialize Timber's JS on docready
638$(timber.init);
639
640window.theme = window.theme || {};
641
642theme.Header = (function() {
643  var cache = {};
644
645  function cacheSelectors() {
646    cache = {
647      $html: $('html'),
648      $body: $('body'),
649      $wrapper: $('.wrapper'),
650      $sidebar: $('#sidebar'),
651      $logo: $('#logo'),
652      $meta: $('#meta'),
653      $announcementBar: $('.announcement-bar'),
654      $siteHeader: $('.site-header'),
655      $menu: $('#menu'),
656      $nav: $('.site-nav'),
657      $siteLogo: $('.site-header__logo'),
658      $siteLogoLink: $('.site-header__logo-link') || null,
659      $siteLogoLinkInverted: $('.site-header__logo-link--inverted') || null,
660      $mobileMenu: $('.nav-bar'),
661      $mobileMenuButton: $('#menu-opener'),
662      $mobileCloseMenuButton: $('#menu-closer'),
663      $pageContainer: $('#PageContainer'),
664      $responsiveMenu: $('#meta').find('.responsive-menu'),
665      $responsiveClose: $('.responsive-close'),
666      $options: $('#options'),
667      $footer: $('#footer'),
668      $content: $('#content'),
669      $allLinks: $('button, a', cache.$mobileMenu),
670      $siteNavs: $('.site-nav'),
671      isindexTemplate: $('body').hasClass('template-index'),
672      menuStyle: $('.site-header').data('menu-style'),
673      touchM: 'ontouchstart' in window,
674      iOS: /(iPad|iPhone|iPod)/g.test(navigator.userAgent),
675      navWidth: 0,
676      logoWidth: 0,
677      navigation: {
678        activeClass: 'opened',
679        childClass: 'site-nav__link--child',
680        active: '.opened',
681        parents: '.site-nav--has-dropdown',
682        links: '.site-nav__link',
683        dropdown: '.site-nav__dropdown'
684      }
685    };
686  }
687
688  function init() {
689    cacheSelectors();
690    if (cache.touchM) {
691      cache.$body.addClass('touch');
692    } else {
693      cache.$body.addClass('no-touch');
694    }
695
696    if ($('header').hasClass('is-dark')) {
697      cache.$pageContainer.addClass('is-dark');
698      cache.$pageContainer.removeClass('is-light');
699    } else if ($('header').hasClass('is-light')) {
700      cache.$pageContainer.addClass('is-light');
701      cache.$pageContainer.removeClass('is-dark');
702    }
703
704    cache.$footer.removeClass('loading');
705
706    /* Enable fit vid & custom solution for posts videos */
707
708    $(
709      'p[style="text-align: center;"] img, p[style="text-align: center;"] iframe'
710    ).each(function() {
711      $(this)
712        .parent()
713        .addClass('centered-media');
714    });
715
716    $('.main-content').fitVids();
717
718    menuStyleCheck();
719    stickyHeader();
720
721    if ($('.link-list').length > 0) {
722      $('.link-list')
723        .clone()
724        .appendTo($('.nav-bar'))
725        .find('a')
726        .attr('tabindex', '-1');
727    }
728
729    menuDrawerButtons();
730    dropDownMenus();
731  }
732
733  /* Function that decides whether to show a hamburger icon or all the links */
734  function fitNav() {
735    var navWiderThanWrapper =
736      cache.$wrapper.width() < cache.navWidth + cache.logoWidth;
737    if (
738      navWiderThanWrapper &&
739      cache.$siteHeader.hasClass('site-header--classic')
740    ) {
741      collapseMenu();
742      hideInvertedLogo();
743    } else if (
744      !navWiderThanWrapper &&
745      cache.$siteHeader.hasClass('site-header--drawer') &&
746      cache.menuStyle !== 'drawer'
747    ) {
748      timber.closeDrawerMenu();
749      expandMenu();
750      showInvertedLogo();
751    }
752    if (navWiderThanWrapper) {
753      cache.$mobileMenu.css('height', $(window).height());
754    }
755    cache.$siteLogo.css('opacity', '1');
756    cache.$nav.css('opacity', '1');
757  }
758
759  function menuStyleCheck() {
760    timber.cache.$window.on('load', function() {
761      cache.logoWidth = cache.$siteLogo.width() || 0;
762      cache.$nav.children('li').each(function() {
763        cache.navWidth += $(this).outerWidth(true);
764      });
765      // Make drawer a11y accessible
766      timber.cache.$navBar.attr('aria-hidden', 'false');
767      fitNav();
768      $(window).on('resize', $.debounce(250, fitNav));
769    });
770  }
771
772  function collapseMenu() {
773    cache.$mobileMenu.removeClass('animate');
774    cache.$announcementBar.addClass('mobile');
775    cache.$siteHeader
776      .addClass('site-header--drawer mobile sticky')
777      .removeClass('site-header--classic active')
778      .find('.btn__buy a')
779      .removeClass('btn--small btn--dark')
780      .addClass('btn--regular btn--light');
781    // Make drawer a11y unaccessible
782    timber.cache.$navBar.attr('aria-hidden', 'true');
783    cache.$allLinks.attr('tabindex', '-1');
784  }
785
786  function expandMenu() {
787    cache.$announcementBar.removeClass('mobile');
788    cache.$siteHeader
789      .addClass('site-header--classic active')
790      .removeClass('site-header--drawer mobile sticky')
791      .find('.btn__buy a')
792      .addClass('btn--small btn--dark')
793      .removeClass('btn--regular btn--light');
794    cache.$mobileMenu.css('height', '100%');
795    // Make drawer a11y accessible
796    timber.cache.$navBar.attr('aria-hidden', 'false');
797    cache.$allLinks.attr('tabindex', '');
798  }
799
800  function stickyHeader() {
801    if (cache.menuStyle === 'drawer') return;
802
803    cache.$siteHeader
804      .attr('aria-hidden', true)
805      .find('a, button')
806      .attr('tabIndex', -1);
807
808    $(window).on('scroll', function() {
809      if (
810        cache.$siteHeader.hasClass('mobile') ||
811        cache.$siteHeader.hasClass('site-header--drawer')
812      )
813        return;
814      if ($(window).scrollTop() > 300) {
815        startAnimateHeader();
816      } else if ($(window).scrollTop() < 300) {
817        stopAnimateHeader();
818        var $menus = cache.$siteNavs.find(cache.navigation.active);
819        closeAllMenus($menus);
820      }
821    });
822  }
823
824  function startAnimateHeader() {
825    cache.$siteHeader.addClass('sticky');
826    hideInvertedLogo();
827    setTimeout(function() {
828      cache.$siteHeader.addClass('active');
829    }, 500);
830  }
831
832  function stopAnimateHeader() {
833    cache.$siteHeader.removeClass('active sticky');
834    showInvertedLogo();
835  }
836
837  function hideInvertedLogo() {
838    if (!cache.isindexTemplate || !cache.$siteLogoLinkInverted.length) return;
839    cache.$siteLogoLink.removeClass('logo--hidden');
840    cache.$siteLogoLinkInverted.addClass('logo--hidden');
841  }
842
843  function showInvertedLogo() {
844    if (!cache.isindexTemplate || !cache.$siteLogoLinkInverted.length) return;
845    cache.$siteLogoLink.addClass('logo--hidden');
846    cache.$siteLogoLinkInverted.removeClass('logo--hidden');
847  }
848
849  function menuDrawerButtons() {
850    cache.$mobileMenuButton.on('click', function(e) {
851      timber.openDrawerMenu();
852      e.preventDefault();
853    });
854
855    cache.$mobileCloseMenuButton.on('click', function(e) {
856      timber.closeDrawerMenu();
857      e.preventDefault();
858    });
859
860    setTimeout(function() {
861      cache.$mobileMenu.addClass('animate');
862    }, 500);
863  }
864
865  function dropDownMenus() {
866    $(cache.navigation.parents)
867      .children(cache.navigation.links)
868      .on('click', function() {
869        var $link = $(this),
870          $parent = $link.parent(),
871          $menus;
872
873        // If I click on an active dropdown parent, close it.
874        if ($parent.hasClass(cache.navigation.activeClass)) {
875          closeMenu($parent);
876          return;
877        }
878
879        if ($link.hasClass(cache.navigation.childClass)) {
880          $menus = $parent.siblings();
881        } else {
882          $menus = cache.$siteNavs.find(cache.navigation.active);
883        }
884
885        closeAllMenus($menus);
886        openMenu($parent);
887      });
888  }
889
890  function openMenu($menu) {
891    $menu.addClass(cache.navigation.activeClass);
892    $menu.children(cache.navigation.links).attr('aria-expanded', true);
893    $menu
894      .children(cache.navigation.dropdown)
895      .stop()
896      .slideDown(200);
897
898    setTimeout(function() {
899      timber.cache.$body.on('click.outsideMegaNav', function(e) {
900        if ($(e.target).is(cache.navigation.links)) return;
901        var $menus = cache.$siteNavs.find(cache.navigation.active);
902        closeAllMenus($menus);
903      });
904    }, 250);
905  }
906
907  function closeMenu($menu) {
908    $menu.removeClass(cache.navigation.activeClass);
909    $menu.children(cache.navigation.links).attr('aria-expanded', false);
910    $menu
911      .children(cache.navigation.dropdown)
912      .stop()
913      .slideUp(150);
914  }
915
916  function closeAllMenus($menus) {
917    $.each($menus, function() {
918      closeMenu($(this));
919    });
920
921    timber.cache.$body.off('click.outsideMegaNav');
922  }
923
924  function onSelect() {
925    if (cache.menuStyle === 'drawer') return;
926    cache.navWidth = 0;
927    cache.logoWidth = cache.$siteLogo.width() || 0;
928    cache.$nav.children('li').each(function() {
929      cache.navWidth += $(this).outerWidth(true);
930    });
931    // Make drawer a11y accessible
932    timber.cache.$navBar.attr('aria-hidden', 'false');
933    fitNav();
934    timber.cache.$window.on('resize', $.debounce(250, fitNav));
935  }
936
937  function unload() {
938    if (cache.$body.hasClass('opened-drawer')) {
939      cache.$body.removeClass('opened-drawer');
940    }
941  }
942
943  return {
944    init: init,
945    unload: unload,
946    onSelect: onSelect
947  };
948})();
949
950window.theme = window.theme || {};
951
952theme.Slideshow = function(el) {
953  this.cache = {
954    $slider: $(el),
955    sliderArgs: {
956      animation: 'slider',
957      animationSpeed: 300,
958      slideshow: false,
959      slideshowSpeed: 5000,
960      directionNav: true,
961      controlNav: true,
962      keyboard: true,
963      prevText: $.themeAssets.arrow_left,
964      nextText: $.themeAssets.arrow_right,
965      smoothHeight: true,
966      before: function(slider) {
967        $(slider)
968          .find('.slide')
969          .not('.flex-active-slide')
970          .removeClass('slide-hide');
971      },
972      after: function(slider) {
973        $(slider)
974          .find('.slide')
975          .not('.flex-active-slide')
976          .addClass('slide-hide');
977        $(slider).resize();
978      },
979      start: function(slider) {
980        $(slider)
981          .find('.slide')
982          .not('.flex-active-slide')
983          .addClass('slide-hide');
984        if (
985          $(slider)
986            .find('.slide')
987            .not('.clone').length === 1
988        ) {
989          $(slider)
990            .find('.flex-direction-nav')
991            .remove();
992        }
993        $(slider).addClass('loaded');
994        if ($('#slider').data('loaded-index') !== undefined) {
995          $('#slider').flexslider($('#slider').data('loaded-index'));
996        }
997      }
998    }
999  };
1000
1001  if (this.cache.$slider.find('li').length === 1) {
1002    this.cache.sliderArgs.touch = false;
1003  }
1004
1005  this.cache.$slider.flexslider(this.cache.sliderArgs);
1006  if (
1007    $(el)
1008      .attr('id')
1009      .indexOf('flexslider--') >= 0
1010  ) {
1011    this.cache.$slider.flexslider('play');
1012  }
1013};
1014
1015
1016/* ================ SECTIONS ================ */
1017window.theme = window.theme || {};
1018
1019theme.HeaderSection = (function() {
1020  function HeaderSection() {
1021    timber.cacheSelectors();
1022    timber.drawersInit();
1023    timber.cartInit();
1024    timber.mobileNavToggle();
1025    theme.Header.init();
1026  }
1027
1028  return HeaderSection;
1029})();
1030
1031theme.HeaderSection.prototype = _.assignIn({}, theme.HeaderSection.prototype, {
1032  onUnload: function() {
1033    theme.Header.unload();
1034  },
1035  onSelect: function() {
1036    theme.Header.onSelect();
1037  }
1038});
1039
1040/* eslint-disable no-new */
1041theme.Product = (function() {
1042  var defaults = {
1043    selectors: {
1044      addToCart: '#AddToCart',
1045      productPrice: '#ProductPrice',
1046      comparePrice: '#ComparePrice',
1047      addToCartText: '#AddToCartText',
1048      quantityElements: '.quantity-selector',
1049      optionSelector: 'productSelect'
1050    }
1051  };
1052
1053  function Product(container) {
1054    var $container = (this.$container = $(container));
1055    var sectionId = $container.attr('data-section-id');
1056
1057    this.settings = $.extend({}, defaults, {
1058      sectionId: sectionId,
1059      enableHistoryState: true,
1060      $container: this.$container,
1061      selectors: {
1062        originalSelectorId: 'productSelect-' + sectionId,
1063        productSection: '#ProductSection-' + sectionId,
1064        productLink: '.product__content--link-' + sectionId,
1065        addToCart: '#AddToCart-' + sectionId,
1066        productPrice: '#ProductPrice-' + sectionId,
1067        comparePrice: '#ComparePrice-' + sectionId,
1068        addToCartText: '#AddToCartText-' + sectionId,
1069        quantityElements: '#quantity-selector-' + sectionId,
1070        slider: '#slider-' + sectionId,
1071        selectorWrapper: '.selector-wrapper' + sectionId,
1072        SKU: '.variant-sku',
1073        shopifyPaymentButton: '.shopify-payment-button'
1074      }
1075    });
1076
1077    // disable history state if on homepage
1078    if ($('body').hasClass('template-index')) {
1079      this.settings.enableHistoryState = false;
1080    }
1081
1082    // Stop parsing if we don't have the product json script tag when loading
1083    // section in the Theme Editor
1084    if (!$('#ProductJson-' + sectionId).html()) {
1085      this.addQuantityButtons();
1086      return;
1087    }
1088
1089    this.productSingleObject = JSON.parse(
1090      document.getElementById('ProductJson-' + sectionId).innerHTML
1091    );
1092    this.init();
1093  }
1094
1095  Product.prototype = _.assignIn({}, Product.prototype, {
1096    init: function() {
1097      this.stringOverrides();
1098      this.initProductVariant();
1099      this.initSliderImages();
1100      this.addQuantityButtons();
1101      theme.customSelectorArrow(this.$container);
1102
1103      $('.image-popup', this.$container).magnificPopup({
1104        type: 'image',
1105        gallery: {
1106          enabled: true,
1107          tCounter: ''
1108        },
1109        mainClass: 'mfp-fade'
1110      });
1111    },
1112
1113    onUnload: function() {
1114      delete theme.slideshows[this.settings.selectors.slider];
1115    },
1116
1117    stringOverrides: function() {
1118      // Override defaults in theme.strings with potential
1119      // template overrides
1120
1121      theme.productStrings = theme.productStrings || {};
1122      $.extend(theme.strings, theme.productStrings);
1123    },
1124
1125    addQuantityButtons: function() {
1126      if (
1127        $(this.settings.selectors.quantityElements).children('input#Quantity')
1128          .length > 0
1129      ) {
1130        $(this.settings.selectors.quantityElements)
1131          .children('input#Quantity')
1132          .after(
1133            '<div class="input-holder plus"><button type="button" value="" class="plus" aria-label="' +
1134              theme.strings.increase_quantity +
1135              '">' +
1136              $.themeAssets.plus +
1137              '</button></div>'
1138          )
1139          .before(
1140            '<div class="input-holder minus"><button type="button" value="" class="minus" aria-label="' +
1141              theme.strings.reduce_quantity +
1142              '">' +
1143              $.themeAssets.minus +
1144              '</button></div>'
1145          );
1146      }
1147    },
1148
1149    initProductVariant: function() {
1150      // this.productSingleObject is a global JSON object defined in theme.liquid
1151      if (!this.productSingleObject) {
1152        return;
1153      }
1154
1155      var self = this;
1156      this.optionSelector = new Shopify.OptionSelectors(
1157        self.settings.selectors.originalSelectorId,
1158        {
1159          selectorClass: self.settings.selectors.optionSelectorClass,
1160          product: self.productSingleObject,
1161          onVariantSelected: self.productVariantCallback,
1162          enableHistoryState: self.settings.enableHistoryState,
1163          settings: self.settings
1164        }
1165      );
1166
1167      // Clean up variant labels if the Shopify-defined
1168      // defaults are the only ones left
1169      this.simplifyVariantLabels(this.productSingleObject);
1170    },
1171
1172    simplifyVariantLabels: function(productObject) {
1173      // Hide variant dropdown if only one exists and title contains 'Default'
1174      if (
1175        productObject.variants.length === 1 &&
1176        productObject.options.length === 1 &&
1177        productObject.options[0].toLowerCase().indexOf('title') >= 0 &&
1178        productObject.variants[0].title
1179          .toLowerCase()
1180          .indexOf('default title') >= 0
1181      ) {
1182        $(this.settings.selectors.productSection + ' .selector-wrapper').hide();
1183      }
1184    },
1185
1186    initSliderImages: function() {
1187      var slideshow = this.settings.selectors.slider;
1188      $('img', this.slideshow).addClass('lazypreload');
1189      // $(slideshow).imagesLoaded().done( function( instance ) {
1190      theme.slideshows[slideshow] = new theme.Slideshow(slideshow);
1191      // });
1192    },
1193
1194    // **WARNING** This function actually inherits `this` from `this.optionSelector` not
1195    // from `product` when passed in as a callback for `option_selection.js`
1196    productVariantCallback: function(variant) {
1197      if (variant) {
1198        // Update variant image, if one is set
1199        if (variant.featured_image) {
1200          var $slider = $(this.settings.selectors.slider);
1201          var $newImg = $slider.find(
1202            '.slide[data-variant-img="' + variant.featured_image.id + '"]'
1203          );
1204          if ($newImg.length > 0) {
1205            if ($slider.hasClass('loaded')) {
1206              $slider.flexslider($newImg.data('index'));
1207            } else {
1208              $slider.data('loaded-index', $newImg.data('index'));
1209            }
1210          }
1211        }
1212
1213        // Update the product link to the current variant
1214        var $productLink = $(this.settings.selectors.productLink);
1215        if ($productLink.length) {
1216          $productLink.attr(
1217            'href',
1218            updateUrlParameter($productLink.attr('href'), 'variant', variant.id)
1219          );
1220        }
1221
1222        // Update the product price
1223        $(this.settings.selectors.productPrice).html(
1224          Shopify.formatMoney(variant.price, theme.settings.moneyFormat)
1225        );
1226
1227        // Show SKU
1228        $(this.settings.selectors.SKU).html(variant.sku);
1229
1230        // Update and show the product's compare price if necessary
1231        if (variant.compare_at_price > variant.price) {
1232          $(this.settings.selectors.comparePrice)
1233            .html(
1234              Shopify.formatMoney(
1235                variant.compare_at_price,
1236                theme.settings.moneyFormat
1237              )
1238            )
1239            .show();
1240        } else {
1241          $(this.settings.selectors.comparePrice).hide();
1242        }
1243
1244        // Select a valid variant if available
1245        if (variant.available) {
1246          // We have a valid product variant, so enable the submit button
1247          $(this.settings.selectors.addToCart)
1248            .removeClass('btn--disabled')
1249            .prop('disabled', false);
1250          $(this.settings.selectors.addToCartText).text(
1251            theme.strings.add_to_cart
1252          );
1253          $(this.settings.selectors.quantityElements).removeClass('hidden');
1254          $(
1255            this.settings.selectors.shopifyPaymentButton,
1256            this.settings.$container
1257          ).show();
1258        } else {
1259          // Variant is sold out, disable the submit button and change the text
1260          $(this.settings.selectors.addToCart)
1261            .addClass('btn--disabled')
1262            .prop('disabled', true);
1263          $(this.settings.selectors.addToCartText).text(theme.strings.sold_out);
1264          $(this.settings.selectors.quantityElements).addClass('hidden');
1265          $(
1266            this.settings.selectors.shopifyPaymentButton,
1267            this.settings.$container
1268          ).hide();
1269        }
1270      } else {
1271        // The variant doesn't exist, disable submit button and change the text.
1272        // This may be an error or notice that a specific variant is not available.
1273        $(this.settings.selectors.addToCart)
1274          .addClass('btn--disabled')
1275          .prop('disabled', true);
1276        $(this.settings.selectors.addToCartText).text(
1277          theme.strings.unavailable
1278        );
1279        $(this.settings.selectors.quantityElements).addClass('hidden');
1280        $(
1281          this.settings.selectors.shopifyPaymentButton,
1282          this.settings.$container
1283        ).hide();
1284      }
1285
1286      function updateUrlParameter(url, key, value) {
1287        var re = new RegExp('([?&])' + key + '=.*?(&|$)', 'i');
1288        var separator = url.indexOf('?') === -1 ? '?' : '&';
1289
1290        if (url.match(re)) {
1291          return url.replace(re, '$1' + key + '=' + value + '$2');
1292        } else {
1293          return url + separator + key + '=' + value;
1294        }
1295      }
1296    }
1297  });
1298
1299  return Product;
1300})();
1301
1302theme.slideshows = {};
1303
1304theme.SlideshowSection = (function() {
1305  function SlideshowSection(container) {
1306    var $container = (this.$container = $(container));
1307    var id = $container.attr('data-section-id');
1308    var slideshow = (this.slideshow = '#flexslider--' + id);
1309    theme.slideshows[slideshow] = new theme.Slideshow(slideshow);
1310  }
1311
1312  return SlideshowSection;
1313})();
1314
1315theme.SlideshowSection.prototype = _.assignIn(
1316  {},
1317  theme.SlideshowSection.prototype,
1318  {
1319    onUnload: function() {
1320      delete theme.slideshows[this.slideshow];
1321    },
1322    onBlockSelect: function(evt) {
1323      var $slideshow = $(this.slideshow);
1324      // Ignore the cloned version
1325      var $slide = $('#slide-' + evt.detail.blockId + ':not(.clone)');
1326      var slideIndex = $slide.data('flexslider-index');
1327      var $slideImg = $slide.find('img') || $slide.find('svg');
1328
1329      $slide.imagesLoaded($slideImg, function() {
1330        $slideshow.flexslider(slideIndex);
1331        $slideshow.resize();
1332        $slideshow.flexslider('pause');
1333      });
1334    },
1335    onBlockDeselect: function() {
1336      // Resume autoplay
1337      var $slideshow = $(this.slideshow);
1338      $slideshow.flexslider('play');
1339    }
1340  }
1341);
1342
1343window.theme = window.theme || {};
1344
1345theme.Kickstarter = (function() {
1346  function Kickstarter(container) {
1347    this.$container = $(container);
1348    theme.crowdCampaign(this.$container);
1349  }
1350
1351  Kickstarter.prototype = _.assignIn({}, Kickstarter.prototype, {
1352    init: function() {
1353      theme.crowdCampaign(this.$container);
1354    },
1355    onSelect: function() {
1356      theme.crowdCampaign(this.$container);
1357    }
1358  });
1359
1360  return Kickstarter;
1361})();
1362
1363window.theme = window.theme || {};
1364
1365theme.FAQs = (function() {
1366  function FAQs(container) {
1367    var $container = (this.$container = $(container));
1368
1369    this.faqSelector = '.jumpstart-accordion-' + this.sectionId;
1370
1371    theme.accordionFAQs(this.$container);
1372
1373    this.$blocks = $('.section', $container);
1374    this.$opened = $('.opened', $container);
1375  }
1376
1377  FAQs.prototype = _.assignIn({}, FAQs.prototype, {
1378    init: function() {
1379      this.$opened.find('.content').slidedown(0);
1380
1381      this.$blocks
1382        .find('.title')
1383        .prepend($.themeAssets.plus + $.themeAssets.minus);
1384
1385      this.$blocks.on('click', function(evt) {
1386        var blockId = $(evt.target).attr('data-block-id');
1387        this.focusFAQ(blockId);
1388      });
1389    },
1390    focusFAQ: function(blockId, isEditorEvent) {
1391      var $accordionItem = $('.section-' + blockId);
1392
1393      if ($accordionItem.hasClass('opened') && !isEditorEvent) {
1394        $accordionItem.removeClass('opened');
1395        $accordionItem
1396          .children('div')
1397          .stop()
1398          .slideUp(300);
1399      } else {
1400        $accordionItem.addClass('opened');
1401        $accordionItem
1402          .children('div')
1403          .stop()
1404          .slideDown(300);
1405        this.$blocks
1406          .not($accordionItem)
1407          .removeClass('opened')
1408          .children('div')
1409          .stop()
1410          .slideUp(300);
1411      }
1412    },
1413    onBlockSelect: function(evt) {
1414      this.focusFAQ(evt.detail.blockId, true);
1415    },
1416    onload: function() {
1417      theme.accordionFAQs(this.$container);
1418    }
1419  });
1420
1421  return FAQs;
1422})();
1423
1424theme.Maps = (function() {
1425  var config = {
1426    zoom: 14
1427  };
1428  var apiStatus = null;
1429  var mapsToLoad = [];
1430
1431  function Map(container) {
1432    theme.$currentMapContainer = this.$container = $(container);
1433    var key = this.$container.data('api-key');
1434
1435    if (typeof key !== 'string' || key === '') {
1436      return;
1437    }
1438
1439    if (apiStatus === 'loaded') {
1440      var self = this;
1441
1442      // Check if the script has previously been loaded with this key
1443      var $script = $('script[src*="' + key + '&"]');
1444      if ($script.length === 0) {
1445        $.getScript(
1446          'https://maps.googleapis.com/maps/api/js?key=' + key
1447        ).then(function() {
1448          apiStatus = 'loaded';
1449          self.createMap();
1450        });
1451      } else {
1452        this.createMap();
1453      }
1454    } else {
1455      mapsToLoad.push(this);
1456
1457      if (apiStatus !== 'loading') {
1458        apiStatus = 'loading';
1459        if (typeof window.google === 'undefined') {
1460          $.getScript(
1461            'https://maps.googleapis.com/maps/api/js?key=' + key
1462          ).then(function() {
1463            apiStatus = 'loaded';
1464            initAllMaps();
1465          });
1466        }
1467      }
1468    }
1469  }
1470
1471  function initAllMaps() {
1472    // API has loaded, load all Map instances in queue
1473    $.each(mapsToLoad, function(index, instance) {
1474      instance.createMap();
1475    });
1476  }
1477
1478  function geolocate($map) {
1479    var deferred = $.Deferred();
1480    var geocoder = new google.maps.Geocoder();
1481    var address = $map.data('address-setting');
1482
1483    geocoder.geocode({ address: address }, function(results, status) {
1484      if (status !== google.maps.GeocoderStatus.OK) {
1485        deferred.reject(status);
1486      }
1487
1488      deferred.resolve(results);
1489    });
1490
1491    return deferred;
1492  }
1493
1494  Map.prototype = _.assignIn({}, Map.prototype, {
1495    createMap: function() {
1496      var $map = this.$container.find('.map-section__container');
1497
1498      return geolocate($map)
1499        .then(
1500          function(results) {
1501            var mapOptions = {
1502              zoom: config.zoom,
1503              styles: config.styles,
1504              center: results[0].geometry.location,
1505              draggable: false,
1506              clickableIcons: false,
1507              scrollwheel: false,
1508              disableDoubleClickZoom: true,
1509              disableDefaultUI: true
1510            };
1511
1512            var map = (this.map = new google.maps.Map($map[0], mapOptions));
1513            var center = (this.center = map.getCenter());
1514
1515            //eslint-disable-next-line no-unused-vars
1516            var marker = new google.maps.Marker({
1517              map: map,
1518              position: center
1519            });
1520
1521            google.maps.event.addDomListener(
1522              window,
1523              'resize',
1524              $.debounce(250, function() {
1525                google.maps.event.trigger(map, 'resize');
1526                map.setCenter(center);
1527              })
1528            );
1529          }.bind(this)
1530        )
1531        .fail(function() {
1532          var errorMessage;
1533
1534          switch (status) {
1535            case 'ZERO_RESULTS':
1536              errorMessage = theme.strings.addressNoResults;
1537              break;
1538            case 'OVER_QUERY_LIMIT':
1539              errorMessage = theme.strings.addressQueryLimit;
1540              break;
1541            default:
1542              errorMessage = theme.strings.addressError;
1543              break;
1544          }
1545
1546          var $mapContainer = $map.parents('.map-section');
1547
1548          // Only show error in the theme editor
1549          if (Shopify.designMode) {
1550            $mapContainer.addClass('page-width map-section--load-error');
1551            $mapContainer.find('.map-section__content-wrapper').remove();
1552            $mapContainer
1553              .find('.map-section__wrapper')
1554              .html(
1555                '<div class="errors text-center" style="width: 100%;">' +
1556                  errorMessage +
1557                  '</div>'
1558              );
1559          } else {
1560            $mapContainer.removeClass('map-section--display-map');
1561          }
1562        });
1563    },
1564
1565    onUnload: function() {
1566      if (typeof window.google !== 'undefined') {
1567        google.maps.event.clearListeners(this.map, 'resize');
1568      }
1569    }
1570  });
1571
1572  return Map;
1573})();
1574
1575// Global function called by Google on auth errors.
1576// Show an auto error message on all map instances.
1577// eslint-disable-next-line camelcase, no-unused-vars
1578function gm_authFailure() {
1579  if (Shopify.designMode) {
1580    theme.$currentMapContainer.addClass('page-width map-section--load-error');
1581    theme.$currentMapContainer.find('.map-section__content-wrapper').remove();
1582    theme.$currentMapContainer
1583      .find('.map-section__wrapper')
1584      .html(
1585        '<div class="errors text-center" style="width: 100%;">
1585' +
1586          theme.strings.authError +
1587          '</div>'
1588      );
1589  } else {
1590    theme.$currentMapContainer.removeClass('map-section--display-map');
1591  }
1592}
1593
1594
1595/* ================ TEMPLATES ================ */
1596window.theme = window.theme || {};
1597
1598theme.Collection = (function() {
1599  function Collection() {
1600    theme.collectionGridMasonry();
1601  }
1602
1603  Collection.prototype = _.assignIn({}, Collection.prototype, {
1604    init: function() {
1605      theme.collectionGridMasonry();
1606    },
1607    onSelect: function() {
1608      theme.collectionGridMasonry();
1609    }
1610  });
1611
1612  return Collection;
1613})();
1614
1615window.theme = window.theme || {};
1616
1617theme.Search = (function() {
1618  function Search() {
1619    theme.collectionGridMasonry();
1620  }
1621
1622  Search.prototype = _.assignIn({}, Search.prototype, {
1623    init: function() {
1624      theme.collectionGridMasonry();
1625    },
1626    onSelect: function() {
1627      theme.collectionGridMasonry();
1628    }
1629  });
1630
1631  return Search;
1632})();
1633
1634
1635theme.cacheSelectors = function() {
1636  theme.cache = {
1637    $html: $('html'),
1638    $body: $('body'),
1639    $wrapper: $('.wrapper'),
1640    $sidebar: $('#sidebar'),
1641    $logo: $('#logo'),
1642    $meta: $('#meta'),
1643    $siteHeader: $('.site-header'),
1644    $menu: $('#menu'),
1645    $nav: $('#AccessibleNav'),
1646    $siteLogo: $('.site-header__logo'),
1647    $mobileMenu: $('.nav-bar'),
1648    $mobileMenuButton: $('#menu-opener'),
1649    $responsiveMenu: $('#meta').find('.responsive-menu'),
1650    $responsiveClose: $('.responsive-close'),
1651    $options: $('#options'),
1652    $footer: $('#footer'),
1653    $content: $('#content'),
1654    touchM: 'ontouchstart' in window,
1655    iOS: /(iPad|iPhone|iPod)/g.test(navigator.userAgent),
1656    navWidth: 0,
1657    logoWidth: 0
1658  };
1659};
1660
1661theme.customSelectorArrow = function(el) {
1662  var scope = el || document;
1663  $('select', $(scope)).each(function() {
1664    $(this).wrap('<div class="jumpstart-selector"></div>');
1665    $(this)
1666      .parent()
1667      .attr('style', $(this).attr('style'));
1668    $(this)
1669      .parent()
1670      .append('<span class="arrow">' + $.themeAssets.arrow_down + '</span>');
1671  });
1672};
1673
1674theme.collectionGridMasonry = function() {
1675  if (typeof $.fn.packery !== 'undefined' && $('.collection-list').length > 0) {
1676    $('.collection-list').imagesLoaded(function() {
1677      $('.collection-list').packery({
1678        itemSelector: '.product',
1679        transitionDuration: 0
1680      });
1681    });
1682  }
1683};
1684
1685theme.parallaxBg = function() {
1686  if (!$('.parallax-bg').length > 0 || !$('#section-a').length > 0) return;
1687
1688  var $prlxBg, $prlxTxt;
1689
1690  if ($('#section-a').length > 0) {
1691    $prlxBg = $('#section-a span.prlx-bg');
1692    $prlxTxt = $('#section-a .wrapper').addClass('prlx-txt');
1693    $prlxBg.parent().addClass('parallax-bg');
1694  } else {
1695    $prlxBg = $('.prlx-bg');
1696    $prlxTxt = $('.prlx-txt');
1697  }
1698  $(window).on('scroll', function() {
1699    if (!$(window).scrollTop() < $prlxBg.height()) return;
1700
1701    $prlxBg.css(
1702      'transform',
1703      'translate3d(0px, ' + $(window).scrollTop() / 4 + 'px, 0px)'
1704    );
1705    $prlxTxt.css(
1706      'transform',
1707      'translate3d(0px, ' + $(window).scrollTop() / 8 + 'px, 0px)'
1708    );
1709  });
1710};
1711
1712theme.quantityButtons = function() {
1713  if ($('input#Quantity').length > 0) {
1714    $(document).on('click', '.plus, .minus', function() {
1715      var $qty = $(this).siblings('#Quantity'),
1716        currentVal = parseFloat($qty.val()),
1717        max = parseFloat($qty.attr('max')),
1718        min = parseFloat($qty.attr('min')),
1719        step = $qty.attr('step');
1720
1721      if (!currentVal || currentVal === '' || currentVal === 'NaN')
1722        currentVal = 0;
1723      if (max === '' || max === 'NaN') max = '';
1724      if (min === '' || min === 'NaN') min = 0;
1725      if (
1726        step === 'any' ||
1727        step === '' ||
1728        step === undefined ||
1729        parseFloat(step) === 'NaN'
1730      )
1731        step = 1;
1732
1733      if ($(this).is('.plus')) {
1734        if (max && (max === currentVal || currentVal > max)) {
1735          $qty.val(max);
1736        } else {
1737          $qty.val(currentVal + parseFloat(step));
1738        }
1739      } else {
1740        if (min && (min === currentVal || currentVal < min)) {
1741          $qty.val(min);
1742        } else if (currentVal > 0) {
1743          $qty.val(currentVal - parseFloat(step));
1744        }
1745      }
1746      $qty.trigger('change');
1747    });
1748  }
1749};
1750
1751theme.passwordFooter = function() {
1752  if (!$('.template-password').length > 0) return;
1753
1754  var $pageContainer = $('#PageContainer'),
1755    $passwordFooter = $('#password-footer');
1756  $(window)
1757    .on('resize', function() {
1758      if ($(window).height() < $pageContainer.height()) {
1759        $passwordFooter.removeClass('full');
1760      } else {
1761        $passwordFooter.addClass('full');
1762      }
1763    })
1764    .trigger('resize');
1765};
1766
1767theme.infiniteBlog = function() {
1768  var $infiniteLink = $('#infinite-link'),
1769    $infiniteURL = $infiniteLink.children('a'),
1770    $blogList = $('.blog-list');
1771
1772  if ($infiniteLink.length > 0) {
1773    $infiniteURL.on('click', function(e) {
1774      $infiniteURL.addClass('btn--disabled').text('Loading ...');
1775      var href = $(this).attr('href');
1776      $.ajax({
1777        url: href,
1778        dataType: 'html',
1779        success: function(data) {
1780          var $data = $(data),
1781            $posts = $data.find('a.article'),
1782            $infinite = $data.find('#infinite-link');
1783          $posts.imagesLoaded(function() {
1784            $posts.css('display', 'none');
1785            $blogList.append($posts);
1786            $posts.slideDown(300);
1787            if ($infinite.length > 0) {
1788              $infiniteURL
1789                .removeClass('btn--disabled')
1790                .text('More posts')
1791                .prop('href', $infinite.children('a').prop('href'));
1792            } else {
1793              $infiniteURL.text('All posts loaded');
1794            }
1795          });
1796        }
1797      });
1798      e.preventDefault();
1799    });
1800  }
1801};
1802
1803theme.homeGallery = function() {
1804  if ($('.home-gallery').length > 0) {
1805    $('.home-gallery').imagesLoaded(function() {
1806      $('.home-gallery')
1807        .find('.item')
1808        .each(function() {
1809          var $img = $(this).find('img');
1810          if ($img[0].naturalWidth <= $img[0].naturalHeight) {
1811            $(this).addClass('one-quarter medium-down--one-half');
1812          } else {
1813            $(this).addClass('one-half medium-down--one-whole');
1814          }
1815        });
1816      $('.home-gallery')
1817        .find('.packery-container')
1818        .packery({
1819          itemSelector: '.grid__item',
1820          gutter: 0,
1821          percentPosition: true,
1822          transitionDuration: 0
1823        });
1824      $('.home-gallery').addClass('init');
1825      $('.home-gallery')
1826        .find('.packery-container')
1827        .packery();
1828    });
1829  }
1830};
1831
1832theme.iframePopUp = function() {
1833  $('.video-overlay').magnificPopup({
1834    type: 'iframe',
1835    mainClass: 'mfp-fade'
1836  });
1837};
1838
1839theme.accordionFAQs = function(el) {
1840  var scope = el || document;
1841
1842  if ($('.jumpstart-accordion', $(scope)).length > 0) {
1843    $('.jumpstart-accordion', $(scope)).each(function() {
1844      var $sections = $(this).children('div');
1845      var $opened = $sections.filter('.opened');
1846      $opened.children('div').slideDown(0);
1847      $(this)
1848        .children('div')
1849        .children('h3')
1850        .prepend($.themeAssets.plus + $.themeAssets.minus)
1851        .click(function() {
1852          var $this = $(this).parent();
1853          if ($this.hasClass('opened')) {
1854            $this.removeClass('opened');
1855            $this
1856              .children('div')
1857              .stop()
1858              .slideUp(300);
1859          } else {
1860            $this.addClass('opened');
1861            $this
1862              .children('div')
1863              .stop()
1864              .slideDown(300);
1865            $sections
1866              .not($this)
1867              .removeClass('opened')
1868              .children('div')
1869              .stop()
1870              .slideUp(300);
1871          }
1872        });
1873    });
1874  }
1875};
1876
1877theme.crowdCampaign = function($campaignContainer) {
1878  if (!$('.home-kickstarter').length > 0) return;
1879
1880  var sectionId = $campaignContainer.data('section-id');
1881
1882  // PIE
1883  $('.kickstarter__graphic.pie', $campaignContainer).html(
1884    '<canvas id="kickstarter__pie--help--' +
1885      sectionId +
1886      '" width="110" height="110"></canvas><canvas id="kickstarter__pie--' +
1887      sectionId +
1888      '" width="110" height="110"></canvas>'
1889  );
1890
1891  var progress = 0,
1892    pieI = null,
1893    pieValue = Math.min(
1894      parseInt($('.kickstarter__graphic', $campaignContainer).data('value')) /
1895        100,
1896      1
1897    ),
1898    pieColor = $('.kickstarter__graphic', $campaignContainer).data('color'),
1899    pieCanvas = document.getElementById('kickstarter__pie--' + sectionId),
1900    context = pieCanvas.getContext('2d'),
1901    centerX = pieCanvas.width / 2,
1902    centerY = pieCanvas.height / 2,
1903    radius = 45;
1904
1905  context.lineWidth = 15;
1906  context.strokeStyle = pieColor;
1907  context.lineCap = 'round';
1908
1909  pieI = setInterval(function() {
1910    progress = progress + 0.0025;
1911    context.clearRect(0, 0, pieCanvas.width, pieCanvas.height);
1912    context.beginPath();
1913    context.arc(centerX, centerY, radius, 0, 2 * progress * Math.PI, false);
1914    context.stroke();
1915    if (progress >= pieValue) {
1916      clearInterval(pieI);
1917    }
1918  }, 5);
1919
1920  var pieCanvasHelp = document.getElementById(
1921      'kickstarter__pie--help--' + sectionId
1922    ),
1923    contextHelp = pieCanvasHelp.getContext('2d'),
1924    centerXHelp = pieCanvasHelp.width / 2,
1925    centerYHelp = pieCanvasHelp.height / 2,
1926    radiusHelp = 45;
1927
1928  contextHelp.lineWidth = 15;
1929  contextHelp.strokeStyle = '#e9e9e9';
1930  contextHelp.lineCap = 'round';
1931  contextHelp.beginPath();
1932  contextHelp.arc(centerXHelp, centerYHelp, radiusHelp, 0, 2 * Math.PI, false);
1933  contextHelp.stroke();
1934
1935  // BAR
1936
1937  var barValue = Math.min(
1938    parseInt($('.kickstarter__graphic.bar', $campaignContainer).data('value')),
1939    100
1940  );
1941  $('.kickstarter__graphic.bar', $campaignContainer).append(
1942    '<div class="value"></div>'
1943  );
1944  $('.kickstarter__graphic.bar .value', $campaignContainer).css(
1945    'width',
1946    barValue + '%'
1947  );
1948};
1949
1950$(document).ready(function() {
1951  var sections = new theme.Sections();
1952
1953  sections.register('header-section', theme.HeaderSection);
1954  sections.register('slideshow-section', theme.SlideshowSection);
1955  sections.register('product', theme.Product);
1956  sections.register('home-product', theme.Product);
1957  sections.register('collection-template', theme.Collection);
1958  sections.register('list-collection-template', theme.Collection);
1959  sections.register('home-kickstarter', theme.Kickstarter);
1960  sections.register('home-faq', theme.FAQs);
1961  sections.register('feature-collection', theme.Collection);
1962  sections.register('map-section', theme.Maps);
1963  sections.register('search', theme.Search);
1964});
1965
1966(function($) {
1967  $(document).ready(function($) {
1968    'use strict';
1969
1970    /* Elements */
1971
1972    /* eslint-disable */
1973    var $html = $('html'),
1974      $body = $('body'),
1975      $wrapper = $('.wrapper'),
1976      $sidebar = $('#sidebar'),
1977      $logo = $('#logo'),
1978      $meta = $('#meta'),
1979      $siteHeader = $('.site-header'),
1980      $menu = $('#menu'),
1981      $nav = $('#AccessibleNav'),
1982      $siteLogo = $('.site-header__logo'),
1983      $mobileMenu = $('.nav-bar'),
1984      $mobileMenuButton = $('#menu-opener'),
1985      $responsiveMenu = $meta.find('.responsive-menu'),
1986      $responsiveClose = $('.responsive-close'),
1987      $options = $('#options'),
1988      $footer = $('#footer'),
1989      $content = $('#content'),
1990      touchM = 'ontouchstart' in window,
1991      iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent),
1992      navWidth = 0,
1993      logoWidth = 0;
1994    /* eslint-enable */
1995  });
1996})(jQuery);
1997
1998theme.init = function() {
1999  theme.cacheSelectors();
2000  theme.parallaxBg();
2001  theme.customSelectorArrow();
2002  theme.quantityButtons();
2003  theme.passwordFooter();
2004  theme.infiniteBlog();
2005  theme.homeGallery();
2006  theme.iframePopUp();
2007
2008  if (theme.cache.$body.hasClass('template-index')) {
2009    if (
2010      $('.main-content')
2011        .children('.index-sections')
2012        .children('.shopify-section').length %
2013        2 !==
2014      0
2015    ) {
2016      $('.social-footer').addClass('even');
2017    }
2018  }
2019};
2020$(theme.init);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.