123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- /* global FORM_KEY */
- (function (factory) {
- 'use strict';
- if (typeof define === 'function' && define.amd) {
- define([
- 'jquery',
- 'jquery/ui'
- ], factory);
- } else {
- factory(jQuery);
- }
- }(function ($) {
- 'use strict';
- var rhash, isLocal;
- // mage.tabs base functionality
- $.widget('mage.tabs', $.ui.tabs, {
- options: {
- spinner: false,
- groups: null,
- tabPanelClass: '',
- excludedPanel: ''
- },
- /**
- * Tabs creation
- * @protected
- */
- _create: function () {
- var activeIndex = this._getTabIndex(this.options.active);
- this.options.active = activeIndex >= 0 ? activeIndex : 0;
- this._super();
- },
- /**
- * @override
- * @private
- * @return {Array} Array of DOM-elements
- */
- _getList: function () {
- if (this.options.groups) {
- return this.element.find(this.options.groups);
- }
- return this._super();
- },
- /**
- * Get active anchor
- * @return {Element}
- */
- activeAnchor: function () {
- return this.anchors.eq(this.option('active'));
- },
- /**
- * Get tab index by tab id
- * @protected
- * @param {String} id - id of tab
- * @return {Number}
- */
- _getTabIndex: function (id) {
- var anchors = this.anchors ?
- this.anchors :
- this._getList().find('> li > a[href]');
- return anchors.index($('#' + id));
- },
- /**
- * Switch between tabs
- * @protected
- * @param {Object} event - event object
- * @param {undefined|Object} eventData
- */
- _toggle: function (event, eventData) {
- var anchor = $(eventData.newTab).find('a');
- if ($(eventData.newTab).find('a').data().tabType === 'link') {
- location.href = anchor.prop('href');
- } else {
- this._superApply(arguments);
- }
- }
- });
- rhash = /#.*$/;
- /**
- * @param {*} anchor
- * @return {Boolean}
- */
- isLocal = function (anchor) {
- return anchor.hash.length > 1 &&
- anchor.href.replace(rhash, '') ===
- location.href.replace(rhash, '')
- // support: Safari 5.1
- // Safari 5.1 doesn't encode spaces in window.location
- // but it does encode spaces from anchors (#8777)
- .replace(/\s/g, '%20');
- };
- // Extension for mage.tabs - Move panels in destination element
- $.widget('mage.tabs', $.mage.tabs, {
- /**
- * Move panels in destination element on creation
- * @protected
- * @override
- */
- _create: function () {
- this._super();
- this._movePanelsInDestination(this.panels);
- },
- /**
- * Get panel for tab. If panel no exist in tabs container, then find panel in destination element
- * @protected
- * @override
- * @param {Element} tab - tab "li" DOM-element
- * @return {Element}
- */
- _getPanelForTab: function (tab) {
- var panel = this._superApply(arguments),
- id;
- if (!panel.length) {
- id = $(tab).attr('aria-controls');
- panel = $(this.options.destination).find(this._sanitizeSelector('#' + id));
- }
- return panel;
- },
- /**
- * @private
- */
- _processTabs: function () {
- var that = this;
- this.tablist = this._getList()
- .addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all')
- .attr('role', 'tablist');
- this.tabs = this.tablist.find('> li:has(a[href])')
- .addClass('ui-state-default ui-corner-top')
- .attr({
- role: 'tab',
- tabIndex: -1
- });
- this.anchors = this.tabs.map(function () {
- return $('a', this)[ 0 ];
- })
- .addClass('ui-tabs-anchor')
- .attr({
- role: 'presentation',
- tabIndex: -1
- });
- this.panels = $();
- this.anchors.each(function (i, anchor) {
- var selector, panel, panelId,
- anchorId = $(anchor).uniqueId().attr('id'),
- tab = $(anchor).closest('li'),
- originalAriaControls = tab.attr('aria-controls');
- // inline tab
- if (isLocal(anchor)) {
- selector = anchor.hash;
- panel = that.document.find(that._sanitizeSelector(selector));
- // remote tab
- } else {
- panelId = that._tabId(tab);
- selector = '#' + panelId;
- panel = that.document.find(selector);
- if (!panel.length) {
- panel = that._createPanel(panelId);
- panel.insertAfter(that.panels[ i - 1 ] || that.tablist);
- }
- panel.attr('aria-live', 'polite');
- }
- if (panel.length) {
- that.panels = that.panels.add(panel);
- }
- if (originalAriaControls) {
- tab.data('ui-tabs-aria-controls', originalAriaControls);
- }
- tab.attr({
- 'aria-controls': selector.substring(1),
- 'aria-labelledby': anchorId
- });
- panel.attr('aria-labelledby', anchorId);
- if (that.options.excludedPanel.indexOf(anchorId + '_content') < 0) {
- panel.addClass(that.options.tabPanelClass);
- }
- });
- this.panels
- .addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
- .attr('role', 'tabpanel');
- },
- /**
- * Move panels in destination element
- * @protected
- * @override
- */
- _movePanelsInDestination: function (panels) {
- if (this.options.destination && !panels.parents(this.options.destination).length) {
- this.element.trigger('beforePanelsMove', panels);
- panels.find('script:not([type]), script[type="text/javascript"]').remove();
- panels.appendTo(this.options.destination)
- .each($.proxy(function (i, panel) {
- $(panel).trigger('move.tabs', this.anchors.eq(i));
- }, this));
- }
- },
- /**
- * Move panels in destination element on tabs switching
- * @protected
- * @override
- * @param {Object} event - event object
- * @param {Object} eventData
- */
- _toggle: function (event, eventData) {
- this._movePanelsInDestination(eventData.newPanel);
- this._superApply(arguments);
- }
- });
- // Extension for mage.tabs - Ajax functionality for tabs
- $.widget('mage.tabs', $.mage.tabs, {
- options: {
- ajaxOptions: {
- data: {
- isAjax: true,
- 'form_key': typeof FORM_KEY !== 'undefined' ? FORM_KEY : null
- }
- },
- /**
- * Replacing href attribute with loaded panel id
- * @param {Object} event - event object
- * @param {Object} ui
- */
- load: function (event, ui) {
- var panel = $(ui.panel);
- $(ui.tab).prop('href', '#' + panel.prop('id'));
- panel.trigger('contentUpdated');
- }
- }
- });
- // Extension for mage.tabs - Attach event handlers to tabs
- $.widget('mage.tabs', $.mage.tabs, {
- options: {
- tabIdArgument: 'tab',
- tabsBlockPrefix: null
- },
- /**
- * Attach event handlers to tabs, on creation
- * @protected
- * @override
- */
- _refresh: function () {
- this._super();
- $.each(this.tabs, $.proxy(function (i, tab) {
- $(this._getPanelForTab(tab))
- .off('changed' + this.eventNamespace)
- .off('highlight.validate' + this.eventNamespace)
- .off('focusin' + this.eventNamespace)
- .on('changed' + this.eventNamespace, {
- index: i
- }, $.proxy(this._onContentChange, this))
- .on('highlight.validate' + this.eventNamespace, {
- index: i
- }, $.proxy(this._onInvalid, this))
- .on('focusin' + this.eventNamespace, {
- index: i
- }, $.proxy(this._onFocus, this));
- }, this));
- ($(this.options.destination).is('form') ?
- $(this.options.destination) :
- $(this.options.destination).closest('form'))
- .off('beforeSubmit' + this.eventNamespace)
- .on('beforeSubmit' + this.eventNamespace, $.proxy(this._onBeforeSubmit, this));
- },
- /**
- * Mark tab as changed if some field inside tab panel is changed
- * @protected
- * @param {Object} e - event object
- */
- _onContentChange: function (e) {
- var cssChanged = '_changed';
- this.anchors.eq(e.data.index).addClass(cssChanged);
- this._updateNavTitleMessages(e, cssChanged);
- },
- /**
- * Clone messages (tooltips) from anchor to parent element
- * @protected
- * @param {Object} e - event object
- * @param {String} messageType - changed or error
- */
- _updateNavTitleMessages: function (e, messageType) {
- var curAnchor = this.anchors.eq(e.data.index),
- curItem = curAnchor.parents('[data-role="container"]').find('[data-role="title"]'),
- curItemMessages = curItem.find('[data-role="title-messages"]'),
- activeClass = '_active';
- if (curItemMessages.is(':empty')) {
- curAnchor
- .find('[data-role="item-messages"]')
- .clone()
- .appendTo(curItemMessages);
- }
- curItemMessages.find('.' + messageType).addClass(activeClass);
- },
- /**
- * Mark tab as error if some field inside tab panel is not passed validation
- * @param {Object} e - event object
- * @protected
- */
- _onInvalid: function (e) {
- var cssError = '_error',
- fakeEvent = e;
- fakeEvent.currentTarget = $(this.anchors).eq(e.data.index);
- this._eventHandler(fakeEvent);
- this.anchors.eq(e.data.index).addClass(cssError).find('.' + cssError).show();
- this._updateNavTitleMessages(e, cssError);
- },
- /**
- * Show tab panel if focus event triggered of some field inside tab panel
- * @param {Object} e - event object
- * @protected
- */
- _onFocus: function (e) {
- this.option('_active', e.data.index);
- },
- /**
- * Add active tab id in data object when "beforeSubmit" event is triggered
- * @param {Object} e - event object
- * @param {Object} data - event data object
- * @protected
- */
- _onBeforeSubmit: function (e, data) { //eslint-disable-line no-unused-vars
- var activeAnchor = this.activeAnchor(),
- activeTabId = activeAnchor.prop('id'),
- options;
- if (this.options.tabsBlockPrefix) {
- if (activeAnchor.is('[id*="' + this.options.tabsBlockPrefix + '"]')) {
- activeTabId = activeAnchor.prop('id').substr(this.options.tabsBlockPrefix.length);
- }
- }
- $(this.anchors).removeClass('error');
- options = {
- action: {
- args: {}
- }
- };
- options.action.args[this.options.tabIdArgument] = activeTabId;
- data = data ? $.extend(data, options) : options;
- }
- });
- // Extension for mage.tabs - Shadow tabs functionality
- $.widget('mage.tabs', $.mage.tabs, {
- /**
- * Add shadow tabs functionality on creation
- * @protected
- * @override
- */
- _refresh: function () {
- var anchors, shadowTabs, tabs;
- this._super();
- anchors = this.anchors;
- shadowTabs = this.options.shadowTabs;
- tabs = this.tabs;
- if (shadowTabs) {
- anchors.each($.proxy(function (i, anchor) {
- var anchorId = $(anchor).prop('id');
- if (shadowTabs[anchorId]) {
- $(anchor).parents('li').on('click', $.proxy(function () {
- $.each(shadowTabs[anchorId], $.proxy(function (key, id) {
- this.load($(tabs).index($('#' + id).parents('li')), {});
- }, this));
- }, this));
- }
- }, this));
- }
- }
- });
- return $.mage.tabs;
- }));
|