Ver código fonte

Change the calculation way for total width and height to insert non-slide elements in a slider.

NaotoshiFujita 5 anos atrás
pai
commit
14ae6d1d49

+ 1 - 1
dist/css/splide-core.min.css

@@ -1 +1 @@
-@keyframes splide-loading{0%{transform:rotate(0)}to{transform:rotate(1turn)}}.splide__container{position:relative;box-sizing:border-box}.splide__list{display:flex;flex-wrap:wrap;margin:0!important;padding:0!important}.splide__pagination{display:inline-flex;align-items:center;width:95%;flex-wrap:wrap;justify-content:center;margin:0}.splide__pagination li{list-style-type:none;display:inline-block;line-height:1;margin:0}.splide{position:relative;visibility:hidden}.splide.is-active{visibility:visible}.splide__slide{position:relative;box-sizing:border-box;list-style-type:none!important;margin:0;outline:none}.splide__slide img{vertical-align:bottom}.splide__slider{position:relative}.splide__spinner{position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;display:inline-block;width:20px;height:20px;border-radius:50%;border:2px solid #999;border-left-color:transparent;animation:splide-loading 1s linear infinite}.splide__track{position:relative;z-index:0;overflow:hidden}.splide--draggable>.splide__track>.splide__list>.splide__slide{-webkit-user-select:none;user-select:none}.splide--fade>.splide__track>.splide__list{display:block}.splide--fade>.splide__track>.splide__list>.splide__slide{position:absolute;top:0;left:0;z-index:0;opacity:0}.splide--fade>.splide__track>.splide__list>.splide__slide.is-active{position:relative;z-index:1;opacity:1}.splide--rtl{direction:rtl}.splide--ttb>.splide__track>.splide__list{display:block}.splide--ttb>.splide__pagination{width:auto}
+@keyframes splide-loading{0%{transform:rotate(0)}to{transform:rotate(1turn)}}.splide__container{position:relative;box-sizing:border-box}.splide__list{margin:0!important;padding:0!important}.splide.is-active .splide__list{display:flex}.splide__pagination{display:inline-flex;align-items:center;width:95%;flex-wrap:wrap;justify-content:center;margin:0}.splide__pagination li{list-style-type:none;display:inline-block;line-height:1;margin:0}.splide{position:relative;visibility:hidden}.splide.is-active{visibility:visible}.splide__slide{position:relative;box-sizing:border-box;list-style-type:none!important;margin:0;outline:none;flex-shrink:0}.splide__slide img{vertical-align:bottom}.splide__slider{position:relative}.splide__spinner{position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;display:inline-block;width:20px;height:20px;border-radius:50%;border:2px solid #999;border-left-color:transparent;animation:splide-loading 1s linear infinite}.splide__track{position:relative;z-index:0;overflow:hidden}.splide--draggable>.splide__track>.splide__list>.splide__slide{-webkit-user-select:none;user-select:none}.splide--fade>.splide__track>.splide__list{display:block}.splide--fade>.splide__track>.splide__list>.splide__slide{position:absolute;top:0;left:0;z-index:0;opacity:0}.splide--fade>.splide__track>.splide__list>.splide__slide.is-active{position:relative;z-index:1;opacity:1}.splide--rtl{direction:rtl}.splide--ttb>.splide__track>.splide__list{display:block}.splide--ttb>.splide__pagination{width:auto}

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/css/splide.min.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/css/themes/splide-default.min.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/css/themes/splide-sea-green.min.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/css/themes/splide-skyblue.min.css


+ 114 - 124
dist/js/splide.esm.js

@@ -496,17 +496,29 @@ function find(elm, selector) {
  * @param {Element} parent         - A parent element.
  * @param {Element} parent         - A parent element.
  * @param {string}  tagOrClassName - A tag or class name.
  * @param {string}  tagOrClassName - A tag or class name.
  *
  *
- * @return {Element|null} - A found element on success. Null on failure.
+ * @return {Element|undefined} - A found element on success or undefined on failure.
  */
  */
 
 
 function child(parent, tagOrClassName) {
 function child(parent, tagOrClassName) {
+  return children(parent, tagOrClassName)[0];
+}
+/**
+ * Return chile elements that matches the provided tag or class name.
+ *
+ * @param {Element} parent         - A parent element.
+ * @param {string}  tagOrClassName - A tag or class name.
+ *
+ * @return {Element[]} - Found elements.
+ */
+
+function children(parent, tagOrClassName) {
   if (parent) {
   if (parent) {
     return values(parent.children).filter(function (child) {
     return values(parent.children).filter(function (child) {
       return hasClass(child, tagOrClassName.split(' ')[0]) || child.tagName === tagOrClassName;
       return hasClass(child, tagOrClassName.split(' ')[0]) || child.tagName === tagOrClassName;
-    })[0] || null;
+    });
   }
   }
 
 
-  return null;
+  return [];
 }
 }
 /**
 /**
  * Create an element with some optional attributes.
  * Create an element with some optional attributes.
@@ -682,6 +694,17 @@ function removeAttribute(elms, names) {
     });
     });
   });
   });
 }
 }
+/**
+ * Return the Rect object of the provided object.
+ *
+ * @param {Element} elm - An element.
+ *
+ * @return {ClientRect|DOMRect} - A rect object.
+ */
+
+function getRect(elm) {
+  return elm.getBoundingClientRect();
+}
 /**
 /**
  * Trigger the given callback after all images contained by the element are loaded.
  * Trigger the given callback after all images contained by the element are loaded.
  *
  *
@@ -1991,7 +2014,7 @@ var STYLE_RESTORE_EVENTS = 'update.slide';
     /**
     /**
      * Container element if available.
      * Container element if available.
      *
      *
-     * @type {Element|null}
+     * @type {Element|undefined}
      */
      */
     container: child(slide, Splide.classes.container),
     container: child(slide, Splide.classes.container),
 
 
@@ -2383,7 +2406,7 @@ var UID_NAME = 'uid';
     Elements.track = find(root, "." + classes.track);
     Elements.track = find(root, "." + classes.track);
     Elements.list = child(Elements.track, classes.list);
     Elements.list = child(Elements.track, classes.list);
     exist(Elements.track && Elements.list, 'Track or list was not found.');
     exist(Elements.track && Elements.list, 'Track or list was not found.');
-    Elements.slides = values(Elements.list.children);
+    Elements.slides = children(Elements.list, classes.slide);
     var arrows = findParts(classes.arrows);
     var arrows = findParts(classes.arrows);
     Elements.arrows = {
     Elements.arrows = {
       prev: find(arrows, "." + classes.prev),
       prev: find(arrows, "." + classes.prev),
@@ -2404,12 +2427,12 @@ var UID_NAME = 'uid';
   function getClasses() {
   function getClasses() {
     var rootClass = classes.root;
     var rootClass = classes.root;
     var options = Splide.options;
     var options = Splide.options;
-    return [rootClass + "--" + options.type, rootClass + "--" + options.direction, options.drag ? rootClass + "--draggable" : '', options.isNavigation ? rootClass + "--nav" : ''];
+    return [rootClass + "--" + options.type, rootClass + "--" + options.direction, options.drag ? rootClass + "--draggable" : '', options.isNavigation ? rootClass + "--nav" : '', STATUS_CLASSES.active];
   }
   }
   /**
   /**
    * Find parts only from children of the root or track.
    * Find parts only from children of the root or track.
    *
    *
-   * @return {Element|null} - A found element or null.
+   * @return {Element} - A found element or undefined.
    */
    */
 
 
 
 
@@ -2784,18 +2807,7 @@ var controller_floor = Math.floor;
      * @return {Object} - Calculated position.
      * @return {Object} - Calculated position.
      */
      */
     toPosition: function toPosition(index) {
     toPosition: function toPosition(index) {
-      return -((index + Components.Clones.length / 2) * (Layout.slideHeight() + Layout.gap) + this.offset());
-    },
-
-    /**
-     * Calculate the closest slide index from the given position.
-     *
-     * @return {number} - The closest slide index.
-     */
-    toIndex: function toIndex(position) {
-      var slideHeight = Layout.slideHeight();
-      var cloneOffset = (slideHeight + Layout.gap) * Components.Clones.length / 2;
-      return Math.round(-(position + cloneOffset + this.offset()) / (slideHeight + Layout.gap));
+      return -(Layout.totalHeight(index) - Layout.slideHeight() - Layout.gap + this.offset());
     },
     },
 
 
     /**
     /**
@@ -2806,7 +2818,7 @@ var controller_floor = Math.floor;
      * @return {number} - Trimmed position.
      * @return {number} - Trimmed position.
      */
      */
     trim: function trim(position) {
     trim: function trim(position) {
-      var edge = -(Layout.listHeight - (Layout.height + Layout.gap));
+      var edge = -(Layout.totalHeight() - (Layout.height + Layout.gap));
       return between(position, edge, 0);
       return between(position, edge, 0);
     },
     },
 
 
@@ -2836,7 +2848,6 @@ var controller_floor = Math.floor;
  */
  */
 
 
 
 
-
 /**
 /**
  * The resolver component for horizontal move.
  * The resolver component for horizontal move.
  *
  *
@@ -2853,13 +2864,6 @@ var controller_floor = Math.floor;
    * @type {Object}
    * @type {Object}
    */
    */
   var Layout;
   var Layout;
-  /**
-   * Hold the Elements component.
-   *
-   * @type {Object}
-   */
-
-  var Elements;
   return {
   return {
     /**
     /**
      * Axis of translate.
      * Axis of translate.
@@ -2880,45 +2884,18 @@ var controller_floor = Math.floor;
      */
      */
     init: function init() {
     init: function init() {
       Layout = Components.Layout;
       Layout = Components.Layout;
-      Elements = Components.Elements;
     },
     },
 
 
     /**
     /**
-     * Calculate position by index.
+     * Calculate the track position by a slide index.
      *
      *
      * @param {number} index - Slide index.
      * @param {number} index - Slide index.
      *
      *
      * @return {Object} - Calculated position.
      * @return {Object} - Calculated position.
      */
      */
     toPosition: function toPosition(index) {
     toPosition: function toPosition(index) {
-      return this.sign * (Layout.totalWidth(index - 1) + this.offset(index));
-    },
-
-    /**
-     * Calculate the closest slide index from the given position.
-     *
-     * @return {number} - The closest slide position.
-     */
-    toIndex: function toIndex(position) {
-      position *= this.sign;
-
-      if (Splide.is(SLIDE)) {
-        position = between(position, Layout.totalWidth(Elements.total), 0);
-      }
-
-      var Slides = Elements.getSlides(true);
-
-      for (var i in Slides) {
-        var Slide = Slides[i];
-        var slideIndex = Slide.index;
-        var slidePosition = this.sign * this.toPosition(slideIndex);
-
-        if (slidePosition < position && position <= slidePosition + Layout.slideWidth(slideIndex) + Layout.gap) {
-          return slideIndex;
-        }
-      }
-
-      return 0;
+      var slidePosition = Layout.totalWidth(index) - Layout.slideWidth(index) - Layout.gap;
+      return this.sign * (slidePosition + this.offset(index));
     },
     },
 
 
     /**
     /**
@@ -2929,7 +2906,7 @@ var controller_floor = Math.floor;
      * @return {number} - Trimmed position.
      * @return {number} - Trimmed position.
      */
      */
     trim: function trim(position) {
     trim: function trim(position) {
-      var edge = this.sign * (Layout.totalWidth(Elements.total) - (Layout.width + Layout.gap));
+      var edge = this.sign * (Layout.totalWidth() - (Layout.width + Layout.gap));
       return between(position, edge, 0);
       return between(position, edge, 0);
     },
     },
 
 
@@ -3095,6 +3072,30 @@ var controller_floor = Math.floor;
       return this._s.trim(position);
       return this._s.trim(position);
     },
     },
 
 
+    /**
+     * Calculate the closest slide index from the given position.
+     *
+     * @param {number} position - A position converted to an slide index.
+     *
+     * @return {number} - The closest slide index.
+     */
+    toIndex: function toIndex(position) {
+      var _this2 = this;
+
+      var index = 0;
+      var minDistance = Infinity;
+      Components.Elements.getSlides(true).forEach(function (Slide) {
+        var slideIndex = Slide.index;
+        var distance = Math.abs(_this2.toPosition(slideIndex) - position);
+
+        if (distance < minDistance) {
+          minDistance = distance;
+          index = slideIndex;
+        }
+      });
+      return index;
+    },
+
     /**
     /**
      * Return coordinates object by the given position.
      * Return coordinates object by the given position.
      *
      *
@@ -3346,13 +3347,6 @@ var controller_floor = Math.floor;
 
 
 
 
 
 
-/**
- * Max width of a slide.
- *
- * @type {number}
- */
-
-var SLIDE_MAX_WIDTH = 5000;
 /**
 /**
  * The resolver component for horizontal layout.
  * The resolver component for horizontal layout.
  *
  *
@@ -3405,13 +3399,6 @@ var SLIDE_MAX_WIDTH = 5000;
      */
      */
     height: 0,
     height: 0,
 
 
-    /**
-     * Always 0 because the height will be determined by inner contents.
-     *
-     * @type {number}
-     */
-    listHeight: 0,
-
     /**
     /**
      * Initialization.
      * Initialization.
      */
      */
@@ -3435,20 +3422,34 @@ var SLIDE_MAX_WIDTH = 5000;
     },
     },
 
 
     /**
     /**
-     * Accumulate slide width including the gap to the designated index.
+     * Return total width from the left of the list to the right of the slide specified by the provided index.
      *
      *
-     * @param {number|undefined} index - If undefined, width of all slides will be accumulated.
+     * @param {number} index - Optional. A slide index. If undefined, total width of the slider will be returned.
      *
      *
-     * @return {number} - Accumulated width.
+     * @return {number} - Total width to the right side of the specified slide, or 0 for an invalid index.
      */
      */
     totalWidth: function totalWidth(index) {
     totalWidth: function totalWidth(index) {
-      var _this = this;
+      if (index === void 0) {
+        index = Splide.length - 1;
+      }
+
+      var Slide = Elements.getSlide(index);
+      var width = 0;
+
+      if (Slide) {
+        var slideRect = getRect(Slide.slide);
+        var listRect = getRect(Elements.list);
+
+        if (options.direction === RTL) {
+          width = listRect.right - slideRect.left;
+        } else {
+          width = slideRect.right - listRect.left;
+        }
 
 
-      return Elements.getSlides(true).filter(function (Slide) {
-        return Slide.index <= index;
-      }).reduce(function (accumulator, Slide) {
-        return accumulator + _this.slideWidth(Slide.index) + _this.gap;
-      }, 0);
+        width += this.gap;
+      }
+
+      return width;
     },
     },
 
 
     /**
     /**
@@ -3485,16 +3486,6 @@ var SLIDE_MAX_WIDTH = 5000;
      */
      */
     get width() {
     get width() {
       return track.clientWidth - this.padding.left - this.padding.right;
       return track.clientWidth - this.padding.left - this.padding.right;
-    },
-
-    /**
-     * Return list width.
-     *
-     * @return {number} - Current list width.
-     */
-    get listWidth() {
-      var total = Elements.total;
-      return options.autoWidth ? total * SLIDE_MAX_WIDTH : this.totalWidth(total);
     }
     }
 
 
   };
   };
@@ -3576,6 +3567,27 @@ var SLIDE_MAX_WIDTH = 5000;
       });
       });
     },
     },
 
 
