2025-11-02 10:20:51 +01:00
|
|
|
class HippieTaskBar {
|
2025-11-02 09:26:19 +01:00
|
|
|
constructor(element, placeholder, options) {
|
2025-10-27 21:33:38 +01:00
|
|
|
this.element = element;
|
|
|
|
|
this.placeholder = placeholder;
|
2025-11-02 09:26:19 +01:00
|
|
|
this.date = null;
|
2025-10-27 21:33:38 +01:00
|
|
|
this.offsetX = 0;
|
|
|
|
|
this.offsetY = 0;
|
|
|
|
|
this.isDragging = false;
|
2025-11-02 09:26:19 +01:00
|
|
|
this.barSize = '64px';
|
|
|
|
|
// TODO: Erweitern auf allgemeine Möglichkeiten und dann aus JSON-Datei laden
|
2025-11-02 10:14:54 +01:00
|
|
|
this.options = options || {
|
|
|
|
|
direction: 0,
|
|
|
|
|
date: {
|
|
|
|
|
year: 'numeric',
|
|
|
|
|
month: '2-digit',
|
|
|
|
|
day: '2-digit'
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-10-27 21:33:38 +01:00
|
|
|
|
|
|
|
|
this.init();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-31 19:47:19 +01:00
|
|
|
// TODO: Ereignisse besser delegieren
|
2025-10-27 21:33:38 +01:00
|
|
|
init() {
|
|
|
|
|
this.element.addEventListener('mousedown', this.onMouseDown.bind(this));
|
|
|
|
|
document.addEventListener('mousemove', this.onMouseMove.bind(this));
|
|
|
|
|
document.addEventListener('mouseup', this.onMouseUp.bind(this));
|
2025-11-02 09:26:19 +01:00
|
|
|
|
|
|
|
|
const dateElement = document.createElement('span');
|
|
|
|
|
|
|
|
|
|
dateElement.id = 'date';
|
|
|
|
|
this.element.querySelector('.clock').appendChild(dateElement);
|
2025-11-02 10:14:54 +01:00
|
|
|
this.date = new DateDisplay(dateElement, this.options.date);
|
2025-11-02 09:26:19 +01:00
|
|
|
|
2025-11-02 10:14:54 +01:00
|
|
|
this.setOptions('bottom');
|
2025-10-27 21:33:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMouseDown(event) {
|
2025-10-31 19:47:19 +01:00
|
|
|
if (checkButtonAndTarget(event, this.element, 0)) {
|
|
|
|
|
console.debug('Drag mode enabled');
|
|
|
|
|
|
2025-10-27 23:24:02 +01:00
|
|
|
this.isDragging = true;
|
2025-10-27 21:33:38 +01:00
|
|
|
|
2025-10-31 19:47:19 +01:00
|
|
|
// TODO: Platzhalter anpassen je nach Ziel
|
2025-10-27 23:24:02 +01:00
|
|
|
this.showPlaceholder();
|
2025-10-27 21:53:57 +01:00
|
|
|
|
2025-10-27 23:24:02 +01:00
|
|
|
this.offsetX = this.placeholder.getBoundingClientRect().width / 2;
|
|
|
|
|
this.offsetY = this.placeholder.getBoundingClientRect().height / 2;
|
2025-10-27 21:53:57 +01:00
|
|
|
|
2025-11-02 11:40:54 +01:00
|
|
|
const x = event.clientX - this.offsetX;
|
|
|
|
|
const y = event.clientY - this.offsetY;
|
2025-10-27 21:53:57 +01:00
|
|
|
|
2025-10-27 23:24:02 +01:00
|
|
|
this.placeholder.style.left = `${x}px`;
|
|
|
|
|
this.placeholder.style.top = `${y}px`;
|
|
|
|
|
}
|
2025-10-27 21:53:57 +01:00
|
|
|
|
2025-10-27 21:33:38 +01:00
|
|
|
event.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMouseMove(event) {
|
2025-10-31 19:47:19 +01:00
|
|
|
if (this.isDragging) {
|
|
|
|
|
if (!this.isDragging) return;
|
2025-10-27 21:33:38 +01:00
|
|
|
|
2025-11-02 11:40:54 +01:00
|
|
|
const x = event.clientX - this.offsetX;
|
|
|
|
|
const y = event.clientY - this.offsetY;
|
|
|
|
|
const closestEdge = getClosestEdge(this.placeholder);
|
2025-10-27 21:33:38 +01:00
|
|
|
|
2025-10-31 19:47:19 +01:00
|
|
|
this.placeholder.style.left = `${x}px`;
|
|
|
|
|
this.placeholder.style.top = `${y}px`;
|
2025-11-02 11:40:54 +01:00
|
|
|
|
|
|
|
|
switch (closestEdge) {
|
|
|
|
|
case 'right':
|
|
|
|
|
case 'left':
|
|
|
|
|
this.placeholder.style.flexDirection = 'column';
|
|
|
|
|
break;
|
|
|
|
|
case 'top':
|
|
|
|
|
case 'bottom':
|
|
|
|
|
default:
|
|
|
|
|
this.placeholder.style.flexDirection = 'row';
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-10-31 19:47:19 +01:00
|
|
|
}
|
2025-10-27 21:33:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMouseUp() {
|
2025-10-31 19:47:19 +01:00
|
|
|
if (event.target === this.placeholder) {
|
|
|
|
|
console.debug('Drag mode disabled');
|
2025-10-27 21:33:38 +01:00
|
|
|
|
2025-10-31 19:47:19 +01:00
|
|
|
if (!this.isDragging) return;
|
|
|
|
|
this.isDragging = false;
|
|
|
|
|
|
|
|
|
|
this.snapToEdges();
|
|
|
|
|
this.hidePlaceholder();
|
|
|
|
|
}
|
2025-10-27 21:33:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
showPlaceholder() {
|
2025-10-27 23:24:02 +01:00
|
|
|
this.element.style.display = 'none';
|
2025-11-02 11:40:54 +01:00
|
|
|
this.placeholder.style.display = 'flex';
|
2025-10-27 21:33:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hidePlaceholder() {
|
|
|
|
|
this.placeholder.style.display = 'none';
|
2025-10-27 23:24:02 +01:00
|
|
|
this.element.style.display = '';
|
2025-10-27 21:33:38 +01:00
|
|
|
}
|
|
|
|
|
|
2025-10-31 19:47:19 +01:00
|
|
|
// TODO: Prüfung auf Ziel auslagern und schon bei Mausbewegung verfügbar machen
|
2025-10-27 21:33:38 +01:00
|
|
|
snapToEdges() {
|
2025-11-02 11:40:54 +01:00
|
|
|
const closestEdge = getClosestEdge(this.placeholder);
|
2025-10-27 21:33:38 +01:00
|
|
|
|
2025-11-02 10:14:54 +01:00
|
|
|
this.setOptions(closestEdge);
|
|
|
|
|
this.date.changeFormat(this.options.date, this.options.direction);
|
2025-10-27 21:33:38 +01:00
|
|
|
}
|
|
|
|
|
|
2025-11-02 10:14:54 +01:00
|
|
|
setOptions(position) {
|
2025-11-02 09:26:19 +01:00
|
|
|
const attributes = {
|
|
|
|
|
top: {
|
|
|
|
|
className: 'top',
|
|
|
|
|
styles: {
|
|
|
|
|
top: '0', right: '0', bottom: '', left: '0',
|
|
|
|
|
width: '', height: this.barSize,
|
|
|
|
|
flexDirection: 'row'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
right: {
|
|
|
|
|
className: 'right',
|
|
|
|
|
styles: {
|
|
|
|
|
top: '0', right: '0', bottom: '0', left: '',
|
|
|
|
|
width: this.barSize, height: '',
|
|
|
|
|
flexDirection: 'column'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
bottom: {
|
|
|
|
|
className: 'bottom',
|
|
|
|
|
styles: {
|
|
|
|
|
top: '', right: '0', bottom: '0', left: '0',
|
|
|
|
|
width: '', height: this.barSize,
|
|
|
|
|
flexDirection: 'row'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
left: {
|
|
|
|
|
className: 'left',
|
|
|
|
|
styles: {
|
|
|
|
|
top: '0',
|
|
|
|
|
right: '',
|
|
|
|
|
bottom: '0',
|
|
|
|
|
left: '0',
|
|
|
|
|
width: this.barSize,
|
|
|
|
|
height: '',
|
|
|
|
|
flexDirection: 'column'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.element.classList.remove(...Object.values(attributes).map(pos => pos.className));
|
|
|
|
|
Object.keys(attributes[position].styles).forEach(key => {
|
|
|
|
|
this.element.style[key] = '';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.element.classList.add(attributes[position].className);
|
|
|
|
|
Object.entries(attributes[position].styles).forEach(([key, value]) => {
|
|
|
|
|
this.element.style[key] = value;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
switch (position) {
|
2025-10-27 21:33:38 +01:00
|
|
|
case 'right':
|
2025-11-02 09:26:19 +01:00
|
|
|
case 'left':
|
2025-11-02 10:14:54 +01:00
|
|
|
this.options.date = {year: '2-digit', month: '2-digit', day: '2-digit'};
|
|
|
|
|
this.options.direction = 1;
|
2025-10-27 21:33:38 +01:00
|
|
|
break;
|
|
|
|
|
case 'top':
|
|
|
|
|
case 'bottom':
|
2025-11-02 09:26:19 +01:00
|
|
|
default:
|
2025-11-02 10:14:54 +01:00
|
|
|
this.options.date = {year: 'numeric', month: '2-digit', day: '2-digit'};
|
|
|
|
|
this.options.direction = 0;
|
2025-10-27 21:33:38 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|