/lib/yuilib/3.9.1/build/tabview/tabview.js
JavaScript | 418 lines | 298 code | 66 blank | 54 comment | 27 complexity | d1877fe2eb96431f08dd75e53e665c0f MD5 | raw file
- /* YUI 3.9.1 (build 5852) Copyright 2013 Yahoo! Inc. http://yuilibrary.com/license/ */
- YUI.add('tabview', function (Y, NAME) {
- /**
- * The TabView module
- *
- * @module tabview
- */
- var _queries = Y.TabviewBase._queries,
- _classNames = Y.TabviewBase._classNames,
- DOT = '.',
- /**
- * Provides a tabbed widget interface
- * @param config {Object} Object literal specifying tabview configuration properties.
- *
- * @class TabView
- * @constructor
- * @extends Widget
- * @uses WidgetParent
- */
- TabView = Y.Base.create('tabView', Y.Widget, [Y.WidgetParent], {
- _afterChildAdded: function() {
- this.get('contentBox').focusManager.refresh();
- },
- _defListNodeValueFn: function() {
- return Y.Node.create(TabView.LIST_TEMPLATE);
- },
- _defPanelNodeValueFn: function() {
- return Y.Node.create(TabView.PANEL_TEMPLATE);
- },
- _afterChildRemoved: function(e) { // update the selected tab when removed
- var i = e.index,
- selection = this.get('selection');
- if (!selection) { // select previous item if selection removed
- selection = this.item(i - 1) || this.item(0);
- if (selection) {
- selection.set('selected', 1);
- }
- }
- this.get('contentBox').focusManager.refresh();
- },
- _initAria: function() {
- var contentBox = this.get('contentBox'),
- tablist = contentBox.one(_queries.tabviewList);
- if (tablist) {
- tablist.setAttrs({
- //'aria-labelledby':
- role: 'tablist'
- });
- }
- },
- bindUI: function() {
- // Use the Node Focus Manager to add keyboard support:
- // Pressing the left and right arrow keys will move focus
- // among each of the tabs.
- this.get('contentBox').plug(Y.Plugin.NodeFocusManager, {
- descendants: DOT + _classNames.tabLabel,
- keys: { next: 'down:39', // Right arrow
- previous: 'down:37' }, // Left arrow
- circular: true
- });
- this.after('render', this._setDefSelection);
- this.after('addChild', this._afterChildAdded);
- this.after('removeChild', this._afterChildRemoved);
- },
-
- renderUI: function() {
- var contentBox = this.get('contentBox');
- this._renderListBox(contentBox);
- this._renderPanelBox(contentBox);
- this._childrenContainer = this.get('listNode');
- this._renderTabs(contentBox);
- },
- _setDefSelection: function() {
- // If no tab is selected, select the first tab.
- var selection = this.get('selection') || this.item(0);
- this.some(function(tab) {
- if (tab.get('selected')) {
- selection = tab;
- return true;
- }
- });
- if (selection) {
- // TODO: why both needed? (via widgetParent/Child)?
- this.set('selection', selection);
- selection.set('selected', 1);
- }
- },
- _renderListBox: function(contentBox) {
- var node = this.get('listNode');
- if (!node.inDoc()) {
- contentBox.append(node);
- }
- },
- _renderPanelBox: function(contentBox) {
- var node = this.get('panelNode');
- if (!node.inDoc()) {
- contentBox.append(node);
- }
- },
- _renderTabs: function(contentBox) {
- var tabs = contentBox.all(_queries.tab),
- panelNode = this.get('panelNode'),
- panels = (panelNode) ? this.get('panelNode').get('children') : null,
- tabview = this;
- if (tabs) { // add classNames and fill in Tab fields from markup when possible
- tabs.addClass(_classNames.tab);
- contentBox.all(_queries.tabLabel).addClass(_classNames.tabLabel);
- contentBox.all(_queries.tabPanel).addClass(_classNames.tabPanel);
- tabs.each(function(node, i) {
- var panelNode = (panels) ? panels.item(i) : null;
- tabview.add({
- boundingBox: node,
- contentBox: node.one(DOT + _classNames.tabLabel),
- panelNode: panelNode
- });
- });
- }
- }
- }, {
- LIST_TEMPLATE: '<ul class="' + _classNames.tabviewList + '"></ul>',
- PANEL_TEMPLATE: '<div class="' + _classNames.tabviewPanel + '"></div>',
- ATTRS: {
- defaultChildType: {
- value: 'Tab'
- },
- listNode: {
- setter: function(node) {
- node = Y.one(node);
- if (node) {
- node.addClass(_classNames.tabviewList);
- }
- return node;
- },
- valueFn: '_defListNodeValueFn'
- },
- panelNode: {
- setter: function(node) {
- node = Y.one(node);
- if (node) {
- node.addClass(_classNames.tabviewPanel);
- }
- return node;
- },
- valueFn: '_defPanelNodeValueFn'
- },
- tabIndex: {
- value: null
- //validator: '_validTabIndex'
- }
- },
- HTML_PARSER: {
- listNode: _queries.tabviewList,
- panelNode: _queries.tabviewPanel
- }
- });
- Y.TabView = TabView;
- var Lang = Y.Lang,
- _classNames = Y.TabviewBase._classNames;
- /**
- * Provides Tab instances for use with TabView
- * @param config {Object} Object literal specifying tabview configuration properties.
- *
- * @class Tab
- * @constructor
- * @extends Widget
- * @uses WidgetChild
- */
- Y.Tab = Y.Base.create('tab', Y.Widget, [Y.WidgetChild], {
- BOUNDING_TEMPLATE: '<li class="' + _classNames.tab + '"></li>',
- CONTENT_TEMPLATE: '<a class="' + _classNames.tabLabel + '"></a>',
- PANEL_TEMPLATE: '<div class="' + _classNames.tabPanel + '"></div>',
- _uiSetSelectedPanel: function(selected) {
- this.get('panelNode').toggleClass(_classNames.selectedPanel, selected);
- },
- _afterTabSelectedChange: function(event) {
- this._uiSetSelectedPanel(event.newVal);
- },
- _afterParentChange: function(e) {
- if (!e.newVal) {
- this._remove();
- } else {
- this._add();
- }
- },
- _initAria: function() {
- var anchor = this.get('contentBox'),
- id = anchor.get('id'),
- panel = this.get('panelNode');
-
- if (!id) {
- id = Y.guid();
- anchor.set('id', id);
- }
- // Apply the ARIA roles, states and properties to each tab
- anchor.set('role', 'tab');
- anchor.get('parentNode').set('role', 'presentation');
-
-
- // Apply the ARIA roles, states and properties to each panel
- panel.setAttrs({
- role: 'tabpanel',
- 'aria-labelledby': id
- });
- },
- syncUI: function() {
- this.set('label', this.get('label'));
- this.set('content', this.get('content'));
- this._uiSetSelectedPanel(this.get('selected'));
- },
- bindUI: function() {
- this.after('selectedChange', this._afterTabSelectedChange);
- this.after('parentChange', this._afterParentChange);
- },
- renderUI: function() {
- this._renderPanel();
- this._initAria();
- },
- _renderPanel: function() {
- this.get('parent').get('panelNode')
- .appendChild(this.get('panelNode'));
- },
- _add: function() {
- var parent = this.get('parent').get('contentBox'),
- list = parent.get('listNode'),
- panel = parent.get('panelNode');
- if (list) {
- list.appendChild(this.get('boundingBox'));
- }
- if (panel) {
- panel.appendChild(this.get('panelNode'));
- }
- },
-
- _remove: function() {
- this.get('boundingBox').remove();
- this.get('panelNode').remove();
- },
- _onActivate: function(e) {
- if (e.target === this) {
- // Prevent the browser from navigating to the URL specified by the
- // anchor's href attribute.
- e.domEvent.preventDefault();
- e.target.set('selected', 1);
- }
- },
-
- initializer: function() {
- this.publish(this.get('triggerEvent'), {
- defaultFn: this._onActivate
- });
- },
- _defLabelGetter: function() {
- return this.get('contentBox').getHTML();
- },
- _defLabelSetter: function(label) {
- var labelNode = this.get('contentBox');
- if (labelNode.getHTML() !== label) { // Avoid rewriting existing label.
- labelNode.setHTML(label);
- }
- return label;
- },
- _defContentSetter: function(content) {
- var panel = this.get('panelNode');
- if (panel.getHTML() !== content) { // Avoid rewriting existing content.
- panel.setHTML(content);
- }
- return content;
- },
- _defContentGetter: function() {
- return this.get('panelNode').getHTML();
- },
- // find panel by ID mapping from label href
- _defPanelNodeValueFn: function() {
- var href = this.get('contentBox').get('href') || '',
- parent = this.get('parent'),
- hashIndex = href.indexOf('#'),
- panel;
- href = href.substr(hashIndex);
- if (href.charAt(0) === '#') { // in-page nav, find by ID
- panel = Y.one(href);
- if (panel) {
- panel.addClass(_classNames.tabPanel);
- }
- }
- // use the one found by id, or else try matching indices
- if (!panel && parent) {
- panel = parent.get('panelNode')
- .get('children').item(this.get('index'));
- }
- if (!panel) { // create if none found
- panel = Y.Node.create(this.PANEL_TEMPLATE);
- }
- return panel;
- }
- }, {
- ATTRS: {
- /**
- * @attribute triggerEvent
- * @default "click"
- * @type String
- */
- triggerEvent: {
- value: 'click'
- },
- /**
- * @attribute label
- * @type HTML
- */
- label: {
- setter: '_defLabelSetter',
- getter: '_defLabelGetter'
- },
- /**
- * @attribute content
- * @type HTML
- */
- content: {
- setter: '_defContentSetter',
- getter: '_defContentGetter'
- },
- /**
- * @attribute panelNode
- * @type Y.Node
- */
- panelNode: {
- setter: function(node) {
- node = Y.one(node);
- if (node) {
- node.addClass(_classNames.tabPanel);
- }
- return node;
- },
- valueFn: '_defPanelNodeValueFn'
- },
-
- tabIndex: {
- value: null,
- validator: '_validTabIndex'
- }
- },
- HTML_PARSER: {
- selected: function() {
- var ret = (this.get('boundingBox').hasClass(_classNames.selectedTab)) ?
- 1 : 0;
- return ret;
- }
- }
- });
- }, '3.9.1', {
- "requires": [
- "widget",
- "widget-parent",
- "widget-child",
- "tabview-base",
- "node-pluginhost",
- "node-focusmanager"
- ],
- "skinnable": true
- });