innerSliderUtils.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. // import supportsPassive from '../../../_util/supportsPassive';
  3. export function clamp(number, lowerBound, upperBound) {
  4. return Math.max(lowerBound, Math.min(number, upperBound));
  5. }
  6. export const safePreventDefault = event => {
  7. const passiveEvents = ['touchstart', 'touchmove', 'wheel'];
  8. if (!passiveEvents.includes(event.type)) {
  9. event.preventDefault();
  10. }
  11. };
  12. export const getOnDemandLazySlides = spec => {
  13. const onDemandSlides = [];
  14. const startIndex = lazyStartIndex(spec);
  15. const endIndex = lazyEndIndex(spec);
  16. for (let slideIndex = startIndex; slideIndex < endIndex; slideIndex++) {
  17. if (spec.lazyLoadedList.indexOf(slideIndex) < 0) {
  18. onDemandSlides.push(slideIndex);
  19. }
  20. }
  21. return onDemandSlides;
  22. };
  23. // return list of slides that need to be present
  24. export const getRequiredLazySlides = spec => {
  25. const requiredSlides = [];
  26. const startIndex = lazyStartIndex(spec);
  27. const endIndex = lazyEndIndex(spec);
  28. for (let slideIndex = startIndex; slideIndex < endIndex; slideIndex++) {
  29. requiredSlides.push(slideIndex);
  30. }
  31. return requiredSlides;
  32. };
  33. // startIndex that needs to be present
  34. export const lazyStartIndex = spec => spec.currentSlide - lazySlidesOnLeft(spec);
  35. export const lazyEndIndex = spec => spec.currentSlide + lazySlidesOnRight(spec);
  36. export const lazySlidesOnLeft = spec => spec.centerMode ? Math.floor(spec.slidesToShow / 2) + (parseInt(spec.centerPadding) > 0 ? 1 : 0) : 0;
  37. export const lazySlidesOnRight = spec => spec.centerMode ? Math.floor((spec.slidesToShow - 1) / 2) + 1 + (parseInt(spec.centerPadding) > 0 ? 1 : 0) : spec.slidesToShow;
  38. // get width of an element
  39. export const getWidth = elem => elem && elem.offsetWidth || 0;
  40. export const getHeight = elem => elem && elem.offsetHeight || 0;
  41. export const getSwipeDirection = function (touchObject) {
  42. let verticalSwiping = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  43. let swipeAngle;
  44. const xDist = touchObject.startX - touchObject.curX;
  45. const yDist = touchObject.startY - touchObject.curY;
  46. const r = Math.atan2(yDist, xDist);
  47. swipeAngle = Math.round(r * 180 / Math.PI);
  48. if (swipeAngle < 0) {
  49. swipeAngle = 360 - Math.abs(swipeAngle);
  50. }
  51. if (swipeAngle <= 45 && swipeAngle >= 0 || swipeAngle <= 360 && swipeAngle >= 315) {
  52. return 'left';
  53. }
  54. if (swipeAngle >= 135 && swipeAngle <= 225) {
  55. return 'right';
  56. }
  57. if (verticalSwiping === true) {
  58. if (swipeAngle >= 35 && swipeAngle <= 135) {
  59. return 'up';
  60. } else {
  61. return 'down';
  62. }
  63. }
  64. return 'vertical';
  65. };
  66. // whether or not we can go next
  67. export const canGoNext = spec => {
  68. let canGo = true;
  69. if (!spec.infinite) {
  70. if (spec.centerMode && spec.currentSlide >= spec.slideCount - 1) {
  71. canGo = false;
  72. } else if (spec.slideCount <= spec.slidesToShow || spec.currentSlide >= spec.slideCount - spec.slidesToShow) {
  73. canGo = false;
  74. }
  75. }
  76. return canGo;
  77. };
  78. // given an object and a list of keys, return new object with given keys
  79. export const extractObject = (spec, keys) => {
  80. const newObject = {};
  81. keys.forEach(key => newObject[key] = spec[key]);
  82. return newObject;
  83. };
  84. // get initialized state
  85. export const initializedState = spec => {
  86. // spec also contains listRef, trackRef
  87. const slideCount = spec.children.length;
  88. const listNode = spec.listRef;
  89. const listWidth = Math.ceil(getWidth(listNode));
  90. const trackNode = spec.trackRef;
  91. const trackWidth = Math.ceil(getWidth(trackNode));
  92. let slideWidth;
  93. if (!spec.vertical) {
  94. let centerPaddingAdj = spec.centerMode && parseInt(spec.centerPadding) * 2;
  95. if (typeof spec.centerPadding === 'string' && spec.centerPadding.slice(-1) === '%') {
  96. centerPaddingAdj *= listWidth / 100;
  97. }
  98. slideWidth = Math.ceil((listWidth - centerPaddingAdj) / spec.slidesToShow);
  99. } else {
  100. slideWidth = listWidth;
  101. }
  102. const slideHeight = listNode && getHeight(listNode.querySelector('[data-index="0"]'));
  103. const listHeight = slideHeight * spec.slidesToShow;
  104. let currentSlide = spec.currentSlide === undefined ? spec.initialSlide : spec.currentSlide;
  105. if (spec.rtl && spec.currentSlide === undefined) {
  106. currentSlide = slideCount - 1 - spec.initialSlide;
  107. }
  108. let lazyLoadedList = spec.lazyLoadedList || [];
  109. const slidesToLoad = getOnDemandLazySlides(_extends(_extends({}, spec), {
  110. currentSlide,
  111. lazyLoadedList
  112. }), spec);
  113. lazyLoadedList = lazyLoadedList.concat(slidesToLoad);
  114. const state = {
  115. slideCount,
  116. slideWidth,
  117. listWidth,
  118. trackWidth,
  119. currentSlide,
  120. slideHeight,
  121. listHeight,
  122. lazyLoadedList
  123. };
  124. if (spec.autoplaying === null && spec.autoplay) {
  125. state['autoplaying'] = 'playing';
  126. }
  127. return state;
  128. };
  129. export const slideHandler = spec => {
  130. const {
  131. waitForAnimate,
  132. animating,
  133. fade,
  134. infinite,
  135. index,
  136. slideCount,
  137. lazyLoad,
  138. currentSlide,
  139. centerMode,
  140. slidesToScroll,
  141. slidesToShow,
  142. useCSS
  143. } = spec;
  144. let {
  145. lazyLoadedList
  146. } = spec;
  147. if (waitForAnimate && animating) return {};
  148. let animationSlide = index;
  149. let finalSlide;
  150. let animationLeft;
  151. let finalLeft;
  152. let state = {};
  153. let nextState = {};
  154. const targetSlide = infinite ? index : clamp(index, 0, slideCount - 1);
  155. if (fade) {
  156. if (!infinite && (index < 0 || index >= slideCount)) return {};
  157. if (index < 0) {
  158. animationSlide = index + slideCount;
  159. } else if (index >= slideCount) {
  160. animationSlide = index - slideCount;
  161. }
  162. if (lazyLoad && lazyLoadedList.indexOf(animationSlide) < 0) {
  163. lazyLoadedList = lazyLoadedList.concat(animationSlide);
  164. }
  165. state = {
  166. animating: true,
  167. currentSlide: animationSlide,
  168. lazyLoadedList,
  169. targetSlide: animationSlide
  170. };
  171. nextState = {
  172. animating: false,
  173. targetSlide: animationSlide
  174. };
  175. } else {
  176. finalSlide = animationSlide;
  177. if (animationSlide < 0) {
  178. finalSlide = animationSlide + slideCount;
  179. if (!infinite) finalSlide = 0;else if (slideCount % slidesToScroll !== 0) {
  180. finalSlide = slideCount - slideCount % slidesToScroll;
  181. }
  182. } else if (!canGoNext(spec) && animationSlide > currentSlide) {
  183. animationSlide = finalSlide = currentSlide;
  184. } else if (centerMode && animationSlide >= slideCount) {
  185. animationSlide = infinite ? slideCount : slideCount - 1;
  186. finalSlide = infinite ? 0 : slideCount - 1;
  187. } else if (animationSlide >= slideCount) {
  188. finalSlide = animationSlide - slideCount;
  189. if (!infinite) finalSlide = slideCount - slidesToShow;else if (slideCount % slidesToScroll !== 0) finalSlide = 0;
  190. }
  191. if (!infinite && animationSlide + slidesToShow >= slideCount) {
  192. finalSlide = slideCount - slidesToShow;
  193. }
  194. animationLeft = getTrackLeft(_extends(_extends({}, spec), {
  195. slideIndex: animationSlide
  196. }));
  197. finalLeft = getTrackLeft(_extends(_extends({}, spec), {
  198. slideIndex: finalSlide
  199. }));
  200. if (!infinite) {
  201. if (animationLeft === finalLeft) animationSlide = finalSlide;
  202. animationLeft = finalLeft;
  203. }
  204. if (lazyLoad) {
  205. lazyLoadedList = lazyLoadedList.concat(getOnDemandLazySlides(_extends(_extends({}, spec), {
  206. currentSlide: animationSlide
  207. })));
  208. }
  209. if (!useCSS) {
  210. state = {
  211. currentSlide: finalSlide,
  212. trackStyle: getTrackCSS(_extends(_extends({}, spec), {
  213. left: finalLeft
  214. })),
  215. lazyLoadedList,
  216. targetSlide
  217. };
  218. } else {
  219. state = {
  220. animating: true,
  221. currentSlide: finalSlide,
  222. trackStyle: getTrackAnimateCSS(_extends(_extends({}, spec), {
  223. left: animationLeft
  224. })),
  225. lazyLoadedList,
  226. targetSlide
  227. };
  228. nextState = {
  229. animating: false,
  230. currentSlide: finalSlide,
  231. trackStyle: getTrackCSS(_extends(_extends({}, spec), {
  232. left: finalLeft
  233. })),
  234. swipeLeft: null,
  235. targetSlide
  236. };
  237. }
  238. }
  239. return {
  240. state,
  241. nextState
  242. };
  243. };
  244. export const changeSlide = (spec, options) => {
  245. let previousInt, slideOffset, targetSlide;
  246. const {
  247. slidesToScroll,
  248. slidesToShow,
  249. slideCount,
  250. currentSlide,
  251. targetSlide: previousTargetSlide,
  252. lazyLoad,
  253. infinite
  254. } = spec;
  255. const unevenOffset = slideCount % slidesToScroll !== 0;
  256. const indexOffset = unevenOffset ? 0 : (slideCount - currentSlide) % slidesToScroll;
  257. if (options.message === 'previous') {
  258. slideOffset = indexOffset === 0 ? slidesToScroll : slidesToShow - indexOffset;
  259. targetSlide = currentSlide - slideOffset;
  260. if (lazyLoad && !infinite) {
  261. previousInt = currentSlide - slideOffset;
  262. targetSlide = previousInt === -1 ? slideCount - 1 : previousInt;
  263. }
  264. if (!infinite) {
  265. targetSlide = previousTargetSlide - slidesToScroll;
  266. }
  267. } else if (options.message === 'next') {
  268. slideOffset = indexOffset === 0 ? slidesToScroll : indexOffset;
  269. targetSlide = currentSlide + slideOffset;
  270. if (lazyLoad && !infinite) {
  271. targetSlide = (currentSlide + slidesToScroll) % slideCount + indexOffset;
  272. }
  273. if (!infinite) {
  274. targetSlide = previousTargetSlide + slidesToScroll;
  275. }
  276. } else if (options.message === 'dots') {
  277. // Click on dots
  278. targetSlide = options.index * options.slidesToScroll;
  279. } else if (options.message === 'children') {
  280. // Click on the slides
  281. targetSlide = options.index;
  282. if (infinite) {
  283. const direction = siblingDirection(_extends(_extends({}, spec), {
  284. targetSlide
  285. }));
  286. if (targetSlide > options.currentSlide && direction === 'left') {
  287. targetSlide = targetSlide - slideCount;
  288. } else if (targetSlide < options.currentSlide && direction === 'right') {
  289. targetSlide = targetSlide + slideCount;
  290. }
  291. }
  292. } else if (options.message === 'index') {
  293. targetSlide = Number(options.index);
  294. }
  295. return targetSlide;
  296. };
  297. export const keyHandler = (e, accessibility, rtl) => {
  298. if (e.target.tagName.match('TEXTAREA|INPUT|SELECT') || !accessibility) {
  299. return '';
  300. }
  301. if (e.keyCode === 37) return rtl ? 'next' : 'previous';
  302. if (e.keyCode === 39) return rtl ? 'previous' : 'next';
  303. return '';
  304. };
  305. export const swipeStart = (e, swipe, draggable) => {
  306. e.target.tagName === 'IMG' && safePreventDefault(e);
  307. if (!swipe || !draggable && e.type.indexOf('mouse') !== -1) return '';
  308. return {
  309. dragging: true,
  310. touchObject: {
  311. startX: e.touches ? e.touches[0].pageX : e.clientX,
  312. startY: e.touches ? e.touches[0].pageY : e.clientY,
  313. curX: e.touches ? e.touches[0].pageX : e.clientX,
  314. curY: e.touches ? e.touches[0].pageY : e.clientY
  315. }
  316. };
  317. };
  318. export const swipeMove = (e, spec) => {
  319. // spec also contains, trackRef and slideIndex
  320. const {
  321. scrolling,
  322. animating,
  323. vertical,
  324. swipeToSlide,
  325. verticalSwiping,
  326. rtl,
  327. currentSlide,
  328. edgeFriction,
  329. edgeDragged,
  330. onEdge,
  331. swiped,
  332. swiping,
  333. slideCount,
  334. slidesToScroll,
  335. infinite,
  336. touchObject,
  337. swipeEvent,
  338. listHeight,
  339. listWidth
  340. } = spec;
  341. if (scrolling) return;
  342. if (animating) return safePreventDefault(e);
  343. if (vertical && swipeToSlide && verticalSwiping) safePreventDefault(e);
  344. let swipeLeft;
  345. let state = {};
  346. const curLeft = getTrackLeft(spec);
  347. touchObject.curX = e.touches ? e.touches[0].pageX : e.clientX;
  348. touchObject.curY = e.touches ? e.touches[0].pageY : e.clientY;
  349. touchObject.swipeLength = Math.round(Math.sqrt(Math.pow(touchObject.curX - touchObject.startX, 2)));
  350. const verticalSwipeLength = Math.round(Math.sqrt(Math.pow(touchObject.curY - touchObject.startY, 2)));
  351. if (!verticalSwiping && !swiping && verticalSwipeLength > 10) {
  352. return {
  353. scrolling: true
  354. };
  355. }
  356. if (verticalSwiping) touchObject.swipeLength = verticalSwipeLength;
  357. let positionOffset = (!rtl ? 1 : -1) * (touchObject.curX > touchObject.startX ? 1 : -1);
  358. if (verticalSwiping) {
  359. positionOffset = touchObject.curY > touchObject.startY ? 1 : -1;
  360. }
  361. const dotCount = Math.ceil(slideCount / slidesToScroll);
  362. const swipeDirection = getSwipeDirection(spec.touchObject, verticalSwiping);
  363. let touchSwipeLength = touchObject.swipeLength;
  364. if (!infinite) {
  365. if (currentSlide === 0 && (swipeDirection === 'right' || swipeDirection === 'down') || currentSlide + 1 >= dotCount && (swipeDirection === 'left' || swipeDirection === 'up') || !canGoNext(spec) && (swipeDirection === 'left' || swipeDirection === 'up')) {
  366. touchSwipeLength = touchObject.swipeLength * edgeFriction;
  367. if (edgeDragged === false && onEdge) {
  368. onEdge(swipeDirection);
  369. state['edgeDragged'] = true;
  370. }
  371. }
  372. }
  373. if (!swiped && swipeEvent) {
  374. swipeEvent(swipeDirection);
  375. state['swiped'] = true;
  376. }
  377. if (!vertical) {
  378. if (!rtl) {
  379. swipeLeft = curLeft + touchSwipeLength * positionOffset;
  380. } else {
  381. swipeLeft = curLeft - touchSwipeLength * positionOffset;
  382. }
  383. } else {
  384. swipeLeft = curLeft + touchSwipeLength * (listHeight / listWidth) * positionOffset;
  385. }
  386. if (verticalSwiping) {
  387. swipeLeft = curLeft + touchSwipeLength * positionOffset;
  388. }
  389. state = _extends(_extends({}, state), {
  390. touchObject,
  391. swipeLeft,
  392. trackStyle: getTrackCSS(_extends(_extends({}, spec), {
  393. left: swipeLeft
  394. }))
  395. });
  396. if (Math.abs(touchObject.curX - touchObject.startX) < Math.abs(touchObject.curY - touchObject.startY) * 0.8) {
  397. return state;
  398. }
  399. if (touchObject.swipeLength > 10) {
  400. state['swiping'] = true;
  401. safePreventDefault(e);
  402. }
  403. return state;
  404. };
  405. export const swipeEnd = (e, spec) => {
  406. const {
  407. dragging,
  408. swipe,
  409. touchObject,
  410. listWidth,
  411. touchThreshold,
  412. verticalSwiping,
  413. listHeight,
  414. swipeToSlide,
  415. scrolling,
  416. onSwipe,
  417. targetSlide,
  418. currentSlide,
  419. infinite
  420. } = spec;
  421. if (!dragging) {
  422. if (swipe) safePreventDefault(e);
  423. return {};
  424. }
  425. const minSwipe = verticalSwiping ? listHeight / touchThreshold : listWidth / touchThreshold;
  426. const swipeDirection = getSwipeDirection(touchObject, verticalSwiping);
  427. // reset the state of touch related state variables.
  428. const state = {
  429. dragging: false,
  430. edgeDragged: false,
  431. scrolling: false,
  432. swiping: false,
  433. swiped: false,
  434. swipeLeft: null,
  435. touchObject: {}
  436. };
  437. if (scrolling) {
  438. return state;
  439. }
  440. if (!touchObject.swipeLength) {
  441. return state;
  442. }
  443. if (touchObject.swipeLength > minSwipe) {
  444. safePreventDefault(e);
  445. if (onSwipe) {
  446. onSwipe(swipeDirection);
  447. }
  448. let slideCount, newSlide;
  449. const activeSlide = infinite ? currentSlide : targetSlide;
  450. switch (swipeDirection) {
  451. case 'left':
  452. case 'up':
  453. newSlide = activeSlide + getSlideCount(spec);
  454. slideCount = swipeToSlide ? checkNavigable(spec, newSlide) : newSlide;
  455. state['currentDirection'] = 0;
  456. break;
  457. case 'right':
  458. case 'down':
  459. newSlide = activeSlide - getSlideCount(spec);
  460. slideCount = swipeToSlide ? checkNavigable(spec, newSlide) : newSlide;
  461. state['currentDirection'] = 1;
  462. break;
  463. default:
  464. slideCount = activeSlide;
  465. }
  466. state['triggerSlideHandler'] = slideCount;
  467. } else {
  468. // Adjust the track back to it's original position.
  469. const currentLeft = getTrackLeft(spec);
  470. state['trackStyle'] = getTrackAnimateCSS(_extends(_extends({}, spec), {
  471. left: currentLeft
  472. }));
  473. }
  474. return state;
  475. };
  476. export const getNavigableIndexes = spec => {
  477. const max = spec.infinite ? spec.slideCount * 2 : spec.slideCount;
  478. let breakpoint = spec.infinite ? spec.slidesToShow * -1 : 0;
  479. let counter = spec.infinite ? spec.slidesToShow * -1 : 0;
  480. const indexes = [];
  481. while (breakpoint < max) {
  482. indexes.push(breakpoint);
  483. breakpoint = counter + spec.slidesToScroll;
  484. counter += Math.min(spec.slidesToScroll, spec.slidesToShow);
  485. }
  486. return indexes;
  487. };
  488. export const checkNavigable = (spec, index) => {
  489. const navigables = getNavigableIndexes(spec);
  490. let prevNavigable = 0;
  491. if (index > navigables[navigables.length - 1]) {
  492. index = navigables[navigables.length - 1];
  493. } else {
  494. for (const n in navigables) {
  495. if (index < navigables[n]) {
  496. index = prevNavigable;
  497. break;
  498. }
  499. prevNavigable = navigables[n];
  500. }
  501. }
  502. return index;
  503. };
  504. export const getSlideCount = spec => {
  505. const centerOffset = spec.centerMode ? spec.slideWidth * Math.floor(spec.slidesToShow / 2) : 0;
  506. if (spec.swipeToSlide) {
  507. let swipedSlide;
  508. const slickList = spec.listRef;
  509. const slides = slickList.querySelectorAll && slickList.querySelectorAll('.slick-slide') || [];
  510. Array.from(slides).every(slide => {
  511. if (!spec.vertical) {
  512. if (slide.offsetLeft - centerOffset + getWidth(slide) / 2 > spec.swipeLeft * -1) {
  513. swipedSlide = slide;
  514. return false;
  515. }
  516. } else {
  517. if (slide.offsetTop + getHeight(slide) / 2 > spec.swipeLeft * -1) {
  518. swipedSlide = slide;
  519. return false;
  520. }
  521. }
  522. return true;
  523. });
  524. if (!swipedSlide) {
  525. return 0;
  526. }
  527. const currentIndex = spec.rtl === true ? spec.slideCount - spec.currentSlide : spec.currentSlide;
  528. const slidesTraversed = Math.abs(swipedSlide.dataset.index - currentIndex) || 1;
  529. return slidesTraversed;
  530. } else {
  531. return spec.slidesToScroll;
  532. }
  533. };
  534. export const checkSpecKeys = (spec, keysArray) => keysArray.reduce((value, key) => value && spec.hasOwnProperty(key), true) ? null : console.error('Keys Missing:', spec);
  535. export const getTrackCSS = spec => {
  536. checkSpecKeys(spec, ['left', 'variableWidth', 'slideCount', 'slidesToShow', 'slideWidth']);
  537. let trackWidth, trackHeight;
  538. const trackChildren = spec.slideCount + 2 * spec.slidesToShow;
  539. if (!spec.vertical) {
  540. trackWidth = getTotalSlides(spec) * spec.slideWidth;
  541. } else {
  542. trackHeight = trackChildren * spec.slideHeight;
  543. }
  544. let style = {
  545. opacity: 1,
  546. transition: '',
  547. WebkitTransition: ''
  548. };
  549. if (spec.useTransform) {
  550. const WebkitTransform = !spec.vertical ? 'translate3d(' + spec.left + 'px, 0px, 0px)' : 'translate3d(0px, ' + spec.left + 'px, 0px)';
  551. const transform = !spec.vertical ? 'translate3d(' + spec.left + 'px, 0px, 0px)' : 'translate3d(0px, ' + spec.left + 'px, 0px)';
  552. const msTransform = !spec.vertical ? 'translateX(' + spec.left + 'px)' : 'translateY(' + spec.left + 'px)';
  553. style = _extends(_extends({}, style), {
  554. WebkitTransform,
  555. transform,
  556. msTransform
  557. });
  558. } else {
  559. if (spec.vertical) {
  560. style['top'] = spec.left;
  561. } else {
  562. style['left'] = spec.left;
  563. }
  564. }
  565. if (spec.fade) style = {
  566. opacity: 1
  567. };
  568. if (trackWidth) style.width = trackWidth + 'px';
  569. if (trackHeight) style.height = trackHeight + 'px';
  570. // Fallback for IE8
  571. if (window && !window.addEventListener && window.attachEvent) {
  572. if (!spec.vertical) {
  573. style.marginLeft = spec.left + 'px';
  574. } else {
  575. style.marginTop = spec.left + 'px';
  576. }
  577. }
  578. return style;
  579. };
  580. export const getTrackAnimateCSS = spec => {
  581. checkSpecKeys(spec, ['left', 'variableWidth', 'slideCount', 'slidesToShow', 'slideWidth', 'speed', 'cssEase']);
  582. const style = getTrackCSS(spec);
  583. // useCSS is true by default so it can be undefined
  584. if (spec.useTransform) {
  585. style.WebkitTransition = '-webkit-transform ' + spec.speed + 'ms ' + spec.cssEase;
  586. style.transition = 'transform ' + spec.speed + 'ms ' + spec.cssEase;
  587. } else {
  588. if (spec.vertical) {
  589. style.transition = 'top ' + spec.speed + 'ms ' + spec.cssEase;
  590. } else {
  591. style.transition = 'left ' + spec.speed + 'ms ' + spec.cssEase;
  592. }
  593. }
  594. return style;
  595. };
  596. export const getTrackLeft = spec => {
  597. if (spec.unslick) {
  598. return 0;
  599. }
  600. checkSpecKeys(spec, ['slideIndex', 'trackRef', 'infinite', 'centerMode', 'slideCount', 'slidesToShow', 'slidesToScroll', 'slideWidth', 'listWidth', 'variableWidth', 'slideHeight']);
  601. const {
  602. slideIndex,
  603. trackRef,
  604. infinite,
  605. centerMode,
  606. slideCount,
  607. slidesToShow,
  608. slidesToScroll,
  609. slideWidth,
  610. listWidth,
  611. variableWidth,
  612. slideHeight,
  613. fade,
  614. vertical
  615. } = spec;
  616. let slideOffset = 0;
  617. let targetLeft;
  618. let targetSlide;
  619. let verticalOffset = 0;
  620. if (fade || spec.slideCount === 1) {
  621. return 0;
  622. }
  623. let slidesToOffset = 0;
  624. if (infinite) {
  625. slidesToOffset = -getPreClones(spec); // bring active slide to the beginning of visual area
  626. // if next scroll doesn't have enough children, just reach till the end of original slides instead of shifting slidesToScroll children
  627. if (slideCount % slidesToScroll !== 0 && slideIndex + slidesToScroll > slideCount) {
  628. slidesToOffset = -(slideIndex > slideCount ? slidesToShow - (slideIndex - slideCount) : slideCount % slidesToScroll);
  629. }
  630. // shift current slide to center of the frame
  631. if (centerMode) {
  632. slidesToOffset += parseInt(slidesToShow / 2);
  633. }
  634. } else {
  635. if (slideCount % slidesToScroll !== 0 && slideIndex + slidesToScroll > slideCount) {
  636. slidesToOffset = slidesToShow - slideCount % slidesToScroll;
  637. }
  638. if (centerMode) {
  639. slidesToOffset = parseInt(slidesToShow / 2);
  640. }
  641. }
  642. slideOffset = slidesToOffset * slideWidth;
  643. verticalOffset = slidesToOffset * slideHeight;
  644. if (!vertical) {
  645. targetLeft = slideIndex * slideWidth * -1 + slideOffset;
  646. } else {
  647. targetLeft = slideIndex * slideHeight * -1 + verticalOffset;
  648. }
  649. if (variableWidth === true) {
  650. let targetSlideIndex;
  651. const trackElem = trackRef;
  652. targetSlideIndex = slideIndex + getPreClones(spec);
  653. targetSlide = trackElem && trackElem.childNodes[targetSlideIndex];
  654. targetLeft = targetSlide ? targetSlide.offsetLeft * -1 : 0;
  655. if (centerMode === true) {
  656. targetSlideIndex = infinite ? slideIndex + getPreClones(spec) : slideIndex;
  657. targetSlide = trackElem && trackElem.children[targetSlideIndex];
  658. targetLeft = 0;
  659. for (let slide = 0; slide < targetSlideIndex; slide++) {
  660. targetLeft -= trackElem && trackElem.children[slide] && trackElem.children[slide].offsetWidth;
  661. }
  662. targetLeft -= parseInt(spec.centerPadding);
  663. targetLeft += targetSlide && (listWidth - targetSlide.offsetWidth) / 2;
  664. }
  665. }
  666. return targetLeft;
  667. };
  668. export const getPreClones = spec => {
  669. if (spec.unslick || !spec.infinite) {
  670. return 0;
  671. }
  672. if (spec.variableWidth) {
  673. return spec.slideCount;
  674. }
  675. return spec.slidesToShow + (spec.centerMode ? 1 : 0);
  676. };
  677. export const getPostClones = spec => {
  678. if (spec.unslick || !spec.infinite) {
  679. return 0;
  680. }
  681. return spec.slideCount;
  682. };
  683. export const getTotalSlides = spec => spec.slideCount === 1 ? 1 : getPreClones(spec) + spec.slideCount + getPostClones(spec);
  684. export const siblingDirection = spec => {
  685. if (spec.targetSlide > spec.currentSlide) {
  686. if (spec.targetSlide > spec.currentSlide + slidesOnRight(spec)) {
  687. return 'left';
  688. }
  689. return 'right';
  690. } else {
  691. if (spec.targetSlide < spec.currentSlide - slidesOnLeft(spec)) {
  692. return 'right';
  693. }
  694. return 'left';
  695. }
  696. };
  697. export const slidesOnRight = _ref => {
  698. let {
  699. slidesToShow,
  700. centerMode,
  701. rtl,
  702. centerPadding
  703. } = _ref;
  704. // returns no of slides on the right of active slide
  705. if (centerMode) {
  706. let right = (slidesToShow - 1) / 2 + 1;
  707. if (parseInt(centerPadding) > 0) right += 1;
  708. if (rtl && slidesToShow % 2 === 0) right += 1;
  709. return right;
  710. }
  711. if (rtl) {
  712. return 0;
  713. }
  714. return slidesToShow - 1;
  715. };
  716. export const slidesOnLeft = _ref2 => {
  717. let {
  718. slidesToShow,
  719. centerMode,
  720. rtl,
  721. centerPadding
  722. } = _ref2;
  723. // returns no of slides on the left of active slide
  724. if (centerMode) {
  725. let left = (slidesToShow - 1) / 2 + 1;
  726. if (parseInt(centerPadding) > 0) left += 1;
  727. if (!rtl && slidesToShow % 2 === 0) left += 1;
  728. return left;
  729. }
  730. if (rtl) {
  731. return slidesToShow - 1;
  732. }
  733. return 0;
  734. };
  735. export const canUseDOM = () => !!(typeof window !== 'undefined' && window.document && window.document.createElement);