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; }; }(); var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } (function ($, anim) { 'use strict'; var _defaults = { duration: 300, onShow: null, swipeable: false, responsiveThreshold: Infinity // breakpoint for swipeable }; /** * @class * */ var Tabs = function (_Component) { _inherits(Tabs, _Component); /** * Construct Tabs instance * @constructor * @param {Element} el * @param {Object} options */ function Tabs(el, options) { _classCallCheck(this, Tabs); var _this = _possibleConstructorReturn(this, (Tabs.__proto__ || Object.getPrototypeOf(Tabs)).call(this, Tabs, el, options)); _this.el.M_Tabs = _this; /** * Options for the Tabs * @member Tabs#options * @prop {Number} duration * @prop {Function} onShow * @prop {Boolean} swipeable * @prop {Number} responsiveThreshold */ _this.options = $.extend({}, Tabs.defaults, options); // Setup _this.$tabLinks = _this.$el.children('li.tab').children('a'); _this.index = 0; _this._setTabsAndTabWidth(); _this._setupActiveTabLink(); _this._createIndicator(); if (_this.options.swipeable) { _this._setupSwipeableTabs(); } else { _this._setupNormalTabs(); } _this._setupEventHandlers(); return _this; } _createClass(Tabs, [{ key: 'destroy', /** * Teardown component */ value: function destroy() { this._removeEventHandlers(); this._indicator.parentNode.removeChild(this._indicator); if (this.options.swipeable) { this._teardownSwipeableTabs(); } else { this._teardownNormalTabs(); } this.$el[0].M_Tabs = undefined; } /** * Setup Event Handlers */ }, { key: '_setupEventHandlers', value: function _setupEventHandlers() { this._handleWindowResizeBound = this._handleWindowResize.bind(this); window.addEventListener('resize', this._handleWindowResizeBound); this._handleTabClickBound = this._handleTabClick.bind(this); this.el.addEventListener('click', this._handleTabClickBound); } /** * Remove Event Handlers */ }, { key: '_removeEventHandlers', value: function _removeEventHandlers() { window.removeEventListener('resize', this._handleWindowResizeBound); this.el.removeEventListener('click', this._handleTabClickBound); } /** * Handle window Resize */ }, { key: '_handleWindowResize', value: function _handleWindowResize() { this._setTabsAndTabWidth(); if (this.tabWidth !== 0 && this.tabsWidth !== 0) { this._indicator.style.left = this._calcLeftPos(this.$activeTabLink) + 'px'; this._indicator.style.right = this._calcRightPos(this.$activeTabLink) + 'px'; } } /** * Handle tab click * @param {Event} e */ }, { key: '_handleTabClick', value: function _handleTabClick(e) { var _this2 = this; var tab = $(e.target).closest('li.tab'); var tabLink = $(e.target).closest('a'); // Handle click on tab link only if (!tabLink.length || !tabLink.parent().hasClass('tab')) { return; } if (tab.hasClass('disabled')) { e.preventDefault(); return; } // Act as regular link if target attribute is specified. if (!!tabLink.attr("target")) { return; } this._setTabsAndTabWidth(); // Make the old tab inactive. this.$activeTabLink.removeClass('active'); var $oldContent = this.$content; // Update the variables with the new link and content this.$activeTabLink = tabLink; this.$content = $(M.escapeHash(tabLink[0].hash)); this.$tabLinks = this.$el.children('li.tab').children('a'); // Make the tab active. this.$activeTabLink.addClass('active'); var prevIndex = this.index; this.index = Math.max(this.$tabLinks.index(tabLink), 0); // Swap content if (this.options.swipeable) { if (this._tabsCarousel) { this._tabsCarousel.set(this.index, function () { if (typeof _this2.options.onShow === "function") { _this2.options.onShow.call(_this2, _this2.$content[0]); } }); } } else { if (this.$content.length) { this.$content[0].style.display = 'block'; this.$content.addClass('active'); if (typeof this.options.onShow === 'function') { this.options.onShow.call(this, this.$content[0]); } if ($oldContent.length && !$oldContent.is(this.$content)) { $oldContent[0].style.display = 'none'; $oldContent.removeClass('active'); } } } // Update indicator this._animateIndicator(prevIndex); // Prevent the anchor's default click action e.preventDefault(); } /** * Generate elements for tab indicator. */ }, { key: '_createIndicator', value: function _createIndicator() { var _this3 = this; var indicator = document.createElement('li'); indicator.classList.add('indicator'); this.el.appendChild(indicator); this._indicator = indicator; setTimeout(function () { _this3._indicator.style.left = _this3._calcLeftPos(_this3.$activeTabLink) + 'px'; _this3._indicator.style.right = _this3._calcRightPos(_this3.$activeTabLink) + 'px'; }, 0); } /** * Setup first active tab link. */ }, { key: '_setupActiveTabLink', value: function _setupActiveTabLink() { // If the location.hash matches one of the links, use that as the active tab. this.$activeTabLink = $(this.$tabLinks.filter('[href="' + location.hash + '"]')); // If no match is found, use the first link or any with class 'active' as the initial active tab. if (this.$activeTabLink.length === 0) { this.$activeTabLink = this.$el.children('li.tab').children('a.active').first(); } if (this.$activeTabLink.length === 0) { this.$activeTabLink = this.$el.children('li.tab').children('a').first(); } this.$tabLinks.removeClass('active'); this.$activeTabLink[0].classList.add('active'); this.index = Math.max(this.$tabLinks.index(this.$activeTabLink), 0); if (this.$activeTabLink.length) { this.$content = $(M.escapeHash(this.$activeTabLink[0].hash)); this.$content.addClass('active'); } } /** * Setup swipeable tabs */ }, { key: '_setupSwipeableTabs', value: function _setupSwipeableTabs() { var _this4 = this; // Change swipeable according to responsive threshold if (window.innerWidth > this.options.responsiveThreshold) { this.options.swipeable = false; } var $tabsContent = $(); this.$tabLinks.each(function (link) { var $currContent = $(M.escapeHash(link.hash)); $currContent.addClass('carousel-item'); $tabsContent = $tabsContent.add($currContent); }); var $tabsWrapper = $('
'); $tabsContent.first().before($tabsWrapper); $tabsWrapper.append($tabsContent); $tabsContent[0].style.display = ''; this._tabsCarousel = M.Carousel.init($tabsWrapper[0], { fullWidth: true, noWrap: true, onCycleTo: function (item) { var prevIndex = _this4.index; _this4.index = $(item).index(); _this4.$activeTabLink.removeClass('active'); _this4.$activeTabLink = _this4.$tabLinks.eq(_this4.index); _this4.$activeTabLink.addClass('active'); _this4._animateIndicator(prevIndex); if (typeof _this4.options.onShow === "function") { _this4.options.onShow.call(_this4, _this4.$content[0]); } } }); } /** * Teardown normal tabs. */ }, { key: '_teardownSwipeableTabs', value: function _teardownSwipeableTabs() { var $tabsWrapper = this._tabsCarousel.$el; this._tabsCarousel.destroy(); // Unwrap $tabsWrapper.after($tabsWrapper.children()); $tabsWrapper.remove(); } /** * Setup normal tabs. */ }, { key: '_setupNormalTabs', value: function _setupNormalTabs() { // Hide Tabs Content this.$tabLinks.not(this.$activeTabLink).each(function (link) { if (!!link.hash) { var $currContent = $(M.escapeHash(link.hash)); if ($currContent.length) { $currContent[0].style.display = 'none'; } } }); } /** * Teardown normal tabs. */ }, { key: '_teardownNormalTabs', value: function _teardownNormalTabs() { // show Tabs Content this.$tabLinks.each(function (link) { if (!!link.hash) { var $currContent = $(M.escapeHash(link.hash)); if ($currContent.length) { $currContent[0].style.display = ''; } } }); } /** * set tabs and tab width */ }, { key: '_setTabsAndTabWidth', value: function _setTabsAndTabWidth() { this.tabsWidth = this.$el.width(); this.tabWidth = Math.max(this.tabsWidth, this.el.scrollWidth) / this.$tabLinks.length; } /** * Finds right attribute for indicator based on active tab. * @param {cash} el */ }, { key: '_calcRightPos', value: function _calcRightPos(el) { return Math.ceil(this.tabsWidth - el.position().left - el[0].getBoundingClientRect().width); } /** * Finds left attribute for indicator based on active tab. * @param {cash} el */ }, { key: '_calcLeftPos', value: function _calcLeftPos(el) { return Math.floor(el.position().left); } }, { key: 'updateTabIndicator', value: function updateTabIndicator() { this._animateIndicator(this.index); } /** * Animates Indicator to active tab. * @param {Number} prevIndex */ }, { key: '_animateIndicator', value: function _animateIndicator(prevIndex) { var leftDelay = 0, rightDelay = 0; if (this.index - prevIndex >= 0) { leftDelay = 90; } else { rightDelay = 90; } // Animate var animOptions = { targets: this._indicator, left: { value: this._calcLeftPos(this.$activeTabLink), delay: leftDelay }, right: { value: this._calcRightPos(this.$activeTabLink), delay: rightDelay }, duration: this.options.duration, easing: 'easeOutQuad' }; anim.remove(this._indicator); anim(animOptions); } /** * Select tab. * @param {String} tabId */ }, { key: 'select', value: function select(tabId) { var tab = this.$tabLinks.filter('[href="#' + tabId + '"]'); if (tab.length) { tab.trigger('click'); } } }], [{ key: 'init', value: function init(els, options) { return _get(Tabs.__proto__ || Object.getPrototypeOf(Tabs), 'init', this).call(this, this, els, options); } /** * Get Instance */ }, { key: 'getInstance', value: function getInstance(el) { var domElem = !!el.jquery ? el[0] : el; return domElem.M_Tabs; } }, { key: 'defaults', get: function () { return _defaults; } }]); return Tabs; }(Component); window.M.Tabs = Tabs; if (M.jQueryLoaded) { M.initializeJqueryWrapper(Tabs, 'tabs', 'M_Tabs'); } })(cash, M.anime);