+    /**
+     * Return total height from the top of the list to the bottom of the slide specified by the provided index.
+     *
+     * @param {number} index - Optional. A slide index. If undefined, total height of the slider will be returned.
+     *
+     * @return {number} - Total height to the bottom of the specified slide, or 0 for an invalid index.
+     */
+    totalHeight: function totalHeight(index) {
+      if (index === void 0) {
+        index = Splide.length - 1;
+      }
+
+      var Slide = Elements.getSlide(index);
+
+      if (Slide) {
+        return getRect(Slide.slide).bottom - getRect(Elements.list).top + this.gap;
+      }
+
+      return 0;
+    },
+
     /**
     /**
      * Return the slide width in px.
      * Return the slide width in px.
      *
      *
@@ -3613,24 +3625,6 @@ var SLIDE_MAX_WIDTH = 5000;
       var height = options.height || this.width * options.heightRatio;
       var height = options.height || this.width * options.heightRatio;
       exist(height, '"height" or "heightRatio" is missing.');
       exist(height, '"height" or "heightRatio" is missing.');
       return toPixel(root, height) - this.padding.top - this.padding.bottom;
       return toPixel(root, height) - this.padding.top - this.padding.bottom;
-    },
-
-    /**
-     * Return list width.
-     *
-     * @return {number} - Current list width.
-     */
-    get listWidth() {
-      return this.width;
-    },
-
-    /**
-     * Return list height.
-     *
-     * @return {number} - Current list height.
-     */
-    get listHeight() {
-      return (this.slideHeight() + this.gap) * Elements.total;
     }
     }
 
 
   };
   };
