-
Notifications
You must be signed in to change notification settings - Fork 38
/
TabItem.js
205 lines (196 loc) · 6.9 KB
/
TabItem.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
const { getTransDur, hasParentSelector } = require('./../../helper');
const __prototypeExtensions = require('./../PrototypeExtensions');
class PhotonTabItem extends HTMLElement {
constructor() {
super();
const self = this;
// Mouse down hanlder for this item
this.addEventListener("mousedown", PhotonTabItem.__handleMouseDown);
//this.addEventListener("mousemove", PhotonTabItem.__handleMouseMove);
// Global mouseup handling for this element (Mouseup outside of window)
window.addEventListener("mouseup", (event) => {
// If this item is the current one that's be dragged
if (this.dragging) {
PhotonTabItem.__handleMouseUp.apply(this, [event]);
}
});
// Global mousemove handling for this element (Mousemove outside of window)
window.addEventListener("mousemove", (event) => {
// If this item is the current one that's be dragged
if (this.dragging) {
PhotonTabItem.__handleMouseMove.apply(this, [event]);
}
});
this.addEventListener("click", (event) => {
// Get target path to a button
var btnTarget = hasParentSelector(event.target, "button");
// If button exist, the click was on a button
if (btnTarget) {
var btnClose = btnTarget.last;
this.actions[btnClose.getAttribute("action")](this);
}
if (this.isButton) {
this.actions[this.action](this);
}
});
this.actions = {
close(item) {
const group = self.parentNode;
group.closeTab(item, {
animated: true
});
},
add(item) {
const group = self.parentNode;
group.addTab({
animated: true,
position: "last",
closeBtn: true,
isActive: true,
content: "New Tab"
});
}
};
}
attributeChangedCallback(attr, oldValue, newValue) {
}
move(index) {
const group = this.parentNode;
return group.moveTab(this, index);
}
close(options = {}) {
const group = this.parentNode;
return group.closeTab(this, options);
}
activate() {
const group = this.parentNode;
group.activateTab(this);
}
static __handleMouseDown(event) {
// Get target path to a button
var btnTarget = hasParentSelector(event.target, "button");
const group = this.parentNode;
for (let item of group.items) {
item.__staticBoundings = item.getBoundingClientRect();
}
this.__dragStart = {
x: event.pageX,
y: event.pageY
};
if (!btnTarget) {
if (this.dragability) {
// Add a 'dragging' class to the item
this.classList.add("dragging");
// Add a 'in-drag' class to the tab group to determine this state
group.classList.add("in-drag");
// Activate this item
}
// Activate this item
group.activateTab(this);
}
}
static __handleMouseUp(event) {
const group = this.parentNode;
if (this.dragging) {
// Dragging is over, remove "dragging" class from item but keep "in-drag" class on group in general because the animation after a succesfull drag is not finished and therefore, the current active tab needs special CSS rules
this.classList.remove("dragging");
this.style.removeProperty("transform");
const pos = {
x: event.pageX,
y: event.pageY
};
var newPos = (function(x) {
for (let i = 0; i < group.items.length; i++) {
let item = group.items[i];
// If current drag position is within the boundings of the tab item we ware looking for and this position can be achived because the item there is draggable
if (item.__staticBoundings.left <= x && item.__staticBoundings.right > x && item.dragability) {
// Seems to be exactly this new position
return i;
}
}
// Mouse pointer is outside of tab group (E.g. out of window)
// Therefore, use the most left or morst right item that draggable (Excludes fixed items)
return Math.abs(x - group.itemsDraggable[0].__staticBoundings.left) >= Math.abs(x - group.itemsDraggable.last.__staticBoundings.right) ? group.itemsDraggable.last.__nodePos : group.itemsDraggable[0].__nodePos;
})(pos.x);
// Calculate difference between old and new position
var diffX = group.items[newPos].__staticBoundings.left - this.__staticBoundings.left;
diffX += diffX >= 0 ? -2 : 2;
// If the new position is different from the old one, move the item to it
if (this.__nodePos != newPos) {
this.style.transform = "translate(" + diffX + "px, 0px)";
}
// Wait for transition to be finished (Animating the dragged item to its target position)
setTimeout(function(group, currItem) {
// Move item in DOM context
currItem.move(newPos);
// Remove all tab item's 'transform' style property
for (let item of group.items) {
item.style.removeProperty("transform");
}
// Remove classes 'in-drag' because dragging process is completly over
group.classList.remove("in-drag");
}, getTransDur(this) * 1000, group, this);
}
}
static __handleMouseMove(event) {
const group = this.parentNode;
if (this.dragging) {
const pos = {
x: event.pageX,
y: event.pageY
};
var dragDiff = pos.x - this.__dragStart.x;
this.style.transform = "translate(" + (dragDiff) + "px, 0px)";
for (let i = 0; i < group.items.length; i++) {
let item = group.items[i];
let leftX = item.__staticBoundings.left;
let rightX = item.__staticBoundings.right;
// If current item is before the dragged one
if (i < this.__nodePos) {
if (pos.x < rightX && item.dragability) {
item.style.transform = "translate(" + (this.__staticBoundings.width) + "px, 0px)";
}
else item.style.removeProperty("transform");
}
// If current item is after the dragged one
if (i > this.__nodePos) {
if (pos.x > leftX && item.dragability) {
item.style.transform = "translate(" + (-this.__staticBoundings.width) + "px, 0px)";
}
else item.style.removeProperty("transform");
}
}
}
}
get active() {
return this.classList.contains("active");
}
get dragging() {
return this.classList.contains("dragging");
}
get isButton() {
return !!this.action;
}
get __nodePos() {
return __prototypeExtensions.nodePos(this);
}
get action() {
return this.getAttribute("action");
}
set action(value) {
this.setAttribute("action", value);
}
get type() {
return this.getAttribute("type");
}
set type(value) {
this.setAttribute("type", value);
}
// Computed property that returns wether the item is draggable
get dragability() {
// Just check for a fixed type property
return this.type != "fixed";
}
}
PhotonTabItem.observedAttributes = ["action"];
module.exports = PhotonTabItem;