@atlassian/aui
Version:
Atlassian User Interface library
126 lines (105 loc) • 3.75 kB
JavaScript
import { I18n } from './i18n';
import $ from './jquery';
import skate from './internal/skate';
import globalize from './internal/globalize';
import widget from './internal/widget';
/**
* Navigation (".aui-nav" elements).
*
* @param {(string|HtmlElement|jQuery)} selector - An expression
* representing a single .aui-nav element; you may also pass an expression
* for a descendent element, in which case the closest containing
* .aui-nav element is used.
* @constructor
*/
function Navigation(selector) {
this.$el = $(selector).closest('.aui-nav');
// If there are multiple objects, initialise them separately
if (this.$el.length > 1) {
return this.$el.map(function (idx, elm) {
return new Navigation(elm);
})[0];
}
// If already initialised, return existing object
if (this.$el.data('aui-navigation')) {
return this.$el.data('aui-navigation');
}
this.$el.data('aui-navigation', this);
this.$treeParent = this.$el.parent('li[aria-expanded]');
this.$subtreeToggleIcon = this.$treeParent
.children('.aui-nav-subtree-toggle')
.children('span.aui-icon');
// Add child-selected class to relevant attributes
this.$el.children('li:has(.aui-nav-selected)').addClass('aui-nav-child-selected');
// Auto-expand if child is selected
var $selected = this.$el.children('.aui-nav-selected');
$selected
.parents('.aui-nav > [aria-expanded=false]')
.add($selected.filter('[aria-expanded=false]'))
.each(function () {
var nav = navigationWidget($(this).children('.aui-nav'));
nav.expand();
});
// Toggle expand on click
var $togglers = this.$el.find('> li[aria-expanded] > .aui-nav-subtree-toggle');
$togglers.on('click', function () {
var nav = navigationWidget($(this).siblings('.aui-nav'));
nav.toggle();
});
// Make sure subtree togglers have proper a11y label
$togglers.each(function () {
var $parent = $(this).parent('li[aria-expanded]');
var $icon = $(this).find('.aui-icon');
var isListItemExpanded = $parent.attr('aria-expanded') === 'true';
$icon.text(
isListItemExpanded
? I18n.getText('aui.words.collapse')
: I18n.getText('aui.words.expand')
);
});
return this;
}
Navigation.prototype.isNested = function () {
return this.$treeParent.length === 1;
};
Navigation.prototype.isCollapsed = function () {
return this.$treeParent.attr('aria-expanded') === 'false';
};
Navigation.prototype.expand = function () {
this.$treeParent.attr('aria-expanded', 'true');
this.$subtreeToggleIcon
.removeClass('aui-iconfont-collapsed')
.addClass('aui-iconfont-expanded')
.text(I18n.getText('aui.words.collapse'));
return this;
};
Navigation.prototype.collapse = function () {
this.$treeParent.attr('aria-expanded', 'false');
this.$subtreeToggleIcon
.removeClass('aui-iconfont-expanded')
.addClass('aui-iconfont-collapsed')
.text(I18n.getText('aui.words.expand'));
return this;
};
Navigation.prototype.toggle = function () {
if (this.isCollapsed()) {
this.expand();
} else {
this.collapse();
}
return this;
};
const navigationWidget = widget('navigation', Navigation);
// Initialise nav elements
const NavigationEl = skate('aui-nav', {
type: skate.type.CLASSNAME,
attached: function (element) {
new Navigation(element);
},
detached: function (element) {
$(element).removeData();
},
});
globalize('navigation', navigationWidget);
export default navigationWidget;
export { NavigationEl };