Pārlūkot izejas kodu

Revised the internal event system by utilizing native events.

NaotoshiFujita 3 gadi atpakaļ
vecāks
revīzija
80445b6723
33 mainītis faili ar 866 papildinājumiem un 922 dzēšanām
  1. 0 0
      dist/js/splide-renderer.min.js
  2. 12 12
      dist/js/splide.cjs.js
  3. 12 12
      dist/js/splide.esm.js
  4. 82 109
      dist/js/splide.js
  5. 0 0
      dist/js/splide.min.js
  6. BIN
      dist/js/splide.min.js.gz
  7. 0 0
      dist/js/splide.min.js.map
  8. 2 0
      dist/types/index.d.ts
  9. 12 26
      src/js/components/Controller/Controller.ts
  10. 2 4
      src/js/components/Elements/Elements.ts
  11. 5 5
      src/js/components/Media/Media.ts
  12. 5 1
      src/js/components/Move/Move.ts
  13. 0 13
      src/js/constants/priority.ts
  14. 153 0
      src/js/constructors/EventBinder/EventBinder.ts
  15. 77 0
      src/js/constructors/EventBinder/test/bind.test.ts
  16. 46 0
      src/js/constructors/EventBinder/test/destroy.test.ts
  17. 33 0
      src/js/constructors/EventBinder/test/dispatch.test.ts
  18. 231 0
      src/js/constructors/EventBinder/test/unbind.test.ts
  19. 0 135
      src/js/constructors/EventBus/EventBus.ts
  20. 0 45
      src/js/constructors/EventBus/test/destroy.test.ts
  21. 0 86
      src/js/constructors/EventBus/test/key.test.ts
  22. 0 107
      src/js/constructors/EventBus/test/off.test.ts
  23. 0 93
      src/js/constructors/EventBus/test/on.test.ts
  24. 34 117
      src/js/constructors/EventInterface/EventInterface.ts
  25. 19 1
      src/js/constructors/EventInterface/test/general.test.ts
  26. 1 1
      src/js/constructors/index.ts
  27. 7 8
      src/js/core/Splide/Splide.ts
  28. 3 3
      src/js/test/php/examples/add.php
  29. 32 32
      src/js/test/php/examples/default.php
  30. 1 1
      src/js/test/php/examples/extension.php
  31. 1 1
      src/js/test/php/examples/json.php
  32. 95 109
      src/js/test/php/examples/multiple.php
  33. 1 1
      src/js/test/php/examples/nest.php

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/js/splide-renderer.min.js


+ 12 - 12
dist/js/splide.cjs.js

@@ -715,9 +715,8 @@ function Elements(Splide2, Components2, options) {
     addClass(root, classes = getClasses());
   }
   function mount() {
-    const priority = DEFAULT_EVENT_PRIORITY - 2;
-    on(EVENT_REFRESH, destroy, priority);
-    on(EVENT_REFRESH, setup, priority);
+    on(EVENT_REFRESH, destroy);
+    on(EVENT_REFRESH, setup);
     on(EVENT_UPDATED, update);
   }
   function destroy() {
@@ -1304,7 +1303,8 @@ function Move(Splide2, Components2, options) {
     getPosition,
     getLimit,
     isBusy,
-    exceededLimit
+    exceededLimit,
+    reposition
   };
 }
 
