Skip to content

Commit

Permalink
feat(tab): Get tabs by their ID
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickrodee committed Dec 5, 2018
1 parent 167add5 commit b66522a
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 19 deletions.
6 changes: 3 additions & 3 deletions packages/mdc-tab-bar/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

/* eslint-disable no-unused-vars */
import {MDCTabDimensions} from '@material/tab/adapter';
import {MDCTab} from '@material/tab/index';
import {MDCTabFoundation} from '@material/tab/index';
/* eslint-enable no-unused-vars */

/**
Expand Down Expand Up @@ -134,10 +134,10 @@ class MDCTabBarAdapter {

/**
* Returns the index of the given tab
* @param {!MDCTab} tab The tab whose index to determin
* @param {string} id The ID of the tab whose index to determine
* @return {number}
*/
getIndexOfTab(tab) {}
getIndexOfTabByID(id) {}

/**
* Emits the MDCTabBar:activated event
Expand Down
4 changes: 2 additions & 2 deletions packages/mdc-tab-bar/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class MDCTabBarFoundation extends MDCFoundation {
getTabDimensionsAtIndex: () => {},
getPreviousActiveTabIndex: () => {},
getFocusedTabIndex: () => {},
getIndexOfTab: () => {},
getIndexOfTabByID: () => {},
getTabListLength: () => {},
notifyTabActivated: () => {},
});
Expand Down Expand Up @@ -174,7 +174,7 @@ class MDCTabBarFoundation extends MDCFoundation {
* @param {!Event} evt
*/
handleTabInteraction(evt) {
this.adapter_.setActiveTab(this.adapter_.getIndexOfTab(evt.detail.tab));
this.adapter_.setActiveTab(this.adapter_.getIndexOfTabByID(evt.detail.tabId));
}

/**
Expand Down
51 changes: 43 additions & 8 deletions packages/mdc-tab-bar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import {MDCTabScroller} from '@material/tab-scroller/index';
import MDCTabBarAdapter from './adapter';
import MDCTabBarFoundation from './foundation';

let tabIdCounter = 0;

/**
* @extends {MDCComponent<!MDCTabBarFoundation>}
* @final
Expand Down Expand Up @@ -84,13 +86,8 @@ class MDCTabBar extends MDCComponent {
tabScrollerFactory = (el) => new MDCTabScroller(el)) {
this.tabFactory_ = tabFactory;
this.tabScrollerFactory_ = tabScrollerFactory;

this.tabList_ = this.getTabElements_().map((el) => this.tabFactory_(el));

const tabScrollerElement = this.root_.querySelector(MDCTabBarFoundation.strings.TAB_SCROLLER_SELECTOR);
if (tabScrollerElement) {
this.tabScroller_ = this.tabScrollerFactory_(tabScrollerElement);
}
this.tabList_ = this.instantiateTabs_(this.tabFactory_);
this.tabScroller_ = this.instantiateTabsScroller_(this.tabScrollerFactory_);
}

initialSyncWithDOM() {
Expand Down Expand Up @@ -147,7 +144,14 @@ class MDCTabBar extends MDCComponent {
const activeElement = document.activeElement;
return tabElements.indexOf(activeElement);
},
getIndexOfTab: (tabToFind) => this.tabList_.indexOf(tabToFind),
getIndexOfTabByID: (id) => {
for (let i = 0; i < this.tabList_.length; i++) {
if (this.tabList_[i].id === id) {
return i;
}
}
return -1;
},
getTabListLength: () => this.tabList_.length,
notifyTabActivated: (index) => this.emit(MDCTabBarFoundation.strings.TAB_ACTIVATED_EVENT, {index}, true),
})
Expand All @@ -170,9 +174,40 @@ class MDCTabBar extends MDCComponent {
this.foundation_.scrollIntoView(index);
}

/**
* Returns all the tab elements in a nice clean array
* @return {!Array<!HTMLElement>}
* @private
*/
getTabElements_() {
return [].slice.call(this.root_.querySelectorAll(MDCTabBarFoundation.strings.TAB_SELECTOR));
}

/**
* Instantiates tab components on all child tab elements
* @param {(function(!Element): !MDCTab)} tabFactory
* @return {!Array<!MDCTab>}
* @private
*/
instantiateTabs_(tabFactory) {
return this.getTabElements_().map((el) => {
el.id = el.id || `mdc-tab-${++tabIdCounter}`;
return tabFactory(el);
});
}

/**
* Instantiates tab scroller component on the child tab scroller element
* @param {(function(!Element): !MDCTabScroller)} tabScrollerFactory
* @return {!MDCTabScroller=}
* @private
*/
instantiateTabsScroller_(tabScrollerFactory) {
const tabScrollerElement = this.root_.querySelector(MDCTabBarFoundation.strings.TAB_SCROLLER_SELECTOR);
if (tabScrollerElement) {
return tabScrollerFactory(tabScrollerElement);
}
}
}