@@ -3811,15 +3805,10 @@ function createInterval(callback, interval, progress) {
 
 
 
 
   function resize() {
   function resize() {
-    applyStyle(Elements.list, {
-      width: unit(Layout.listWidth),
-      height: unit(Layout.listHeight)
-    });
     applyStyle(Elements.track, {
     applyStyle(Elements.track, {
       height: unit(Layout.height)
       height: unit(Layout.height)
     });
     });
     var slideHeight = unit(Layout.slideHeight());
     var slideHeight = unit(Layout.slideHeight());
-    var width = Layout.width;
     Elements.each(function (Slide) {
     Elements.each(function (Slide) {
       applyStyle(Slide.container, {
       applyStyle(Slide.container, {
         height: slideHeight
         height: slideHeight
@@ -3828,11 +3817,7 @@ function createInterval(callback, interval, progress) {
         width: Splide.options.autoWidth ? null : unit(Layout.slideWidth(Slide.index)),
         width: Splide.options.autoWidth ? null : unit(Layout.slideWidth(Slide.index)),
         height: Slide.container ? null : slideHeight
         height: Slide.container ? null : slideHeight
       });
       });
-    }); // When the scrollbar is made hidden, the track width is changed but the resize event is not fired.
-
-    if (width !== Layout.width) {
-      resize();
-    }
+    });
   }
   }
 
 
   return Layout;
   return Layout;
@@ -3850,6 +3835,12 @@ function createInterval(callback, interval, progress) {
 
 
 
 
 var abs = Math.abs;
 var abs = Math.abs;
+/**
+ * If the absolute velocity is greater thant this value,
+ * a slider always goes to a different slide after drag, not allowed to stay on a current slide.
+ */
+
+var MIN_VELOCITY = 0.1;
 /**
 /**
  * Adjust how much the track can be pulled on the first or last page.
  * Adjust how much the track can be pulled on the first or last page.
  * The larger number this is, the farther the track moves.
  * The larger number this is, the farther the track moves.
@@ -4086,7 +4077,6 @@ var FRICTION_REDUCER = 7;
       var options = Splide.options;
       var options = Splide.options;
       var index = Splide.index;
       var index = Splide.index;
       var sign = velocity < 0 ? -1 : 1;
       var sign = velocity < 0 ? -1 : 1;
-      var adjacent = index + sign * Track.sign;
       var destIndex = index;
       var destIndex = index;
 
 
       if (!Splide.is(FADE)) {
       if (!Splide.is(FADE)) {
@@ -4099,13 +4089,13 @@ var FRICTION_REDUCER = 7;
         destIndex = Track.toIndex(destination);
         destIndex = Track.toIndex(destination);
       }
       }
       /*
       /*
-       * Do not allow the track to go to a previous position.
+       * Do not allow the track to go to a previous position if there is enough velocity.
        * Always use the adjacent index for the fade mode.
        * Always use the adjacent index for the fade mode.
        */
        */
 
 
 
 
-      if (destIndex === index) {
-        destIndex = adjacent;
+      if (destIndex === index && absV > MIN_VELOCITY) {
+        destIndex = index + sign * Track.sign;
       }
       }
 
 
       if (Splide.is(SLIDE)) {
       if (Splide.is(SLIDE)) {

+ 114 - 124
dist/js/splide.js

@@ -486,17 +486,29 @@ function find(elm, selector) {
  * @param {Element} parent         - A parent element.
  * @param {Element} parent         - A parent element.
  * @param {string}  tagOrClassName - A tag or class name.
  * @param {string}  tagOrClassName - A tag or class name.
  *
  *
- * @return {Element|null} - A found element on success. Null on failure.
+ * @return {Element|undefined} - A found element on success or undefined on failure.
  */
  */
 
 
 function child(parent, tagOrClassName) {
 function child(parent, tagOrClassName) {
+  return children(parent, tagOrClassName)[0];
+}
+/**
+ * Return chile elements that matches the provided tag or class name.
+ *
+ * @param {Element} parent         - A parent element.
+ * @param {string}  tagOrClassName - A tag or class name.
+ *
+ * @return {Element[]} - Found elements.
+ */
+
+function children(parent, tagOrClassName) {
   if (parent) {
   if (parent) {
     return values(parent.children).filter(function (child) {
     return values(parent.children).filter(function (child) {
       return hasClass(child, tagOrClassName.split(' ')[0]) || child.tagName === tagOrClassName;
       return hasClass(child, tagOrClassName.split(' ')[0]) || child.tagName === tagOrClassName;
-    })[0] || null;
+    });
   }
   }
 
 
-  return null;
+  return [];
 }
 }
 /**
 /**
  * Create an element with some optional attributes.
  * Create an element with some optional attributes.
@@ -672,6 +684,17 @@ function removeAttribute(elms, names) {
     });
     });
   });
   });
 }
 }
+/**
+ * Return the Rect object of the provided object.
+ *
+ * @param {Element} elm - An element.
+ *
+ * @return {ClientRect|DOMRect} - A rect object.
+ */
+
+function getRect(elm) {
+  return elm.getBoundingClientRect();
+}
 /**
 /**
  * Trigger the given callback after all images contained by the element are loaded.
  * Trigger the given callback after all images contained by the element are loaded.
  *
  *
@@ -1981,7 +2004,7 @@ var STYLE_RESTORE_EVENTS = 'update.slide';
     /**
     /**
      * Container element if available.
      * Container element if available.
      *
      *
-     * @type {Element|null}
+     * @type {Element|undefined}
      */
      */
     container: child(slide, Splide.classes.container),
     container: child(slide, Splide.classes.container),
 
 
@@ -2373,7 +2396,7 @@ var UID_NAME = 'uid';
     Elements.track = find(root, "." + classes.track);
     Elements.track = find(root, "." + classes.track);
     Elements.list = child(Elements.track, classes.list);
     Elements.list = child(Elements.track, classes.list);
     exist(Elements.track && Elements.list, 'Track or list was not found.');
     exist(Elements.track && Elements.list, 'Track or list was not found.');
-    Elements.slides = values(Elements.list.children);
+    Elements.slides = children(Elements.list, classes.slide);
     var arrows = findParts(classes.arrows);
     var arrows = findParts(classes.arrows);
     Elements.arrows = {
     Elements.arrows = {
       prev: find(arrows, "." + classes.prev),
       prev: find(arrows, "." + classes.prev),
@@ -2394,12 +2417,12 @@ var UID_NAME = 'uid';
   function getClasses() {
   function getClasses() {
     var rootClass = classes.root;
     var rootClass = classes.root;
     var options = Splide.options;
     var options = Splide.options;
-    return [rootClass + "--" + options.type, rootClass + "--" + options.direction, options.drag ? rootClass + "--draggable" : '', options.isNavigation ? rootClass + "--nav" : ''];
+    return [rootClass + "--" + options.type, rootClass + "--" + options.direction, options.drag ? rootClass + "--draggable" : '', options.isNavigation ? rootClass + "--nav" : '', STATUS_CLASSES.active];
   }
   }
   /**
   /**
    * Find parts only from children of the root or track.
    * Find parts only from children of the root or track.
    *
    *
-   * @return {Element|null} - A found element or null.
+   * @return {Element} - A found element or undefined.
    */
    */
 
 
 
 
@@ -2774,18 +2797,7 @@ var controller_floor = Math.floor;
      * @return {Object} - Calculated position.
      * @return {Object} - Calculated position.
      */
      */
     toPosition: function toPosition(index) {
     toPosition: function toPosition(index) {
-      return -((index + Components.Clones.length / 2) * (Layout.slideHeight() + Layout.gap) + this.offset());
-    },
-
-    /**
-     * Calculate the closest slide index from the given position.
-     *
-     * @return {number} - The closest slide index.
-     */
-    toIndex: function toIndex(position) {
-      var slideHeight = Layout.slideHeight();
-      var cloneOffset = (slideHeight + Layout.gap) * Components.Clones.length / 2;
-      return Math.round(-(position + cloneOffset + this.offset()) / (slideHeight + Layout.gap));
+      return -(Layout.totalHeight(index) - Layout.slideHeight() - Layout.gap + this.offset());
     },
     },
 
 
     /**
     /**
@@ -2796,7 +2808,7 @@ var controller_floor = Math.floor;
      * @return {number} - Trimmed position.
      * @return {number} - Trimmed position.
      */
      */
     trim: function trim(position) {
     trim: function trim(position) {
-      var edge = -(Layout.listHeight - (Layout.height + Layout.gap));
+      var edge = -(Layout.totalHeight() - (Layout.height + Layout.gap));
       return between(position, edge, 0);
       return between(position, edge, 0);
     },
     },
 
 
@@ -2826,7 +2838,6 @@ var controller_floor = Math.floor;
  */
  */
 
 
 
 
-
 /**
 /**
  * The resolver component for horizontal move.
  * The resolver component for horizontal move.
  *
  *
@@ -2843,13 +2854,6 @@ var controller_floor = Math.floor;
    * @type {Object}
    * @type {Object}
    */
    */
   var Layout;
   var Layout;
-  /**
-   * Hold the Elements component.
-   *
-   * @type {Object}
-   */
-
-  var Elements;
   return {
   return {
     /**
     /**
      * Axis of translate.
      * Axis of translate.
@@ -2870,45 +2874,18 @@ var controller_floor = Math.floor;
      */
      */
     init: function init() {
     init: function init() {
       Layout = Components.Layout;
       Layout = Components.Layout;
-      Elements = Components.Elements;
     },
     },
 
 
     /**
     /**
-     * Calculate position by index.
+     * Calculate the track position by a slide index.
      *
      *
      * @param {number} index - Slide index.
      * @param {number} index - Slide index.
      *
      *
      * @return {Object} - Calculated position.
      * @return {Object} - Calculated position.
      */
      */
     toPosition: function toPosition(index) {
     toPosition: function toPosition(index) {
-      return this.sign * (Layout.totalWidth(index - 1) + this.offset(index));
-    },
-
-    /**
-     * Calculate the closest slide index from the given position.
-     *
-     * @return {number} - The closest slide position.
-     */
-    toIndex: function toIndex(position) {
-      position *= this.sign;
-
-      if (Splide.is(SLIDE)) {
-        position = between(position, Layout.totalWidth(Elements.total), 0);
-      }
-
-      var Slides = Elements.getSlides(true);
-
-      for (var i in Slides) {
-        var Slide = Slides[i];
-        var slideIndex = Slide.index;
-        var slidePosition = this.sign * this.toPosition(slideIndex);
-
-        if (slidePosition < position && position <= slidePosition + Layout.slideWidth(slideIndex) + Layout.gap) {
-          return slideIndex;
-        }
-      }
-
-      return 0;
+      var slidePosition = Layout.totalWidth(index) - Layout.slideWidth(index) - Layout.gap;
+      return this.sign * (slidePosition + this.offset(index));
     },
     },
 
 
     /**
     /**
@@ -2919,7 +2896,7 @@ var controller_floor = Math.floor;
      * @return {number} - Trimmed position.
      * @return {number} - Trimmed position.
      */
      */
     trim: function trim(position) {
     trim: function trim(position) {
-      var edge = this.sign * (Layout.totalWidth(Elements.total) - (Layout.width + Layout.gap));
+      var edge = this.sign * (Layout.totalWidth() - (Layout.width + Layout.gap));
       return between(position, edge, 0);
       return between(position, edge, 0);
     },
     },
 
 
@@ -3085,6 +3062,30 @@ var controller_floor = Math.floor;
       return this._s.trim(position);
       return this._s.trim(position);
     },
     },
 
 
+    /**
+     * Calculate the closest slide index from the given position.
+     *
+     * @param {number} position - A position converted to an slide index.
+     *
+     * @return {number} - The closest slide index.
+     */
+    toIndex: function toIndex(position) {
+      var _this2 = this;
+
+      var index = 0;
+      var minDistance = Infinity;
+      Components.Elements.getSlides(true).forEach(function (Slide) {
+        var slideIndex = Slide.index;
+        var distance = Math.abs(_this2.toPosition(slideIndex) - position);
+
+        if (distance < minDistance) {
+          minDistance = distance;
+          index = slideIndex;
+        }
+      });
+      return index;
+    },
+
     /**
     /**
      * Return coordinates object by the given position.
      * Return coordinates object by the given position.
      *
      *
@@ -3336,13 +3337,6 @@ var controller_floor = Math.floor;
 
 
 
 
 
 
-/**
- * Max width of a slide.
- *
- * @type {number}
- */
-
-var SLIDE_MAX_WIDTH = 5000;
 /**
 /**
  * The resolver component for horizontal layout.
  * The resolver component for horizontal layout.
  *
  *
@@ -3395,13 +3389,6 @@ var SLIDE_MAX_WIDTH = 5000;
      */
      */
     height: 0,
     height: 0,
 
 
-    /**
-     * Always 0 because the height will be determined by inner contents.
-     *
-     * @type {number}
-     */
-    listHeight: 0,
-
     /**
     /**
      * Initialization.
      * Initialization.
      */
      */
@@ -3425,20 +3412,34 @@ var SLIDE_MAX_WIDTH = 5000;
     },
     },
 
 
     /**
     /**
-     * Accumulate slide width including the gap to the designated index.
+     * Return total width from the left of the list to the right of the slide specified by the provided index.
      *
      *
-     * @param {number|undefined} index - If undefined, width of all slides will be accumulated.
+     * @param {number} index - Optional. A slide index. If undefined, total width of the slider will be returned.
      *
      *
-     * @return {number} - Accumulated width.
+     * @return {number} - Total width to the right side of the specified slide, or 0 for an invalid index.
      */
      */
     totalWidth: function totalWidth(index) {
     totalWidth: function totalWidth(index) {
-      var _this = this;
+      if (index === void 0) {
+        index = Splide.length - 1;
+      }
+
+      var Slide = Elements.getSlide(index);
+      var width = 0;
+
+      if (Slide) {
+        var slideRect = getRect(Slide.slide);
+        var listRect = getRect(Elements.list);
+
+        if (options.direction === RTL) {
+          width = listRect.right - slideRect.left;
+        } else {
+          width = slideRect.right - listRect.left;
+        }
 
 
-      return Elements.getSlides(true).filter(function (Slide) {
-        return Slide.index <= index;
-      }).reduce(function (accumulator, Slide) {
-        return accumulator + _this.slideWidth(Slide.index) + _this.gap;
-      }, 0);
+        width += this.gap;
+      }
+
+      return width;
     },
     },
 
 
     /**
     /**
@@ -3475,16 +3476,6 @@ var SLIDE_MAX_WIDTH = 5000;
      */
      */
     get width() {
     get width() {
       return track.clientWidth - this.padding.left - this.padding.right;
       return track.clientWidth - this.padding.left - this.padding.right;
-    },
-
-    /**
-     * Return list width.
-     *
-     * @return {number} - Current list width.
-     */
-    get listWidth() {
-      var total = Elements.total;
-      return options.autoWidth ? total * SLIDE_MAX_WIDTH : this.totalWidth(total);
     }
     }
 
 
   };
   };
@@ -3566,6 +3557,27 @@ var SLIDE_MAX_WIDTH = 5000;
       });
       });
     },
     },
 
 
+    /**
+     * Return total height from the top of the list to the bottom of the slide specified by the provided index.
+     *
+     * @param {number} index - Optional. A slide index. If undefined, total height of the slider will be returned.
+     *
+     * @return {number} - Total height to the bottom of the specified slide, or 0 for an invalid index.
+     */
+    totalHeight: function totalHeight(index) {
+      if (index === void 0) {
+        index = Splide.length - 1;
+      }
+
+      var Slide = Elements.getSlide(index);
+
+      if (Slide) {
+        return getRect(Slide.slide).bottom - getRect(Elements.list).top + this.gap;
+      }
+
+      return 0;
+    },
+
     /**
     /**
      * Return the slide width in px.
      * Return the slide width in px.
      *
      *
@@ -3603,24 +3615,6 @@ var SLIDE_MAX_WIDTH = 5000;
       var height = options.height || this.width * options.heightRatio;
       var height = options.height || this.width * options.heightRatio;
       exist(height, '"height" or "heightRatio" is missing.');
       exist(height, '"height" or "heightRatio" is missing.');
       return toPixel(root, height) - this.padding.top - this.padding.bottom;
       return toPixel(root, height) - this.padding.top - this.padding.bottom;
-    },
-
-    /**
-     * Return list width.
-     *
-     * @return {number} - Current list width.
-     */
-    get listWidth() {
-      return this.width;
-    },
-
-    /**
-     * Return list height.
-     *
-     * @return {number} - Current list height.
-     */
-    get listHeight() {
-      return (this.slideHeight() + this.gap) * Elements.total;
     }
     }
 
 
   };
   };
@@ -3801,15 +3795,10 @@ function createInterval(callback, interval, progress) {
 
 
 
 
   function resize() {
   function resize() {
-    applyStyle(Elements.list, {
-      width: unit(Layout.listWidth),
-      height: unit(Layout.listHeight)
-    });
     applyStyle(Elements.track, {
     applyStyle(Elements.track, {
       height: unit(Layout.height)
       height: unit(Layout.height)
     });
     });
     var slideHeight = unit(Layout.slideHeight());
     var slideHeight = unit(Layout.slideHeight());
-    var width = Layout.width;
     Elements.each(function (Slide) {
     Elements.each(function (Slide) {
       applyStyle(Slide.container, {
       applyStyle(Slide.container, {
         height: slideHeight
         height: slideHeight
@@ -3818,11 +3807,7 @@ function createInterval(callback, interval, progress) {
         width: Splide.options.autoWidth ? null : unit(Layout.slideWidth(Slide.index)),
         width: Splide.options.autoWidth ? null : unit(Layout.slideWidth(Slide.index)),
         height: Slide.container ? null : slideHeight
         height: Slide.container ? null : slideHeight
       });
       });
-    }); // When the scrollbar is made hidden, the track width is changed but the resize event is not fired.
-
-    if (width !== Layout.width) {
-      resize();
-    }
+    });
   }
   }
 
 
   return Layout;
   return Layout;
@@ -3840,6 +3825,12 @@ function createInterval(callback, interval, progress) {
 
 
 
 
 var abs = Math.abs;
 var abs = Math.abs;
+/**
+ * If the absolute velocity is greater thant this value,
+ * a slider always goes to a different slide after drag, not allowed to stay on a current slide.
+ */
+
+var MIN_VELOCITY = 0.1;
 /**
 /**
  * Adjust how much the track can be pulled on the first or last page.
  * Adjust how much the track can be pulled on the first or last page.
  * The larger number this is, the farther the track moves.
  * The larger number this is, the farther the track moves.
@@ -4076,7 +4067,6 @@ var FRICTION_REDUCER = 7;
       var options = Splide.options;
       var options = Splide.options;
       var index = Splide.index;
       var index = Splide.index;
       var sign = velocity < 0 ? -1 : 1;
       var sign = velocity < 0 ? -1 : 1;
-      var adjacent = index + sign * Track.sign;
       var destIndex = index;
       var destIndex = index;
 
 
       if (!Splide.is(FADE)) {
       if (!Splide.is(FADE)) {
@@ -4089,13 +4079,13 @@ var FRICTION_REDUCER = 7;
         destIndex = Track.toIndex(destination);
         destIndex = Track.toIndex(destination);
       }
       }
       /*
       /*
-       * Do not allow the track to go to a previous position.
+       * Do not allow the track to go to a previous position if there is enough velocity.
        * Always use the adjacent index for the fade mode.
        * Always use the adjacent index for the fade mode.
        */
        */
 
 
 
 
-      if (destIndex === index) {
-        destIndex = adjacent;
+      if (destIndex === index && absV > MIN_VELOCITY) {
+        destIndex = index + sign * Track.sign;
       }
       }
 
 
       if (Splide.is(SLIDE)) {
       if (Splide.is(SLIDE)) {

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/js/splide.min.js


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


+ 1 - 1
package.json

@@ -50,7 +50,7 @@
   "scripts": {
   "scripts": {
     "build:js": "gulp build:js",
     "build:js": "gulp build:js",
     "build:sass": "gulp build:sass",
     "build:sass": "gulp build:sass",
-    "test": "jest",
+    "test": "jest --clearCache && jest",
     "lint": "gulp lint"
     "lint": "gulp lint"
   }
   }
 }
 }

+ 5 - 3
src/js/components/elements/index.js

@@ -11,6 +11,7 @@ import {
 	addClass,
 	addClass,
 	removeClass,
 	removeClass,
 	child,
 	child,
+	children,
 	remove,
 	remove,
 	append,
 	append,
 	before,
 	before,
@@ -19,8 +20,8 @@ import {
 	loaded,
 	loaded,
 } from '../../utils/dom';
 } from '../../utils/dom';
 import { exist } from '../../utils/error';
 import { exist } from '../../utils/error';
-import { values } from '../../utils/object';
 import { pad } from "../../utils/utils";
 import { pad } from "../../utils/utils";
+import { STATUS_CLASSES } from "../../constants/classes";
 
 
 
 
 /**
 /**
@@ -244,7 +245,7 @@ export default ( Splide, Components ) => {
 
 
 		exist( Elements.track && Elements.list, 'Track or list was not found.' );
 		exist( Elements.track && Elements.list, 'Track or list was not found.' );
 
 
-		Elements.slides = values( Elements.list.children );
+		Elements.slides = children( Elements.list, classes.slide );
 
 
 		const arrows = findParts( classes.arrows );
 		const arrows = findParts( classes.arrows );
 		Elements.arrows = {
 		Elements.arrows = {
@@ -273,13 +274,14 @@ export default ( Splide, Components ) => {
 			`${ rootClass }--${ options.direction }`,
 			`${ rootClass }--${ options.direction }`,
 			options.drag ? `${ rootClass }--draggable` : '',
 			options.drag ? `${ rootClass }--draggable` : '',
 			options.isNavigation ? `${ rootClass }--nav` : '',
 			options.isNavigation ? `${ rootClass }--nav` : '',
+			STATUS_CLASSES.active,
 		];
 		];
 	}
 	}
 
 
 	/**
 	/**
 	 * Find parts only from children of the root or track.
 	 * Find parts only from children of the root or track.
 	 *
 	 *
-	 * @return {Element|null} - A found element or null.
+	 * @return {Element} - A found element or undefined.
 	 */
 	 */
 	function findParts( className ) {
 	function findParts( className ) {
 		return child( root, className ) || child( Elements.slider, className );
 		return child( root, className ) || child( Elements.slider, className );

+ 1 - 1
src/js/components/elements/slide.js

@@ -77,7 +77,7 @@ export default ( Splide, index, realIndex, slide ) => {
 		/**
 		/**
 		 * Container element if available.
 		 * Container element if available.
 		 *
 		 *
-		 * @type {Element|null}
+		 * @type {Element|undefined}
 		 */
 		 */
 		container: child( slide, Splide.classes.container ),
 		container: child( slide, Splide.classes.container ),
 
 

+ 23 - 34
src/js/components/layout/directions/horizontal.js

@@ -5,17 +5,10 @@
  * @copyright Naotoshi Fujita. All rights reserved.
  * @copyright Naotoshi Fujita. All rights reserved.
  */
  */
 
 
-import { applyStyle } from "../../../utils/dom";
+import { applyStyle, getRect } from "../../../utils/dom";
 import { unit, toPixel } from "../../../utils/utils";
 import { unit, toPixel } from "../../../utils/utils";
 import { RTL } from '../../../constants/directions';
 import { RTL } from '../../../constants/directions';
 
 
-/**
- * Max width of a slide.
- *
- * @type {number}
- */
-const SLIDE_MAX_WIDTH = 5000;
-
 
 
 /**
 /**
  * The resolver component for horizontal layout.
  * The resolver component for horizontal layout.
@@ -69,13 +62,6 @@ export default ( Splide, Components ) => {
 		 */
 		 */
 		height: 0,
 		height: 0,
 
 
-		/**
-		 * Always 0 because the height will be determined by inner contents.
-		 *
-		 * @type {number}
-		 */
-		listHeight: 0,
-
 		/**
 		/**
 		 * Initialization.
 		 * Initialization.
 		 */
 		 */
@@ -100,18 +86,31 @@ export default ( Splide, Components ) => {
 		},
 		},
 
 
 		/**
 		/**
-		 * Accumulate slide width including the gap to the designated index.
+		 * Return total width from the left of the list to the right of the slide specified by the provided index.
 		 *
 		 *
-		 * @param {number|undefined} index - If undefined, width of all slides will be accumulated.
+		 * @param {number} index - Optional. A slide index. If undefined, total width of the slider will be returned.
 		 *
 		 *
-		 * @return {number} - Accumulated width.
+		 * @return {number} - Total width to the right side of the specified slide, or 0 for an invalid index.
 		 */
 		 */
-		totalWidth( index ) {
-			return Elements.getSlides( true )
-				.filter( Slide => Slide.index <= index )
-				.reduce( ( accumulator, Slide ) => {
-					return accumulator + this.slideWidth( Slide.index ) + this.gap;
-				}, 0 );
+		totalWidth( index = Splide.length - 1 ) {
+			const Slide = Elements.getSlide( index );
+
+			let width = 0;
+
+			if ( Slide ) {
+				const slideRect = getRect( Slide.slide );
+				const listRect  = getRect( Elements.list );
+
+				if ( options.direction === RTL ) {
+					width = listRect.right - slideRect.left;
+				} else {
+					width = slideRect.right - listRect.left;
+				}
+
+				width += this.gap;
+			}
+
+			return width;
 		},
 		},
 
 
 		/**
 		/**
@@ -149,15 +148,5 @@ export default ( Splide, Components ) => {
 		get width() {
 		get width() {
 			return track.clientWidth - this.padding.left - this.padding.right;
 			return track.clientWidth - this.padding.left - this.padding.right;
 		},
 		},
-
-		/**
-		 * Return list width.
-		 *
-		 * @return {number} - Current list width.
-		 */
-		get listWidth() {
-			const total = Elements.total;
-			return options.autoWidth ? total * SLIDE_MAX_WIDTH : this.totalWidth( total );
-		},
 	}
 	}
 }
 }

+ 18 - 19
src/js/components/layout/directions/vertical.js

@@ -5,7 +5,7 @@
  * @copyright Naotoshi Fujita. All rights reserved.
  * @copyright Naotoshi Fujita. All rights reserved.
  */
  */
 
 
-import { applyStyle } from "../../../utils/dom";
+import { applyStyle, getRect } from "../../../utils/dom";
 import { toPixel, unit } from "../../../utils/utils";
 import { toPixel, unit } from "../../../utils/utils";
 import { exist } from "../../../utils/error";
 import { exist } from "../../../utils/error";
 
 
@@ -78,6 +78,23 @@ export default ( Splide, Components ) => {
 			} );
 			} );
 		},
 		},
 
 
+		/**
+		 * Return total height from the top of the list to the bottom of the slide specified by the provided index.
+		 *
+		 * @param {number} index - Optional. A slide index. If undefined, total height of the slider will be returned.
+		 *
+		 * @return {number} - Total height to the bottom of the specified slide, or 0 for an invalid index.
+		 */
+		totalHeight( index = Splide.length - 1 ) {
+			const Slide = Elements.getSlide( index );
+
+			if ( Slide ) {
+				return getRect( Slide.slide ).bottom - getRect( Elements.list ).top + this.gap;
+			}
+
+			return 0;
+		},
+
 		/**
 		/**
 		 * Return the slide width in px.
 		 * Return the slide width in px.
 		 *
 		 *
@@ -116,23 +133,5 @@ export default ( Splide, Components ) => {
 			exist( height, '"height" or "heightRatio" is missing.' );
 			exist( height, '"height" or "heightRatio" is missing.' );
 			return toPixel( root, height ) - this.padding.top - this.padding.bottom;
 			return toPixel( root, height ) - this.padding.top - this.padding.bottom;
 		},
 		},
-
-		/**
-		 * Return list width.
-		 *
-		 * @return {number} - Current list width.
-		 */
-		get listWidth() {
-			return this.width;
-		},
-
-		/**
-		 * Return list height.
-		 *
-		 * @return {number} - Current list height.
-		 */
-		get listHeight() {
-			return ( this.slideHeight() + this.gap ) * Elements.total;
-		},
 	}
 	}
 }
 }

+ 0 - 7
src/js/components/layout/index.js

@@ -80,11 +80,9 @@ export default ( Splide, Components ) => {
 	 * Resize the list and slides including clones.
 	 * Resize the list and slides including clones.
 	 */
 	 */
 	function resize() {
 	function resize() {
-		applyStyle( Elements.list, { width: unit( Layout.listWidth ), height: unit( Layout.listHeight ) } );
 		applyStyle( Elements.track, { height: unit( Layout.height ) } );
 		applyStyle( Elements.track, { height: unit( Layout.height ) } );
 
 
 		const slideHeight = unit( Layout.slideHeight() );
 		const slideHeight = unit( Layout.slideHeight() );
-		const width       = Layout.width;
 
 
 		Elements.each( Slide => {
 		Elements.each( Slide => {
 			applyStyle( Slide.container, { height: slideHeight } );
 			applyStyle( Slide.container, { height: slideHeight } );
@@ -94,11 +92,6 @@ export default ( Splide, Components ) => {
 				height: Slide.container ? null : slideHeight,
 				height: Slide.container ? null : slideHeight,
 			} );
 			} );
 		} );
 		} );
-
-		// When the scrollbar is made hidden, the track width is changed but the resize event is not fired.
-		if ( width !== Layout.width ) {
-			resize();
-		}
 	}
 	}
 
 
 	return Layout;
 	return Layout;

+ 5 - 41
src/js/components/track/directions/horizontal.js

@@ -7,7 +7,6 @@
 
 
 import { between } from '../../../utils/utils';
 import { between } from '../../../utils/utils';
 import { RTL } from "../../../constants/directions";
 import { RTL } from "../../../constants/directions";
-import { SLIDE } from "../../../constants/types";
 
 
 
 
 /**
 /**
@@ -26,13 +25,6 @@ export default ( Splide, Components ) => {
 	 */
 	 */
 	let Layout;
 	let Layout;
 
 
-	/**
-	 * Hold the Elements component.
-	 *
-	 * @type {Object}
-	 */
-	let Elements;
-
 	return {
 	return {
 		/**
 		/**
 		 * Axis of translate.
 		 * Axis of translate.
@@ -52,47 +44,19 @@ export default ( Splide, Components ) => {
 		 * Initialization.
 		 * Initialization.
 		 */
 		 */
 		init() {
 		init() {
-			Layout   = Components.Layout;
-			Elements = Components.Elements;
+			Layout = Components.Layout;
 		},
 		},
 
 
 		/**
 		/**
-		 * Calculate position by index.
+		 * Calculate the track position by a slide index.
 		 *
 		 *
 		 * @param {number} index - Slide index.
 		 * @param {number} index - Slide index.
 		 *
 		 *
 		 * @return {Object} - Calculated position.
 		 * @return {Object} - Calculated position.
 		 */
 		 */
 		toPosition( index ) {
 		toPosition( index ) {
-			return this.sign * ( Layout.totalWidth( index - 1 ) + this.offset( index ) );
-		},
-
-		/**
-		 * Calculate the closest slide index from the given position.
-		 *
-		 * @return {number} - The closest slide position.
-		 */
-		toIndex( position ) {
-			position *= this.sign;
-
-			if ( Splide.is( SLIDE ) ) {
-				position = between( position, Layout.totalWidth( Elements.total ), 0 );
-			}
-
-			const Slides = Elements.getSlides( true );
-
-			for ( const i in Slides ) {
-				const Slide = Slides[ i ];
-
-				const slideIndex    = Slide.index;
-				const slidePosition = this.sign * this.toPosition( slideIndex );
-
-				if ( slidePosition < position && position <= slidePosition + Layout.slideWidth( slideIndex ) + Layout.gap ) {
-					return slideIndex;
-				}
-			}
-
-			return 0;
+			const slidePosition = Layout.totalWidth( index ) - Layout.slideWidth( index ) - Layout.gap;
+			return this.sign * ( slidePosition + this.offset( index ) );
 		},
 		},
 
 
 		/**
 		/**
@@ -103,7 +67,7 @@ export default ( Splide, Components ) => {
 		 * @return {number} - Trimmed position.
 		 * @return {number} - Trimmed position.
 		 */
 		 */
 		trim( position ) {
 		trim( position ) {
-			const edge = this.sign * ( Layout.totalWidth( Elements.total ) - ( Layout.width + Layout.gap ) );
+			const edge = this.sign * ( Layout.totalWidth() - ( Layout.width + Layout.gap ) );
 			return between( position, edge, 0 );
 			return between( position, edge, 0 );
 		},
 		},
 
 

+ 2 - 13
src/js/components/track/directions/vertical.js

@@ -54,18 +54,7 @@ export default ( Splide, Components ) => {
 		 * @return {Object} - Calculated position.
 		 * @return {Object} - Calculated position.
 		 */
 		 */
 		toPosition( index ) {
 		toPosition( index ) {
-			return - ( ( index + Components.Clones.length / 2 ) * ( Layout.slideHeight() + Layout.gap ) + this.offset() );
-		},
-
-		/**
-		 * Calculate the closest slide index from the given position.
-		 *
-		 * @return {number} - The closest slide index.
-		 */
-		toIndex( position ) {
-			const slideHeight = Layout.slideHeight();
-			const cloneOffset = ( slideHeight + Layout.gap ) * Components.Clones.length / 2;
-			return Math.round( - ( position + cloneOffset + this.offset() ) / ( slideHeight + Layout.gap ) );
+			return - ( Layout.totalHeight( index ) - Layout.slideHeight() - Layout.gap + this.offset() );
 		},
 		},
 
 
 		/**
 		/**
@@ -76,7 +65,7 @@ export default ( Splide, Components ) => {
 		 * @return {number} - Trimmed position.
 		 * @return {number} - Trimmed position.
 		 */
 		 */
 		trim( position ) {
 		trim( position ) {
-			const edge = -( Layout.listHeight - ( Layout.height + Layout.gap ) );
+			const edge = -( Layout.totalHeight() - ( Layout.height + Layout.gap ) );
 			return between( position, edge, 0 );
 			return between( position, edge, 0 );
 		},
 		},
 
 

+ 24 - 0
src/js/components/track/index.js

@@ -138,6 +138,30 @@ export default ( Splide, Components ) => {
 			return this._s.trim( position );
 			return this._s.trim( position );
 		},
 		},
 
 
+		/**
+		 * Calculate the closest slide index from the given position.
+		 *
+		 * @param {number} position - A position converted to an slide index.
+		 *
+		 * @return {number} - The closest slide index.
+		 */
+		toIndex( position ) {
+			let index = 0;
+			let minDistance = Infinity;
+
+			Components.Elements.getSlides( true ).forEach( Slide => {
+				const slideIndex = Slide.index;
+				const distance   = Math.abs( this.toPosition( slideIndex ) - position );
+
+				if ( distance < minDistance ) {
+					minDistance = distance;
+					index = slideIndex;
+				}
+			} );
+
+			return index;
+		},
+
 		/**
 		/**
 		 * Return coordinates object by the given position.
 		 * Return coordinates object by the given position.
 		 *
 		 *

+ 1 - 2
src/js/splide.d.ts

@@ -522,13 +522,12 @@ export interface Keyboard extends Component {}
 export interface Layout extends Component {
 export interface Layout extends Component {
 	margin: string;
 	margin: string;
 	height: number;
 	height: number;
-	listHeight: number;
 
 
 	readonly width: number;
 	readonly width: number;
-	readonly listWidth: number;
 
 
 	init(): void;
 	init(): void;
 	totalWidth( index: number | undefined ): number;
 	totalWidth( index: number | undefined ): number;
+	totalHeight( index: number | undefined ): number;
 	slideWidth( index: number ): number;
 	slideWidth( index: number ): number;
 	slideHeight( index: number ): number;
 	slideHeight( index: number ): number;
 }
 }

+ 26 - 3
src/js/utils/dom.js

@@ -28,16 +28,28 @@ export function find( elm, selector ) {
  * @param {Element} parent         - A parent element.
  * @param {Element} parent         - A parent element.
  * @param {string}  tagOrClassName - A tag or class name.
  * @param {string}  tagOrClassName - A tag or class name.
  *
  *
- * @return {Element|null} - A found element on success. Null on failure.
+ * @return {Element|undefined} - A found element on success or undefined on failure.
  */
  */
 export function child( parent, tagOrClassName ) {
 export function child( parent, tagOrClassName ) {
+	return children( parent, tagOrClassName )[0];
+}
+
+/**
+ * Return chile elements that matches the provided tag or class name.
+ *
+ * @param {Element} parent         - A parent element.
+ * @param {string}  tagOrClassName - A tag or class name.
+ *
+ * @return {Element[]} - Found elements.
+ */
+export function children( parent, tagOrClassName ) {
 	if ( parent ) {
 	if ( parent ) {
 		return values( parent.children ).filter( child => {
 		return values( parent.children ).filter( child => {
 			return hasClass( child, tagOrClassName.split( ' ' )[0] ) || child.tagName === tagOrClassName;
 			return hasClass( child, tagOrClassName.split( ' ' )[0] ) || child.tagName === tagOrClassName;
-		} )[0] || null;
+		} );
 	}
 	}
 
 
-	return null;
+	return [];
 }
 }
 
 
 /**
 /**
@@ -211,6 +223,17 @@ export function removeAttribute( elms, names ) {
 	} );
 	} );
 }
 }
 
 
+/**
+ * Return the Rect object of the provided object.
+ *
+ * @param {Element} elm - An element.
+ *
+ * @return {ClientRect|DOMRect} - A rect object.
+ */
+export function getRect( elm ) {
+	return elm.getBoundingClientRect();
+}
+
 /**
 /**
  * Trigger the given callback after all images contained by the element are loaded.
  * Trigger the given callback after all images contained by the element are loaded.
  *
  *

+ 8 - 2
src/sass/core/object/objects/_list.scss

@@ -1,8 +1,14 @@
 .splide {
 .splide {
+  $root: &;
+
   &__list {
   &__list {
-    display: flex;
-    flex-wrap: wrap;
     margin: 0!important;
     margin: 0!important;
     padding: 0 !important;
     padding: 0 !important;
   }
   }
+
+  &.is-active {
+    #{$root}__list {
+      display: flex;
+    }
+  }
 }
 }

+ 1 - 0
src/sass/core/object/objects/_slide.scss

@@ -5,6 +5,7 @@
     list-style-type: none!important;
     list-style-type: none!important;
     margin: 0;
     margin: 0;
     outline: none;
     outline: none;
+    flex-shrink: 0;
 
 
     img {
     img {
       vertical-align: bottom;
       vertical-align: bottom;

+ 1 - 1
tests/data/html.js

@@ -34,7 +34,7 @@ export const sync = minimum + `
   </div>
   </div>
 `;
 `;
 
 
-export const width = `
+export const autoWidth = `
   <div id="splide" style="width: 800px" class="splide">
   <div id="splide" style="width: 800px" class="splide">
     <div class="splide__track">
     <div class="splide__track">
       <ul class="splide__list">
       <ul class="splide__list">

+ 36 - 17
tests/functionality/autowidth.test.js

@@ -1,46 +1,65 @@
-import { width } from '../data/html';
+import { autoWidth } from '../data/html';
 import Splide from '../../src/js/splide';
 import Splide from '../../src/js/splide';
 import { COMPLETE } from '../../src/js/components';
 import { COMPLETE } from '../../src/js/components';
 
 
 
 
 describe( 'When the autoWidth option is true, ', () => {
 describe( 'When the autoWidth option is true, ', () => {
 	let splide;
 	let splide;
+	const width = 800;
 
 
 	beforeEach( () => {
 	beforeEach( () => {
-		document.body.innerHTML = width;
+		document.body.innerHTML = autoWidth;
 		splide = new Splide( '#splide', { autoWidth: true }, COMPLETE );
 		splide = new Splide( '#splide', { autoWidth: true }, COMPLETE );
 
 
-		Object.defineProperty( splide.root.querySelector( '.splide__track' ), 'clientWidth', { value: 800 } );
+		Object.defineProperty( splide.root.querySelector( '.splide__track' ), 'clientWidth', { value: width } );
+
+		let accumulatedWidth = 0;
+
 		splide.root.querySelectorAll( '.splide__slide' ).forEach( slide => {
 		splide.root.querySelectorAll( '.splide__slide' ).forEach( slide => {
-			Object.defineProperty( slide, 'offsetWidth', { value: parseInt( slide.style.width ) } );
-			Object.defineProperty( slide, 'clientWidth', { value: parseInt( slide.style.width ) } );
+			const slideWidth = parseInt( slide.style.width );
+
+			Object.defineProperty( slide, 'offsetWidth', { value: slideWidth } );
+			Object.defineProperty( slide, 'clientWidth', { value: slideWidth } );
+
+			accumulatedWidth += slideWidth;
+			const right = accumulatedWidth;
+
+			slide.getBoundingClientRect = jest.fn( () => ( { right } ) );
 		} );
 		} );
 
 
 		splide.mount();
 		splide.mount();
 	} );
 	} );
 
 
 	test( 'Splide should move slides according to their width.', done => {
 	test( 'Splide should move slides according to their width.', done => {
+		const { Elements, Track } = splide.Components;
+
 		splide.on( 'moved', () => {
 		splide.on( 'moved', () => {
-			const slide = splide.Components.Elements.slides[0];
-			expect( Math.abs( splide.Components.Track.position ) ).toBe( slide.offsetWidth );
+			const slide = Elements.getSlide( 0 ).slide;
+			expect( Math.abs( Track.position ) ).toBe( slide.offsetWidth );
 			done();
 			done();
 		} );
 		} );
 
 
 		splide.go( 1 );
 		splide.go( 1 );
-		splide.Components.Elements.list.dispatchEvent( new Event( 'transitionend' ) );
+		Elements.list.dispatchEvent( new Event( 'transitionend' ) );
 	} );
 	} );
 
 
 	test( '"is-visible" class is properly toggled by the slide and viewport width.', done => {
 	test( '"is-visible" class is properly toggled by the slide and viewport width.', done => {
+		const Elements = splide.Components.Elements;
+
+		Element.prototype.hasClass = function( className ) {
+			return this.classList.contains( className );
+		};
+
 		splide.on( 'moved', () => {
 		splide.on( 'moved', () => {
-			const slide1 = splide.Components.Elements.slides[1];
-			const slide2 = splide.Components.Elements.slides[2]; // 300px, active
-			const slide3 = splide.Components.Elements.slides[3]; // 400px
-			const slide4 = splide.Components.Elements.slides[4]; // 500px
-
-			expect( slide1.classList.contains( 'is-visible' ) ).toBeFalsy();
-			expect( slide2.classList.contains( 'is-active' ) && slide2.classList.contains( 'is-visible' ) ).toBeTruthy();
-			expect( slide3.classList.contains( 'is-visible' ) ).toBeTruthy();
-			expect( slide4.classList.contains( 'is-visible' ) ).toBeFalsy(); // Out of the viewport.
+			const slide1 = Elements.slides[1];
+			const slide2 = Elements.slides[2]; // 300px, active
+			const slide3 = Elements.slides[3]; // 400px
+			const slide4 = Elements.slides[4]; // 500px
+
+			expect( slide1.hasClass( 'is-visible' ) ).toBeFalsy();
+			expect( slide2.hasClass( 'is-active' ) && slide2.classList.contains( 'is-visible' ) ).toBeTruthy();
+			expect( slide3.hasClass( 'is-visible' ) ).toBeTruthy();
+			expect( slide4.hasClass( 'is-visible' ) ).toBeFalsy(); // Out of the viewport.
 			done();
 			done();
 		} );
 		} );
 
 

+ 10 - 2
tests/functionality/elements.test.js

@@ -6,10 +6,18 @@ import { COMPLETE } from '../../src/js/components';
 
 
 describe( 'The "slide" type Splide', () => {
 describe( 'The "slide" type Splide', () => {
 	let splide;
 	let splide;
+	const width = 800;
 
 
 	beforeEach( () => {
 	beforeEach( () => {
 		document.body.innerHTML = minimum;
 		document.body.innerHTML = minimum;
 		splide = new Splide( '#splide', {}, COMPLETE ).mount();
 		splide = new Splide( '#splide', {}, COMPLETE ).mount();
+
+		// Set up the getBoundingClientRect.
+		splide.Components.Elements.getSlides( true ).forEach( Slide => {
+			Slide.slide.getBoundingClientRect = jest.fn( () => ( {
+				right: width * ( Slide.index + 1 + splide.Components.Clones.length  / 2 ),
+			} ) );
+		} );
 	} );
 	} );
 
 
 	test( 'should init index and slide attributes correctly.', () => {
 	test( 'should init index and slide attributes correctly.', () => {
@@ -24,12 +32,12 @@ describe( 'The "slide" type Splide', () => {
 
 
 	test( 'should move slides and update attributes correctly.', done => {
 	test( 'should move slides and update attributes correctly.', done => {
 		const { Track, Elements: { track, list } } = splide.Components;
 		const { Track, Elements: { track, list } } = splide.Components;
-		Object.defineProperty( track, 'clientWidth', { value: 800 } );
+		Object.defineProperty( track, 'clientWidth', { value: width } );
 
 
 		expect( parseInt( Track.position ) ).toBe( 0 );
 		expect( parseInt( Track.position ) ).toBe( 0 );
 
 
 		splide.on( 'moved', ( newIndex, prevIndex ) => {
 		splide.on( 'moved', ( newIndex, prevIndex ) => {
-			expect( Track.position ).toBe( -800 );
+			expect( Track.position ).toBe( -width );
 
 
 			const prevSlide   = splide.Components.Elements.getSlide( prevIndex );
 			const prevSlide   = splide.Components.Elements.getSlide( prevIndex );
 			const newSlide    = splide.Components.Elements.getSlide( newIndex );
 			const newSlide    = splide.Components.Elements.getSlide( newIndex );

+ 10 - 4
tests/functionality/loop.test.js

@@ -5,10 +5,18 @@ import { COMPLETE } from '../../src/js/components';
 
 
 describe( 'The "loop" type Splide', () => {
 describe( 'The "loop" type Splide', () => {
 	let splide;
 	let splide;
+	const width = 800;
 
 
 	beforeEach( () => {
 	beforeEach( () => {
 		document.body.innerHTML = minimum;
 		document.body.innerHTML = minimum;
 		splide = new Splide( '#splide', { type: 'loop' }, COMPLETE ).mount();
 		splide = new Splide( '#splide', { type: 'loop' }, COMPLETE ).mount();
+
+		// Set up the getBoundingClientRect.
+		splide.Components.Elements.getSlides( true ).forEach( Slide => {
+			Slide.slide.getBoundingClientRect = jest.fn( () => ( {
+				right: width * ( Slide.index + 1 + splide.Components.Clones.length  / 2 ),
+			} ) );
+		} );
 	} );
 	} );
 
 
 	test( 'should activate a Clones component and yield clone slides', () => {
 	test( 'should activate a Clones component and yield clone slides', () => {
@@ -17,12 +25,10 @@ describe( 'The "loop" type Splide', () => {
 	} );
 	} );
 
 
 	test( 'should init track position according to length of clones.', () => {
 	test( 'should init track position according to length of clones.', () => {
-		const { Track, Clones, Elements: { track } } = splide.Components;
-		const width = 800;
-		Object.defineProperty( track, 'clientWidth', { value: width } );
+		const { Track, Clones, Elements } = splide.Components;
 
 
+		Object.defineProperty( Elements.track, 'clientWidth', { value: width } );
 		global.dispatchEvent( new Event( 'resize' ) );
 		global.dispatchEvent( new Event( 'resize' ) );
-
 		expect( Math.abs( Track.toPosition( 0 ) ) ).toBe( width * Clones.length / 2 );
 		expect( Math.abs( Track.toPosition( 0 ) ) ).toBe( width * Clones.length / 2 );
 	} );
 	} );
 
 

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff