PageSourceSearch

https://www.toutcommenceenfinistere.com/wp-content/themes/finist%C3%A8re/plugins/zoomist/zoomist.js?ver=7.1.2

js toutcommenceenfinistere.com collected 2026-10-02 03:59:53 UTC 34,667 bytes, 1,116 lines download raw bytes

1/*!
2 * zoomist.js v1.0.2
3 * https://github.com/cotton123236/zoomist#readme
4 *
5 * Copyright 2021-present Wilson Wu
6 * Released under the MIT license
7 *
8 * Date: 2022-03-26T09:56:17.746Z
9 */
10
11(function (global, factory) {
12  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
13  typeof define === 'function' && define.amd ? define(factory) :
14  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Zoomist = factory());
15})(this, (function () { 'use strict';
16
17  const NAME = 'zoomist';
18  const MODULES$1 = ['slider', 'zoomer'];
19  const CLASS_CONTAINER = `${NAME}-container`;
20  const CLASS_WRAPPER = `${NAME}-wrapper`;
21  const CLASS_IMAGE = `${NAME}-image`;
22  const CLASS_SLIDER = `${NAME}-slider`;
23  const CLASS_SLIDER_MAIN = `${NAME}-slider-main`;
24  const CLASS_SLIDER_BAR = `${NAME}-slider-bar`;
25  const CLASS_SLIDER_BUTTON = `${NAME}-slider-button`;
26  const CLASS_ZOOMER = `${NAME}-zoomer`;
27  const CLASS_ZOOMER_IN = `${NAME}-in-zoomer`;
28  const CLASS_ZOOMER_OUT = `${NAME}-out-zoomer`;
29  const CLASS_ZOOMER_DISABLE = `${NAME}-zoomer-disable`;
30  const IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined';
31  const IS_TOUCH = IS_BROWSER && 'ontouchstart' in window ? true : false;
32  const EVENT_TOUCH_START = IS_TOUCH ? 'touchstart' : 'mousedown';
33  const EVENT_TOUCH_MOVE = IS_TOUCH ? 'touchmove' : 'mousemove';
34  const EVENT_TOUCH_END = IS_TOUCH ? 'touchend' : 'mouseup';
35  const EVENT_RESIZE = 'resize';
36  const EVENT_WHEEL = 'wheel';
37
38  var DEFAULT_OPTIONS = {
39    // {String} set initial image status
40    fill: 'cover',
41    // {String / querySelector} the attribute of image source or a image element
42    src: 'data-zoomist-src',
43    // {Boolean} set is draggable or not
44    draggable: true,
45    // {Boolean} set is wheelable or not
46    wheelable: true,
47    // {Boolean} set is pinchable or not
48    pinchable: true,
49    // {Boolean} set image can be drag out of the bounds (it will set to false when fill is contain)
50    bounds: true,
51    // {Number} the ratio of zoom at one time
52    zoomRatio: 0.1,
53    // {Number > 1, False} the max ratio of the image (compare to the initial image status)
54    maxRatio: false,
55    // {Boolean / String}
56    height: 'auto'
57  };
58  const DEFAULT_SLIDER_OPTIONS = {
59    // {String / querySelector} the css selector string or a element of the slider
60    el: CLASS_SLIDER,
61    // {String} the direction of the slider 'horizontal' or 'vertical'
62    direction: 'horizontal',
63    // {Number} the max ratio of the slider (only work on options.maxRatio = false)
64    maxRatio: 2
65  };
66  const DEFAULT_ZOOMER_OPTIONS = {
67    // {String / querySelector} the css selector string or a element of the in zoomer
68    inEl: CLASS_ZOOMER_IN,
69    // {String / querySelector} the css selector string or a element of the out zoomer
70    outEl: CLASS_ZOOMER_OUT,
71    // {Boolean} in zoomer and out zoomer will be disabled when image comes to maximin or minimum
72    disableOnBounds: true
73  };
74  const EVENTS = {
75    // invoked when zoomist instance ready
76    ready: null,
77    // invoked when image is zooming
78    zoom: null,
79    // invoked when wheeling
80    wheel: null,
81    // invoked when mousedown on wrapper
82    dragStart: null,
83    // invoked when dragging the image
84    drag: null,
85    // invoked when mouseup on wrapper
86    dragEnd: null,
87    // invoked when mousedown on wrapper
88    pinchStart: null,
89    // invoked when pinching the image
90    pinch: null,
91    // invoked when mouseup on wrapper
92    pinchEnd: null,
93    // invoked when mousedown on slider
94    slideStart: null,
95    // invoked when sliding the slider
96    slide: null,
97    // invoked when mouseup on slider
98    slideEnd: null,
99    // invoked when image changes it's size
100    resize: null,
101    // invoked when reset methods be used
102    reset: null,
103    // invoked when destroy methods be used
104    destroy: null,
105    // invoked when update methods be used
106    update: null
107  };
108
109  const isObject = value => {
110    return typeof value === 'object' && value !== null;
111  }; // check value is a plain object
112
113  const isPlainObject = value => {
114    if (!isObject(value)) return false;
115
116    try {
117      const {
118        constructor
119      } = value;
120      const {
121        prototype
122      } = constructor;
123      const {
124        hasOwnProperty
125      } = Object.prototype;
126      return constructor && prototype && hasOwnProperty.call(prototype, 'isPrototypeOf');
127    } catch (error) {
128      return false;
129    }
130  }; // set object key and value
131
132  const setObject = (obj, value) => {
133    if (!obj) obj = {};
134
135    for (const [k, v] of Object.entries(value)) {
136      obj[k] = v;
137    }
138  }; // make a new object from old object
139
140  const getNewObject = value => {
141    return Object.assign({}, value);
142  }; // check value is string and not empty
143
144  const isString = value => {
145    return typeof value === 'string' && value !== '';
146  }; // check value is number and not NaN
147
148  const isNumber = value => {
149    return typeof value === 'number' && !isNaN(value);
150  }; // check element is exist
151
152  const isElementExist = value => {
153    return getElement(value) !== null;
154  }; // if value is an element then return value, if not then query value
155
156  const getElement = value => {
157    return value instanceof HTMLElement ? value : document.querySelector(value);
158  }; // check value is img tag or not
159
160  const isImg = value => {
161    return isElementExist(value) && getElement(value).tagName === 'IMG';
162  }; // check value is a function
163
164  const isFunction = value => {
165    return typeof value === 'function';
166  }; // check value is percentage
167
168  const isPercentage = value => {
169    return value.indexOf('%') > -1;
170  }; // get elemant style
171
172  const setStyle = (element, obj) => {
173    for (const [k, v] of Object.entries(obj)) {
174      element.style[k] = isNumber(v) ? `${v}px` : v;
175    }
176  }; // get mouse pageX and pageY
177
178  const getPointer = event => {
179    const isNotTouch = !IS_TOUCH || event.type === 'wheel';
180    return {
181      x: isNotTouch ? event.pageX : event.touches[0].pageX,
182      y: isNotTouch ? event.pageY : event.touches[0].pageY,
183      clientX: isNotTouch ? event.clientX : event.touches[0].clientX,
184      clientY: isNotTouch ? event.clientY : event.touches[0].clientY
185    };
186  }; // get transformX
187
188  const getTransformX = target => {
189    const transform = getComputedStyle(target).transform;
190    let mat = transform.match(/^matrix3d\((.+)\)$/);
191    if (mat) return parseFloat(mat[1].split(', ')[12]);
192    mat = transform.match(/^matrix\((.+)\)$/);
193    return mat ? parseFloat(mat[1].split(', ')[4]) : 0;
194  }; // get transformY
195
196  const getTransformY = target => {
197    const transform = getComputedStyle(target).transform;
198    let mat = transform.match(/^matrix3d\((.+)\)$/);
199    if (mat) return parseFloat(mat[1].split(', ')[13]);
200    mat = transform.match(/^matrix\((.+)\)$/);
201    return mat ? parseFloat(mat[1].split(', ')[5]) : 0;
202  }; // like .toFixed(2)
203
204  const roundToTwo = value => {
205    return +(Math.round(value + "e+2") + "e-2");
206  }; // limit value
207
208  const minmax = (value, min, max) => {
209    return Math.min(Math.max(value, min), max);
210  }; // first letter to uppercase
211
212  const upperFirstLetter = value => {
213    return value.charAt(0).toUpperCase() + value.slice(1);
214  };
215
216  var METHODS = {
217    /**
218     * get container (element) data
219     * @returns {Object}
220     */
221    getContainerData() {
222      return getNewObject(this.data.containerData);
223    },
224
225    /**
226     * get image data
227     * @returns {Object}
228     */
229    getImageData() {
230      return getNewObject(this.data.imageData);
231    },
232
233    /**
234     * get slider value
235     * @returns {Number}
236     */
237    getSliderValue() {
238      return this.__modules__.slider?.value;
239    },
240
241    /**
242     * get now zoom ratio
243     * @returns {Number}
244     */
245    getZoomRatio() {
246      return this.ratio;
247    },
248
249    /**
250     * zoom
251     * zoomRatio - zoomin when pass a positive number, zoomout when pass a negative number
252     * pointer - a object which return from getPoiner()
253     * @param {Number, Object} 
254     */
255    zoom(zoomRatio, pointer) {
256      const {
257        image,
258        data,
259        options,
260        ratio
261      } = this;
262      const {
263        bounds,
264        maxRatio
265      } = options;
266      if (bounds && ratio === 1 && zoomRatio < 0) return;
267      if (maxRatio && ratio === maxRatio && zoomRatio > 0) return;
268      const {
269        originImageData
270      } = data;
271      const containerData = this.getContainerData();
272      const imageData = this.getImageData();
273      const imageRect = image.getBoundingClientRect();
274      const calcRatio = roundToTwo(ratio * (zoomRatio + 1));
275      const newRatio = bounds && calcRatio < 1 ? 1 : maxRatio && calcRatio > maxRatio ? maxRatio : calcRatio;
276      const newZoomRatio = newRatio / ratio - 1;
277      const newWidth = originImageData.width * newRatio;
278      const newHeight = originImageData.height * newRatio;
279      const newLeft = (containerData.width - newWidth) / 2;
280      const newTop = (containerData.height - newHeight) / 2;
281      const distanceX = pointer ? (imageData.width / 2 - pointer.clientX + imageRect.left) * newZoomRatio + getTransformX(image) : getTransformX(image);
282      const distanceY = pointer ? (imageData.height / 2 - pointer.clientY + imageRect.top) * newZoomRatio + getTransformY(image) : getTransformY(image);
283      const transformX = bounds ? minmax(distanceX, newLeft, -newLeft) : distanceX;
284      const transformY = bounds ? minmax(distanceY, newTop, -newTop) : distanceY;
285      const newData = {
286        width: newWidth,
287        height: newHeight,
288        left: newLeft,
289        top: newTop
290      };
291      setObject(data.imageData, newData);
292      setStyle(image, { ...newData,
293        transform: `translate(${transformX}px, ${transformY}px)`
294      });
295      this.ratio = newRatio;
296      this.emit('zoom', newRatio); // if has slider
297
298      if (options.slider) {
299        const {
300          slider
301        } = this.__modules__;
302        const ratioPercentage = roundToTwo(1 - (slider.maxRatio - newRatio) / (slider.maxRatio - 1)) * 100;
303        slider.value = minmax(ratioPercentage, 0, 100);
304        this.slideTo(ratioPercentage, true);
305      } // if zoomer disableOnBounds
306
307
308      if (options.zoomer) {
309        const {
310          zoomer
311        } = this.__modules__;
312
313        if (zoomer.disableOnBounds) {
314          const {
315            bounds
316          } = options;
317          const {
318            zoomerInEl,
319            zoomerOutEl
320          } = this.__modules__.zoomer;
321          bounds && this.ratio === 1 ? zoomerOutEl.classList.add(CLASS_ZOOMER_DISABLE) : zoomerOutEl.classList.remove(CLASS_ZOOMER_DISABLE);
322          this.ratio === maxRatio ? zoomerInEl.classList.add(CLASS_ZOOMER_DISABLE) : zoomerInEl.classList.remove(CLASS_ZOOMER_DISABLE);
323        }
324      }
325
326      return this;
327    },
328
329    /**
330     * zoomTo (zoom to a specific ratio)
331     * zoomRatio - zoomin when pass a number more than 1, zoomout when pass a number less than 1
332     * @param {Number} 
333     */
334    zoomTo(zoomRatio) {
335      const {
336        ratio
337      } = this;
338
339      if (zoomRatio !== ratio) {
340        const calcRatio = zoomRatio / ratio - 1;
341        this.zoom(calcRatio);
342      }
343
344      return this;
345    },
346
347    move(x = 0, y = 0) {
348      const {
349        image,
350        data,
351        options
352      } = this;
353      const {
354        imageData,
355        dragData
356      } = data;
357      const {
358        top,
359        left
360      } = imageData;
361      const {
362        transX,
363        transY
364      } = dragData;
365      const {
366        bounds
367      } = options;
368      const calcTransX = bounds ? minmax(transX - x, left, -left) : transX - x;
369      const calcTransY = bounds ? minmax(transY - y, top, -top) : transY - y;
370      const newTransX = roundToTwo(calcTransX);
371      const newTransY = roundToTwo(calcTransY);
372      setObject(dragData, {
373        transX: newTransX,
374        transY: newTransY
375      });
376      image.style.transform = `translate(${newTransX}px, ${newTransY}px)`;
377      return this;
378    },
379
380    moveTo(x, y) {
381      const {
382        data,
383        options
384      } = this;
385      const {
386        imageData,
387        dragData
388      } = data;
389      const {
390        top,
391        left
392      } = imageData;
393      const {
394        transX,
395        transY
396      } = dragData;
397      const {
398        bounds
399      } = options;
400      x = x ?? Math.abs(left);
401      y = y ?? Math.abs(top);
402      const calcTransX = bounds ? minmax(left + x + transX, left, -left) : left + x + transX;
403      const calcTransY = bounds ? minmax(top + y + transY, top, -top) : top + y + transY;
404      this.move(calcTransX, calcTransY);
405      return this;
406    },
407
408    /**
409     * slideTo (only work on the slider)
410     * value - a numer between 0-100
411     * @param {Number}
412     */
413    slideTo(value, onlySlide) {
414      const {
415        __modules__
416      } = this;
417      if (!__modules__.slider) return;
418      const {
419        slider
420      } = __modules__;
421      const position = slider.direction === 'horizontal' ? 'left' : 'top';
422      const symbol = slider.direction === 'horizontal' ? '' : '-';
423      const distance = minmax(value, 0, 100);
424      slider.sliderButton.style[position] = `${symbol}${distance}%`;
425
426      if (!onlySlide) {
427        const percentage = distance / 100;
428        const minRatio = this.ratio < 1 ? this.ratio : 1;
429        const maxRatio = this.ratio > slider.maxRatio ? this.ratio : slider.maxRatio;
430        const ratio = (maxRatio - minRatio) * percentage + minRatio;
431        this.zoomTo(ratio);
432      }
433
434      return this;
435    },
436
437    /**
438     * reset image to initial status
439     */
440    reset() {
441      const {
442        image
443      } = this;
444      this.zoomTo(1);
445      setStyle(image, {
446        transform: 'translate(0, 0)'
447      });
448      this.emit('reset');
449      return this;
450    },
451
452    /**
453     * destory the instance of zoomist
454     */
455    destroy() {
456      const {
457        element,
458        wrapper
459      } = this;
460      const {
461        slider,
462        zoomer
463      } = this.__modules__;
464      element[NAME] = undefined;
465      this.mounted = false;
466      if (slider) this.destroySlider();
467      if (zoomer) this.destroyZoomer();
468      wrapper.remove();
469      element.style.removeProperty('width');
470      element.style.removeProperty('padding-bottom');
471      element.classList.remove(CLASS_CONTAINER);
472      this.emit('destroy');
473      return this;
474    },
475
476    /**
477     * a syntactic sugar of destroy and init
478     */
479    update() {
480      this.destroy().init();
481      this.emit('update');
482      return this;
483    },
484
485    /**
486     * add handler on __events__
487     * @param {String} events 
488     * @param {Function} handler 
489     */
490    on(events, handler) {
491      if (!isFunction(handler)) return this;
492      const {
493        __events__
494      } = this;
495      events.split(' ').forEach(evt => {
496        if (!__events__[evt]) __events__[evt] = [];
497
498        __events__[evt].push(handler);
499      });
500      return this;
501    },
502
503    /**
504     * invoke handlers in __events__[event]
505     * @param  {String, ...} args 
506     */
507    emit(...args) {
508      const {
509        __events__
510      } = this;
511      const event = args[0];
512      const data = args.slice(1, args.length);
513      if (!__events__[event]) return this;
514
515      __events__[event].forEach(handler => {
516        if (isFunction(handler)) handler.apply(this, data);
517      });
518
519      return this;
520    }
521
522  };
523
524  var bindEvents = (zoomist => {
525    const {
526      element,
527      wrapper,
528      image,
529      options,
530      data
531    } = zoomist;
532    const {
533      containerData,
534      imageData,
535      originImageData
536    } = data; // set image size on window resize
537
538    const resize = () => {
539      if (containerData.width === element.offsetWidth) return;
540      const widthRatio = element.offsetWidth / containerData.width;
541      const heightRatio = element.offsetHeight / containerData.height;
542      const originImageWidth = originImageData.width * widthRatio;
543      const originImageHeight = originImageData.height * heightRatio;
544      const originImageLeft = originImageData.left * widthRatio;
545      const originImageTop = originImageData.top * heightRatio;
546      const imageWidth = imageData.width * widthRatio;
547      const imageHeight = imageData.height * heightRatio;
548      const imageLeft = imageData.left * widthRatio;
549      const imageTop = imageData.top * heightRatio;
550      const transformX = getTransformX(image) * widthRatio;
551      const transformY = getTransformY(image) * heightRatio;
552      setObject(containerData, {
553        width: element.offsetWidth,
554        height: element.offsetHeight
555      });
556      setObject(originImageData, {
557        width: originImageWidth,
558        height: originImageHeight,
559        left: originImageLeft,
560        top: originImageTop
561      });
562      setObject(imageData, {
563        width: imageWidth,
564        height: imageHeight,
565        left: imageLeft,
566        top: imageTop
567      });
568      setStyle(zoomist.image, {
569        width: imageWidth,
570        height: imageHeight,
571        left: imageLeft,
572        top: imageTop,
573        transform: `translate(${transformX}px, ${transformY}px)`
574      });
575      zoomist.emit('resize');
576    };
577
578    window.addEventListener(EVENT_RESIZE, resize); // set image drag event
579
580    zoomist.dragging = false;
581    zoomist.data.dragData = {
582      startX: 0,
583      startY: 0,
584      transX: 0,
585      transY: 0
586    };
587    if (options.fill === 'contain' && options.bounds) options.bounds = false;
588    const {
589      dragData
590    } = data;
591
592    const dragStart = e => {
593      if (!options.draggable) return;
594      if (e.which === 2 || e.which === 3) return;
595      const isPinch = e.touches && e.touches.length === 2;
596      setObject(dragData, {
597        startX: isPinch ? (e.touches[0].pageX + e.touches[1].pageX) / 2 : getPointer(e).x,
598        startY: isPinch ? (e.touches[0].pageY + e.touches[1].pageY) / 2 : getPointer(e).y,
599        transX: getTransformX(image),
600        transY: getTransformY(image)
601      });
602      zoomist.dragging = true;
603      zoomist.emit('dragStart', {
604        x: dragData.transX,
605        y: dragData.transY
606      }, e);
607      document.addEventListener(EVENT_TOUCH_MOVE, dragMove);
608      document.addEventListener(EVENT_TOUCH_END, dragEnd);
609    };
610
611    const dragMove = e => {
612      if (!zoomist.dragging) return;
613      const isPinch = e.touches && e.touches.length === 2;
614      const pageX = isPinch ? (e.touches[0].pageX + e.touches[1].pageX) / 2 : getPointer(e).x;
615      const pageY = isPinch ? (e.touches[0].pageY + e.touches[1].pageY) / 2 : getPointer(e).y;
616
617      if (options.bounds) {
618        const minPageX = dragData.startX - (dragData.transX - imageData.left);
619        const maxPageX = dragData.startX - (dragData.transX + imageData.left);
620        const minPageY = dragData.startY - (dragData.transY - imageData.top);
621        const maxPageY = dragData.startY - (dragData.transY + imageData.top);
622        if (pageX < minPageX) dragData.startX += pageX - minPageX;
623        if (pageX > maxPageX) dragData.startX += pageX - maxPageX;
624        if (pageY < minPageY) dragData.startY += pageY - minPageY;
625        if (pageY > maxPageY) dragData.startY += pageY - maxPageY;
626      }
627
628      const transformX = roundToTwo(pageX - dragData.startX + dragData.transX);
629      const transformY = roundToTwo(pageY - dragData.startY + dragData.transY);
630      image.style.transform = `translate(${transformX}px, ${transformY}px)`;
631      zoomist.emit('drag', {
632        x: transformX,
633        y: transformY
634      }, e);
635    };
636
637    const dragEnd = e => {
638      zoomist.dragging = false;
639      setObject(dragData, {
640        transX: getTransformX(image),
641        transY: getTransformY(image)
642      });
643      zoomist.emit('dragEnd', {
644        x: dragData.transX,
645        y: dragData.transY
646      }, e);
647      document.removeEventListener(EVENT_TOUCH_MOVE, dragMove);
648      document.removeEventListener(EVENT_TOUCH_END, dragEnd);
649    }; // set image pinch event
650
651
652    zoomist.pinching = false;
653    zoomist.data.pinchData = {
654      dist: 0,
655      startX: 0,
656      startY: 0
657    };
658
659    const pinchStart = e => {
660      if (!options.pinchable) return;
661      if (!e.touches || e.touches.length !== 2) return;
662      const {
663        pinchData
664      } = zoomist.data;
665      setObject(pinchData, {
666        dist: Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY),
667        startX: e.touches[0].clientX,
668        startY: e.touches[0].clientY
669      }); // zoomist.dragging = false
670
671      zoomist.pinching = true;
672      zoomist.emit('pinchStart', e);
673      document.addEventListener(EVENT_TOUCH_MOVE, pinchMove);
674      document.addEventListener(EVENT_TOUCH_END, pinchEnd);
675    };
676
677    const pinchMove = e => {
678      if (!zoomist.pinching) return;
679      const {
680        pinchData
681      } = zoomist.data;
682      const pinchDist = Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY);
683      const zoomRatio = roundToTwo((pinchDist - pinchData.dist) / 100);
684      const pointer = {
685        clientX: (e.touches[0].clientX + e.touches[1].clientX) / 2,
686        clientY: (e.touches[0].clientY + e.touches[1].clientY) / 2
687      };
688      zoomist.zoom(zoomRatio, pointer);
689      pinchData.dist = pinchDist;
690      zoomist.emit('pinch', e);
691    };
692
693    const pinchEnd = e => {
694      zoomist.pinching = false;
695      zoomist.emit('pinchEnd', e);
696      document.removeEventListener(EVENT_TOUCH_MOVE, pinchMove);
697      document.removeEventListener(EVENT_TOUCH_END, pinchEnd);
698    }; // touch start handler
699
700
701    const touchStart = e => {
702      dragStart(e);
703      pinchStart(e);
704    };
705
706    wrapper.addEventListener(EVENT_TOUCH_START, touchStart); // set zomm on mousewheel event
707
708    zoomist.wheeling = false;
709
710    const wheel = e => {
711      if (!options.wheelable) return;
712      e.preventDefault();
713      const {
714        zoomRatio
715      } = options;
716      if (zoomist.wheeling) return; // prevent wheeling too fast
717
718      zoomist.wheeling = true;
719      setTimeout(() => {
720        zoomist.wheeling = false;
721      }, 30);
722      let delta;
723      if (e.deltaY) delta = e.deltaY > 0 ? -1 : 1;else if (e.wheelDelta) delta = e.wheelDelta / 120;else if (e.detail) delta = e.detail > 0 ? -1 : 1;
724      zoomist.zoom(delta * zoomRatio, getPointer(e));
725      zoomist.emit('wheel', e);
726    };
727
728    wrapper.addEventListener(EVENT_WHEEL, wheel);
729  }); // slider events
730
731  const sliderEvents = zoomist => {
732    const {
733      slider
734    } = zoomist.__modules__; // events
735
736    slider.sliding = false;
737    const isHorizontal = slider.direction === 'horizontal';
738
739    const slideHandler = e => {
740      const rect = slider.sliderMain.getBoundingClientRect();
741      const mousePoint = isHorizontal ? getPointer(e).clientX : -getPointer(e).clientY;
742      const sliderTotal = isHorizontal ? rect.width : rect.height;
743      const sliderStart = isHorizontal ? rect.left : -rect.bottom;
744      const percentage = minmax(roundToTwo((mousePoint - sliderStart) / sliderTotal), 0, 1);
745      const minRatio = zoomist.ratio < 1 ? zoomist.ratio : 1;
746      const maxRatio = zoomist.ratio > slider.maxRatio ? zoomist.ratio : slider.maxRatio;
747      const ratio = (maxRatio - minRatio) * percentage + minRatio;
748      zoomist.zoomTo(ratio);
749    };
750
751    const slideStart = e => {
752      slideHandler(e);
753      slider.sliding = true;
754      zoomist.emit('slideStart', zoomist.getSliderValue(), e);
755      document.addEventListener(EVENT_TOUCH_MOVE, slideMove);
756      document.addEventListener(EVENT_TOUCH_END, slideEnd);
757    };
758
759    const slideMove = e => {
760      if (!slider.sliding) return;
761      slideHandler(e);
762      zoomist.emit('slide', zoomist.getSliderValue(), e);
763    };
764
765    const slideEnd = e => {
766      slider.sliding = false;
767      zoomist.emit('slideEnd', zoomist.getSliderValue(), e);
768      document.removeEventListener(EVENT_TOUCH_MOVE, slideMove);
769      document.removeEventListener(EVENT_TOUCH_END, slideEnd);
770    };
771
772    slider.sliderMain.addEventListener(EVENT_TOUCH_START, slideStart);
773    slider.sliderMain.event = slideStart;
774  }; // zoomer events
775
776  const zoomerEvents = zoomist => {
777    const {
778      zoomRatio
779    } = zoomist.options;
780    const {
781      zoomer
782    } = zoomist.__modules__;
783
784    const zoomInHandler = () => zoomist.zoom(zoomRatio);
785
786    const zoomOutHandler = () => zoomist.zoom(-zoomRatio);
787
788    zoomer.zoomerInEl.addEventListener('click', zoomInHandler);
789    zoomer.zoomerOutEl.addEventListener('click', zoomOutHandler);
790    zoomer.zoomerInEl.event = zoomInHandler;
791    zoomer.zoomerOutEl.event = zoomOutHandler;
792  };
793
794  const sliderTemp = `
795  <div class="${CLASS_SLIDER_MAIN}">
796    <span class="${CLASS_SLIDER_BAR}"></span>
797    <span class="${CLASS_SLIDER_BUTTON}"></span>
798  </div>
799`;
800  const inZoomerIcon = `
801<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 12 12">
802  <polygon points="12,5.5 6.5,5.5 6.5,0 5.5,0 5.5,5.5 0,5.5 0,6.5 5.5,6.5 5.5,12 6.5,12 6.5,6.5 12,6.5 "/>
803</svg>
804`;
805  const outZoomerIcon = `
806<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 12 12">
807  <rect y="5.5" width="12" height="1"/>
808</svg>
809`;
810
811  var MODULES = {
812    /**
813     * create all modules
814     */
815    createModules() {
816      const {
817        options
818      } = this;
819      this.__modules__ = {};
820      MODULES$1.forEach(module => {
821        if (options[module]) this[`create${upperFirstLetter(module)}`]();
822      });
823    },
824
825    /**
826     * create slider module
827     */
828    createSlider() {
829      const {
830        element,
831        options,
832        __modules__
833      } = this;
834      __modules__.slider = Object.assign({}, DEFAULT_SLIDER_OPTIONS, options.slider);
835      const {
836        slider
837      } = __modules__;
838      if (options.maxRatio) Object.assign(slider, {
839        maxRatio: options.maxRatio
840      });
841      if (slider.direction !== 'horizontal' && slider.direction !== 'vertical') slider.direction = 'horizontal';
842      slider.value = 0; // mount
843
844      if (slider.mounted) slider.sliderMain.remove();
845      const isCustomEl = slider.isCustomEl = slider.el && isElementExist(slider.el);
846      const sliderEl = isCustomEl ? getElement(slider.el) : document.createElement('div');
847      if (!isCustomEl) sliderEl.classList.add(CLASS_SLIDER);
848      sliderEl.innerHTML = sliderTemp;
849      slider.sliderEl = sliderEl;
850      slider.sliderMain = sliderEl.querySelector(`.${CLASS_SLIDER_MAIN}`);
851      slider.sliderBar = sliderEl.querySelector(`.${CLASS_SLIDER_BAR}`);
852      slider.sliderButton = sliderEl.querySelector(`.${CLASS_SLIDER_BUTTON}`);
853      slider.sliderMain.classList.add(`${CLASS_SLIDER}-${slider.direction}`); // events
854
855      sliderEvents(this);
856      slider.mounted = true; // render
857
858      if (!isCustomEl) element.append(sliderEl);
859    },
860
861    /**
862     * destroy slider module
863     */
864    destroySlider() {
865      const {
866        slider
867      } = this.__modules__;
868      if (!slider || !slider.mounted) return;
869      if (slider.isCustomEl) slider.sliderMain.remove();else slider.sliderEl.remove();
870      slider.mounted = false;
871    },
872
873    /**
874     * create zoomer module
875     */
876    createZoomer() {
877      const {
878        element,
879        options,
880        __modules__
881      } = this;
882      __modules__.zoomer = Object.assign({}, DEFAULT_ZOOMER_OPTIONS, options.zoomer);
883      const {
884        zoomer
885      } = __modules__; // mount
886
887      if (zoomer.mounted && zoomer.zoomerEl) zoomer.sliderMain.remove();
888      const isCustomInEl = zoomer.isCustomInEl = zoomer.inEl && isElementExist(zoomer.inEl);
889      const isCustomOutEl = zoomer.isCustomOutEl = zoomer.outEl && isElementExist(zoomer.outEl);
890      //£ ACCESSIBILITE transformation des div en bouton
891      const zoomerInEl = isCustomInEl ? getElement(zoomer.inEl) : document.createElement('button');
892      const zoomerOutEl = isCustomOutEl ? getElement(zoomer.outEl) : document.createElement('button');
893
894      //£ ACCESSIBILITE ajout d'un titre aux boutons
895      zoomerInEl.setAttribute("title", "Zoomer sur la carte")
896      zoomerOutEl.setAttribute("title", "Dézoomer sur la carte")
897
898      if (!isCustomInEl) {
899        zoomerInEl.classList.add(CLASS_ZOOMER_IN);
900        zoomerInEl.innerHTML = inZoomerIcon;
901      }
902
903      if (!isCustomOutEl) {
904        zoomerOutEl.classList.add(CLASS_ZOOMER_OUT);
905        zoomerOutEl.innerHTML = outZoomerIcon;
906      }
907
908      zoomer.zoomerInEl = zoomerInEl;
909      zoomer.zoomerOutEl = zoomerOutEl;
910
911      if (zoomer.disableOnBounds) {
912        const {
913          bounds,
914          maxRatio
915        } = options;
916        if (bounds && this.ratio === 1) zoomerOutEl.classList.add(CLASS_ZOOMER_DISABLE);
917        if (this.ratio === maxRatio) zoomerInEl.classList.add(CLASS_ZOOMER_DISABLE);
918      } // events
919
920
921      zoomerEvents(this);
922      zoomer.mounted = true; // render
923
924      if (!isCustomInEl || !isCustomOutEl) {
925        const zoomerEl = document.createElement('div');
926        zoomerEl.classList.add(CLASS_ZOOMER);
927        if (!isCustomInEl) zoomerEl.append(zoomerInEl);
928        if (!isCustomOutEl) zoomerEl.append(zoomerOutEl);
929        zoomer.zoomerEl = zoomerEl;
930        element.append(zoomerEl);
931      }
932    },
933
934    /**
935     * destroy zoomer module
936     */
937    destroyZoomer() {
938      const {
939        zoomer
940      } = this.__modules__;
941      if (!zoomer || !zoomer.mounted) return;
942
943      const unbindZoomer = target => {
944        target.removeEventListener('click', target.event);
945        target.event = undefined;
946        target.classList.remove(CLASS_ZOOMER_DISABLE);
947      };
948
949      if (zoomer.isCustomInEl) unbindZoomer(zoomer.zoomerInEl);else zoomer.zoomerInEl.remove();
950      if (zoomer.isCustomOutEl) unbindZoomer(zoomer.zoomerOutEl);else zoomer.zoomerOutEl.remove();
951      if (zoomer.zoomerEl) zoomer.zoomerEl.remove();
952      zoomer.mounted = false;
953    }
954
955  };
956
957  class Zoomist {
958    /**
959     * 
960     * @param {Element} element - target element 
961     * @param {Object} options - the configuration options
962     */
963    constructor(element, options = {}) {
964      if (!element) throw new Error('The first argument is required.');
965      if (!isElementExist(element)) throw new Error('This element is not exist.');
966      this.element = getElement(element);
967      this.options = Object.assign({}, DEFAULT_OPTIONS, isPlainObject(options) && options);
968      this.init();
969    }
970
971    init() {
972      const {
973        element,
974        options
975      } = this;
976      const {
977        src
978      } = options;
979      if (element[NAME]) return;
980      element[NAME] = this;
981      const source = options.src = isString(src) || isImg(src) ? src : DEFAULT_OPTIONS.src;
982      const url = isImg(source) ? source.src : element.getAttribute(source);
983      if (!url) throw new Error(`Cannot find src from ${source}`);
984      this.create(url);
985    }
986
987    create(url) {
988      if (!url) return;
989      const {
990        options
991      } = this;
992      this.url = url;
993      this.data = {};
994      this.ratio = 1;
995      this.__events__ = EVENTS;
996
997      if (options.on) {
998        for (const [k, v] of Object.entries(options.on)) {
999          this.__events__[k] = [v];
1000        }
1001      }
1002
1003      this.mount();
1004    }
1005
1006    mount() {
1007      if (this.mounted) return;
1008      const {
1009        element,
1010        options,
1011        data,
1012        url
1013      } = this;
1014      const {
1015        fill,
1016        maxRatio,
1017        height
1018      } = options;
1019      if (this.wrapper) this.wrapper.remove();
1020      const wrapper = document.createElement('div');
1021      wrapper.classList.add(CLASS_WRAPPER);
1022      const image = document.createElement('img');
1023      image.classList.add(CLASS_IMAGE);
1024      image.src = url;
1025      //£ ACCESSIBILITE récupération de l'attribut data-zoomist-alt pour en faire l'alt de l'img carte
1026      //£ ACCESSIBILITE TODO: long desc ?
1027      image.alt = element.dataset.zoomistAlt
1028
1029      image.onload = () => {
1030        this.wrapper = wrapper;
1031        this.image = image;
1032        const {
1033          naturalWidth,
1034          naturalHeight
1035        } = image;
1036        const imageRatio = naturalWidth / naturalHeight; // set container height
1037
1038        if (height) {
1039          setStyle(element, {
1040            width: '100%'
1041          });
1042          if (height === 'auto') setStyle(element, {
1043            paddingBottom: `${roundToTwo(naturalHeight / naturalWidth * 100)}%`
1044          });else if (isNumber(height)) setStyle(element, {
1045            height: height
1046          });else if (isPercentage(height)) setStyle(element, {
1047            paddingBottom: height
1048          });
1049        }
1050
1051        const {
1052          offsetWidth,
1053          offsetHeight
1054        } = element;
1055        this.data.containerData = {
1056          width: offsetWidth,
1057          height: offsetHeight,
1058          aspectRatio: offsetWidth / offsetHeight
1059        }; // get base on width or height
1060
1061        const {
1062          containerData
1063        } = data;
1064        let baseSide;
1065        if (fill !== 'cover' && fill !== 'contain' && fill !== 'none') options.fill = 'cover';
1066        if (options.fill !== 'contain') baseSide = containerData.aspectRatio === imageRatio ? 'both' : containerData.aspectRatio > imageRatio ? 'width' : 'height';
1067        if (options.fill === 'contain') baseSide = containerData.aspectRatio === imageRatio ? 'both' : containerData.aspectRatio > imageRatio ? 'height' : 'width'; // calculate the image width, height, left, top
1068
1069        const imageWidth = options.fill === 'none' ? naturalWidth : baseSide === 'both' || baseSide === 'width' ? containerData.width : containerData.height * imageRatio;
1070        const imageHeight = options.fill === 'none' ? naturalHeight : baseSide === 'both' || baseSide === 'height' ? containerData.height : containerData.width / imageRatio;
1071        const imageLeft = (containerData.width - imageWidth) / 2;
1072        const imageTop = (containerData.height - imageHeight) / 2;
1073        this.data.originImageData = {
1074          naturalWidth,
1075          naturalHeight,
1076          aspectRatio: imageRatio,
1077          width: imageWidth,
1078          height: imageHeight,
1079          left: imageLeft,
1080          top: imageTop
1081        };
1082        this.data.imageData = Object.assign({}, this.data.originImageData);
1083        setStyle(image, {
1084          width: imageWidth,
1085          height: imageHeight,
1086          left: imageLeft,
1087          top: imageTop
1088        }); // if has maxRatio
1089
1090        if ((!isNumber(maxRatio) || maxRatio <= 1) && maxRatio !== false) options.maxRatio = false;
1091        bindEvents(this);
1092        this.mounted = true;
1093        this.render();
1094      };
1095    }
1096
1097    render() {
1098      const {
1099        element,
1100        wrapper,
1101        image
1102      } = this;
1103      element.classList.add(CLASS_CONTAINER);
1104      wrapper.append(image);
1105      element.append(wrapper);
1106      this.createModules();
1107      this.emit('ready');
1108    }
1109
1110  }
1111
1112  Object.assign(Zoomist.prototype, METHODS, MODULES);
1113
1114  return Zoomist;
1115
1116}));

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.