export {MDCTabBar, MDCTabBarFoundation};
12 changes: 11 additions & 1 deletion packages/mdc-tab/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@
*/
let MDCTabDimensions;

/**
* @typedef {{
* detail: {
* tabId: string,
* },
* bubbles: boolean,
* }}
*/
let MDCTabInteractionEventType;

/**
* Adapter for MDC Tab.
*
Expand Down Expand Up @@ -112,4 +122,4 @@ class MDCTabAdapter {
focus() {}
}

export {MDCTabDimensions, MDCTabAdapter};
export {MDCTabDimensions, MDCTabInteractionEventType, MDCTabAdapter};
9 changes: 7 additions & 2 deletions packages/mdc-tab/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import MDCComponent from '@material/base/component';
/* eslint-disable no-unused-vars */
import {MDCRipple, MDCRippleFoundation, RippleCapableSurface} from '@material/ripple/index';
import {MDCTabIndicator, MDCTabIndicatorFoundation} from '@material/tab-indicator/index';
import {MDCTabAdapter, MDCTabDimensions} from './adapter';
import {MDCTabAdapter, MDCTabDimensions, MDCTabInteractionEventType} from './adapter';
/* eslint-enable no-unused-vars */

import MDCTabFoundation from './foundation';
Expand All @@ -41,6 +41,9 @@ class MDCTab extends MDCComponent {
*/
constructor(...args) {
super(...args);

/** @type {string} */
this.id;
/** @private {?MDCRipple} */
this.ripple_;
/** @private {?MDCTabIndicator} */
Expand All @@ -63,6 +66,7 @@ class MDCTab extends MDCComponent {
initialize(
rippleFactory = (el, foundation) => new MDCRipple(el, foundation),
tabIndicatorFactory = (el) => new MDCTabIndicator(el)) {
this.id = this.root_.id;
const rippleSurface = this.root_.querySelector(MDCTabFoundation.strings.RIPPLE_SELECTOR);
const rippleAdapter = Object.assign(MDCRipple.createAdapter(/** @type {!RippleCapableSurface} */ (this)), {
addClass: (className) => rippleSurface.classList.add(className),
Expand Down Expand Up @@ -101,7 +105,8 @@ class MDCTab extends MDCComponent {
hasClass: (className) => this.root_.classList.contains(className),
activateIndicator: (previousIndicatorClientRect) => this.tabIndicator_.activate(previousIndicatorClientRect),
deactivateIndicator: () => this.tabIndicator_.deactivate(),
notifyInteracted: () => this.emit(MDCTabFoundation.strings.INTERACTED_EVENT, {tab: this}, true /* bubble */),
notifyInteracted: () => this.emit(
MDCTabFoundation.strings.INTERACTED_EVENT, {tabId: this.id}, true /* bubble */),
getOffsetLeft: () => this.root_.offsetLeft,
getOffsetWidth: () => this.root_.offsetWidth,
getContentOffsetLeft: () => this.content_.offsetLeft,
Expand Down
2 changes: 1 addition & 1 deletion test/unit/mdc-tab-bar/foundation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ test('defaultAdapter returns a complete adapter implementation', () => {
'getOffsetWidth', 'isRTL', 'setActiveTab',
'activateTabAtIndex', 'deactivateTabAtIndex', 'focusTabAtIndex',
'getTabIndicatorClientRectAtIndex', 'getTabDimensionsAtIndex',
'getPreviousActiveTabIndex', 'getFocusedTabIndex', 'getIndexOfTab', 'getTabListLength',
'getPreviousActiveTabIndex', 'getFocusedTabIndex', 'getIndexOfTabByID', 'getTabListLength',
'notifyTabActivated',
]);
});
Expand Down
6 changes: 4 additions & 2 deletions test/unit/mdc-tab-bar/mdc-tab-bar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ test('attachTo returns an MDCTabBar instance', () => {
assert.isOk(MDCTabBar.attachTo(getFixture()) instanceof MDCTabBar);
});

let fakeTabIdCounter = 0;
class FakeTab {
constructor() {
this.id = `mdc-tab-${++fakeTabIdCounter}`;
this.destroy = td.function();
this.activate = td.function();
this.deactivate = td.function();
Expand Down Expand Up @@ -206,10 +208,10 @@ test('#adapter.getPreviousActiveTabIndex returns the index of the active tab', (
assert.strictEqual(component.getDefaultFoundation().adapter_.getPreviousActiveTabIndex(), 1);
});

test('#adapter.getIndexOfTab returns the index of the given tab', () => {
test('#adapter.getIndexOfTabByID; returns the index of the given tab', () => {
const {component} = setupTest();
const tab = component.tabList_[2];
assert.strictEqual(component.getDefaultFoundation().adapter_.getIndexOfTab(tab), 2);
assert.strictEqual(component.getDefaultFoundation().adapter_.getIndexOfTabByID(tab.id), 2);
});

test('#adapter.getTabListLength returns the length of the tab list', () => {
Expand Down

0 comments on commit b66522a

Please sign in to comment.