Version 3.18.1
Show:

File: tabview/js/tab.js

  1. /**
  2. * Provides Tab instances for use with TabView
  3. * @param config {Object} Object literal specifying tabview configuration properties.
  4. *
  5. * @class Tab
  6. * @constructor
  7. * @extends Widget
  8. * @uses WidgetChild
  9. */
  10. Y.Tab = Y.Base.create('tab', Y.Widget, [Y.WidgetChild], {
  11. BOUNDING_TEMPLATE: '<li></li>',
  12. CONTENT_TEMPLATE: '<a></a>',
  13. PANEL_TEMPLATE: '<div></div>',
  14. _uiSetSelectedPanel: function(selected) {
  15. this.get('panelNode').toggleClass(Y.TabviewBase._classNames.selectedPanel, selected);
  16. },
  17. _afterTabSelectedChange: function(event) {
  18. this._uiSetSelectedPanel(event.newVal);
  19. },
  20. _afterParentChange: function(e) {
  21. if (!e.newVal) {
  22. this._remove();
  23. } else {
  24. this._add();
  25. }
  26. },
  27. _initAria: function() {
  28. var anchor = this.get('contentBox'),
  29. id = anchor.get('id'),
  30. panel = this.get('panelNode');
  31. if (!id) {
  32. id = Y.guid();
  33. anchor.set('id', id);
  34. }
  35. // Apply the ARIA roles, states and properties to each tab
  36. anchor.set('role', 'tab');
  37. anchor.get('parentNode').set('role', 'presentation');
  38. // Apply the ARIA roles, states and properties to each panel
  39. panel.setAttrs({
  40. role: 'tabpanel',
  41. 'aria-labelledby': id
  42. });
  43. },
  44. syncUI: function() {
  45. var _classNames = Y.TabviewBase._classNames;
  46. this.get('boundingBox').addClass(_classNames.tab);
  47. this.get('contentBox').addClass(_classNames.tabLabel);
  48. this.set('label', this.get('label'));
  49. this.set('content', this.get('content'));
  50. this._uiSetSelectedPanel(this.get('selected'));
  51. },
  52. bindUI: function() {
  53. this.after('selectedChange', this._afterTabSelectedChange);
  54. this.after('parentChange', this._afterParentChange);
  55. },
  56. renderUI: function() {
  57. this._renderPanel();
  58. this._initAria();
  59. },
  60. _renderPanel: function() {
  61. this.get('parent').get('panelNode')
  62. .appendChild(this.get('panelNode'));
  63. },
  64. _add: function() {
  65. var parent = this.get('parent').get('contentBox'),
  66. list = parent.get('listNode'),
  67. panel = parent.get('panelNode');
  68. if (list) {
  69. list.appendChild(this.get('boundingBox'));
  70. }
  71. if (panel) {
  72. panel.appendChild(this.get('panelNode'));
  73. }
  74. },
  75. _remove: function() {
  76. this.get('boundingBox').remove();
  77. this.get('panelNode').remove();
  78. },
  79. _onActivate: function(e) {
  80. if (e.target === this) {
  81. // Prevent the browser from navigating to the URL specified by the
  82. // anchor's href attribute.
  83. e.domEvent.preventDefault();
  84. e.target.set('selected', 1);
  85. }
  86. },
  87. initializer: function() {
  88. this.publish(this.get('triggerEvent'), {
  89. defaultFn: this._onActivate
  90. });
  91. },
  92. _defLabelGetter: function() {
  93. return this.get('contentBox').getHTML();
  94. },
  95. _defLabelSetter: function(label) {
  96. var labelNode = this.get('contentBox');
  97. if (labelNode.getHTML() !== label) { // Avoid rewriting existing label.
  98. labelNode.setHTML(label);
  99. }
  100. return label;
  101. },
  102. _defContentSetter: function(content) {
  103. var panel = this.get('panelNode');
  104. if (panel.getHTML() !== content) { // Avoid rewriting existing content.
  105. panel.setHTML(content);
  106. }
  107. return content;
  108. },
  109. _defContentGetter: function() {
  110. return this.get('panelNode').getHTML();
  111. },
  112. // find panel by ID mapping from label href
  113. _defPanelNodeValueFn: function() {
  114. var _classNames = Y.TabviewBase._classNames,
  115. href = this.get('contentBox').get('href') || '',
  116. parent = this.get('parent'),
  117. hashIndex = href.indexOf('#'),
  118. panel;
  119. href = href.substr(hashIndex);
  120. if (href.charAt(0) === '#') { // in-page nav, find by ID
  121. panel = Y.one(href);
  122. if (panel) {
  123. panel.addClass(_classNames.tabPanel);
  124. }
  125. }
  126. // use the one found by id, or else try matching indices
  127. if (!panel && parent) {
  128. panel = parent.get('panelNode')
  129. .get('children').item(this.get('index'));
  130. }
  131. if (!panel) { // create if none found
  132. panel = Y.Node.create(this.PANEL_TEMPLATE);
  133. panel.addClass(_classNames.tabPanel);
  134. }
  135. return panel;
  136. }
  137. }, {
  138. ATTRS: {
  139. /**
  140. * @attribute triggerEvent
  141. * @default "click"
  142. * @type String
  143. */
  144. triggerEvent: {
  145. value: 'click'
  146. },
  147. /**
  148. * @attribute label
  149. * @type HTML
  150. */
  151. label: {
  152. setter: '_defLabelSetter',
  153. getter: '_defLabelGetter'
  154. },
  155. /**
  156. * @attribute content
  157. * @type HTML
  158. */
  159. content: {
  160. setter: '_defContentSetter',
  161. getter: '_defContentGetter'
  162. },
  163. /**
  164. * @attribute panelNode
  165. * @type Y.Node
  166. */
  167. panelNode: {
  168. setter: function(node) {
  169. node = Y.one(node);
  170. if (node) {
  171. node.addClass(Y.TabviewBase._classNames.tabPanel);
  172. }
  173. return node;
  174. },
  175. valueFn: '_defPanelNodeValueFn'
  176. },
  177. tabIndex: {
  178. value: null,
  179. validator: '_validTabIndex'
  180. }
  181. },
  182. HTML_PARSER: {
  183. selected: function() {
  184. var ret = (this.get('boundingBox').hasClass(Y.TabviewBase._classNames.selectedTab)) ?
  185. 1 : 0;
  186. return ret;
  187. }
  188. }
  189. });