PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 1.10.4
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v1.10.4
2.3.2 2.3.1 2.3.0 2.2.8 2.2.7 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.11.1 1.11.2 1.6 1.7 1.8 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 1.9.10 1.9.11 All 60 releases
merchant / assets / js / carousel.js

carousel.js in Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant 1.10.4, at assets/js/carousel.js

940 lines 36.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Siema v1.5.1
3 * Lightweight and simple carousel in pure JavaScript
4 * https://pawelgrzybek.github.io/siema/
5 *
6 * Copyright (c) 2017 Paweł Grzybek (https://pawelgrzybek.com/)
7 *
8 * Released under the MIT License
9 *
10 * Modified by aThemes
11 *
12 * @cc_on
13 */
14
15 'use strict';
16
17 function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
18 function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
19 function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
20 function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
21 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
22 function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
23 function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
24 function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
25 function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
26 var Siema = /*#__PURE__*/function () {
27 /**
28 * Create a Siema.
29 * @param {Object} options - Optional settings object.
30 */
31 function Siema(options) {
32 var _this2 = this;
33 _classCallCheck(this, Siema);
34 // Merge defaults with user's settings
35 this.config = Siema.mergeSettings(options);
36
37 // Resolve parent selector's type
38 this.parentSelector = typeof this.config.parentSelector === 'string' ? document.querySelector(this.config.parentSelector) : this.config.parentSelector;
39
40 // Resolve selector's type
41 this.selector = typeof this.config.selector === 'string' ? document.querySelector(this.config.selector) : this.config.selector;
42 if (this.parentSelector) {
43 this.selector = this.parentSelector.querySelector('.merchant-carousel-stage');
44 }
45
46 // Early throw if selector doesn't exists
47 if (this.selector === null) {
48 throw new Error('Something wrong with your selector 😭');
49 }
50 if (this.parentSelector.getAttribute('data-initialized') === 'true') {
51 return false;
52 }
53
54 // update perPage number dependable of user value
55 this.resolveSlidesNumber();
56
57 // Create global references
58 this.selectorWidth = this.selector.offsetWidth;
59 this.innerElements = [].slice.call(this.selector.children);
60 this.currentSlide = this.config.loop ? this.config.startIndex % this.innerElements.length : Math.max(0, Math.min(this.config.startIndex, this.innerElements.length - this.perPage));
61 this.transformProperty = Siema.webkitOrNot();
62
63 // Bind all event handlers for referencability
64 ['resizeHandler', 'touchstartHandler', 'touchendHandler', 'touchmoveHandler', 'mousedownHandler', 'mouseupHandler', 'mouseleaveHandler', 'mousemoveHandler', 'clickHandler', 'navNextHandler', 'navPrevHandler'].forEach(function (method) {
65 _this2[method] = _this2[method].bind(_this2);
66 });
67
68 // Build markup and apply required styling to elements
69 this.init();
70 }
71
72 /**
73 * Overrides default settings with custom ones.
74 * @param {Object} options - Optional settings object.
75 * @returns {Object} - Custom Siema settings.
76 */
77 _createClass(Siema, [{
78 key: "attachEvents",
79 value:
80 /**
81 * Attaches listeners to required events.
82 */
83 function attachEvents() {
84 // Resize element on window resize
85 window.addEventListener('resize', this.resizeHandler);
86
87 // If element is draggable / swipable, add event handlers
88 if (this.config.draggable) {
89 // Keep track pointer hold and dragging distance
90 this.pointerDown = false;
91 this.drag = {
92 startX: 0,
93 endX: 0,
94 startY: 0,
95 letItGo: null,
96 preventClick: false
97 };
98
99 // Touch events
100 this.selector.addEventListener('touchstart', this.touchstartHandler);
101 this.selector.addEventListener('touchend', this.touchendHandler);
102 this.selector.addEventListener('touchmove', this.touchmoveHandler);
103
104 // Mouse events
105 this.selector.addEventListener('mousedown', this.mousedownHandler);
106 this.selector.addEventListener('mouseup', this.mouseupHandler);
107 this.selector.addEventListener('mouseleave', this.mouseleaveHandler);
108 this.selector.addEventListener('mousemove', this.mousemoveHandler);
109
110 // Click
111 this.selector.addEventListener('click', this.clickHandler);
112
113 // Navigation
114 this.parentSelector.querySelector('.merchant-carousel-nav-next').addEventListener('click', this.navNextHandler);
115 this.parentSelector.querySelector('.merchant-carousel-nav-prev').addEventListener('click', this.navPrevHandler);
116 }
117 }
118 }, {
119 key: "detachEvents",
120 value:
121 /**
122 * Detaches listeners from required events.
123 */
124 function detachEvents() {
125 window.removeEventListener('resize', this.resizeHandler);
126 this.selector.removeEventListener('touchstart', this.touchstartHandler);
127 this.selector.removeEventListener('touchend', this.touchendHandler);
128 this.selector.removeEventListener('touchmove', this.touchmoveHandler);
129 this.selector.removeEventListener('mousedown', this.mousedownHandler);
130 this.selector.removeEventListener('mouseup', this.mouseupHandler);
131 this.selector.removeEventListener('mouseleave', this.mouseleaveHandler);
132 this.selector.removeEventListener('mousemove', this.mousemoveHandler);
133 this.selector.removeEventListener('click', this.clickHandler);
134 this.parentSelector.querySelector('.merchant-carousel-nav-next').removeEventListener('click', this.navNextHandler);
135 this.parentSelector.querySelector('.merchant-carousel-nav-prev').removeEventListener('click', this.navPrevHandler);
136 }
137
138 /**
139 * Builds the markup and attaches listeners to required events.
140 */
141 }, {
142 key: "init",
143 value: function init() {
144 // build navigation
145 this.buildNavigation();
146 this.attachEvents();
147
148 // hide everything out of selector's boundaries
149 this.selector.style.overflow = 'hidden';
150
151 // rtl or ltr
152 this.selector.style.direction = this.config.rtl ? 'rtl' : 'ltr';
153
154 // build a frame and slide to a currentSlide
155 this.buildSliderFrame();
156 this.config.onInit.call(this);
157 this.parentSelector.querySelector('.merchant-carousel-stage').classList.add('show');
158 if (this.parentSelector !== null) {
159 this.parentSelector.setAttribute('data-initialized', true);
160 }
161 }
162 }, {
163 key: "buildNavigation",
164 value: function buildNavigation() {
165 var next = document.createElement('a'),
166 nextSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg"),
167 prev = document.createElement('a'),
168 prevSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg");
169
170 // Next button
171 next.role = 'button';
172 next.href = '#';
173 next.className = 'merchant-carousel-nav merchant-carousel-nav-next';
174 nextSVG.setAttribute('width', 18);
175 nextSVG.setAttribute('height', 18);
176 nextSVG.setAttribute('viewBox', '0 0 10 16');
177 nextSVG.setAttribute('fill', 'none');
178 nextSVG.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
179 nextSVG.setAttribute('class', 'stroke-based');
180 nextSVG.innerHTML = '<path d="M1.5 14.667L8.16667 8.00033L1.5 1.33366" stroke="#242021" stroke-width="1.5"></path>';
181 next.append(nextSVG);
182 this.parentSelector.querySelector('.merchant-carousel-wrapper').append(next);
183
184 // Prev button
185 prev.role = 'button';
186 prev.href = '#';
187 prev.className = 'merchant-carousel-nav merchant-carousel-nav-prev';
188 prevSVG.setAttribute('width', 18);
189 prevSVG.setAttribute('height', 18);
190 prevSVG.setAttribute('viewBox', '0 0 10 16');
191 prevSVG.setAttribute('fill', 'none');
192 prevSVG.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
193 prevSVG.setAttribute('class', 'stroke-based');
194 prevSVG.innerHTML = '<path d="M8.5 1.33301L1.83333 7.99967L8.5 14.6663" stroke="#242021" stroke-width="1.5"></path>';
195 prev.append(prevSVG);
196 this.parentSelector.querySelector('.merchant-carousel-wrapper').append(prev);
197 }
198
199 /**
200 * Build a sliderFrame and slide to a current item.
201 */
202 }, {
203 key: "buildSliderFrame",
204 value: function buildSliderFrame() {
205 if (this.innerElements.length <= this.perPage) {
206 var _this$parentSelector$, _this$parentSelector$2;
207 this.parentSelector.classList.add('no-nav');
208 (_this$parentSelector$ = this.parentSelector.querySelector('.merchant-carousel-nav-next')) === null || _this$parentSelector$ === void 0 ? void 0 : _this$parentSelector$.remove();
209 (_this$parentSelector$2 = this.parentSelector.querySelector('.merchant-carousel-nav-prev')) === null || _this$parentSelector$2 === void 0 ? void 0 : _this$parentSelector$2.remove();
210 return false;
211 }
212 var widthItem = (this.selectorWidth + this.config.margin) / this.perPage;
213 var itemsToBuild = this.config.loop ? this.innerElements.length + 2 * this.perPage : this.innerElements.length;
214
215 // Create frame and apply styling
216 this.sliderFrame = document.createElement('div');
217 this.sliderFrame.style.width = widthItem * itemsToBuild + 'px';
218 this.enableTransition();
219 if (this.config.draggable) {
220 this.selector.style.cursor = '-webkit-grab';
221 }
222
223 // Create a document fragment to put slides into it
224 var docFragment = document.createDocumentFragment();
225
226 // Loop through the slides, add styling and add them to document fragment
227 if (this.config.loop) {
228 for (var i = this.innerElements.length - this.perPage; i < this.innerElements.length; i++) {
229 var element = this.buildSliderFrameItem(this.innerElements[i].cloneNode(true));
230 docFragment.appendChild(element);
231 }
232 }
233 for (var _i = 0; _i < this.innerElements.length; _i++) {
234 var element = this.buildSliderFrameItem(this.innerElements[_i]);
235 docFragment.appendChild(element);
236 }
237 if (this.config.loop) {
238 for (var _i2 = 0; _i2 < this.perPage; _i2++) {
239 var element = this.buildSliderFrameItem(this.innerElements[_i2].cloneNode(true));
240 docFragment.appendChild(element);
241 }
242 }
243
244 // Add fragment to the frame
245 this.sliderFrame.appendChild(docFragment);
246
247 // Clear selector (just in case something is there) and insert a frame
248 this.selector.innerHTML = '';
249 this.selector.appendChild(this.sliderFrame);
250
251 // Go to currently active slide after initial build
252 this.slideToCurrent();
253 }
254 }, {
255 key: "buildSliderFrameItem",
256 value: function buildSliderFrameItem(elm) {
257 var elementContainer = document.createElement('div');
258 elementContainer.style.cssFloat = this.config.rtl ? 'right' : 'left';
259 elementContainer.style.float = this.config.rtl ? 'right' : 'left';
260 elementContainer.style.width = (this.config.loop ? 100 / (this.innerElements.length + this.perPage * 2) : 100 / this.innerElements.length) + '%';
261 elementContainer.style.marginRight = this.config.margin + 'px';
262 elementContainer.appendChild(elm);
263 return elementContainer;
264 }
265
266 /**
267 * Determinates slides number accordingly to clients viewport.
268 */
269 }, {
270 key: "resolveSlidesNumber",
271 value: function resolveSlidesNumber() {
272 if (typeof this.config.perPage === 'number') {
273 this.perPage = this.config.perPage;
274 } else if (_typeof(this.config.perPage) === 'object') {
275 this.perPage = 1;
276 for (var viewport in this.config.perPage) {
277 if (window.innerWidth >= viewport) {
278 this.perPage = this.config.perPage[viewport];
279 }
280 }
281 }
282 }
283
284 /**
285 * Go to previous slide.
286 * @param {number} [howManySlides=1] - How many items to slide backward.
287 * @param {function} callback - Optional callback function.
288 */
289 }, {
290 key: "prev",
291 value: function prev() {
292 var howManySlides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
293 var callback = arguments.length > 1 ? arguments[1] : undefined;
294 // early return when there is nothing to slide
295 if (this.innerElements.length <= this.perPage) {
296 return;
297 }
298 var beforeChange = this.currentSlide;
299 if (this.config.loop) {
300 var isNewIndexClone = this.currentSlide - howManySlides < 0;
301 if (isNewIndexClone) {
302 this.disableTransition();
303 var mirrorSlideIndex = this.currentSlide + this.innerElements.length;
304 var mirrorSlideIndexOffset = this.perPage;
305 var moveTo = mirrorSlideIndex + mirrorSlideIndexOffset;
306 var offset = (this.config.rtl ? 1 : -1) * moveTo * (this.selectorWidth / this.perPage);
307 var dragDistance = this.config.draggable ? this.drag.endX - this.drag.startX : 0;
308 this.sliderFrame.style[this.transformProperty] = "translate3d(".concat(offset + dragDistance, "px, 0, 0)");
309 this.currentSlide = mirrorSlideIndex - howManySlides;
310 } else {
311 this.currentSlide = this.currentSlide - howManySlides;
312 }
313 } else {
314 this.currentSlide = Math.max(this.currentSlide - howManySlides, 0);
315 }
316 if (beforeChange !== this.currentSlide) {
317 this.slideToCurrent(this.config.loop);
318 this.config.onChange.call(this);
319 if (callback) {
320 callback.call(this);
321 }
322 }
323 }
324
325 /**
326 * Go to next slide.
327 * @param {number} [howManySlides=1] - How many items to slide forward.
328 * @param {function} callback - Optional callback function.
329 */
330 }, {
331 key: "next",
332 value: function next() {
333 var howManySlides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
334 var callback = arguments.length > 1 ? arguments[1] : undefined;
335 // early return when there is nothing to slide
336 if (this.innerElements.length <= this.perPage) {
337 return;
338 }
339 var beforeChange = this.currentSlide;
340 if (this.config.loop) {
341 var isNewIndexClone = this.currentSlide + howManySlides > this.innerElements.length - this.perPage;
342 if (isNewIndexClone) {
343 this.disableTransition();
344 var mirrorSlideIndex = this.currentSlide - this.innerElements.length;
345 var mirrorSlideIndexOffset = this.perPage;
346 var moveTo = mirrorSlideIndex + mirrorSlideIndexOffset;
347 var offset = (this.config.rtl ? 1 : -1) * moveTo * (this.selectorWidth / this.perPage);
348 var dragDistance = this.config.draggable ? this.drag.endX - this.drag.startX : 0;
349 this.sliderFrame.style[this.transformProperty] = "translate3d(".concat(offset + dragDistance, "px, 0, 0)");
350 this.currentSlide = mirrorSlideIndex + howManySlides;
351 } else {
352 this.currentSlide = this.currentSlide + howManySlides;
353 }
354 } else {
355 this.currentSlide = Math.min(this.currentSlide + howManySlides, this.innerElements.length - this.perPage);
356 }
357 if (beforeChange !== this.currentSlide) {
358 this.slideToCurrent(this.config.loop);
359 this.config.onChange.call(this);
360 if (callback) {
361 callback.call(this);
362 }
363 }
364 }
365
366 /**
367 * Disable transition on sliderFrame.
368 */
369 }, {
370 key: "disableTransition",
371 value: function disableTransition() {
372 this.sliderFrame.style.webkitTransition = "all 0ms ".concat(this.config.easing);
373 this.sliderFrame.style.transition = "all 0ms ".concat(this.config.easing);
374 }
375
376 /**
377 * Enable transition on sliderFrame.
378 */
379 }, {
380 key: "enableTransition",
381 value: function enableTransition() {
382 if (typeof this.sliderFrame === 'undefined') {
383 return false;
384 }
385 this.sliderFrame.style.webkitTransition = "all ".concat(this.config.duration, "ms ").concat(this.config.easing);
386 this.sliderFrame.style.transition = "all ".concat(this.config.duration, "ms ").concat(this.config.easing);
387 }
388
389 /**
390 * Go to slide with particular index
391 * @param {number} index - Item index to slide to.
392 * @param {function} callback - Optional callback function.
393 */
394 }, {
395 key: "goTo",
396 value: function goTo(index, callback) {
397 if (this.innerElements.length <= this.perPage) {
398 return;
399 }
400 var beforeChange = this.currentSlide;
401 this.currentSlide = this.config.loop ? index % this.innerElements.length : Math.min(Math.max(index, 0), this.innerElements.length - this.perPage);
402 if (beforeChange !== this.currentSlide) {
403 this.slideToCurrent();
404 this.config.onChange.call(this);
405 if (callback) {
406 callback.call(this);
407 }
408 }
409 }
410
411 /**
412 * Moves sliders frame to position of currently active slide
413 */
414 }, {
415 key: "slideToCurrent",
416 value: function slideToCurrent(enableTransition) {
417 var _this = this;
418 var currentSlide = this.config.loop ? this.currentSlide + this.perPage : this.currentSlide;
419 var offset = (this.config.rtl ? 1 : -1) * currentSlide * ((this.selectorWidth + this.config.margin) / this.perPage);
420 if (typeof this.sliderFrame === 'undefined') {
421 return false;
422 }
423 if (enableTransition) {
424 requestAnimationFrame(function () {
425 requestAnimationFrame(function () {
426 _this.enableTransition();
427 _this.sliderFrame.style[_this.transformProperty] = 'translate3d(' + offset + 'px, 0, 0)';
428 });
429 });
430 } else {
431 this.enableTransition();
432 this.sliderFrame.style[this.transformProperty] = 'translate3d(' + offset + 'px, 0, 0)';
433 }
434 }
435
436 /**
437 * Recalculate drag /swipe event and reposition the frame of a slider
438 */
439 }, {
440 key: "updateAfterDrag",
441 value: function updateAfterDrag() {
442 var movement = (this.config.rtl ? -1 : 1) * (this.drag.endX - this.drag.startX);
443 var movementDistance = Math.abs(movement);
444 var howManySliderToSlide = this.config.multipleDrag ? Math.ceil(movementDistance / (this.selectorWidth / this.perPage)) : 1;
445 var slideToNegativeClone = movement > 0 && this.currentSlide - howManySliderToSlide < 0;
446 var slideToPositiveClone = movement < 0 && this.currentSlide + howManySliderToSlide > this.innerElements.length - this.perPage;
447 if (movement > 0 && movementDistance > this.config.threshold && this.innerElements.length > this.perPage) {
448 this.prev(howManySliderToSlide);
449 } else if (movement < 0 && movementDistance > this.config.threshold && this.innerElements.length > this.perPage) {
450 this.next(howManySliderToSlide);
451 }
452 this.slideToCurrent(slideToNegativeClone || slideToPositiveClone);
453 }
454
455 /**
456 * When window resizes, resize slider components as well
457 */
458 }, {
459 key: "resizeHandler",
460 value: function resizeHandler() {
461 // update perPage number dependable of user value
462 this.resolveSlidesNumber();
463
464 // relcalculate currentSlide
465 // prevent hiding items when browser width increases
466 if (this.currentSlide + this.perPage > this.innerElements.length) {
467 this.currentSlide = this.innerElements.length <= this.perPage ? 0 : this.innerElements.length - this.perPage;
468 }
469 this.selectorWidth = this.selector.offsetWidth;
470 this.buildSliderFrame();
471 }
472
473 /**
474 * Clear drag after touchend and mouseup event
475 */
476 }, {
477 key: "clearDrag",
478 value: function clearDrag() {
479 this.drag = {
480 startX: 0,
481 endX: 0,
482 startY: 0,
483 letItGo: null,
484 preventClick: this.drag.preventClick
485 };
486 }
487
488 /**
489 * touchstart event handler
490 */
491 }, {
492 key: "touchstartHandler",
493 value: function touchstartHandler(e) {
494 // Prevent dragging / swiping on inputs, selects and textareas
495 var ignoreSiema = ['TEXTAREA', 'OPTION', 'INPUT', 'SELECT'].indexOf(e.target.nodeName) !== -1;
496 if (ignoreSiema) {
497 return;
498 }
499 e.stopPropagation();
500 this.pointerDown = true;
501 this.drag.startX = e.touches[0].pageX;
502 this.drag.startY = e.touches[0].pageY;
503 }
504
505 /**
506 * touchend event handler
507 */
508 }, {
509 key: "touchendHandler",
510 value: function touchendHandler(e) {
511 e.stopPropagation();
512 this.pointerDown = false;
513 this.enableTransition();
514 if (this.drag.endX) {
515 this.updateAfterDrag();
516 }
517 this.clearDrag();
518 }
519
520 /**
521 * touchmove event handler
522 */
523 }, {
524 key: "touchmoveHandler",
525 value: function touchmoveHandler(e) {
526 e.stopPropagation();
527 if (this.drag.letItGo === null) {
528 this.drag.letItGo = Math.abs(this.drag.startY - e.touches[0].pageY) < Math.abs(this.drag.startX - e.touches[0].pageX);
529 }
530 if (this.pointerDown && this.drag.letItGo) {
531 e.preventDefault();
532 this.drag.endX = e.touches[0].pageX;
533 this.sliderFrame.style.webkitTransition = "all 0ms ".concat(this.config.easing);
534 this.sliderFrame.style.transition = "all 0ms ".concat(this.config.easing);
535 var currentSlide = this.config.loop ? this.currentSlide + this.perPage : this.currentSlide;
536 var currentOffset = currentSlide * ((this.selectorWidth + this.config.margin) / this.perPage);
537 var dragOffset = this.drag.endX - this.drag.startX;
538 var offset = this.config.rtl ? currentOffset + dragOffset : currentOffset - dragOffset;
539 this.sliderFrame.style[this.transformProperty] = "translate3d(".concat((this.config.rtl ? 1 : -1) * offset, "px, 0, 0)");
540 }
541 }
542
543 /**
544 * mousedown event handler
545 */
546 }, {
547 key: "mousedownHandler",
548 value: function mousedownHandler(e) {
549 // Prevent dragging / swiping on inputs, selects and textareas
550 var ignoreSiema = ['TEXTAREA', 'OPTION', 'INPUT', 'SELECT'].indexOf(e.target.nodeName) !== -1;
551 if (ignoreSiema) {
552 return;
553 }
554 e.preventDefault();
555 e.stopPropagation();
556 this.pointerDown = true;
557 this.drag.startX = e.pageX;
558 }
559
560 /**
561 * mouseup event handler
562 */
563 }, {
564 key: "mouseupHandler",
565 value: function mouseupHandler(e) {
566 e.stopPropagation();
567 this.pointerDown = false;
568 this.selector.style.cursor = '-webkit-grab';
569 this.enableTransition();
570 if (this.drag.endX) {
571 this.updateAfterDrag();
572 }
573 this.clearDrag();
574 }
575
576 /**
577 * mousemove event handler
578 */
579 }, {
580 key: "mousemoveHandler",
581 value: function mousemoveHandler(e) {
582 e.preventDefault();
583 if (this.pointerDown) {
584 // if dragged element is a link
585 // mark preventClick prop as a true
586 // to detemine about browser redirection later on
587 if (typeof e.target.closest('a') !== 'null') {
588 this.drag.preventClick = true;
589 }
590 if (typeof this.sliderFrame === 'undefined') {
591 return false;
592 }
593 this.drag.endX = e.pageX;
594 this.selector.style.cursor = '-webkit-grabbing';
595 this.sliderFrame.style.webkitTransition = "all 0ms ".concat(this.config.easing);
596 this.sliderFrame.style.transition = "all 0ms ".concat(this.config.easing);
597 var currentSlide = this.config.loop ? this.currentSlide + this.perPage : this.currentSlide;
598 var currentOffset = currentSlide * ((this.selectorWidth + this.config.margin) / this.perPage);
599 var dragOffset = this.drag.endX - this.drag.startX;
600 var offset = this.config.rtl ? currentOffset + dragOffset : currentOffset - dragOffset;
601 this.sliderFrame.style[this.transformProperty] = "translate3d(".concat((this.config.rtl ? 1 : -1) * offset, "px, 0, 0)");
602 }
603 }
604
605 /**
606 * mouseleave event handler
607 */
608 }, {
609 key: "mouseleaveHandler",
610 value: function mouseleaveHandler(e) {
611 if (this.pointerDown) {
612 this.pointerDown = false;
613 this.selector.style.cursor = '-webkit-grab';
614 this.drag.endX = e.pageX;
615 this.drag.preventClick = false;
616 this.enableTransition();
617 this.updateAfterDrag();
618 this.clearDrag();
619 }
620 }
621
622 /**
623 * click event handler
624 */
625 }, {
626 key: "clickHandler",
627 value: function clickHandler(e) {
628 // if the dragged element is a link
629 // prevent browsers from folowing the link
630 if (this.drag.preventClick) {
631 e.preventDefault();
632 }
633 this.drag.preventClick = false;
634 }
635 }, {
636 key: "navNextHandler",
637 value: function navNextHandler(e) {
638 e.preventDefault();
639 this.next(1);
640 }
641 }, {
642 key: "navPrevHandler",
643 value: function navPrevHandler(e) {
644 e.preventDefault();
645 this.prev(1);
646 }
647
648 /**
649 * Remove item from carousel.
650 * @param {number} index - Item index to remove.
651 * @param {function} callback - Optional callback to call after remove.
652 */
653 }, {
654 key: "remove",
655 value: function remove(index, callback) {
656 if (index < 0 || index >= this.innerElements.length) {
657 throw new Error('Item to remove doesn\'t exist 😭');
658 }
659
660 // Shift sliderFrame back by one item when:
661 // 1. Item with lower index than currenSlide is removed.
662 // 2. Last item is removed.
663 var lowerIndex = index < this.currentSlide;
664 var lastItem = this.currentSlide + this.perPage - 1 === index;
665 if (lowerIndex || lastItem) {
666 this.currentSlide--;
667 }
668 this.innerElements.splice(index, 1);
669
670 // build a frame and slide to a currentSlide
671 this.buildSliderFrame();
672 if (callback) {
673 callback.call(this);
674 }
675 }
676
677 /**
678 * Insert item to carousel at particular index.
679 * @param {HTMLElement} item - Item to insert.
680 * @param {number} index - Index of new new item insertion.
681 * @param {function} callback - Optional callback to call after insert.
682 */
683 }, {
684 key: "insert",
685 value: function insert(item, index, callback) {
686 if (index < 0 || index > this.innerElements.length + 1) {
687 throw new Error('Unable to inset it at this index 😭');
688 }
689 if (this.innerElements.indexOf(item) !== -1) {
690 throw new Error('The same item in a carousel? Really? Nope 😭');
691 }
692
693 // Avoid shifting content
694 var shouldItShift = index <= this.currentSlide > 0 && this.innerElements.length;
695 this.currentSlide = shouldItShift ? this.currentSlide + 1 : this.currentSlide;
696 this.innerElements.splice(index, 0, item);
697
698 // build a frame and slide to a currentSlide
699 this.buildSliderFrame();
700 if (callback) {
701 callback.call(this);
702 }
703 }
704
705 /**
706 * Prepernd item to carousel.
707 * @param {HTMLElement} item - Item to prepend.
708 * @param {function} callback - Optional callback to call after prepend.
709 */
710 }, {
711 key: "prepend",
712 value: function prepend(item, callback) {
713 this.insert(item, 0);
714 if (callback) {
715 callback.call(this);
716 }
717 }
718
719 /**
720 * Append item to carousel.
721 * @param {HTMLElement} item - Item to append.
722 * @param {function} callback - Optional callback to call after append.
723 */
724 }, {
725 key: "append",
726 value: function append(item, callback) {
727 this.insert(item, this.innerElements.length + 1);
728 if (callback) {
729 callback.call(this);
730 }
731 }
732
733 /**
734 * Removes listeners and optionally restores to initial markup
735 * @param {boolean} restoreMarkup - Determinants about restoring an initial markup.
736 * @param {function} callback - Optional callback function.
737 */
738 }, {
739 key: "destroy",
740 value: function destroy() {
741 var restoreMarkup = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
742 var callback = arguments.length > 1 ? arguments[1] : undefined;
743 this.detachEvents();
744 this.selector.style.cursor = 'auto';
745 if (restoreMarkup) {
746 var slides = document.createDocumentFragment();
747 for (var i = 0; i < this.innerElements.length; i++) {
748 slides.appendChild(this.innerElements[i]);
749 }
750 this.selector.innerHTML = '';
751 this.selector.appendChild(slides);
752 this.selector.removeAttribute('style');
753 }
754 if (callback) {
755 callback.call(this);
756 }
757 }
758 }], [{
759 key: "mergeSettings",
760 value: function mergeSettings(options) {
761 var settings = {
762 selector: '.siema',
763 duration: 200,
764 easing: 'ease-out',
765 perPage: 1,
766 startIndex: 0,
767 draggable: true,
768 multipleDrag: true,
769 threshold: 20,
770 loop: false,
771 rtl: false,
772 onInit: function onInit() {},
773 onChange: function onChange() {}
774 };
775 var userSttings = options;
776 for (var attrname in userSttings) {
777 settings[attrname] = userSttings[attrname];
778 }
779 return settings;
780 }
781
782 /**
783 * Determine if browser supports unprefixed transform property.
784 * Google Chrome since version 26 supports prefix-less transform
785 * @returns {string} - Transform property supported by client.
786 */
787 }, {
788 key: "webkitOrNot",
789 value: function webkitOrNot() {
790 var style = document.documentElement.style;
791 if (typeof style.transform === 'string') {
792 return 'transform';
793 }
794 return 'WebkitTransform';
795 }
796 }]);
797 return Siema;
798 }();
799 /**
800 * Merchant Carousel
801 *
802 */
803 var merchant = merchant || {};
804 merchant.carousel = {
805 domReady: function domReady(fn) {
806 if (typeof fn !== 'function') {
807 return;
808 }
809 if (document.readyState === 'interactive' || document.readyState === 'complete') {
810 return fn();
811 }
812 var that = this;
813 document.addEventListener('DOMContentLoaded', function () {
814 that.init(); // Required for some themes
815 });
816
817 jQuery(document).on('photoSliderTriggered', function () {
818 that.init();
819 });
820 },
821 init: function init() {
822 this.build();
823 this.events();
824 },
825 build: function build() {
826 if (document.querySelector('.merchant-carousel') === null && document.querySelector('.has-cross-sells-carousel') === null && document.querySelector('.merchant-woocommerce-mini-cart__cross-sell') === null) {
827 return false;
828 }
829 var carouselEls = document.querySelectorAll('.merchant-carousel, #masthead .cross-sells, .merchant-side-mini-cart .cross-sells, .cart-collaterals .cross-sells');
830 var _iterator = _createForOfIteratorHelper(carouselEls),
831 _step;
832 try {
833 for (_iterator.s(); !(_step = _iterator.n()).done;) {
834 var carouselEl = _step.value;
835 if (carouselEl.querySelector('.merchant-carousel-stage') === null) {
836 carouselEl.querySelector('.products').classList.add('merchant-carousel-stage');
837 }
838 if (carouselEl.getAttribute('data-initialized') !== 'true') {
839 var perPage = carouselEl.getAttribute('data-per-page');
840 if (perPage === null) {
841 var stageClassList = carouselEl.querySelector('.products').classList.value;
842 [1, 2, 3, 4, 5].forEach(function (columns) {
843 if (stageClassList.indexOf('columns-' + columns) > 0) {
844 perPage = columns;
845 }
846 });
847 }
848 var loop = carouselEl.getAttribute('data-loop') !== '0';
849
850 // Mount carousel wrapper
851 var wrapper = document.createElement('div'),
852 stage = carouselEl.querySelector('.merchant-carousel-stage');
853 wrapper.className = 'merchant-carousel-wrapper';
854 wrapper.innerHTML = stage.outerHTML;
855 stage.remove();
856 carouselEl.append(wrapper);
857
858 // Margin
859 var margin = 30;
860 if (typeof merchant_carousel !== 'undefined') {
861 margin = parseInt(merchant_carousel.margin_desktop);
862 } else if (carouselEl.closest('.merchant-woocommerce-mini-cart__cross-sell') !== null) {
863 margin = 15;
864 }
865
866 // Initialize
867 var carousel = new Siema({
868 parentSelector: carouselEl,
869 selector: '.merchant-carousel-stage',
870 duration: 200,
871 easing: 'ease-out',
872 perPage: perPage !== null ? {
873 0: 1,
874 768: 2,
875 1025: parseInt(perPage)
876 } : 2,
877 startIndex: 0,
878 draggable: true,
879 multipleDrag: false,
880 threshold: 20,
881 loop: loop,
882 rtl: false,
883 // autoplay: true, TO DO
884 margin: margin,
885 onInit: function onInit() {
886 var _this$innerElements;
887 window.dispatchEvent(new Event('merchant.carousel.initialized'));
888
889 // Fix for theme that has lazy-load but not working
890 this === null || this === void 0 ? void 0 : (_this$innerElements = this.innerElements) === null || _this$innerElements === void 0 ? void 0 : _this$innerElements.forEach(function (item) {
891 var img = item.querySelector('img');
892 var src = img === null || img === void 0 ? void 0 : img.getAttribute('src');
893 if (src !== null && src !== void 0 && src.startsWith('data')) {
894 img.src = img === null || img === void 0 ? void 0 : img.getAttribute('data-src');
895 }
896 });
897 }
898 });
899 }
900 }
901 } catch (err) {
902 _iterator.e(err);
903 } finally {
904 _iterator.f();
905 }
906 },
907 events: function events() {
908 var _this = this;
909 if (typeof jQuery !== 'undefined') {
910 var onpageload = true;
911 jQuery(document.body).on('wc_fragment_refresh added_to_cart removed_from_cart', function () {
912 setTimeout(function () {
913 var mini_cart = document.getElementById('site-header-cart'),
914 mini_cart_list = mini_cart === null || mini_cart === void 0 ? void 0 : mini_cart.querySelector('.cart_list');
915 if (mini_cart_list !== null) {
916 if ((mini_cart_list === null || mini_cart_list === void 0 ? void 0 : mini_cart_list.children.length) > 2) {
917 mini_cart === null || mini_cart === void 0 ? void 0 : mini_cart.classList.remove('mini-cart-has-no-scroll');
918 mini_cart === null || mini_cart === void 0 ? void 0 : mini_cart.classList.add('mini-cart-has-scroll');
919 } else {
920 mini_cart === null || mini_cart === void 0 ? void 0 : mini_cart.classList.remove('mini-cart-has-scroll');
921 mini_cart === null || mini_cart === void 0 ? void 0 : mini_cart.classList.add('mini-cart-has-no-scroll');
922 }
923 }
924 _this.build();
925 onpageload = false;
926 }, onpageload ? 1000 : 0);
927 });
928 }
929 }
930 };
931
932 // Initialize.
933 merchant.carousel.domReady(function () {
934 var _merchant$carousel;
935 merchant === null || merchant === void 0 ? void 0 : (_merchant$carousel = merchant.carousel) === null || _merchant$carousel === void 0 ? void 0 : _merchant$carousel.init();
936 });
937 jQuery(document).on('photoSliderTriggered', function () {
938 var _merchant$carousel2;
939 merchant === null || merchant === void 0 ? void 0 : (_merchant$carousel2 = merchant.carousel) === null || _merchant$carousel2 === void 0 ? void 0 : _merchant$carousel2.init();
940 });