Skip to content

Commit d7127b5

Browse files
create api.factory.js file
1 parent 7ba9198 commit d7127b5

File tree

2 files changed

+169
-166
lines changed

2 files changed

+169
-166
lines changed

src/api.factory.js

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/**
2+
*
3+
* @param {Object} options
4+
* @param {HTMLElement} options.containerElement - the first ancestor of the Tablist element which has a hidden overflow
5+
* @param {HTMLElement} options.buttonElement - should be next sibling element of the Tablist element
6+
* @param {String} [options.tabDisplay="flex"] - default value is "inline-flex". would be display of li tag
7+
* @param {String} [options.containerDisplay="flex"] - default value is "inline-flex". would be display of containerElement
8+
*/
9+
const Api = function (deps, options = {}) {
10+
this._setOptions(options);
11+
this._tablistEl = null;
12+
const {getElManagementIns} = deps();
13+
this._getElManagementIns = getElManagementIns;
14+
this._tabs = null;
15+
this._tabsCount = null;
16+
this._setEls();
17+
};
18+
Api.prototype = {
19+
_setOptions: function (options) {
20+
this._options = Object.assign(
21+
{},
22+
{containerDisplay: 'flex', tabDisplay: 'flex', buttonElement: null, containerElement: null},
23+
options,
24+
);
25+
},
26+
_setEls: function () {
27+
this._tablistEl = this._options.buttonElement.previousElementSibling;
28+
this._tablistEl.style.overflow = 'visible';
29+
this._options.containerElement.style.overflow = 'hidden';
30+
return this;
31+
},
32+
_showBtn: function () {
33+
this._options.buttonElement.style.opacity = 1;
34+
this._options.buttonElement.style.position = 'relative';
35+
this._options.buttonElement.style.pointerEvents = 'all';
36+
},
37+
_hideBtn: function () {
38+
this._options.buttonElement.style.opacity = 0;
39+
this._options.buttonElement.style.position = 'absolute';
40+
this._options.buttonElement.style.pointerEvents = 'none';
41+
},
42+
_checkOverflow: function (lastTab) {
43+
return this.els.getDistance(lastTab).value < 0;
44+
},
45+
_showAll: function () {
46+
this._options.containerElement.style.display = 'none';
47+
const tabDisplay = this._options.tabDisplay;
48+
for (let i = 0, tabs = this._tablistEl.children, tabsCount = tabs.length; i < tabsCount; i++) {
49+
tabs[i].style.display = tabDisplay;
50+
}
51+
this._hideBtn();
52+
this._options.containerElement.style.display = this._options.containerDisplay;
53+
},
54+
_hideTabs: function (firstHiddenTabIndex, selectedTabInfo, includeSelectedTab) {
55+
const hiddenTabs = [];
56+
this._options.containerElement.style.display = 'none';
57+
const {index: selectedTabIndex} = selectedTabInfo;
58+
for (let i = firstHiddenTabIndex, tabsCount = this._tabsCount; i < tabsCount; i++) {
59+
if (includeSelectedTab || i !== selectedTabIndex) {
60+
this._tabs[i].style.display = 'none';
61+
hiddenTabs.push({el: this._tabs[i], index: i});
62+
}
63+
}
64+
this._showBtn();
65+
this._options.containerElement.style.display = this._options.containerDisplay;
66+
return hiddenTabs;
67+
},
68+
_getSelectedTabInfo: function (tabs, selectedTabIndex) {
69+
const index = selectedTabIndex;
70+
const el = index >= 0 ? tabs[index] : null;
71+
const overflow = el
72+
? this.els.getDistance(el).sub(this.els.getEl(this._options.buttonElement).getFullSize()).value <= 0
73+
: false;
74+
const overflowFullSize = overflow ? this.els.getEl(el).getFullSize() : 0;
75+
return {index, overflowFullSize};
76+
},
77+
_validateTabsCount: function () {
78+
this._tabs = this._tablistEl.children;
79+
this._tabsCount = this._tabs.length;
80+
return this._tabsCount ? true : false;
81+
},
82+
/**
83+
*
84+
* @param {Number} selectedTabIndex
85+
* @param {"ltr"|"rtl"} [direction="ltr"]
86+
* @param {Boolean} [isVertical=false]
87+
* @returns {Array.<{el: HTMLElement , index: Number}>}
88+
*/
89+
resize: function (selectedTabIndex = '', direction = 'ltr', isVertical = false) {
90+
if (this._validateTabsCount() === false) {
91+
return [];
92+
}
93+
this._showAll();
94+
this.els = this._getElManagementIns({
95+
baseEl: this._options.containerElement,
96+
isVertical,
97+
dir: direction,
98+
});
99+
const _lastTab = this._tabs[this._tabsCount - 1];
100+
if (this._checkOverflow(_lastTab) === false) {
101+
return [];
102+
}
103+
const selectedTabInfo = this._getSelectedTabInfo(this._tabs, selectedTabIndex);
104+
return this._validateSliderMinSize(selectedTabInfo)
105+
? this._hideTabs(
106+
this._findFirstHiddenTabIndexFactory(
107+
selectedTabInfo,
108+
this._getSearchBoundries(selectedTabInfo),
109+
this._getOrder(_lastTab),
110+
),
111+
selectedTabInfo,
112+
)
113+
: this._hideTabs(0, selectedTabInfo, true);
114+
},
115+
_validateSliderMinSize: function (selectedTabInfo) {
116+
//the slider's size should greater than size of selected tab + more button
117+
return selectedTabInfo.overflowFullSize + this.els.getEl(this._options.buttonElement).getFullSize() >=
118+
this.els.getEl(this._options.containerElement).getSize()
119+
? false
120+
: true;
121+
},
122+
_getOrder: function (lastTab) {
123+
return Math.abs(this.els.getDistance(lastTab).value) > this.els.getEl(this._options.containerElement).getSize()
124+
? 'asc'
125+
: 'desc';
126+
},
127+
_getSearchBoundries: function (selectedTabInfo) {
128+
const {overflowFullSize, index: pivotIndex} = selectedTabInfo;
129+
//if selected tab is not existed
130+
if (pivotIndex < 0) {
131+
return [0, this._tabsCount - 2];
132+
}
133+
const isSelectedTabOverflow = overflowFullSize > 0;
134+
return isSelectedTabOverflow ? [0, pivotIndex - 1] : [pivotIndex + 1, this._tabsCount - 2];
135+
},
136+
_getTabDis: function (selectedTabInfo, el) {
137+
return this.els
138+
.getDistance(el)
139+
.sub(selectedTabInfo.overflowFullSize)
140+
.sub(this.els.getEl(this._options.buttonElement).getFullSize());
141+
},
142+
_findFirstHiddenTabIndexDSCE: function (selectedTabInfo, start, stop) {
143+
let value = this._tabsCount - 1;
144+
for (let i = stop; i >= start; i--) {
145+
if (this._getTabDis(selectedTabInfo, this._tabs[i]).value <= 0) {
146+
value = i;
147+
} else {
148+
break;
149+
}
150+
}
151+
return value;
152+
},
153+
_findFirstHiddenTabIndexASC: function (selectedTabInfo, start, stop) {
154+
for (let i = start; i <= stop; i++) {
155+
if (this._getTabDis(selectedTabInfo, this._tabs[i]).value <= 0) {
156+
return i;
157+
}
158+
}
159+
return this._tabsCount - 1;
160+
},
161+
_findFirstHiddenTabIndexFactory: function (selectedTabInfo, [start, stop], order) {
162+
return order === 'asc'
163+
? this._findFirstHiddenTabIndexASC(selectedTabInfo, start, stop)
164+
: this._findFirstHiddenTabIndexDSCE(selectedTabInfo, start, stop);
165+
},
166+
};
167+
export default Api;

src/api.js

Lines changed: 2 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -1,167 +1,3 @@
11
import ElManagement from './distanceFromFactory.js';
2-
/**
3-
*
4-
* @param {Object} options
5-
* @param {HTMLElement} options.containerElement - the first ancestor of the Tablist element which has a hidden overflow
6-
* @param {HTMLElement} options.buttonElement - should be next sibling element of the Tablist element
7-
* @param {String} [options.tabDisplay="flex"] - default value is "inline-flex". would be display of li tag
8-
* @param {String} [options.containerDisplay="flex"] - default value is "inline-flex". would be display of containerElement
9-
*/
10-
const Api = function (options = {}) {
11-
this._setOptions(options);
12-
this._tablistEl = null;
13-
this._getElManagementIns = (param) => new ElManagement(param);
14-
this._tabs = null;
15-
this._tabsCount = null;
16-
this._setEls();
17-
};
18-
Api.prototype = {
19-
_setOptions: function (options) {
20-
this._options = Object.assign(
21-
{},
22-
{containerDisplay: 'flex', tabDisplay: 'flex', buttonElement: null, containerElement: null},
23-
options,
24-
);
25-
},
26-
_setEls: function () {
27-
this._tablistEl = this._options.buttonElement.previousElementSibling;
28-
this._tablistEl.style.overflow = 'visible';
29-
this._options.containerElement.style.overflow = 'hidden';
30-
return this;
31-
},
32-
_showBtn: function () {
33-
this._options.buttonElement.style.opacity = 1;
34-
this._options.buttonElement.style.position = 'relative';
35-
this._options.buttonElement.style.pointerEvents = 'all';
36-
},
37-
_hideBtn: function () {
38-
this._options.buttonElement.style.opacity = 0;
39-
this._options.buttonElement.style.position = 'absolute';
40-
this._options.buttonElement.style.pointerEvents = 'none';
41-
},
42-
_checkOverflow: function (lastTab) {
43-
return this.els.getDistance(lastTab).value < 0;
44-
},
45-
_showAll: function () {
46-
this._options.containerElement.style.display = 'none';
47-
const tabDisplay = this._options.tabDisplay;
48-
for (let i = 0, tabs = this._tablistEl.children, tabsCount = tabs.length; i < tabsCount; i++) {
49-
tabs[i].style.display = tabDisplay;
50-
}
51-
this._hideBtn();
52-
this._options.containerElement.style.display = this._options.containerDisplay;
53-
},
54-
_hideTabs: function (firstHiddenTabIndex, selectedTabInfo, includeSelectedTab) {
55-
const hiddenTabs = [];
56-
this._options.containerElement.style.display = 'none';
57-
const {index: selectedTabIndex} = selectedTabInfo;
58-
for (let i = firstHiddenTabIndex, tabsCount = this._tabsCount; i < tabsCount; i++) {
59-
if (includeSelectedTab || i !== selectedTabIndex) {
60-
this._tabs[i].style.display = 'none';
61-
hiddenTabs.push({el: this._tabs[i], index: i});
62-
}
63-
}
64-
this._showBtn();
65-
this._options.containerElement.style.display = this._options.containerDisplay;
66-
return hiddenTabs;
67-
},
68-
_getSelectedTabInfo: function (tabs, selectedTabIndex) {
69-
const index = selectedTabIndex;
70-
const el = index >= 0 ? tabs[index] : null;
71-
const overflow = el
72-
? this.els.getDistance(el).sub(this.els.getEl(this._options.buttonElement).getFullSize()).value <= 0
73-
: false;
74-
const overflowFullSize = overflow ? this.els.getEl(el).getFullSize() : 0;
75-
return {index, overflowFullSize};
76-
},
77-
_validateTabsCount: function () {
78-
this._tabs = this._tablistEl.children;
79-
this._tabsCount = this._tabs.length;
80-
return this._tabsCount ? true : false;
81-
},
82-
/**
83-
*
84-
* @param {Number} selectedTabIndex
85-
* @param {"ltr"|"rtl"} [direction="ltr"]
86-
* @param {Boolean} [isVertical=false]
87-
* @returns {Array.<{el: HTMLElement , index: Number}>}
88-
*/
89-
resize: function (selectedTabIndex = '', direction = 'ltr', isVertical = false) {
90-
if (this._validateTabsCount() === false) {
91-
return [];
92-
}
93-
this._showAll();
94-
this.els = this._getElManagementIns({
95-
baseEl: this._options.containerElement,
96-
isVertical,
97-
dir: direction,
98-
});
99-
const _lastTab = this._tabs[this._tabsCount - 1];
100-
if (this._checkOverflow(_lastTab) === false) {
101-
return [];
102-
}
103-
const selectedTabInfo = this._getSelectedTabInfo(this._tabs, selectedTabIndex);
104-
return this._validateSliderMinSize(selectedTabInfo)
105-
? this._hideTabs(
106-
this._findFirstHiddenTabIndexFactory(
107-
selectedTabInfo,
108-
this._getSearchBoundries(selectedTabInfo),
109-
this._getOrder(_lastTab),
110-
),
111-
selectedTabInfo,
112-
)
113-
: this._hideTabs(0, selectedTabInfo, true);
114-
},
115-
_validateSliderMinSize: function (selectedTabInfo) {
116-
//the slider's size should greater than size of selected tab + more button
117-
return selectedTabInfo.overflowFullSize + this.els.getEl(this._options.buttonElement).getFullSize() >=
118-
this.els.getEl(this._options.containerElement).getSize()
119-
? false
120-
: true;
121-
},
122-
_getOrder: function (lastTab) {
123-
return Math.abs(this.els.getDistance(lastTab).value) > this.els.getEl(this._options.containerElement).getSize()
124-
? 'asc'
125-
: 'desc';
126-
},
127-
_getSearchBoundries: function (selectedTabInfo) {
128-
const {overflowFullSize, index: pivotIndex} = selectedTabInfo;
129-
//if selected tab is not existed
130-
if (pivotIndex < 0) {
131-
return [0, this._tabsCount - 2];
132-
}
133-
const isSelectedTabOverflow = overflowFullSize > 0;
134-
return isSelectedTabOverflow ? [0, pivotIndex - 1] : [pivotIndex + 1, this._tabsCount - 2];
135-
},
136-
_getTabDis: function (selectedTabInfo, el) {
137-
return this.els
138-
.getDistance(el)
139-
.sub(selectedTabInfo.overflowFullSize)
140-
.sub(this.els.getEl(this._options.buttonElement).getFullSize());
141-
},
142-
_findFirstHiddenTabIndexDSCE: function (selectedTabInfo, start, stop) {
143-
let value = this._tabsCount - 1;
144-
for (let i = stop; i >= start; i--) {
145-
if (this._getTabDis(selectedTabInfo, this._tabs[i]).value <= 0) {
146-
value = i;
147-
} else {
148-
break;
149-
}
150-
}
151-
return value;
152-
},
153-
_findFirstHiddenTabIndexASC: function (selectedTabInfo, start, stop) {
154-
for (let i = start; i <= stop; i++) {
155-
if (this._getTabDis(selectedTabInfo, this._tabs[i]).value <= 0) {
156-
return i;
157-
}
158-
}
159-
return this._tabsCount - 1;
160-
},
161-
_findFirstHiddenTabIndexFactory: function (selectedTabInfo, [start, stop], order) {
162-
return order === 'asc'
163-
? this._findFirstHiddenTabIndexASC(selectedTabInfo, start, stop)
164-
: this._findFirstHiddenTabIndexDSCE(selectedTabInfo, start, stop);
165-
},
166-
};
167-
export default Api;
2+
import ApiFactory from './api.factory.js';
3+
export default ApiFactory.bind(undefined, () => ({getElManagementIns: (param) => new ElManagement(param)}));

0 commit comments

Comments
 (0)