@@ -1315,6 +1315,8 @@ function Controller(Splide2, Components2, options) {
   const { isEnough, getLength } = Components2.Slides;
   const isLoop = Splide2.is(LOOP);
   const isSlide = Splide2.is(SLIDE);
+  const getNext = apply(getAdjacent, false);
+  const getPrev = apply(getAdjacent, true);
   let currIndex = options.start || 0;
   let prevIndex = currIndex;
   let slideCount;
@@ -1322,13 +1324,17 @@ function Controller(Splide2, Components2, options) {
   let perPage;
   function mount() {
     init();
-    on([EVENT_UPDATED, EVENT_REFRESH], init, DEFAULT_EVENT_PRIORITY - 1);
+    on([EVENT_UPDATED, EVENT_REFRESH], init);
   }
   function init() {
     slideCount = getLength(true);
     perMove = options.perMove;
     perPage = options.perPage;
-    currIndex = clamp(currIndex, 0, slideCount - 1);
+    const index = clamp(currIndex, 0, slideCount - 1);
+    if (index !== currIndex) {
+      currIndex = index;
+      Move.reposition();
+    }
   }
   function go(control, allowSameIndex, callback) {
     const dest = parse(control);
@@ -1365,12 +1371,6 @@ function Controller(Splide2, Components2, options) {
     }
     return index;
   }
-  function getNext(destination) {
-    return getAdjacent(false, destination);
-  }
-  function getPrev(destination) {
-    return getAdjacent(true, destination);
-  }
   function getAdjacent(prev, destination) {
     const number = perMove || (hasFocus() ? 1 : perPage);
     const dest = computeDestIndex(currIndex + number * (prev ? -1 : 1), currIndex);

+ 12 - 12
dist/js/splide.esm.js

@@ -711,9 +711,8 @@ function Elements(Splide2, Components2, options) {
     addClass(root, classes = getClasses());
   }
   function mount() {
-    const priority = DEFAULT_EVENT_PRIORITY - 2;
-    on(EVENT_REFRESH, destroy, priority);
-    on(EVENT_REFRESH, setup, priority);
+    on(EVENT_REFRESH, destroy);
+    on(EVENT_REFRESH, setup);
     on(EVENT_UPDATED, update);
   }
   function destroy() {
@@ -1300,7 +1299,8 @@ function Move(Splide2, Components2, options) {
     getPosition,
     getLimit,
     isBusy,
-    exceededLimit
+    exceededLimit,
+    reposition
   };
 }
 
@@ -1311,6 +1311,8 @@ function Controller(Splide2, Components2, options) {
   const { isEnough, getLength } = Components2.Slides;
   const isLoop = Splide2.is(LOOP);
   const isSlide = Splide2.is(SLIDE);
+  const getNext = apply(getAdjacent, false);
+  const getPrev = apply(getAdjacent, true);
   let currIndex = options.start || 0;
   let prevIndex = currIndex;
   let slideCount;
@@ -1318,13 +1320,17 @@ function Controller(Splide2, Components2, options) {
   let perPage;
   function mount() {
     init();
-    on([EVENT_UPDATED, EVENT_REFRESH], init, DEFAULT_EVENT_PRIORITY - 1);
+    on([EVENT_UPDATED, EVENT_REFRESH], init);
   }
   function init() {
     slideCount = getLength(true);
     perMove = options.perMove;
     perPage = options.perPage;
-    currIndex = clamp(currIndex, 0, slideCount - 1);
+    const index = clamp(currIndex, 0, slideCount - 1);
+    if (index !== currIndex) {
+      currIndex = index;
+      Move.reposition();
+    }
   }
   function go(control, allowSameIndex, callback) {
     const dest = parse(control);
@@ -1361,12 +1367,6 @@ function Controller(Splide2, Components2, options) {
     }
     return index;
   }
-  function getNext(destination) {
-    return getAdjacent(false, destination);
-  }
-  function getPrev(destination) {
-    return getAdjacent(true, destination);
-  }
   function getAdjacent(prev, destination) {
     const number = perMove || (hasFocus() ? 1 : perPage);
     const dest = computeDestIndex(currIndex + number * (prev ? -1 : 1), currIndex);

+ 82 - 109
dist/js/splide.js

@@ -59,8 +59,6 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     DRAGGING: DRAGGING,
     DESTROYED: DESTROYED
   };
-  var DEFAULT_EVENT_PRIORITY = 10;
-  var DEFAULT_USER_EVENT_PRIORITY = 20;
 
   function empty(array) {
     array.length = 0;
@@ -382,91 +380,23 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     return "" + prefix + pad(ids[prefix] = (ids[prefix] || 0) + 1);
   }
 
-  function EventBus() {
-    var handlers = {};
-
-    function on(events, callback, key, priority) {
-      if (priority === void 0) {
-        priority = DEFAULT_EVENT_PRIORITY;
-      }
-
-      forEachEvent(events, function (event, namespace) {
-        var events2 = handlers[event] = handlers[event] || [];
-        events2.push([callback, namespace, priority, key]);
-        events2.sort(function (handler1, handler2) {
-          return handler1[2] - handler2[2];
-        });
-      });
-    }
-
-    function off(events, key) {
-      forEachEvent(events, function (event, namespace) {
-        handlers[event] = (handlers[event] || []).filter(function (handler) {
-          return handler[3] ? handler[3] !== key : key || handler[1] !== namespace;
-        });
-      });
-    }
-
-    function offBy(key) {
-      forOwn(handlers, function (eventHandlers, event) {
-        off(event, key);
-      });
-    }
-
-    function emit(event) {
-      var _arguments = arguments;
-      (handlers[event] || []).forEach(function (handler) {
-        handler[0].apply(handler, slice(_arguments, 1));
-      });
-    }
-
-    function destroy() {
-      handlers = {};
-    }
-
-    function forEachEvent(events, iteratee) {
-      toArray(events).join(" ").split(" ").forEach(function (eventNS) {
-        var fragments = eventNS.split(".");
-        iteratee(fragments[0], fragments[1]);
-      });
-    }
-
-    return {
-      on: on,
-      off: off,
-      offBy: offBy,
-      emit: emit,
-      destroy: destroy
-    };
-  }
-
-  function EventInterface(Splide2, manual) {
-    var event = Splide2.event;
-    var key = {};
+  function EventBinder() {
     var listeners = [];
 
-    function on(events, callback, priority) {
-      event.on(events, callback, key, priority);
-    }
-
-    function off(events) {
-      event.off(events, key);
-    }
-
     function bind(targets, events, callback, options) {
-      forEachEvent(targets, events, function (target, event2) {
+      forEachEvent(targets, events, function (target, event, namespace) {
         var isEventTarget = ("addEventListener" in target);
-        var remover = isEventTarget ? target.removeEventListener.bind(target, event2, callback, options) : target["removeListener"].bind(target, callback);
-        isEventTarget ? target.addEventListener(event2, callback, options) : target["addListener"](callback);
-        listeners.push([target, event2, callback, remover]);
+        var remover = isEventTarget ? target.removeEventListener.bind(target, event, callback, options) : target["removeListener"].bind(target, callback);
+        isEventTarget ? target.addEventListener(event, callback, options) : target["addListener"](callback);
+        listeners.push([target, event, namespace, callback, remover]);
       });
     }
 
     function unbind(targets, events, callback) {
-      forEachEvent(targets, events, function (target, event2) {
+      forEachEvent(targets, events, function (target, event, namespace) {
         listeners = listeners.filter(function (listener) {
-          if (listener[0] === target && listener[1] === event2 && (!callback || listener[2] === callback)) {
-            listener[3]();
+          if (listener[0] === target && listener[1] === event && listener[2] === namespace && (!callback || listener[3] === callback)) {
+            listener[4]();
             return false;
           }
 
@@ -475,32 +405,76 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       });
     }
 
+    function dispatch(target, type, detail) {
+      var e;
+      var bubbles = true;
+
+      if (typeof CustomEvent === "function") {
+        e = new CustomEvent(type, {
+          bubbles: bubbles,
+          detail: detail
+        });
+      } else {
+        e = document.createEvent("CustomEvent");
+        e.initEvent(type, bubbles, false);
+      }
+
+      target.dispatchEvent(e);
+      return e;
+    }
+
     function forEachEvent(targets, events, iteratee) {
       forEach(targets, function (target) {
-        if (target) {
-          events.split(" ").forEach(apply(iteratee, target));
-        }
+        target && forEach(events, function (events2) {
+          events2.split(" ").forEach(function (eventNS) {
+            var fragment = eventNS.split(".");
+            iteratee(target, fragment[0], fragment[1]);
+          });
+        });
       });
     }
 
     function destroy() {
-      listeners = listeners.filter(function (data) {
-        data[3]();
+      listeners.forEach(function (data) {
+        data[4]();
       });
-      event.offBy(key);
+      empty(listeners);
     }
 
-    !manual && event.on(EVENT_DESTROY, destroy, key);
     return {
-      on: on,
-      off: off,
-      emit: event.emit,
       bind: bind,
       unbind: unbind,
+      dispatch: dispatch,
       destroy: destroy
     };
   }
 
+  function EventInterface(Splide2) {
+    var bus = Splide2 ? Splide2.event.bus : document.createDocumentFragment();
+    var binder = EventBinder();
+
+    function on(events, callback) {
+      binder.bind(bus, toArray(events).join(" "), function (e) {
+        callback.apply(callback, isArray(e.detail) ? e.detail : []);
+      });
+    }
+
+    function emit(event) {
+      binder.dispatch(bus, event, slice(arguments, 1));
+    }
+
+    if (Splide2) {
+      Splide2.event.on(EVENT_DESTROY, binder.destroy);
+    }
+
+    return assign(binder, {
+      bus: bus,
+      on: on,
+      off: apply(binder.unbind, bus),
+      emit: emit
+    });
+  }
+
   function RequestInterval(interval, onInterval, onUpdate, limit) {
     var now = Date.now;
     var startTime;
@@ -618,7 +592,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
   }
 
   function Media(Splide2, Components2, options) {
-    var event = EventInterface(Splide2, true);
+    var binder = EventBinder();
     var breakpoints = options.breakpoints || {};
     var userOptions = merge({}, options);
     var queries = [];
@@ -639,14 +613,14 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
 
     function destroy(completely) {
       if (completely) {
-        event.destroy();
+        binder.destroy();
       }
     }
 
     function register(entries) {
       queries.push(entries.map(function (entry) {
         var query = entry[1] && matchMedia(entry[1]);
-        query && event.bind(query, "change", update);
+        query && binder.bind(query, "change", update);
         return [entry[0], query];
       }));
     }
@@ -671,7 +645,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
         var entry = find(entries, function (entry2) {
           return !entry2[1] || entry2[1].matches;
         }) || [];
-        entry[1] && event.emit(EVENT_MEDIA, entry[1]);
+        entry[1] && Splide2.emit(EVENT_MEDIA, entry[1]);
         return merge(merged, entry[0] || {});
       }, merge({}, userOptions));
     }
@@ -789,9 +763,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     }
 
     function mount() {
-      var priority = DEFAULT_EVENT_PRIORITY - 2;
-      on(EVENT_REFRESH, destroy, priority);
-      on(EVENT_REFRESH, setup, priority);
+      on(EVENT_REFRESH, destroy);
+      on(EVENT_REFRESH, setup);
       on(EVENT_UPDATED, update);
     }
 
@@ -1529,7 +1502,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       getPosition: getPosition,
       getLimit: getLimit,
       isBusy: isBusy,
-      exceededLimit: exceededLimit
+      exceededLimit: exceededLimit,
+      reposition: reposition
     };
   }
 
@@ -1545,6 +1519,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
         getLength = _Components2$Slides.getLength;
     var isLoop = Splide2.is(LOOP);
     var isSlide = Splide2.is(SLIDE);
+    var getNext = apply(getAdjacent, false);
+    var getPrev = apply(getAdjacent, true);
     var currIndex = options.start || 0;
     var prevIndex = currIndex;
     var slideCount;
@@ -1553,14 +1529,19 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
 
     function mount() {
       init();
-      on([EVENT_UPDATED, EVENT_REFRESH], init, DEFAULT_EVENT_PRIORITY - 1);
+      on([EVENT_UPDATED, EVENT_REFRESH], init);
     }
 
     function init() {
       slideCount = getLength(true);
       perMove = options.perMove;
       perPage = options.perPage;
-      currIndex = clamp(currIndex, 0, slideCount - 1);
+      var index = clamp(currIndex, 0, slideCount - 1);
+
+      if (index !== currIndex) {
+        currIndex = index;
+        Move.reposition();
+      }
     }
 
     function go(control, allowSameIndex, callback) {
@@ -1608,14 +1589,6 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       return index;
     }
 
-    function getNext(destination) {
-      return getAdjacent(false, destination);
-    }
-
-    function getPrev(destination) {
-      return getAdjacent(true, destination);
-    }
-
     function getAdjacent(prev, destination) {
       var number = perMove || (hasFocus() ? 1 : perPage);
       var dest = computeDestIndex(currIndex + number * (prev ? -1 : 1), currIndex);
@@ -2867,7 +2840,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
 
   var _Splide = /*#__PURE__*/function () {
     function _Splide(target, options) {
-      this.event = EventBus();
+      this.event = EventInterface();
       this.Components = {};
       this.state = State(CREATED);
       this.splides = [];
@@ -2940,7 +2913,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     };
 
     _proto.on = function on(events, callback) {
-      this.event.on(events, callback, null, DEFAULT_USER_EVENT_PRIORITY);
+      this.event.on(events, callback);
       return this;
     };
 
@@ -2987,7 +2960,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
           state = this.state;
 
       if (state.is(CREATED)) {
-        event.on(EVENT_READY, this.destroy.bind(this, completely), this);
+        EventInterface(this).on(EVENT_READY, this.destroy.bind(this, completely));
       } else {
         forOwn(this._Components, function (component) {
           component.destroy && component.destroy(completely);

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/js/splide.min.js


BIN
dist/js/splide.min.js.gz


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/js/splide.min.js.map


+ 2 - 0
dist/types/index.d.ts

@@ -97,6 +97,8 @@ interface MoveComponent extends BaseComponent {
     getLimit(max: boolean): number;
     isBusy(): boolean;
     exceededLimit(max?: boolean | undefined, position?: number): boolean;
+    /** @internal */
+    reposition(): void;
 }
 
 /**

+ 12 - 26
src/js/components/Controller/Controller.ts

@@ -1,10 +1,9 @@
 import { EVENT_REFRESH, EVENT_UPDATED } from '../../constants/events';
-import { DEFAULT_EVENT_PRIORITY } from '../../constants/priority';
 import { LOOP, SLIDE } from '../../constants/types';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { AnyFunction, BaseComponent, Components, Options } from '../../types';
-import { approximatelyEqual, between, clamp, floor, isString, isUndefined, max } from '../../utils';
+import { apply, approximatelyEqual, between, clamp, floor, isString, isUndefined, max } from '../../utils';
 
 
 /**
@@ -45,6 +44,8 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
   const { isEnough, getLength } = Components.Slides;
   const isLoop  = Splide.is( LOOP );
   const isSlide = Splide.is( SLIDE );
+  const getNext = apply( getAdjacent, false );
+  const getPrev = apply( getAdjacent, true );
 
   /**
    * The current index.
@@ -76,18 +77,25 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
    */
   function mount(): void {
     init();
-    on( [ EVENT_UPDATED, EVENT_REFRESH ], init, DEFAULT_EVENT_PRIORITY - 1 );
+    on( [ EVENT_UPDATED, EVENT_REFRESH ], init );
   }
 
   /**
    * Initializes some parameters.
    * Needs to check the slides length since the current index may be out of the range after refresh.
+   * The process order must be Elements -> Controller -> Move.
    */
   function init(): void {
     slideCount = getLength( true );
     perMove    = options.perMove;
     perPage    = options.perPage;
-    currIndex  = clamp( currIndex, 0, slideCount - 1 );
+
+    const index = clamp( currIndex, 0, slideCount - 1 );
+
+    if ( index !== currIndex ) {
+      currIndex = index;
+      Move.reposition();
+    }
   }
 
   /**
@@ -165,28 +173,6 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
     return index;
   }
 
-  /**
-   * Returns a next destination index.
-   *
-   * @param destination - Optional. Determines whether to get a destination index or a slide one.
-   *
-   * @return A next index if available, or otherwise `-1`.
-   */
-  function getNext( destination?: boolean ): number {
-    return getAdjacent( false, destination );
-  }
-
-  /**
-   * Returns a previous destination index.
-   *
-   * @param destination - Optional. Determines whether to get a destination index or a slide one.
-   *
-   * @return A previous index if available, or otherwise `-1`.
-   */
-  function getPrev( destination?: boolean ): number {
-    return getAdjacent( true, destination );
-  }
-
   /**
    * Returns an adjacent destination index.
    *

+ 2 - 4
src/js/components/Elements/Elements.ts

@@ -17,7 +17,6 @@ import {
   CLASS_TRACK,
 } from '../../constants/classes';
 import { EVENT_REFRESH, EVENT_UPDATED } from '../../constants/events';
-import { DEFAULT_EVENT_PRIORITY } from '../../constants/priority';
 import { PROJECT_CODE } from '../../constants/project';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
@@ -121,9 +120,8 @@ export function Elements( Splide: Splide, Components: Components, options: Optio
    * Called when the component is mounted.
    */
   function mount(): void {
-    const priority = DEFAULT_EVENT_PRIORITY - 2;
-    on( EVENT_REFRESH, destroy, priority );
-    on( EVENT_REFRESH, setup, priority );
+    on( EVENT_REFRESH, destroy );
+    on( EVENT_REFRESH, setup );
     on( EVENT_UPDATED, update );
   }
 

+ 5 - 5
src/js/components/Media/Media.ts

@@ -1,6 +1,6 @@
 import { EVENT_MEDIA } from '../../constants/events';
 import { DESTROYED } from '../../constants/states';
-import { EventInterface } from '../../constructors';
+import { EventBinder } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { BaseComponent, Components, Options } from '../../types';
 import { find, merge, noop } from '../../utils';
@@ -26,7 +26,7 @@ export interface MediaComponent extends BaseComponent {
  * @return A Media component object.
  */
 export function Media( Splide: Splide, Components: Components, options: Options ): MediaComponent {
-  const event       = EventInterface( Splide, true );
+  const binder      = EventBinder();
   const breakpoints = options.breakpoints || {};
 
   /**
@@ -65,7 +65,7 @@ export function Media( Splide: Splide, Components: Components, options: Options
    */
   function destroy( completely: boolean ): void {
     if ( completely ) {
-      event.destroy();
+      binder.destroy();
     }
   }
 
@@ -77,7 +77,7 @@ export function Media( Splide: Splide, Components: Components, options: Options
   function register( entries: [ Options, string? ][] ): void {
     queries.push( entries.map<[ Options, MediaQueryList? ]>( entry => {
       const query = entry[ 1 ] && matchMedia( entry[ 1 ] );
-      query && event.bind( query, 'change', update );
+      query && binder.bind( query, 'change', update );
       return [ entry[ 0 ], query ];
     } ) );
   }
@@ -109,7 +109,7 @@ export function Media( Splide: Splide, Components: Components, options: Options
   function accumulate(): Options {
     return queries.reduce<Options>( ( merged, entries ) => {
       const entry = ( find( entries, entry => ! entry[ 1 ] || entry[ 1 ].matches ) || [] );
-      entry[ 1 ] && event.emit( EVENT_MEDIA, entry[ 1 ] );
+      entry[ 1 ] && Splide.emit( EVENT_MEDIA, entry[ 1 ] );
       return merge( merged, entry[ 0 ] || {} );
     }, merge( {}, userOptions ) );
   }

+ 5 - 1
src/js/components/Move/Move.ts

@@ -33,6 +33,9 @@ export interface MoveComponent extends BaseComponent {
   getLimit( max: boolean ): number;
   isBusy(): boolean;
   exceededLimit( max?: boolean | undefined, position?: number ): boolean;
+
+  /** @internal */
+  reposition(): void;
 }
 
 /**
@@ -67,9 +70,9 @@ export function Move( Splide: Splide, Components: Components, options: Options )
 
   /**
    * Repositions the slider.
-   * - This must be called before the Slide component checks the visibility.
    * - Do not call `cancel()` here because LazyLoad may emit resize while transitioning.
    * - iOS Safari emits window resize event while the user swipes the slider because of the bottom bar.
+   * - Slide components listening to the internal repositioned event to update their visibility.
    */
   function reposition(): void {
     if ( ! isBusy() ) {
@@ -302,5 +305,6 @@ export function Move( Splide: Splide, Components: Components, options: Options )
     getLimit,
     isBusy,
     exceededLimit,
+    reposition,
   };
 }

+ 0 - 13
src/js/constants/priority.ts

@@ -1,13 +0,0 @@
-/**
- * The default priority for internal handlers.
- *
- * @since 3.0.0
- */
-export const DEFAULT_EVENT_PRIORITY = 10;
-
-/**
- * The default priority for users' handlers.
- *
- * @since 3.0.0
- */
-export const DEFAULT_USER_EVENT_PRIORITY = 20;

+ 153 - 0
src/js/constructors/EventBinder/EventBinder.ts

@@ -0,0 +1,153 @@
+import { AnyFunction } from '../../types';
+import { empty, forEach } from '../../utils';
+
+
+/**
+ * The type for an EventTarget or an array with EventTarget objects.
+ *
+ * @since 3.7.0
+ */
+type EventTargets = EventTarget | EventTarget[];
+
+/**
+ * The interface for the EventBinder object.
+ *
+ * @since 3.0.0
+ */
+export interface EventBinderObject {
+  bind( target: EventTargets, events: string | string[], callback: AnyFunction, options?: AddEventListenerOptions ): void
+  unbind( target: EventTarget | EventTarget[], events: string | string[], callback?: AnyFunction ): void;
+  dispatch<T>( target: EventTarget, event: string, detail?: T ): void;
+  destroy(): void;
+}
+
+/**
+ * The constructor function to provide methods to subscribe native events.
+ *
+ * @since 3.7.0
+ * @constructor
+ *
+ * @return An EventBinder object.
+ */
+export function EventBinder(): EventBinderObject {
+  /**
+   * Stores all handlers that listen to native events.
+   * `[ target, event, namespace, callback, remover ]`
+   */
+  let listeners: [ EventTarget, string, string | undefined, AnyFunction, () => void ][] = [];
+
+  /**
+   * Listens to native events.
+   * - `destroy()` can unsubscribe all events.
+   * - In IE, mediaQueryList does not inherit EventTarget,
+   *   and only supports deprecated `addListener` and `removeListener`.
+   *
+   * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener
+   *
+   * @param targets  - A target element, the window object or the document object.
+   * @param events   - An event or events to listen to.
+   * @param callback - A callback function.
+   * @param options  - Optional. The options to pass to the `addEventListener` function.
+   */
+  function bind(
+    targets: EventTargets,
+    events: string | string[],
+    callback: AnyFunction,
+    options?: AddEventListenerOptions
+  ): void {
+    forEachEvent( targets, events, ( target, event, namespace ) => {
+      const isEventTarget = 'addEventListener' in target;
+      const remover = isEventTarget
+        ? target.removeEventListener.bind( target, event, callback, options )
+        : target[ 'removeListener' ].bind( target, callback );
+
+      isEventTarget ? target.addEventListener( event, callback, options ) : target[ 'addListener' ]( callback );
+      listeners.push( [ target, event, namespace, callback, remover ] );
+    } );
+  }
+
+  /**
+   * Removes the event handler.
+   *
+   * @param targets  - A target element, the window object or the document object.
+   * @param events   - An event name or names to remove.
+   * @param callback - Optional. Specify the callback to remove.
+   */
+  function unbind( targets: EventTargets, events: string | string[], callback?: AnyFunction ): void {
+    forEachEvent( targets, events, ( target, event, namespace ) => {
+      listeners = listeners.filter( listener => {
+        if ( listener[ 0 ] === target
+          && listener[ 1 ] === event
+          && listener[ 2 ] === namespace
+          && ( ! callback || listener[ 3 ] === callback )
+        ) {
+          listener[ 4 ]();
+          return false;
+        }
+
+        return true;
+      } );
+    } );
+  }
+
+  /**
+   * Dispatches a custom event of the target.
+   *
+   * @param target - An event target.
+   * @param type   - An event type.
+   * @param detail - Optional. The `detail` object of the event.
+   *
+   * @return An event object.
+   */
+  function dispatch<T>( target: EventTarget, type: string, detail?: T ): CustomEvent {
+    let e: CustomEvent;
+    const bubbles = true;
+
+    if ( typeof CustomEvent === 'function' ) {
+      e = new CustomEvent( type, { bubbles, detail } );
+    } else {
+      e = document.createEvent( 'CustomEvent' );
+      e.initEvent( type, bubbles, false );
+    }
+
+    target.dispatchEvent( e );
+    return e;
+  }
+
+  /**
+   * Iterates over each target and event.
+   *
+   * @param targets  - A target element, the window object or the document object.
+   * @param events   - An event name or names.
+   * @param iteratee - An iteratee function.
+   */
+  function forEachEvent(
+    targets: EventTargets,
+    events: string | string[],
+    iteratee: ( target: EventTarget, event: string, namespace: string | undefined ) => void
+  ): void {
+    forEach( targets, target => {
+      target && forEach( events, events => {
+        events.split( ' ' ).forEach( eventNS => {
+          const fragment = eventNS.split( '.' );
+          iteratee( target, fragment[ 0 ], fragment[ 1 ] );
+        } );
+      } );
+    } );
+  }
+
+  /**
+   * Removes all listeners.
+   */
+  function destroy(): void {
+    listeners.forEach( data => { data[ 4 ]() } );
+    empty( listeners );
+  }
+
+  return {
+    bind,
+    unbind,
+    dispatch,
+    destroy,
+  };
+}

+ 77 - 0
src/js/constructors/EventBinder/test/bind.test.ts

@@ -0,0 +1,77 @@
+import { fire } from '../../../test';
+import { EventBinder } from '../EventBinder';
+
+
+describe( 'EventBinder#bind()', () => {
+  const div = document.createElement( 'div' );
+
+  test( 'can listen to native events.', () => {
+    const { bind } = EventBinder();
+    const callback1 = jest.fn();
+    const callback2 = jest.fn();
+
+    bind( window, 'resize', callback1 );
+    bind( div, 'click', callback2 );
+
+    fire( window, 'resize' );
+    fire( div, 'click' );
+
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 1 );
+  } );
+
+  test( 'can accept multiple events separated by spaces.', () => {
+    const { bind } = EventBinder();
+    const callback = jest.fn();
+
+    bind( div, 'load resize click', callback );
+
+    fire( div, 'resize' );
+    expect( callback ).toHaveBeenCalledTimes( 1 );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+  } );
+
+  test( 'can accept multiple events as an array.', () => {
+    const { bind } = EventBinder();
+    const callback = jest.fn();
+
+    bind( div, [ 'load', 'resize', 'click' ], callback );
+
+    fire( div, 'resize' );
+    expect( callback ).toHaveBeenCalledTimes( 1 );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+  } );
+
+  test( 'can accept multiple events by spaces and an array.', () => {
+    const { bind } = EventBinder();
+    const callback = jest.fn();
+
+    bind( div, [ 'load resize click', 'scroll', 'wheel' ], callback );
+
+    fire( div, 'resize' );
+    expect( callback ).toHaveBeenCalledTimes( 1 );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    fire( div, 'scroll' );
+    expect( callback ).toHaveBeenCalledTimes( 3 );
+  } );
+
+  test( 'can accept a namespace by a dot notation.', () => {
+    const { bind } = EventBinder();
+    const callback = jest.fn();
+
+    bind( div, [ 'load.namespace', 'resize.namespace', 'click.namespace' ], callback );
+
+    fire( div, 'resize' );
+    expect( callback ).toHaveBeenCalledTimes( 1 );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+  } );
+} );

+ 46 - 0
src/js/constructors/EventBinder/test/destroy.test.ts

@@ -0,0 +1,46 @@
+import { fire } from '../../../test';
+import { EventBinder } from '../EventBinder';
+
+
+describe( 'EventBinder#destroy()', () => {
+  const div = document.createElement( 'div' );
+
+  test( 'can remove all listeners.', () => {
+    const { bind, destroy } = EventBinder();
+    const callback1 = jest.fn();
+    const callback2 = jest.fn();
+
+    bind( window, 'resize', callback1 );
+    bind( div, 'click', callback2 );
+
+    destroy();
+
+    fire( window, 'resize' );
+    fire( div, 'click' );
+
+    expect( callback1 ).not.toHaveBeenCalled();
+    expect( callback2 ).not.toHaveBeenCalled();
+  } );
+
+  test( 'should not remove listeners bound by other binders.', () => {
+    const binder1 = EventBinder();
+    const binder2 = EventBinder();
+    const binder3 = EventBinder();
+
+    const binder1Callback = jest.fn();
+    const binder2Callback = jest.fn();
+    const binder3Callback = jest.fn();
+
+    binder1.bind( div, 'click', binder1Callback );
+    binder2.bind( div, 'click', binder2Callback );
+    binder3.bind( div, 'click', binder3Callback );
+
+    binder2.destroy();
+
+    fire( div, 'click' );
+
+    expect( binder1Callback ).toHaveBeenCalled();
+    expect( binder2Callback ).not.toHaveBeenCalled();
+    expect( binder3Callback ).toHaveBeenCalled();
+  } );
+} );

+ 33 - 0
src/js/constructors/EventBinder/test/dispatch.test.ts

@@ -0,0 +1,33 @@
+import { EventBinder } from '../EventBinder';
+
+
+describe( 'EventBinder#dispatch()', () => {
+  const div = document.createElement( 'div' );
+
+  test( 'can dispatch a custom event.', () => {
+    const { dispatch } = EventBinder();
+    const callback = jest.fn();
+
+    div.addEventListener( 'myEvent', callback );
+    dispatch( div, 'myEvent' );
+    expect( callback ).toHaveBeenCalled();
+  } );
+
+  test( 'can dispatch a custom event with a detail property.', done => {
+    const { dispatch } = EventBinder();
+    const array = [ 1, 2 ];
+
+    div.addEventListener( 'myEvent', e => {
+      if ( e instanceof CustomEvent ) {
+        expect( e.detail.a ).toBe( 1 );
+        expect( e.detail.b ).toBe( 'b' );
+        expect( e.detail.c ).toBe( array ); // Reference
+        done();
+      } else {
+        fail();
+      }
+    } );
+
+    dispatch( div, 'myEvent', { a: 1, b: 'b', c: array } );
+  } );
+} );

+ 231 - 0
src/js/constructors/EventBinder/test/unbind.test.ts

@@ -0,0 +1,231 @@
+import { fire } from '../../../test';
+import { EventBinder } from '../EventBinder';
+
+
+describe( 'EventBinder#unbind()', () => {
+  const div = document.createElement( 'div' );
+
+  test( 'can remove a listener.', () => {
+    const { bind, unbind } = EventBinder();
+    const callback1 = jest.fn();
+    const callback2 = jest.fn();
+
+    bind( div, 'click', callback1 );
+    bind( div, 'mouseenter', callback2 );
+
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 2 );
+
+    unbind( div, 'click' );
+
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 2 );
+
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 2 );
+
+    expect( callback2 ).not.toHaveBeenCalled();
+  } );
+
+  test( 'can remove multiple listeners by a string.', () => {
+    const { bind, unbind } = EventBinder();
+    const callback = jest.fn();
+
+    bind( div, 'click mouseenter mouseleave', callback );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 1 );
+
+    fire( div, 'mouseenter' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    unbind( div, 'click mouseleave' );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    fire( div, 'mouseleave' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    fire( div, 'mouseenter' );
+    expect( callback ).toHaveBeenCalledTimes( 3 );
+  } );
+
+  test( 'can remove multiple listeners by an array.', () => {
+    const { bind, unbind } = EventBinder();
+    const callback = jest.fn();
+
+    bind( div, 'click mouseenter mouseleave', callback );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 1 );
+
+    fire( div, 'mouseenter' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    unbind( div, [ 'click', 'mouseleave' ] );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    fire( div, 'mouseleave' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    fire( div, 'mouseenter' );
+    expect( callback ).toHaveBeenCalledTimes( 3 );
+  } );
+
+  test( 'can remove multiple listeners by a string and an array.', () => {
+    const { bind, unbind } = EventBinder();
+    const callback = jest.fn();
+
+    bind( div, 'click mouseenter mouseleave mousemove', callback );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 1 );
+
+    fire( div, 'mouseenter' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    unbind( div, [ 'click mousemove', 'mouseleave' ] );
+
+    fire( div, 'click' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    fire( div, 'mouseleave' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    fire( div, 'mousemove' );
+    expect( callback ).toHaveBeenCalledTimes( 2 );
+
+    fire( div, 'mouseenter' );
+    expect( callback ).toHaveBeenCalledTimes( 3 );
+  } );
+
+  test( 'can only remove events that belong to the specified namespace.', () => {
+    const { bind, unbind } = EventBinder();
+    const callback1 = jest.fn();
+    const callback2 = jest.fn();
+    const callback3 = jest.fn();
+
+    bind( div, 'click.namespace1', callback1 );
+    bind( div, 'click.namespace2', callback2 );
+    bind( div, 'click.namespace3', callback3 );
+
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 1 );
+    expect( callback3 ).toHaveBeenCalledTimes( 1 );
+
+    unbind( div, 'click.namespace1' );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 2 );
+    expect( callback3 ).toHaveBeenCalledTimes( 2 );
+
+    unbind( div, 'click.namespace2' );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 2 );
+    expect( callback3 ).toHaveBeenCalledTimes( 3 );
+
+    unbind( div, 'click.namespace3' );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 2 );
+    expect( callback3 ).toHaveBeenCalledTimes( 3 );
+  } );
+
+  test( 'can remove all handlers in the same namespace.', () => {
+    const { bind, unbind } = EventBinder();
+    const callback1 = jest.fn();
+    const callback2 = jest.fn();
+    const callback3 = jest.fn();
+
+    bind( div, 'click.namespace', callback1 );
+    bind( div, 'click.namespace', callback2 );
+    bind( div, 'click.namespace', callback3 );
+
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 1 );
+    expect( callback3 ).toHaveBeenCalledTimes( 1 );
+
+    unbind( div, 'click.namespace' );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 1 );
+    expect( callback3 ).toHaveBeenCalledTimes( 1 );
+  } );
+
+  test( 'can only remove the specified callback.', () => {
+    const { bind, unbind } = EventBinder();
+    const callback1 = jest.fn();
+    const callback2 = jest.fn();
+    const callback3 = jest.fn();
+
+    bind( div, 'click', callback1 );
+    bind( div, 'click', callback2 );
+    bind( div, 'click', callback3 );
+
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 1 );
+    expect( callback3 ).toHaveBeenCalledTimes( 1 );
+
+    unbind( div, 'click', callback1 );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 2 );
+    expect( callback3 ).toHaveBeenCalledTimes( 2 );
+
+    unbind( div, 'click', callback2 );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 2 );
+    expect( callback3 ).toHaveBeenCalledTimes( 3 );
+
+    unbind( div, 'click', callback3 );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 2 );
+    expect( callback3 ).toHaveBeenCalledTimes( 3 );
+  } );
+
+  test( 'can only remove the specified callback in the same namespace.', () => {
+    const { bind, unbind } = EventBinder();
+    const callback1 = jest.fn();
+    const callback2 = jest.fn();
+    const callback3 = jest.fn();
+
+    bind( div, 'click.namespace', callback1 );
+    bind( div, 'click.namespace', callback2 );
+    bind( div, 'click.namespace', callback3 );
+
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 1 );
+    expect( callback3 ).toHaveBeenCalledTimes( 1 );
+
+    unbind( div, 'click.namespace', callback1 );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 2 );
+    expect( callback3 ).toHaveBeenCalledTimes( 2 );
+
+    unbind( div, 'click.namespace', callback2 );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 2 );
+    expect( callback3 ).toHaveBeenCalledTimes( 3 );
+
+    unbind( div, 'click.namespace', callback3 );
+    fire( div, 'click' );
+    expect( callback1 ).toHaveBeenCalledTimes( 1 );
+    expect( callback2 ).toHaveBeenCalledTimes( 2 );
+    expect( callback3 ).toHaveBeenCalledTimes( 3 );
+  } );
+} );

+ 0 - 135
src/js/constructors/EventBus/EventBus.ts

@@ -1,135 +0,0 @@
-import { DEFAULT_EVENT_PRIORITY } from '../../constants/priority';
-import { AnyFunction } from '../../types';
-import { forOwn, slice, toArray } from '../../utils';
-
-
-/**
- * The interface for the EventBus instance.
- *
- * @since 3.0.0
- */
-export interface EventBusObject {
-  on( events: string | string[], callback: EventBusCallback, key?: object, priority?: number ): void;
-  off( events: string | string[], key?: object ): void;
-  offBy( key: object ): void;
-  emit( event: string, ...args: any[] ): void;
-  destroy(): void;
-}
-
-/**
- * The interface for each event handler object.
- *
- * @since 3.0.0
- */
-export type EventHandler = [ AnyFunction, string, number, object? ];
-
-/**
- * The type for a callback function of the EventBus.
- *
- * @since 3.0.0
- */
-export type EventBusCallback = AnyFunction;
-
-/**
- * The constructor to provided a simple event system.
- *
- * @since 3.0.0
- *
- * @return An EventBus object.
- */
-export function EventBus(): EventBusObject {
-  /**
-   * The collection of registered handlers.
-   */
-  let handlers: Record<string, EventHandler[]> = {};
-
-  /**
-   * Registers an event handler.
-   *
-   * @param events   - An event name or names separated by spaces. Use a dot(.) to add a namespace.
-   * @param callback - A callback function to register.
-   * @param key      - Optional. An object for an identifier of the handler.
-   * @param priority - Optional. A priority number for the order in which the callbacks are invoked.
-   *                   Lower numbers correspond with earlier execution. The default value is 10.
-   */
-  function on(
-    events: string | string[],
-    callback: EventBusCallback,
-    key?: object,
-    priority = DEFAULT_EVENT_PRIORITY
-  ): void {
-    forEachEvent( events, ( event, namespace ) => {
-      const events = ( handlers[ event ] = handlers[ event ] || [] );
-      events.push( [ callback, namespace, priority, key ] );
-      events.sort( ( handler1, handler2 ) => handler1[ 2 ] - handler2[ 2 ] );
-    } );
-  }
-
-  /**
-   * Removes event handlers registered by `on()`.
-   * If only the event name is provided, all handlers that associate with the event are removed.
-   * If the event name and namespace are specified, handlers that associate with the event and namespace are removed.
-   *
-   * @param events - An event name or names separated by spaces. Use a dot(.) to add a namespace.
-   * @param key    - Optional. An object for an identifier of the handler.
-   */
-  function off( events: string | string[], key?: object ): void {
-    forEachEvent( events, ( event, namespace ) => {
-      handlers[ event ] = ( handlers[ event ] || [] ).filter( handler => {
-        return handler[ 3 ] ? handler[ 3 ] !== key : key || handler[ 1 ] !== namespace;
-      } );
-    } );
-  }
-
-  /**
-   * Removes all handlers locked by the specified key.
-   *
-   * @param key - A key.
-   */
-  function offBy( key: object ): void {
-    forOwn( handlers, ( eventHandlers, event ) => {
-      off( event, key );
-    } );
-  }
-
-  /**
-   * Triggers callback functions.
-   * This accepts additional arguments and passes them to callbacks.
-   *
-   * @param event - An event name.
-   */
-  function emit( event: string ): void {
-    ( handlers[ event ] || [] ).forEach( handler => {
-      // eslint-disable-next-line prefer-rest-params, prefer-spread
-      handler[ 0 ].apply( handler, slice( arguments, 1 ) );
-    } );
-  }
-
-  /**
-   * Removes all handlers.
-   */
-  function destroy(): void {
-    handlers = {};
-  }
-
-  /**
-   * Parses provided events and iterates over them.
-   *
-   * @param events   - An event or events.
-   * @param iteratee - An iteratee function.
-   */
-  function forEachEvent( events: string | string[], iteratee: ( event: string, namespace: string ) => void ): void {
-    toArray( events ).join( ' ' ).split( ' ' ).forEach( eventNS => {
-      const fragments = eventNS.split( '.' );
-      iteratee( fragments[ 0 ], fragments[ 1 ] );
-    } );
-  }
-
-  return {
-    on,
-    off,
-    offBy,
-    emit,
-    destroy,
-  };
-}

+ 0 - 45
src/js/constructors/EventBus/test/destroy.test.ts

@@ -1,45 +0,0 @@
-import { EventBus } from '../EventBus';
-
-
-describe( 'EventBus#destroy', () => {
-  test( 'can remove all handlers.', () => {
-    const event     = EventBus();
-    const callback1 = jest.fn();
-    const callback2 = jest.fn();
-    const callback3 = jest.fn();
-    const callback4 = jest.fn();
-    const callback5 = jest.fn();
-    const key       = {};
-
-    event.on( 'mounted', callback1 );
-
-    // With a namespace
-    event.on( 'mounted.namespace', callback2 );
-
-    // Multiple events
-    event.on( 'mounted moved', callback3 );
-
-    // With a key
-    event.on( 'mounted', callback4, key );
-
-    // With a key and a namespace
-    event.on( 'mounted.namespace', callback5, key );
-
-    event.emit( 'mounted' );
-
-    expect( callback1 ).toHaveBeenCalledTimes( 1 );
-    expect( callback2 ).toHaveBeenCalledTimes( 1 );
-    expect( callback3 ).toHaveBeenCalledTimes( 1 );
-    expect( callback4 ).toHaveBeenCalledTimes( 1 );
-    expect( callback5 ).toHaveBeenCalledTimes( 1 );
-
-    event.destroy();
-    event.emit( 'mounted' );
-
-    expect( callback1 ).toHaveBeenCalledTimes( 1 );
-    expect( callback2 ).toHaveBeenCalledTimes( 1 );
-    expect( callback3 ).toHaveBeenCalledTimes( 1 );
-    expect( callback4 ).toHaveBeenCalledTimes( 1 );
-    expect( callback5 ).toHaveBeenCalledTimes( 1 );
-  } );
-} );

+ 0 - 86
src/js/constructors/EventBus/test/key.test.ts

@@ -1,86 +0,0 @@
-import { EventBus } from '../EventBus';
-
-
-describe( 'EventBus', () => {
-  test( 'can lock a listener by a key.', () => {
-    const event     = EventBus();
-    const onMounted = jest.fn();
-    const onMoved   = jest.fn();
-    const key       = {};
-
-    event.on( 'mounted', onMounted, key );
-    event.on( 'moved', onMoved, key );
-
-    event.off( 'mounted' );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-
-    expect( onMounted ).toHaveBeenCalledTimes( 1 );
-    expect( onMoved ).toHaveBeenCalledTimes( 1 );
-  } );
-
-  test( 'can remove a listener by a key.', () => {
-    const event     = EventBus();
-    const onMounted = jest.fn();
-    const onMoved   = jest.fn();
-    const key       = {};
-
-    event.on( 'mounted', onMounted, key );
-    event.on( 'moved', onMoved, key );
-
-    event.off( 'mounted', key );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-
-    expect( onMounted ).not.toHaveBeenCalled();
-    expect( onMoved ).toHaveBeenCalledTimes( 1 );
-
-    event.off( 'moved', key );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-
-    expect( onMounted ).not.toHaveBeenCalled();
-    expect( onMoved ).toHaveBeenCalledTimes( 1 );
-  } );
-
-  test( 'can remove all listeners locked by the same key.', () => {
-    const event     = EventBus();
-    const onMounted = jest.fn();
-    const onMoved   = jest.fn();
-    const key       = {};
-
-    event.on( 'mounted', onMounted, key );
-    event.on( 'moved', onMoved, key );
-
-    event.offBy( key );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-
-    expect( onMounted ).not.toHaveBeenCalled();
-    expect( onMoved ).not.toHaveBeenCalled();
-  } );
-
-  test( 'should not remove a handler if a key does not match.', () => {
-    const event     = EventBus();
-    const callback1 = jest.fn();
-    const callback2 = jest.fn();
-    const callback3 = jest.fn();
-    const key       = {};
-
-    event.on( 'mounted', callback1 );
-    event.on( 'mounted', callback2, key );
-    event.on( 'mounted', callback3, key );
-
-    event.off( 'mounted', key );
-
-    event.emit( 'mounted' );
-
-    expect( callback1 ).toHaveBeenCalledTimes( 1 );
-    expect( callback2 ).not.toHaveBeenCalled();
-    expect( callback3 ).not.toHaveBeenCalled();
-  } );
-} );

+ 0 - 107
src/js/constructors/EventBus/test/off.test.ts

@@ -1,107 +0,0 @@
-import { EventBus } from '../EventBus';
-
-
-describe( 'EventBus#off()', () => {
-  test( 'can remove a listener.', () => {
-    const event     = EventBus();
-    const onMounted = jest.fn();
-    const onMoved   = jest.fn();
-
-    event.on( 'mounted', onMounted );
-    event.on( 'moved', onMoved );
-
-    event.off( 'mounted' );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-
-    expect( onMounted ).not.toHaveBeenCalled();
-    expect( onMoved ).toHaveBeenCalledTimes( 1 );
-  } );
-
-  test( 'can remove listeners by a string.', () => {
-    const event     = EventBus();
-    const onMounted = jest.fn();
-    const onMoved   = jest.fn();
-
-    event.on( 'mounted', onMounted );
-    event.on( 'moved', onMoved );
-
-    event.off( 'mounted moved' );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-
-    expect( onMounted ).not.toHaveBeenCalled();
-    expect( onMoved ).not.toHaveBeenCalled();
-  } );
-
-  test( 'can remove listeners by an array.', () => {
-    const event     = EventBus();
-    const onMounted = jest.fn();
-    const onMoved   = jest.fn();
-
-    event.on( 'mounted', onMounted );
-    event.on( 'moved', onMoved );
-
-    event.off( [ 'mounted', 'moved' ] );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-
-    expect( onMounted ).not.toHaveBeenCalled();
-    expect( onMoved ).not.toHaveBeenCalled();
-  } );
-
-  test( 'can remove listeners by a string and an array.', () => {
-    const event     = EventBus();
-    const onMounted = jest.fn();
-    const onMoved   = jest.fn();
-    const onReady   = jest.fn();
-
-    event.on( 'mounted', onMounted );
-    event.on( 'moved', onMoved );
-    event.on( 'ready', onReady );
-
-    event.off( [ 'mounted moved', 'ready' ] );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-    event.emit( 'ready' );
-
-    expect( onMounted ).not.toHaveBeenCalled();
-    expect( onMoved ).not.toHaveBeenCalled();
-    expect( onReady ).not.toHaveBeenCalled();
-  } );
-
-  test( 'can remove a listener that belongs to the specified namespace.', () => {
-    const event     = EventBus();
-    const callback1 = jest.fn();
-    const callback2   = jest.fn();
-    const callback3   = jest.fn();
-
-    event.on( 'mounted.namespace1', callback1 );
-    event.on( 'mounted.namespace2', callback2 );
-    event.on( 'mounted.namespace3', callback3 );
-
-    event.emit( 'mounted' );
-
-    expect( callback1 ).toHaveBeenCalledTimes( 1 );
-    expect( callback2 ).toHaveBeenCalledTimes( 1 );
-    expect( callback3 ).toHaveBeenCalledTimes( 1 );
-
-    event.off( 'mounted.namespace2' );
-    event.emit( 'mounted' );
-
-    expect( callback1 ).toHaveBeenCalledTimes( 2 );
-    expect( callback2 ).toHaveBeenCalledTimes( 1 );
-    expect( callback3 ).toHaveBeenCalledTimes( 2 );
-
-    event.off( 'mounted.namespace3' );
-    event.emit( 'mounted' );
-
-    expect( callback1 ).toHaveBeenCalledTimes( 3 );
-    expect( callback2 ).toHaveBeenCalledTimes( 1 );
-    expect( callback3 ).toHaveBeenCalledTimes( 2 );
-  } );
-} );

+ 0 - 93
src/js/constructors/EventBus/test/on.test.ts

@@ -1,93 +0,0 @@
-import { EventBus } from '../EventBus';
-
-
-describe( 'EventBus#on()', () => {
-  test( 'can listen to an event.', () => {
-    const event     = EventBus();
-    const onMounted = jest.fn();
-    const onMoved   = jest.fn();
-
-    event.on( 'mounted', onMounted );
-    event.on( 'moved', onMoved );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-
-    expect( onMounted ).toHaveBeenCalledTimes( 1 );
-    expect( onMoved ).toHaveBeenCalledTimes( 1 );
-  } );
-
-  test( 'can listen to multiple events by a string.', () => {
-    const event    = EventBus();
-    const callback = jest.fn();
-
-    event.on( 'mounted ready moved', callback );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-    expect( callback ).toHaveBeenCalledTimes( 2 );
-
-    event.emit( 'ready' );
-    expect( callback ).toHaveBeenCalledTimes( 3 );
-  } );
-
-  test( 'can listen to multiple events by an array.', () => {
-    const event    = EventBus();
-    const callback = jest.fn();
-
-    event.on( [ 'mounted', 'moved', 'ready' ], callback );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-    expect( callback ).toHaveBeenCalledTimes( 2 );
-
-    event.emit( 'ready' );
-    expect( callback ).toHaveBeenCalledTimes( 3 );
-  } );
-
-  test( 'can listen to multiple events by a string and an array.', () => {
-    const event    = EventBus();
-    const callback = jest.fn();
-
-    event.on( [ 'mounted moved ready', 'active visible', 'destroy' ], callback );
-
-    event.emit( 'mounted' );
-    event.emit( 'moved' );
-    expect( callback ).toHaveBeenCalledTimes( 2 );
-
-    event.emit( 'active' );
-    event.emit( 'destroy' );
-    expect( callback ).toHaveBeenCalledTimes( 4 );
-  } );
-
-  test( 'can listen to an event with priority.', () => {
-    const event = EventBus();
-    const called: number[] = [];
-
-    event.on( 'mounted', () => {
-      called.push( 3 );
-    }, null, 3 );
-
-    event.on( 'mounted', () => {
-      called.push( 2 );
-    }, null, 2 );
-
-    event.on( 'mounted', () => {
-      called.push( 1 );
-    }, null, 1 );
-
-    event.emit( 'mounted' );
-
-    expect( called ).toEqual( [ 1, 2, 3 ] );
-  } );
-
-  test( 'can receive arguments.', () => {
-    const event    = EventBus();
-    const callback = jest.fn();
-
-    event.on( 'mounted', callback );
-    event.emit( 'mounted', 1, true, 'string' );
-
-    expect( callback ).toHaveBeenCalledWith( 1, true, 'string' );
-  } );
-} );

+ 34 - 117
src/js/constructors/EventInterface/EventInterface.ts

@@ -1,162 +1,79 @@
 import { EVENT_DESTROY } from '../../constants/events';
 import { Splide } from '../../core/Splide/Splide';
 import { AnyFunction, EventMap } from '../../types';
-import { apply, forEach } from '../../utils';
-import { EventBusCallback } from '../EventBus/EventBus';
+import { apply, assign, isArray, slice, toArray } from '../../utils';
+import { EventBinder, EventBinderObject } from '../EventBinder/EventBinder';
 
 
-/**
- * The type for an EventTarget or an array with EventTarget objects.
- *
- * @since 3.7.0
- */
-type EventTargets = EventTarget | EventTarget[];
-
 /**
  * The interface for the EventInterface object.
  *
  * @since 3.0.0
  */
-export interface EventInterfaceObject {
-  on<K extends keyof EventMap>( event: K, callback: EventMap[ K ], priority?: number ): void;
-  on( events: string | string[], callback: EventBusCallback, priority?: number ): void;
+export interface EventInterfaceObject extends EventBinderObject {
+  on<K extends keyof EventMap>( event: K, callback: EventMap[ K ] ): void;
+  on( events: string | string[], callback: AnyFunction ): void;
   off<K extends keyof EventMap>( events: K | K[] | string | string[] ): void;
   emit<K extends keyof EventMap>( event: K, ...args: Parameters<EventMap[ K ]> ): void
   emit( event: string, ...args: any[] ): void;
-  bind( target: EventTargets, events: string, callback: AnyFunction, options?: AddEventListenerOptions ): void
-  unbind( target: EventTarget | EventTarget[], events: string, callback?: AnyFunction ): void;
-  destroy(): void;
+
+  /** @internal */
+  bus: DocumentFragment;
 }
 
 /**
- * The function that provides interface for internal and native events.
+ * The constructor function that provides interface for internal and native events.
  *
  * @since 3.0.0
+ * @constructor
  *
  * @param Splide - A Splide instance.
- * @param manual - Optional. Whether to destroy the interface manually or not.
  *
  * @return A collection of interface functions.
  */
-export function EventInterface( Splide: Splide, manual?: boolean ): EventInterfaceObject {
+export function EventInterface( Splide?: Splide ): EventInterfaceObject {
   /**
-   * Holds the event object.
+   * The document fragment for internal events.
+   * Provide the Splide instance to share the bus.
    */
-  const { event } = Splide;
+  const bus = Splide ? Splide.event.bus : document.createDocumentFragment();
 
   /**
-   * The key for events.
+   * An event binder object.
    */
-  const key = {};
+  const binder = EventBinder();
 
   /**
-   * Stores all handlers that listen to native events.
-   */
-  let listeners: [ EventTarget, string, AnyFunction, () => void ][] = [];
-
-  /**
-   * Registers an event handler with an unique key.
-   * It can only be removed by `off()` method below.
+   * Listens to an internal event or events.
    *
    * @param events   - An event name or names separated by spaces. Use a dot(.) to add a namespace.
    * @param callback - A callback function to register.
-   * @param priority - Optional. A priority number for the order in which the callbacks are invoked.
-   *                   Lower numbers correspond with earlier execution. The default value is 10.
    */
-  function on( events: string | string[], callback: EventBusCallback, priority?: number ): void {
-    event.on( events, callback, key, priority );
-  }
-
-  /**
-   * Removes event handlers registered by `on()`.
-   *
-   * @param events - An event name or names separated by spaces. Use a dot(.) to add a namespace.
-   */
-  function off( events: string | string[] ): void {
-    event.off( events, key );
-  }
-
-  /**
-   * Listens to native events.
-   * Splide#destory() will remove all registered listeners.
-   * In IE and Safari, mediaQueryList does not inherit EventTarget,
-   * and only supports deprecated `addListener` and `removeListener`.
-   *
-   * @param targets  - A target element, the window object or the document object.
-   * @param events   - An event or events to listen to.
-   * @param callback - A callback function.
-   * @param options  - Optional. The options to pass to the `addEventListener` function.
-   */
-  function bind( targets: EventTargets, events: string, callback: AnyFunction, options?: AddEventListenerOptions ): void {
-    forEachEvent( targets, events, ( target, event ) => {
-      const isEventTarget = 'addEventListener' in target;
-      const remover = isEventTarget
-        ? target.removeEventListener.bind( target, event, callback, options )
-        : target[ 'removeListener' ].bind( target, callback );
-
-      isEventTarget ? target.addEventListener( event, callback, options ) : target[ 'addListener' ]( callback );
-      listeners.push( [ target, event, callback, remover ] );
-    } );
-  }
-
-  /**
-   * Removes the event handler.
-   *
-   * @param targets  - A target element, the window object or the document object.
-   * @param events   - An event name or names to remove.
-   * @param callback - Optional. Specify the callback to remove.
-   */
-  function unbind( targets: EventTargets, events: string, callback?: AnyFunction ): void {
-    forEachEvent( targets, events, ( target, event ) => {
-      listeners = listeners.filter( listener => {
-        if ( listener[ 0 ] === target && listener[ 1 ] === event && ( ! callback || listener[ 2 ] === callback ) ) {
-          listener[ 3 ]();
-          return false;
-        }
-
-        return true;
-      } );
+  function on( events: string | string[], callback: AnyFunction ): void {
+    binder.bind( bus, toArray( events ).join( ' ' ), e => {
+      callback.apply( callback, isArray( e.detail ) ? e.detail : [] );
     } );
   }
 
   /**
-   * Iterates over each target and event.
+   * Triggers callback functions.
+   * This accepts additional arguments and passes them to callbacks.
    *
-   * @param targets  - A target element, the window object or the document object.
-   * @param events   - An event name or names.
-   * @param iteratee - An iteratee function.
+   * @param event - An event name.
    */
-  function forEachEvent(
-    targets: EventTargets,
-    events: string,
-    iteratee: ( target: EventTarget, event: string ) => void
-  ): void {
-    forEach( targets, target => {
-      if ( target ) {
-        events.split( ' ' ).forEach( apply( iteratee, target ) );
-      }
-    } );
+  function emit( event: string ): void {
+    // eslint-disable-next-line prefer-rest-params, prefer-spread
+    binder.dispatch( bus, event, slice( arguments, 1 ) );
   }
 
-  /**
-   * Removes all listeners.
-   */
-  function destroy(): void {
-    listeners = listeners.filter( data => { data[ 3 ]() } );
-    event.offBy( key );
+  if ( Splide ) {
+    Splide.event.on( EVENT_DESTROY, binder.destroy );
   }
 
-  /**
-   * Invokes destroy when the slider is destroyed.
-   */
-  ! manual && event.on( EVENT_DESTROY, destroy, key );
-
-  return {
+  return assign( binder, {
+    bus,
     on,
-    off,
-    emit: event.emit,
-    bind,
-    unbind,
-    destroy,
-  };
-}
+    off: apply( binder.unbind, bus ),
+    emit,
+  } );
+}

+ 19 - 1
src/js/constructors/EventInterface/test/general.test.ts

@@ -3,7 +3,7 @@ import { EventInterface } from '../EventInterface';
 
 
 describe( 'EventInterface', () => {
-  const splide = init();
+  const splide = init( { speed: 0 } );
 
   test( 'can provide `on` to listen to internal events and lock listeners.', () => {
     const { on } = EventInterface( splide );
@@ -30,6 +30,24 @@ describe( 'EventInterface', () => {
     expect( callback2 ).toHaveBeenCalledTimes( 2 );
   } );
 
+  test( 'can receive arguments passed by `emit`.', () => {
+    const { on } = EventInterface( splide );
+    const callback1 = jest.fn();
+    const callback2 = jest.fn();
+
+    const array  = [ 1, 2 ];
+    const object = { a: 1, b: 2 };
+
+    on( 'myEvent1', callback1 );
+    on( 'myEvent2', callback2 );
+
+    splide.emit( 'myEvent1', 1, 2, 3 );
+    splide.emit( 'myEvent2', array, object, Infinity );
+
+    expect( callback1 ).toHaveBeenCalledWith( 1, 2, 3 );
+    expect( callback2 ).toHaveBeenCalledWith( array, object, Infinity );
+  } );
+
   test( 'can provide `off` to remove locked listeners.', () => {
     const { on, off } = EventInterface( splide );
     const callback1 = jest.fn();

+ 1 - 1
src/js/constructors/index.ts

@@ -1,4 +1,4 @@
-export * from './EventBus/EventBus';
+export * from './EventBinder/EventBinder';
 export * from './EventInterface/EventInterface';
 export * from './RequestInterval/RequestInterval';
 export * from './State/State';

+ 7 - 8
src/js/core/Splide/Splide.ts

@@ -3,13 +3,12 @@ import { SlideMatcher } from '../../components/Slides/Slides';
 import { CLASS_INITIALIZED } from '../../constants/classes';
 import { DEFAULTS } from '../../constants/defaults';
 import { EVENT_DESTROY, EVENT_MOUNTED, EVENT_READY, EVENT_REFRESH, EVENT_UPDATED } from '../../constants/events';
-import { DEFAULT_USER_EVENT_PRIORITY } from '../../constants/priority';
 import { DATA_ATTRIBUTE } from '../../constants/project';
 import { CREATED, DESTROYED, IDLE, STATES } from '../../constants/states';
 import { FADE } from '../../constants/types';
-import { EventBus, EventBusCallback, EventBusObject, State, StateObject } from '../../constructors';
+import { EventInterface, EventInterfaceObject, State, StateObject } from '../../constructors';
 import { Fade, Slide } from '../../transitions';
-import { ComponentConstructor, Components, EventMap, Options, SyncTarget } from '../../types';
+import { AnyFunction, ComponentConstructor, Components, EventMap, Options, SyncTarget } from '../../types';
 import { addClass, assert, assign, empty, forOwn, getAttribute, isString, merge, query, slice } from '../../utils';
 
 
@@ -37,7 +36,7 @@ export class Splide {
   /**
    * The EventBusObject object.
    */
-  readonly event: EventBusObject = EventBus();
+  readonly event: EventInterfaceObject = EventInterface();
 
   /**
    * The collection of all component objects.
@@ -229,9 +228,9 @@ export class Splide {
    * @return `this`
    */
   on<K extends keyof EventMap>( events: K, callback: EventMap[ K ] ): this;
-  on( events: string | string[], callback: EventBusCallback ): this;
-  on( events: string | string[], callback: EventBusCallback ): this {
-    this.event.on( events, callback, null, DEFAULT_USER_EVENT_PRIORITY );
+  on( events: string | string[], callback: AnyFunction ): this;
+  on( events: string | string[], callback: AnyFunction ): this {
+    this.event.on( events, callback );
     return this;
   }
 
@@ -344,7 +343,7 @@ export class Splide {
 
     if ( state.is( CREATED ) ) {
       // Postpones destruction requested before the slider becomes ready.
-      event.on( EVENT_READY, this.destroy.bind( this, completely ), this );
+      EventInterface( this ).on( EVENT_READY, this.destroy.bind( this, completely ) );
     } else {
       forOwn( this._Components, component => {
         component.destroy && component.destroy( completely );

+ 3 - 3
src/js/test/php/examples/add.php

@@ -25,7 +25,7 @@ $settings = get_settings();
 
 <script>
   var splide = new Splide( '#splide01', {
-    // type   : 'loop',
+    type   : 'loop',
     perPage: 3,
     gap    : '1rem',
   } );
@@ -39,11 +39,11 @@ $settings = get_settings();
     splide.add( [
       '<img src="../../assets/images/pics/slide15.jpg">',
       '<img src="../../assets/images/pics/slide16.jpg">',
-    ], 0 );
+    ] );
   } );
 
   remove.addEventListener( 'click', function() {
-    splide.remove( 0 );
+    splide.remove( splide.length - 1 );
   } );
 </script>
 

+ 32 - 32
src/js/test/php/examples/default.php

@@ -39,44 +39,44 @@ $settings = get_settings();
         // noDrag: 'button',
       } );
 
-	    // splide.on( 'move', () => {
-		  //   console.log( 'move' );
-	    // } );
-	    //
-      // splide.on( 'moved', () => {
-      //   console.log( 'moved' );
-      // } );
-	    //
-      // splide.on( 'visible', Slide => {
-      //   console.log( 'visible', Slide.index );
-      // } );
-	    //
-      // splide.on( 'hidden', Slide => {
-      //   console.log( 'hidden', Slide.index );
-      // } );
-	    //
-      // splide.on( 'click', () => {
-      //   console.log( 'click' );
-      // } );
-	    //
-      // splide.on( 'shifted', () => {
-      //   console.log( 'shifted' );
-      // } );
-	    //
-	    // splide.on( 'drag', () => {
-		  //   console.log( 'drag' );
-	    // } );
-	    //
-	    // splide.on( 'dragged', () => {
-		  //   console.log( 'dragged' );
-	    // } );
+	    splide.on( 'move', function () {
+		    console.log( 'move' );
+	    } );
+
+      splide.on( 'moved', function ( index, prev, dest ) {
+        console.log( 'moved', index, prev, dest );
+      } );
+
+      splide.on( 'visible', Slide => {
+        console.log( 'visible', Slide );
+      } );
+
+      splide.on( 'hidden', Slide => {
+        console.log( 'hidden', Slide );
+      } );
+
+      splide.on( 'click', function () {
+        console.log( 'click' );
+      } );
+
+      splide.on( 'shifted', function () {
+        console.log( 'shifted' );
+      } );
+
+	    splide.on( 'drag', function () {
+		    console.log( 'drag' );
+	    } );
+
+	    splide.on( 'dragged', function () {
+		    console.log( 'dragged' );
+	    } );
 
       splide.mount();
 
 	    const pre = document.querySelector( 'pre' );
 
 	    // Array.from( document.getElementsByTagName( 'button' ) ).forEach( button => {
-			// 	button.addEventListener( 'click', () => {
+			// 	button.addEventListener( 'click', function () {
 			// 		alert( 'click' );
 			// 	} );
 			// } );

+ 1 - 1
src/js/test/php/examples/extension.php

@@ -10,7 +10,7 @@ $settings = get_settings();
 <head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width,initial-scale=1">
-  <title>Default</title>
+  <title>Extension</title>
 
   <link rel="stylesheet" href="../../../../../dist/css/themes/splide-<?php echo $settings['theme'] ?>.min.css">
   <link rel="stylesheet" href="../../assets/css/styles.css">

+ 1 - 1
src/js/test/php/examples/json.php

@@ -10,7 +10,7 @@ $settings = get_settings();
 <head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-  <title>Default</title>
+  <title>JSON</title>
 
   <link rel="stylesheet" href="../../../../../dist/css/themes/splide-<?php echo $settings['theme'] ?>.min.css">
   <link rel="stylesheet" href="../../assets/css/styles.css">

+ 95 - 109
src/js/test/php/examples/multiple.php

@@ -19,104 +19,101 @@ $settings = get_settings();
 
   <script>
     document.addEventListener( 'DOMContentLoaded', function () {
-      new Splide( '#splide01', {
-        type             : 'slide',
-        perPage          : 1,
-        // gap              : '.5rem',
-        pagination: false,
-        // speed: 1000,
-        arrows: false,
-        classes: {
-          arrows: 'splide__arrows splide__test',
-        },
-      } ).mount();
-
-      new Splide( '#splide02', {
-        perPage          : 1,
-        gap              : '1.5rem',
-        pagination: false,
-        arrows: false,
-        classes: {
-          arrows: 'splide__arrows splide__test',
-        },
-      } ).mount();
-
-      new Splide( '#splide03', {
-        type             : 'slide',
-        perPage          : 3,
-        gap              : '1.5rem',
-        pagination: false,
-        arrows: false,
-        classes: {
-          arrows: 'splide__arrows splide__test',
-        },
-      } ).mount();
-
-      new Splide( '#splide04', {
-        type             : 'slide',
-        perPage          : 1,
-        gap              : '1.5rem',
-        pagination: false,
-        arrows: false,
-        classes: {
-          arrows: 'splide__arrows splide__test',
-        },
-      } ).mount();
-
-      new Splide( '#splide05', {
-        type             : 'slide',
-        perPage          : 2,
-        gap              : '1.5rem',
-        pagination: false,
-        arrows: false,
-        classes: {
-          arrows: 'splide__arrows splide__test',
-        },
-      } ).mount();
-
-      new Splide( '#splide06', {
-        type             : 'slide',
-        perPage          : 4,
-        gap              : '1.5rem',
-        pagination: false,
-        arrows: false,
-        classes: {
-          arrows: 'splide__arrows splide__test',
-        },
-      } ).mount();
-
-      new Splide( '#splide07', {
-        type             : 'slide',
-        perPage          : 1,
-        gap              : '1.5rem',
-        pagination: false,
-        arrows: false,
-        classes: {
-          arrows: 'splide__arrows splide__test',
-        },
-      } ).mount();
-
-      new Splide( '#splide08', {
-        type             : 'slide',
-        perPage          : 3,
-        gap              : '1.5rem',
-        pagination: false,
-        arrows: false,
-        classes: {
-          arrows: 'splide__arrows splide__test',
-        },
-      } ).mount();
-
-      new Splide( '#splide09', {
-        type             : 'slide',
-        perPage          : 3,
-        gap              : '1.5rem',
-        pagination: false,
-        arrows: false,
-        classes: {
-          arrows: 'splide__arrows splide__test',
-        },
-      } ).mount();
+	    new Splide( '#splide01', {
+		    type      : 'slide',
+		    perPage   : 2,
+		    pagination: false,
+		    classes   : {
+			    arrows: 'splide__arrows splide__test',
+		    },
+	    } ).mount();
+
+	    new Splide( '#splide02', {
+		    perPage   : 1,
+		    gap       : '1.5rem',
+		    pagination: false,
+		    arrows    : false,
+		    classes   : {
+			    arrows: 'splide__arrows splide__test',
+		    },
+	    } ).mount();
+
+	    new Splide( '#splide03', {
+		    type      : 'slide',
+		    perPage   : 3,
+		    gap       : '1.5rem',
+		    pagination: false,
+		    arrows    : false,
+		    classes   : {
+			    arrows: 'splide__arrows splide__test',
+		    },
+	    } ).mount();
+
+	    new Splide( '#splide04', {
+		    type      : 'slide',
+		    perPage   : 1,
+		    gap       : '1.5rem',
+		    pagination: false,
+		    arrows    : false,
+		    classes   : {
+			    arrows: 'splide__arrows splide__test',
+		    },
+	    } ).mount();
+
+	    new Splide( '#splide05', {
+		    type      : 'slide',
+		    perPage   : 2,
+		    gap       : '1.5rem',
+		    pagination: false,
+		    arrows    : false,
+		    classes   : {
+			    arrows: 'splide__arrows splide__test',
+		    },
+	    } ).mount();
+
+	    new Splide( '#splide06', {
+		    type      : 'slide',
+		    perPage   : 4,
+		    gap       : '1.5rem',
+		    pagination: false,
+		    arrows    : false,
+		    classes   : {
+			    arrows: 'splide__arrows splide__test',
+		    },
+	    } ).mount();
+
+	    new Splide( '#splide07', {
+		    type      : 'slide',
+		    perPage   : 1,
+		    gap       : '1.5rem',
+		    pagination: false,
+		    arrows    : false,
+		    classes   : {
+			    arrows: 'splide__arrows splide__test',
+		    },
+	    } ).mount();
+
+	    new Splide( '#splide08', {
+		    type      : 'slide',
+		    perPage   : 3,
+		    gap       : '1.5rem',
+		    pagination: false,
+		    arrows    : false,
+		    classes   : {
+			    arrows: 'splide__arrows splide__test',
+		    },
+	    } ).mount();
+
+	    new Splide( '#splide09', {
+		    type      : 'slide',
+		    perPage   : 3,
+		    gap       : '1.5rem',
+		    pagination: false,
+		    arrows    : false,
+		    classes   : {
+			    arrows: 'splide__arrows splide__test',
+		    },
+	    } ).mount();
     } );
   </script>
 
@@ -139,16 +136,5 @@ $settings = get_settings();
 <?php render( 'splide08' ); ?>
 <?php render( 'splide09' ); ?>
 
-<script>
-  Array.from( document.querySelectorAll( '.splide' ) ).forEach( elm => {
-    const splide   = new Splide( elm, { rewind: true, interval: 1000 } ).mount();
-    const Autoplay = splide.Components.Autoplay;
-    const observer = new IntersectionObserver( ( [ entry ] ) => {
-      entry.isIntersecting ? Autoplay.play() : Autoplay.pause();
-    }, { threshold: 0.8 } );
-    observer.observe( elm );
-  } );
-</script>
-
 </body>
 </html>

+ 1 - 1
src/js/test/php/examples/nest.php

@@ -20,7 +20,7 @@ $settings = get_settings();
     document.addEventListener( 'DOMContentLoaded', function () {
       var primary = new Splide( '#splide01', {
         gap : '1.5rem',
-        drag: false,
+        // drag: false,
         height: 600,
       } );
 

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels