Browse Source

Accept the `!overflow` key for breakpoints. Reset the carousel position when setting `clones` to `0`.

Naotoshi Fujita 2 năm trước cách đây
mục cha
commit
ea1171cb37

+ 21 - 12
dist/js/splide.js

@@ -376,17 +376,24 @@
   const EVENT_SHIFTED = "sh";
   const EVENT_END_INDEX_CHANGED = "ei";
 
-  function Media(Splide2, Components2, options) {
+  const NOT_OVERFLOW_KEY = "!overflow";
+  function Media(Splide2, Components2, options, event) {
     const { state } = Splide2;
     const breakpoints = options.breakpoints || {};
     const reducedMotion = options.reducedMotion || {};
     const binder = b();
-    const queries = [];
+    const entries = [];
     function setup() {
       const isMin = options.mediaQuery === "min";
       A(breakpoints).sort((n, m) => isMin ? +n - +m : +m - +n).forEach((key) => {
-        register(breakpoints[key], `(${isMin ? "min" : "max"}-width:${key}px)`);
+        if (key !== NOT_OVERFLOW_KEY) {
+          register(breakpoints[key], `(${isMin ? "min" : "max"}-width:${key}px)`);
+        }
       });
+      if (breakpoints[NOT_OVERFLOW_KEY]) {
+        entries.push([breakpoints[NOT_OVERFLOW_KEY], () => Components2.Layout && !Components2.Layout.isOverflow()]);
+        event.on(EVENT_OVERFLOW, update);
+      }
       register(reducedMotion, MEDIA_PREFERS_REDUCED_MOTION);
       update();
     }
@@ -398,13 +405,13 @@
     function register(options2, query) {
       const queryList = matchMedia(query);
       binder.bind(queryList, "change", update);
-      queries.push([options2, queryList]);
+      entries.push([options2, () => queryList.matches]);
     }
     function update() {
       const destroyed = state.is(DESTROYED);
       const direction = options.direction;
-      const merged = queries.reduce((merged2, entry) => {
-        return k(merged2, entry[1].matches ? entry[0] : {});
+      const merged = entries.reduce((merged2, entry) => {
+        return k(merged2, entry[1]() ? entry[0] : {});
       }, {});
       gn(options);
       set(merged);
@@ -778,8 +785,9 @@
       return diff <= distance;
     }
     function pos() {
+      const first = Components.Slides.get()[0];
       const left = resolve("left");
-      return un(tn(slide)[left] - tn(Elements.list)[left]);
+      return first ? un(tn(slide)[left] - tn(first.slide)[left]) : 0;
     }
     function size() {
       return tn(slide)[resolve("width")];
@@ -1021,7 +1029,7 @@
   const MULTIPLIER = 2;
   function Clones(Splide2, Components2, options, event) {
     const { on } = event;
-    const { Elements, Slides } = Components2;
+    const { Elements, Slides, Layout: { resize } } = Components2;
     const { resolve } = Components2.Direction;
     const clones = [];
     let cloneCount;
@@ -1030,12 +1038,13 @@
       on([EVENT_UPDATED, EVENT_RESIZE], observe);
       if (cloneCount = computeCloneCount()) {
         generate(cloneCount);
-        Components2.Layout.resize(true);
+        resize(true);
       }
     }
     function remount() {
       destroy();
       mount();
+      resize(true);
     }
     function destroy() {
       en(clones);
@@ -1046,6 +1055,7 @@
       const count = computeCloneCount();
       if (cloneCount !== count) {
         if (cloneCount < count || !count) {
+          !count && Splide2.go(0);
           event.emit(EVENT_REFRESH);
         }
       }
@@ -1093,7 +1103,7 @@
     const { on, emit } = event;
     const { set } = Splide2.state;
     const { Slides } = Components2;
-    const { slideSize, getPadding, listSize, sliderSize } = Components2.Layout;
+    const { slideSize, getPadding, listSize, sliderSize, totalSize } = Components2.Layout;
     const { resolve, orient } = Components2.Direction;
     const { list, track } = Components2.Elements;
     let Transition;
@@ -1169,8 +1179,7 @@
       return index;
     }
     function toPosition(index, trimming) {
-      const Slide = Slides.getAt(index);
-      const position = Slide ? orient(Slide.pos() - offset(index)) : 0;
+      const position = orient(totalSize(index - 1) - offset(index));
       return trimming ? trim(position) : position;
     }
     function getPosition() {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/js/splide.min.js


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


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/js/splide.min.js.map


+ 5 - 2
src/js/components/Clones/Clones.ts

@@ -51,7 +51,7 @@ export function Clones(
   event: EventInterface
 ): ClonesComponent {
   const { on } = event;
-  const { Elements, Slides } = Components;
+  const { Elements, Slides, Layout: { resize } } = Components;
   const { resolve } = Components.Direction;
 
   /**
@@ -74,7 +74,7 @@ export function Clones(
 
     if ( ( cloneCount = computeCloneCount() ) ) {
       generate( cloneCount );
-      Components.Layout.resize( true );
+      resize( true );
     }
   }
 
@@ -84,6 +84,7 @@ export function Clones(
   function remount(): void {
     destroy();
     mount();
+    resize( true );
   }
 
   /**
@@ -97,12 +98,14 @@ export function Clones(
 
   /**
    * Observes the required clone count and refreshes the slider if necessary.
+   * If clones are disabled by `0`, moves the carousel to the first slide.
    */
   function observe(): void {
     const count = computeCloneCount();
 
     if ( cloneCount !== count ) {
       if ( cloneCount < count || ! count ) {
+        ! count && Splide.go( 0 );
         event.emit( EVENT_REFRESH );
       }
     }

+ 19 - 1
src/js/components/Layout/Layout.ts

@@ -219,6 +219,23 @@ export function Layout(
    * @return The total width of slides in the horizontal slider, or the height in the vertical one.
    */
   function totalSize( index: number, withoutGap?: boolean ): number {
+    // const first = getAt( index );
+    // const last  = getAt( Splide.length - 1 );
+    //
+    // if ( last ) {
+    //   console.log( last.pos() );
+    // }
+    //
+    // const Slide = getAt( index );
+    // if ( Slide ) {
+    //   const right = rect( Slide.slide )[ resolve( 'right' ) ];
+    //   const left  = rect( list )[ resolve( 'left' ) ];
+    //
+    //   return  abs( right - left ) + ( withoutGap ? 0 : getGap() );
+    // }
+    //
+    // return 0;
+
     const Slide = getAt( index );
     return Slide ? Slide.pos() + Slide.size() + ( withoutGap ? 0 : getGap() ) : 0;
   }
@@ -236,7 +253,8 @@ export function Layout(
   }
 
   /**
-   * Compute the gap by the first and second slides.
+   * Computes the gap by the first and second slides,
+   * without using `margin` for the CSS grid `gap`.
    * This always returns 0 if the number of slides is less than 2.
    *
    * @return The gap value in pixel.

+ 25 - 10
src/js/components/Media/Media.ts

@@ -1,9 +1,9 @@
 import { MEDIA_PREFERS_REDUCED_MOTION } from '../../constants/media';
 import { CREATED, DESTROYED } from '../../constants/states';
-import { EventBinder, merge, omit, ownKeys } from '@splidejs/utils';
+import { EventBinder, EventInterface, merge, omit, ownKeys } from '@splidejs/utils';
 import { Splide } from '../../core/Splide/Splide';
 import { BaseComponent, Components, Options } from '../../types';
-import { EVENT_UPDATED } from '../../constants/events';
+import { EVENT_OVERFLOW, EVENT_UPDATED } from '../../constants/events';
 
 
 /**
@@ -17,6 +17,13 @@ export interface MediaComponent extends BaseComponent {
   set( options: Options, base?: boolean, notify?: boolean ): void;
 }
 
+/**
+ * The special breakpoints key when the number of slides are not enough for the list.
+ *
+ * @since 5.0.0
+ */
+const NOT_OVERFLOW_KEY = '!overflow';
+
 /**
  * The component for observing media queries and updating options if necessary.
  * This used to be the Options component.
@@ -29,16 +36,16 @@ export interface MediaComponent extends BaseComponent {
  *
  * @return A Media component object.
  */
-export function Media( Splide: Splide, Components: Components, options: Options ): MediaComponent {
+export function Media( Splide: Splide, Components: Components, options: Options, event: EventInterface ): MediaComponent {
   const { state } = Splide;
   const breakpoints   = options.breakpoints || {};
   const reducedMotion = options.reducedMotion || {};
   const binder        = EventBinder();
 
   /**
-   * Stores options and MediaQueryList object.
+   * Stores options and a predicate function.
    */
-  const queries: Array<[ Options, MediaQueryList ]> = [];
+  const entries: Array<[ Options, () => boolean ]> = [];
 
   /**
    * Called when the component is constructed.
@@ -49,9 +56,16 @@ export function Media( Splide: Splide, Components: Components, options: Options
     ownKeys( breakpoints )
       .sort( ( n, m ) => isMin ? +n - +m : +m - +n )
       .forEach( key => {
-        register( breakpoints[ key ], `(${ isMin ? 'min' : 'max' }-width:${ key }px)` );
+        if ( key !== NOT_OVERFLOW_KEY ) {
+          register( breakpoints[ key ], `(${ isMin ? 'min' : 'max' }-width:${ key }px)` );
+        }
       } );
 
+    if ( breakpoints[ NOT_OVERFLOW_KEY ] ) {
+      entries.push( [ breakpoints[ NOT_OVERFLOW_KEY ], () => Components.Layout && ! Components.Layout.isOverflow() ] );
+      event.on( EVENT_OVERFLOW, update );
+    }
+
     register( reducedMotion, MEDIA_PREFERS_REDUCED_MOTION );
     update();
   }
@@ -68,7 +82,7 @@ export function Media( Splide: Splide, Components: Components, options: Options
   }
 
   /**
-   * Registers entries as [ Options, media query string ].
+   * Registers entries as `[ Options, media query string ]`.
    *
    * @param options - Options merged to current options when the document matches the query.
    * @param query   - A query string.
@@ -76,7 +90,7 @@ export function Media( Splide: Splide, Components: Components, options: Options
   function register( options: Options, query: string ): void {
     const queryList = matchMedia( query );
     binder.bind( queryList, 'change', update );
-    queries.push( [ options, queryList ] );
+    entries.push( [ options,  () => queryList.matches ] );
   }
 
   /**
@@ -85,8 +99,8 @@ export function Media( Splide: Splide, Components: Components, options: Options
   function update(): void {
     const destroyed = state.is( DESTROYED );
     const direction = options.direction;
-    const merged = queries.reduce<Options>( ( merged, entry ) => {
-      return merge( merged, entry[ 1 ].matches ? entry[ 0 ] : {} );
+    const merged = entries.reduce<Options>( ( merged, entry ) => {
+      return merge( merged, entry[ 1 ]() ? entry[ 0 ] : {} );
     }, {} );
 
     omit( options );
@@ -137,6 +151,7 @@ export function Media( Splide: Splide, Components: Components, options: Options
 
   return {
     setup,
+    // mount,
     destroy,
     reduce,
     set,

+ 2 - 3
src/js/components/Move/Move.ts

@@ -56,7 +56,7 @@ export function Move(
   const { on, emit } = event;
   const { set } = Splide.state;
   const { Slides } = Components;
-  const { slideSize, getPadding, listSize, sliderSize } = Components.Layout;
+  const { slideSize, getPadding, listSize, sliderSize, totalSize } = Components.Layout;
   const { resolve, orient } = Components.Direction;
   const { list, track } = Components.Elements;
 
@@ -214,8 +214,7 @@ export function Move(
    * @return The position corresponding with the index.
    */
   function toPosition( index: number, trimming?: boolean ): number {
-    const Slide    = Slides.getAt( index );
-    const position = Slide ? orient( Slide.pos() - offset( index ) ) : 0;
+    const position = orient( totalSize( index - 1 ) - offset( index ) );
     return trimming ? trim( position ) : position;
   }
 

+ 0 - 1
src/js/components/Pagination/test/general.test.ts

@@ -32,7 +32,6 @@ describe( 'Pagination', () => {
 
     expect( items.length ).not.toBe( splide.length );
     expect( items.length ).toBe( splide.Components.Controller.getEnd() + 1 );
-    expect( items.length ).toBe( 8 );
   } );
 
   test( 'can move the slider when the item is clicked.', () => {

+ 3 - 3
src/js/components/Slides/Slide.ts

@@ -54,7 +54,6 @@ import {
   style as _style,
   toggleClass,
 } from '@splidejs/utils';
-import { define } from '../../utils/define/define';
 
 
 /**
@@ -289,8 +288,9 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
    * @return The slide position.
    */
   function pos(): number {
-    const left = resolve( 'left' );
-    return abs( rect( slide )[ left ] - rect( Elements.list )[ left ] );
+    const first = Components.Slides.get()[ 0 ];
+    const left  = resolve( 'left' );
+    return first ? abs( rect( slide )[ left ] - rect( first.slide )[ left ] ) : 0;
   }
 
   /**

+ 11 - 9
src/js/test/php/examples/default.php

@@ -22,6 +22,7 @@ $settings = get_settings();
     document.addEventListener( 'DOMContentLoaded', function () {
       var splide = new Splide( '#splide01', {
         width: 800,
+        start: 1,
         // type        : 'loop',
         perPage: 3,
         // perMove: 3,
@@ -39,15 +40,16 @@ $settings = get_settings();
         focus: 0,
         omitEnd: true,
 
-        // breakpoints: {
-        //   1200: {
-        //     // padding: 5,
-        //   },
-        //   1000: {
-        //     label: 'The destroyed carousel',
-        //     destroy: true,
-        //   },
-        // },
+        breakpoints: {
+          1200: {
+            start: 4,
+            // padding: 5,
+          },
+          1000: {
+            label: 'The destroyed carousel',
+            destroy: true,
+          },
+        },
 
         classes: {
           arrows: 'splide__arrows custom-arrows',

+ 97 - 80
src/js/test/php/examples/overflow.php

@@ -20,100 +20,117 @@ $settings = get_settings();
     document.addEventListener( 'DOMContentLoaded', function () {
       var splide01 = new Splide( '#splide01', {
         fixedWidth : '6rem',
+        type       : 'loop',
         gap        : 10,
         omitEnd    : true,
         focus      : 0,
-      } );
-
-      splide01.on( 'overflow', overflow => {
-        console.log( 'splide01:', overflow );
-        splide01.root.classList.toggle( 'is-inactive', ! overflow );
-        splide01.options = { arrows: overflow, pagination: overflow, drag: overflow };
-      } );
-
-      splide01.mount();
-
-      var splide02 = new Splide( '#splide02', {
-        type      : 'loop',
-        gap       : '1rem',
-        fixedWidth: 100,
-      } );
-
-      splide02.on( 'overflow', overflow => {
-        console.log( 'splide02:', overflow );
-        splide02.root.classList.toggle( 'is-inactive', ! overflow );
-
-        if ( overflow ) {
-          splide02.options = { clones: undefined, arrows: true, pagination: true, drag: true };
-        } else {
-          splide02.go( 0 );
-          splide02.options = { clones: 0, arrows: false, pagination: false, drag: false };
-        }
-      } );
-
-      splide02.mount();
-
-      var splide03 = new Splide( '#splide03', {
-        // height : 400,
-        type   : 'loop',
-        gap    : '1rem',
-        perPage: 3,
-      } );
-
-      splide03.on( 'overflow', overflow => {
-        console.log( 'splide03:', overflow );
-        splide03.go( 0 );
-
-        if ( overflow ) {
-          splide03.options = { clones: undefined, arrows: true, pagination: true, drag: true };
-        } else {
-          splide03.options = { clones: 0, arrows: false, pagination: false, drag: false };
+        breakpoints: {
+          1200: {
+            arrows: true,
+          },
+
+          '!overflow': {
+            arrows    : false,
+            drag      : false,
+            pagination: false,
+            clones    : 0,
+          }
         }
       } );
 
-      splide03.mount();
-
-      var add    = document.getElementById( 'add' );
-      var remove = document.getElementById( 'remove' );
-
-      var index = 1;
-
-      add.addEventListener( 'click', function() {
-        splide03.add( [
-          `<li class="splide__slide"><img src="../../assets/images/pics/slide${ String( ++index ).padStart( 2, '0' ) }.jpg"></li>`,
-        ] );
-      } );
-
-      remove.addEventListener( 'click', function() {
-        splide03.remove( splide03.length - 1 );
-      } );
+      // splide01.on( 'overflow', overflow => {
+      //   console.log( 'splide01:', overflow );
+      //   // splide01.root.classList.toggle( 'is-inactive', ! overflow );
+      //   splide01.options = { clones: overflow ? undefined : 0, arrows: overflow, pagination: overflow, drag: overflow };
+      // } );
 
-      var splide04 = new Splide( '#splide04', {
-        autoWidth : true,
-        gap       : '1rem',
-        focus     : 0,
-        drag      : 'free',
-        omitEnd   : true,
-      } );
-
-      splide04.on( 'overflow', overflow => {
-        console.log( 'splide04:', overflow );
-
-        if ( overflow ) {
-          splide04.options = { arrows: true, pagination: true, drag: true };
-        } else {
-          splide04.options = { arrows: false, pagination: false, drag: false };
-        }
-      } );
+      splide01.mount();
 
-      splide04.mount();
+      // var splide02 = new Splide( '#splide02', {
+      //   type      : 'loop',
+      //   gap       : '1rem',
+      //   fixedWidth: 100,
+      // } );
+      //
+      // splide02.on( 'overflow', overflow => {
+      //   console.log( 'splide02:', overflow );
+      //   splide02.root.classList.toggle( 'is-inactive', ! overflow );
+      //
+      //   if ( overflow ) {
+      //     splide02.options = { clones: undefined, arrows: true, pagination: true, drag: true };
+      //   } else {
+      //     splide02.go( 0 );
+      //     splide02.options = { clones: 0, arrows: false, pagination: false, drag: false };
+      //   }
+      // } );
+      //
+      // splide02.mount();
+      //
+      // var splide03 = new Splide( '#splide03', {
+      //   // height : 400,
+      //   type   : 'loop',
+      //   gap    : '1rem',
+      //   perPage: 3,
+      // } );
+      //
+      // splide03.on( 'overflow', overflow => {
+      //   console.log( 'splide03:', overflow );
+      //   splide03.go( 0 );
+      //
+      //   if ( overflow ) {
+      //     splide03.options = { clones: undefined, arrows: true, pagination: true, drag: true };
+      //   } else {
+      //     splide03.options = { clones: 0, arrows: false, pagination: false, drag: false };
+      //   }
+      // } );
+      //
+      // splide03.mount();
+      //
+      // var add    = document.getElementById( 'add' );
+      // var remove = document.getElementById( 'remove' );
+      //
+      // var index = 1;
+      //
+      // add.addEventListener( 'click', function() {
+      //   splide03.add( [
+      //     `<li class="splide__slide"><img src="../../assets/images/pics/slide${ String( ++index ).padStart( 2, '0' ) }.jpg"></li>`,
+      //   ] );
+      // } );
+      //
+      // remove.addEventListener( 'click', function() {
+      //   splide03.remove( splide03.length - 1 );
+      // } );
+      //
+      // var splide04 = new Splide( '#splide04', {
+      //   autoWidth : true,
+      //   gap       : '1rem',
+      //   focus     : 0,
+      //   drag      : 'free',
+      //   omitEnd   : true,
+      // } );
+      //
+      // splide04.on( 'overflow', overflow => {
+      //   console.log( 'splide04:', overflow );
+      //
+      //   if ( overflow ) {
+      //     splide04.options = { arrows: true, pagination: true, drag: true };
+      //   } else {
+      //     splide04.options = { arrows: false, pagination: false, drag: false };
+      //   }
+      // } );
+      //
+      // splide04.mount();
     } );
   </script>
 
   <style>
-    .splide.is-inactive .splide__list {
+    .splide:not( .is-overflow ) .splide__list {
       justify-content: center;
     }
+
+    .splide:not( .is-overflow ) .splide__slide:last-child {
+      margin: 0 !important;
+    }
   </style>
 </head>
 <body>

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác