carousel.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  2. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  3. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  4. /**
  5. * --------------------------------------------------------------------------
  6. * Bootstrap (v4.0.0-alpha.6): carousel.js
  7. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8. * --------------------------------------------------------------------------
  9. */
  10. var Carousel = function ($) {
  11. /**
  12. * ------------------------------------------------------------------------
  13. * Constants
  14. * ------------------------------------------------------------------------
  15. */
  16. var NAME = 'carousel';
  17. var VERSION = '4.0.0-alpha.6';
  18. var DATA_KEY = 'bs.carousel';
  19. var EVENT_KEY = '.' + DATA_KEY;
  20. var DATA_API_KEY = '.data-api';
  21. var JQUERY_NO_CONFLICT = $.fn[NAME];
  22. var TRANSITION_DURATION = 600;
  23. var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
  24. var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
  25. var Default = {
  26. interval: 5000,
  27. keyboard: true,
  28. slide: false,
  29. pause: 'hover',
  30. wrap: true
  31. };
  32. var DefaultType = {
  33. interval: '(number|boolean)',
  34. keyboard: 'boolean',
  35. slide: '(boolean|string)',
  36. pause: '(string|boolean)',
  37. wrap: 'boolean'
  38. };
  39. var Direction = {
  40. NEXT: 'next',
  41. PREV: 'prev',
  42. LEFT: 'left',
  43. RIGHT: 'right'
  44. };
  45. var Event = {
  46. SLIDE: 'slide' + EVENT_KEY,
  47. SLID: 'slid' + EVENT_KEY,
  48. KEYDOWN: 'keydown' + EVENT_KEY,
  49. MOUSEENTER: 'mouseenter' + EVENT_KEY,
  50. MOUSELEAVE: 'mouseleave' + EVENT_KEY,
  51. LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY,
  52. CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
  53. };
  54. var ClassName = {
  55. CAROUSEL: 'carousel',
  56. ACTIVE: 'active',
  57. SLIDE: 'slide',
  58. RIGHT: 'carousel-item-right',
  59. LEFT: 'carousel-item-left',
  60. NEXT: 'carousel-item-next',
  61. PREV: 'carousel-item-prev',
  62. ITEM: 'carousel-item'
  63. };
  64. var Selector = {
  65. ACTIVE: '.active',
  66. ACTIVE_ITEM: '.active.carousel-item',
  67. ITEM: '.carousel-item',
  68. NEXT_PREV: '.carousel-item-next, .carousel-item-prev',
  69. INDICATORS: '.carousel-indicators',
  70. DATA_SLIDE: '[data-slide], [data-slide-to]',
  71. DATA_RIDE: '[data-ride="carousel"]'
  72. };
  73. /**
  74. * ------------------------------------------------------------------------
  75. * Class Definition
  76. * ------------------------------------------------------------------------
  77. */
  78. var Carousel = function () {
  79. function Carousel(element, config) {
  80. _classCallCheck(this, Carousel);
  81. this._items = null;
  82. this._interval = null;
  83. this._activeElement = null;
  84. this._isPaused = false;
  85. this._isSliding = false;
  86. this._config = this._getConfig(config);
  87. this._element = $(element)[0];
  88. this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];
  89. this._addEventListeners();
  90. }
  91. // getters
  92. // public
  93. Carousel.prototype.next = function next() {
  94. if (this._isSliding) {
  95. throw new Error('Carousel is sliding');
  96. }
  97. this._slide(Direction.NEXT);
  98. };
  99. Carousel.prototype.nextWhenVisible = function nextWhenVisible() {
  100. // Don't call next when the page isn't visible
  101. if (!document.hidden) {
  102. this.next();
  103. }
  104. };
  105. Carousel.prototype.prev = function prev() {
  106. if (this._isSliding) {
  107. throw new Error('Carousel is sliding');
  108. }
  109. this._slide(Direction.PREV);
  110. };
  111. Carousel.prototype.pause = function pause(event) {
  112. if (!event) {
  113. this._isPaused = true;
  114. }
  115. if ($(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) {
  116. Util.triggerTransitionEnd(this._element);
  117. this.cycle(true);
  118. }
  119. clearInterval(this._interval);
  120. this._interval = null;
  121. };
  122. Carousel.prototype.cycle = function cycle(event) {
  123. if (!event) {
  124. this._isPaused = false;
  125. }
  126. if (this._interval) {
  127. clearInterval(this._interval);
  128. this._interval = null;
  129. }
  130. if (this._config.interval && !this._isPaused) {
  131. this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
  132. }
  133. };
  134. Carousel.prototype.to = function to(index) {
  135. var _this = this;
  136. this._activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
  137. var activeIndex = this._getItemIndex(this._activeElement);
  138. if (index > this._items.length - 1 || index < 0) {
  139. return;
  140. }
  141. if (this._isSliding) {
  142. $(this._element).one(Event.SLID, function () {
  143. return _this.to(index);
  144. });
  145. return;
  146. }
  147. if (activeIndex === index) {
  148. this.pause();
  149. this.cycle();
  150. return;
  151. }
  152. var direction = index > activeIndex ? Direction.NEXT : Direction.PREV;
  153. this._slide(direction, this._items[index]);
  154. };
  155. Carousel.prototype.dispose = function dispose() {
  156. $(this._element).off(EVENT_KEY);
  157. $.removeData(this._element, DATA_KEY);
  158. this._items = null;
  159. this._config = null;
  160. this._element = null;
  161. this._interval = null;
  162. this._isPaused = null;
  163. this._isSliding = null;
  164. this._activeElement = null;
  165. this._indicatorsElement = null;
  166. };
  167. // private
  168. Carousel.prototype._getConfig = function _getConfig(config) {
  169. config = $.extend({}, Default, config);
  170. Util.typeCheckConfig(NAME, config, DefaultType);
  171. return config;
  172. };
  173. Carousel.prototype._addEventListeners = function _addEventListeners() {
  174. var _this2 = this;
  175. if (this._config.keyboard) {
  176. $(this._element).on(Event.KEYDOWN, function (event) {
  177. return _this2._keydown(event);
  178. });
  179. }
  180. if (this._config.pause === 'hover' && !('ontouchstart' in document.documentElement)) {
  181. $(this._element).on(Event.MOUSEENTER, function (event) {
  182. return _this2.pause(event);
  183. }).on(Event.MOUSELEAVE, function (event) {
  184. return _this2.cycle(event);
  185. });
  186. }
  187. };
  188. Carousel.prototype._keydown = function _keydown(event) {
  189. if (/input|textarea/i.test(event.target.tagName)) {
  190. return;
  191. }
  192. switch (event.which) {
  193. case ARROW_LEFT_KEYCODE:
  194. event.preventDefault();
  195. this.prev();
  196. break;
  197. case ARROW_RIGHT_KEYCODE:
  198. event.preventDefault();
  199. this.next();
  200. break;
  201. default:
  202. return;
  203. }
  204. };
  205. Carousel.prototype._getItemIndex = function _getItemIndex(element) {
  206. this._items = $.makeArray($(element).parent().find(Selector.ITEM));
  207. return this._items.indexOf(element);
  208. };
  209. Carousel.prototype._getItemByDirection = function _getItemByDirection(direction, activeElement) {
  210. var isNextDirection = direction === Direction.NEXT;
  211. var isPrevDirection = direction === Direction.PREV;
  212. var activeIndex = this._getItemIndex(activeElement);
  213. var lastItemIndex = this._items.length - 1;
  214. var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
  215. if (isGoingToWrap && !this._config.wrap) {
  216. return activeElement;
  217. }
  218. var delta = direction === Direction.PREV ? -1 : 1;
  219. var itemIndex = (activeIndex + delta) % this._items.length;
  220. return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
  221. };
  222. Carousel.prototype._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {
  223. var slideEvent = $.Event(Event.SLIDE, {
  224. relatedTarget: relatedTarget,
  225. direction: eventDirectionName
  226. });
  227. $(this._element).trigger(slideEvent);
  228. return slideEvent;
  229. };
  230. Carousel.prototype._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
  231. if (this._indicatorsElement) {
  232. $(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
  233. var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
  234. if (nextIndicator) {
  235. $(nextIndicator).addClass(ClassName.ACTIVE);
  236. }
  237. }
  238. };
  239. Carousel.prototype._slide = function _slide(direction, element) {
  240. var _this3 = this;
  241. var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
  242. var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
  243. var isCycling = Boolean(this._interval);
  244. var directionalClassName = void 0;
  245. var orderClassName = void 0;
  246. var eventDirectionName = void 0;
  247. if (direction === Direction.NEXT) {
  248. directionalClassName = ClassName.LEFT;
  249. orderClassName = ClassName.NEXT;
  250. eventDirectionName = Direction.LEFT;
  251. } else {
  252. directionalClassName = ClassName.RIGHT;
  253. orderClassName = ClassName.PREV;
  254. eventDirectionName = Direction.RIGHT;
  255. }
  256. if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {
  257. this._isSliding = false;
  258. return;
  259. }
  260. var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
  261. if (slideEvent.isDefaultPrevented()) {
  262. return;
  263. }
  264. if (!activeElement || !nextElement) {
  265. // some weirdness is happening, so we bail
  266. return;
  267. }
  268. this._isSliding = true;
  269. if (isCycling) {
  270. this.pause();
  271. }
  272. this._setActiveIndicatorElement(nextElement);
  273. var slidEvent = $.Event(Event.SLID, {
  274. relatedTarget: nextElement,
  275. direction: eventDirectionName
  276. });
  277. if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) {
  278. $(nextElement).addClass(orderClassName);
  279. Util.reflow(nextElement);
  280. $(activeElement).addClass(directionalClassName);
  281. $(nextElement).addClass(directionalClassName);
  282. $(activeElement).one(Util.TRANSITION_END, function () {
  283. $(nextElement).removeClass(directionalClassName + ' ' + orderClassName).addClass(ClassName.ACTIVE);
  284. $(activeElement).removeClass(ClassName.ACTIVE + ' ' + orderClassName + ' ' + directionalClassName);
  285. _this3._isSliding = false;
  286. setTimeout(function () {
  287. return $(_this3._element).trigger(slidEvent);
  288. }, 0);
  289. }).emulateTransitionEnd(TRANSITION_DURATION);
  290. } else {
  291. $(activeElement).removeClass(ClassName.ACTIVE);
  292. $(nextElement).addClass(ClassName.ACTIVE);
  293. this._isSliding = false;
  294. $(this._element).trigger(slidEvent);
  295. }
  296. if (isCycling) {
  297. this.cycle();
  298. }
  299. };
  300. // static
  301. Carousel._jQueryInterface = function _jQueryInterface(config) {
  302. return this.each(function () {
  303. var data = $(this).data(DATA_KEY);
  304. var _config = $.extend({}, Default, $(this).data());
  305. if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') {
  306. $.extend(_config, config);
  307. }
  308. var action = typeof config === 'string' ? config : _config.slide;
  309. if (!data) {
  310. data = new Carousel(this, _config);
  311. $(this).data(DATA_KEY, data);
  312. }
  313. if (typeof config === 'number') {
  314. data.to(config);
  315. } else if (typeof action === 'string') {
  316. if (data[action] === undefined) {
  317. throw new Error('No method named "' + action + '"');
  318. }
  319. data[action]();
  320. } else if (_config.interval) {
  321. data.pause();
  322. data.cycle();
  323. }
  324. });
  325. };
  326. Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
  327. var selector = Util.getSelectorFromElement(this);
  328. if (!selector) {
  329. return;
  330. }
  331. var target = $(selector)[0];
  332. if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {
  333. return;
  334. }
  335. var config = $.extend({}, $(target).data(), $(this).data());
  336. var slideIndex = this.getAttribute('data-slide-to');
  337. if (slideIndex) {
  338. config.interval = false;
  339. }
  340. Carousel._jQueryInterface.call($(target), config);
  341. if (slideIndex) {
  342. $(target).data(DATA_KEY).to(slideIndex);
  343. }
  344. event.preventDefault();
  345. };
  346. _createClass(Carousel, null, [{
  347. key: 'VERSION',
  348. get: function get() {
  349. return VERSION;
  350. }
  351. }, {
  352. key: 'Default',
  353. get: function get() {
  354. return Default;
  355. }
  356. }]);
  357. return Carousel;
  358. }();
  359. /**
  360. * ------------------------------------------------------------------------
  361. * Data Api implementation
  362. * ------------------------------------------------------------------------
  363. */
  364. $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);
  365. $(window).on(Event.LOAD_DATA_API, function () {
  366. $(Selector.DATA_RIDE).each(function () {
  367. var $carousel = $(this);
  368. Carousel._jQueryInterface.call($carousel, $carousel.data());
  369. });
  370. });
  371. /**
  372. * ------------------------------------------------------------------------
  373. * jQuery
  374. * ------------------------------------------------------------------------
  375. */
  376. $.fn[NAME] = Carousel._jQueryInterface;
  377. $.fn[NAME].Constructor = Carousel;
  378. $.fn[NAME].noConflict = function () {
  379. $.fn[NAME] = JQUERY_NO_CONFLICT;
  380. return Carousel._jQueryInterface;
  381. };
  382. return Carousel;
  383. }(jQuery);
  384. //# sourceMappingURL=carousel.js.map