index.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /**
  2. * The component for handing slide layouts and their sizes.
  3. *
  4. * @author Naotoshi Fujita
  5. * @copyright Naotoshi Fujita. All rights reserved.
  6. */
  7. import Horizontal from './resolvers/horizontal';
  8. import Vertical from './resolvers/vertical';
  9. import { unit } from '../../utils/utils';
  10. import { throttle } from '../../utils/time';
  11. import { subscribe, applyStyle } from '../../utils/dom';
  12. /**
  13. * Interval time for throttle.
  14. *
  15. * @type {number}
  16. */
  17. const THROTTLE = 30;
  18. /**
  19. * The component for handing slide layouts and their sizes.
  20. *
  21. * @param {Splide} Splide - A Splide instance.
  22. * @param {Object} Components - An object containing components.
  23. *
  24. * @return {Object} - The component object.
  25. */
  26. export default ( Splide, Components ) => {
  27. /**
  28. * Store the root element.
  29. *
  30. * @type {Element}
  31. */
  32. const root = Splide.root;
  33. /**
  34. * Store the list element.
  35. *
  36. * @type {Element}
  37. */
  38. let list;
  39. /**
  40. * Store all Slide objects.
  41. *
  42. * @type {Object}
  43. */
  44. let Slides;
  45. /**
  46. * Hold a resolver object.
  47. *
  48. * @type {Object}
  49. */
  50. let Resolver;
  51. /**
  52. * Whether the slider is vertical or not.
  53. * @type {boolean}
  54. */
  55. const isVertical = Splide.options.direction === 'ttb';
  56. /**
  57. * Layout component object.
  58. *
  59. * @type {Object}
  60. */
  61. const Layout = {
  62. /**
  63. * Called when the component is mounted.
  64. */
  65. mount() {
  66. list = Components.Elements.list;
  67. Slides = Components.Slides.getSlides( true, true );
  68. bind();
  69. init();
  70. },
  71. /**
  72. * Return slider width without padding.
  73. *
  74. * @return {number} - Current slide width.
  75. */
  76. get width() {
  77. return Resolver.width;
  78. },
  79. /**
  80. * Return list width.
  81. *
  82. * @return {number} - Current list width.
  83. */
  84. get listWidth() {
  85. return Resolver.listWidth;
  86. },
  87. /**
  88. * Return list height.
  89. *
  90. * @return {number} - Current list height.
  91. */
  92. get listHeight() {
  93. return Resolver.listHeight;
  94. },
  95. /**
  96. * Return slide width including gap size.
  97. * Note that slideWidth * perPage is NOT equal to slider width.
  98. *
  99. * @return {number} - Current slide width including gap size.
  100. */
  101. get slideWidth() {
  102. return Resolver.getSlideWidth( true );
  103. },
  104. /**
  105. * Return slide height.
  106. *
  107. * @return {number} - Computed slide height.
  108. */
  109. get slideHeight() {
  110. return Resolver.getSlideHeight( true );
  111. },
  112. /**
  113. * Return gap in px.
  114. *
  115. * @return {Object} - Gap amount in px.
  116. */
  117. get gap() {
  118. return Resolver.gap;
  119. },
  120. /**
  121. * Return padding object.
  122. *
  123. * @return {Object} - An object containing padding left and right in horizontal mode
  124. * or top and bottom in vertical one.
  125. */
  126. get padding() {
  127. return Resolver.padding;
  128. },
  129. };
  130. /**
  131. * Init slider styles according to options.
  132. */
  133. function init() {
  134. const options = Splide.options;
  135. if ( isVertical ) {
  136. Resolver = Vertical( Splide, Components, options );
  137. } else {
  138. Resolver = Horizontal( Splide, Components, options );
  139. }
  140. Resolver.init();
  141. applyStyle( root, { maxWidth: unit( options.width ) } );
  142. for ( const i in Slides ) {
  143. applyStyle( Slides[ i ].slide, { [ Resolver.marginProp ]: unit( options.gap ) } )
  144. }
  145. resize();
  146. }
  147. /**
  148. * Listen the resize native event with throttle.
  149. * Initialize when the component is mounted or options are updated.
  150. */
  151. function bind() {
  152. const throttledResize = throttle( () => { Splide.emit( 'resize' ) }, THROTTLE );
  153. subscribe( window, 'resize', throttledResize );
  154. Splide.on( 'mounted resize', resize ).on( 'updated', init );
  155. if ( ! isVertical ) {
  156. Splide.on( 'resize', updatePerPage );
  157. }
  158. }
  159. /**
  160. * Resize the list and slides including clones.
  161. */
  162. function resize() {
  163. applyStyle( list, { width: unit( Layout.listWidth ), height: unit( Layout.listHeight ) } );
  164. const slideWidth = unit( Resolver.getSlideWidth( false ) );
  165. const slideHeight = unit( Resolver.getSlideHeight( false ) );
  166. for ( let i in Slides ) {
  167. const { slide, container } = Slides[ i ];
  168. applyStyle( container, { height: slideHeight } );
  169. applyStyle( slide, { width: slideWidth, height: ! container ? slideHeight : '' } );
  170. }
  171. }
  172. /**
  173. * Update the perPage number automatically according to the fixedWidth.
  174. */
  175. function updatePerPage() {
  176. const options = Splide.options;
  177. if ( options.fixedWidth ) {
  178. const perPage = Math.floor( ( Layout.width + Resolver.gap ) / Layout.slideWidth ) || 1;
  179. if ( options.perPage !== perPage ) {
  180. Splide.options = { perPage };
  181. }
  182. }
  183. }
  184. return Layout;
  185. }