123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- define([
- 'jquery',
- 'jquery/ui',
- 'mage/mage',
- 'mage/collapsible'
- ], function ($) {
- 'use strict';
- $.widget('mage.tabs', {
- options: {
- active: 0,
- disabled: [],
- openOnFocus: true,
- collapsible: false,
- collapsibleElement: '[data-role=collapsible]',
- header: '[data-role=title]',
- content: '[data-role=content]',
- trigger: '[data-role=trigger]',
- closedState: null,
- openedState: null,
- disabledState: null,
- ajaxUrlElement: '[data-ajax=true]',
- ajaxContent: false,
- loadingClass: null,
- saveState: false,
- animate: false,
- icons: {
- activeHeader: null,
- header: null
- }
- },
- /**
- * @private
- */
- _create: function () {
- if (typeof this.options.disabled === 'string') {
- this.options.disabled = this.options.disabled.split(' ').map(function (item) {
- return parseInt(item, 10);
- });
- }
- this._processPanels();
- this._handleDeepLinking();
- this._processTabIndex();
- this._closeOthers();
- this._bind();
- },
- /**
- * @private
- */
- _destroy: function () {
- $.each(this.collapsibles, function () {
- $(this).collapsible('destroy');
- });
- },
- /**
- * If deep linking is used, all sections must be closed but the one that contains the anchor.
- * @private
- */
- _handleDeepLinking: function () {
- var self = this,
- anchor = window.location.hash,
- isValid = $.mage.isValidSelector(anchor),
- anchorId = anchor.replace('#', '');
- if (anchor && isValid) {
- $.each(self.contents, function (i) {
- if ($(this).attr('id') === anchorId) {
- self.collapsibles.not(self.collapsibles.eq(i)).collapsible('forceDeactivate');
- return false;
- }
- });
- }
- },
- /**
- * When the widget gets instantiated, the first tab that is not disabled receive focusable property
- * All tabs receive tabIndex 0
- * @private
- */
- _processTabIndex: function () {
- var self = this;
- self.triggers.attr('tabIndex', 0);
- $.each(this.collapsibles, function (i) {
- self.triggers.attr('tabIndex', 0);
- self.triggers.eq(i).attr('tabIndex', 0);
- });
- },
- /**
- * Prepare the elements for instantiating the collapsible widget
- * @private
- */
- _processPanels: function () {
- this.contents = this.element.find(this.options.content);
- this.collapsibles = this.element.find(this.options.collapsibleElement);
- this.collapsibles
- .attr('role', 'presentation')
- .parent()
- .attr('role', 'tablist');
- this.headers = this.element.find(this.options.header);
- if (this.headers.length === 0) {
- this.headers = this.collapsibles;
- }
- this.triggers = this.element.find(this.options.trigger);
- if (this.triggers.length === 0) {
- this.triggers = this.headers;
- }
- this._callCollapsible();
- },
- /**
- * Setting the disabled and active tabs and calling instantiation of collapsible
- * @private
- */
- _callCollapsible: function () {
- var self = this,
- disabled = false,
- active = false;
- $.each(this.collapsibles, function (i) {
- disabled = active = false;
- if ($.inArray(i, self.options.disabled) !== -1) {
- disabled = true;
- }
- if (i === self.options.active) {
- active = true;
- }
- self._instantiateCollapsible(this, i, active, disabled);
- });
- },
- /**
- * Instantiate collapsible.
- *
- * @param {HTMLElement} element
- * @param {Number} index
- * @param {*} active
- * @param {*} disabled
- * @private
- */
- _instantiateCollapsible: function (element, index, active, disabled) {
- $(element).collapsible(
- $.extend({}, this.options, {
- active: active,
- disabled: disabled,
- header: this.headers.eq(index),
- content: this.contents.eq(index),
- trigger: this.triggers.eq(index)
- })
- );
- },
- /**
- * Adding callback to close others tabs when one gets opened
- * @private
- */
- _closeOthers: function () {
- var self = this;
- $.each(this.collapsibles, function () {
- $(this).on('beforeOpen', function () {
- self.collapsibles.not(this).collapsible('forceDeactivate');
- });
- });
- },
- /**
- * @param {*} index
- */
- activate: function (index) {
- this._toggleActivate('activate', index);
- },
- /**
- * @param {*} index
- */
- deactivate: function (index) {
- this._toggleActivate('deactivate', index);
- },
- /**
- * @param {*} action
- * @param {*} index
- * @private
- */
- _toggleActivate: function (action, index) {
- this.collapsibles.eq(index).collapsible(action);
- },
- /**
- * @param {*} index
- */
- disable: function (index) {
- this._toggleEnable('disable', index);
- },
- /**
- * @param {*} index
- */
- enable: function (index) {
- this._toggleEnable('enable', index);
- },
- /**
- * @param {*} action
- * @param {*} index
- * @private
- */
- _toggleEnable: function (action, index) {
- var self = this;
- if ($.isArray(index)) {
- $.each(index, function () {
- self.collapsibles.eq(this).collapsible(action);
- });
- } else if (index === undefined) {
- this.collapsibles.collapsible(action);
- } else {
- this.collapsibles.eq(index).collapsible(action);
- }
- },
- /**
- * @param {jQuery.Event} event
- * @private
- */
- _keydown: function (event) {
- var self = this,
- keyCode, toFocus, toFocusIndex, enabledTriggers, length, currentIndex, nextToFocus;
- if (event.altKey || event.ctrlKey) {
- return;
- }
- keyCode = $.ui.keyCode;
- toFocus = false;
- enabledTriggers = [];
- $.each(this.triggers, function () {
- if (!self.collapsibles.eq(self.triggers.index($(this))).collapsible('option', 'disabled')) {
- enabledTriggers.push(this);
- }
- });
- length = $(enabledTriggers).length;
- currentIndex = $(enabledTriggers).index(event.target);
- /**
- * @param {String} direction
- * @return {*}
- */
- nextToFocus = function (direction) {
- if (length > 0) {
- if (direction === 'right') {
- toFocusIndex = (currentIndex + 1) % length;
- } else {
- toFocusIndex = (currentIndex + length - 1) % length;
- }
- return enabledTriggers[toFocusIndex];
- }
- return event.target;
- };
- switch (event.keyCode) {
- case keyCode.RIGHT:
- case keyCode.DOWN:
- toFocus = nextToFocus('right');
- break;
- case keyCode.LEFT:
- case keyCode.UP:
- toFocus = nextToFocus('left');
- break;
- case keyCode.HOME:
- toFocus = enabledTriggers[0];
- break;
- case keyCode.END:
- toFocus = enabledTriggers[length - 1];
- break;
- }
- if (toFocus) {
- toFocusIndex = this.triggers.index(toFocus);
- $(event.target).attr('tabIndex', -1);
- $(toFocus).attr('tabIndex', 0);
- toFocus.focus();
- if (this.options.openOnFocus) {
- this.activate(toFocusIndex);
- }
- event.preventDefault();
- }
- },
- /**
- * @private
- */
- _bind: function () {
- var events = {
- keydown: '_keydown'
- };
- this._off(this.triggers);
- this._on(this.triggers, events);
- }
- });
- return $.mage.tabs;
- });
|