115 lines
3.5 KiB
JavaScript
115 lines
3.5 KiB
JavaScript
|
|
class ContextMenu extends HTMLElement {
|
||
|
|
constructor() {
|
||
|
|
super();
|
||
|
|
this.app = null;
|
||
|
|
this.currentX = null;
|
||
|
|
this.currentY = null;
|
||
|
|
}
|
||
|
|
|
||
|
|
connectedCallback() {
|
||
|
|
this.innerHTML = `
|
||
|
|
<div id="menuItems">
|
||
|
|
<div class="menu-item" data-action="edit" style="padding: 8px; cursor: pointer; border-bottom: 1px solid var(--border-color);">
|
||
|
|
Edit Name
|
||
|
|
</div>
|
||
|
|
<div class="menu-item" data-action="delete" style="padding: 8px; cursor: pointer;">
|
||
|
|
Delete
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div id="editForm" style="display: none; padding: 10px;">
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
id="nameInput"
|
||
|
|
placeholder="Building name..."
|
||
|
|
style="width: 100%; margin-bottom: 8px;"
|
||
|
|
maxlength="30"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
|
||
|
|
// Menu item clicks
|
||
|
|
this.querySelectorAll('.menu-item').forEach(item => {
|
||
|
|
item.addEventListener('mouseenter', (e) => {
|
||
|
|
e.target.style.background = 'var(--bg-light)';
|
||
|
|
});
|
||
|
|
|
||
|
|
item.addEventListener('mouseleave', (e) => {
|
||
|
|
e.target.style.background = '';
|
||
|
|
});
|
||
|
|
|
||
|
|
item.addEventListener('click', (e) => {
|
||
|
|
const action = e.target.dataset.action;
|
||
|
|
this.handleAction(action);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// Edit form
|
||
|
|
const nameInput = this.querySelector('#nameInput');
|
||
|
|
nameInput.addEventListener('keypress', (e) => {
|
||
|
|
if (e.key === 'Enter') {
|
||
|
|
this.submitEdit();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
nameInput.addEventListener('keydown', (e) => {
|
||
|
|
if (e.key === 'Escape') {
|
||
|
|
this.hide();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Click outside to close
|
||
|
|
document.addEventListener('click', (e) => {
|
||
|
|
if (this.style.display !== 'none' && !this.contains(e.target)) {
|
||
|
|
this.hide();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
show(x, y, tileX, tileY) {
|
||
|
|
this.currentX = tileX;
|
||
|
|
this.currentY = tileY;
|
||
|
|
|
||
|
|
this.style.left = x + 'px';
|
||
|
|
this.style.top = y + 'px';
|
||
|
|
this.style.display = 'block';
|
||
|
|
|
||
|
|
this.querySelector('#menuItems').style.display = 'block';
|
||
|
|
this.querySelector('#editForm').style.display = 'none';
|
||
|
|
}
|
||
|
|
|
||
|
|
hide() {
|
||
|
|
this.style.display = 'none';
|
||
|
|
}
|
||
|
|
|
||
|
|
handleAction(action) {
|
||
|
|
if (action === 'edit') {
|
||
|
|
this.querySelector('#menuItems').style.display = 'none';
|
||
|
|
this.querySelector('#editForm').style.display = 'block';
|
||
|
|
|
||
|
|
const input = this.querySelector('#nameInput');
|
||
|
|
input.value = '';
|
||
|
|
input.focus();
|
||
|
|
} else if (action === 'delete') {
|
||
|
|
if (confirm('Delete this building?')) {
|
||
|
|
if (this.app) {
|
||
|
|
this.app.removeBuilding(this.currentX, this.currentY);
|
||
|
|
}
|
||
|
|
this.hide();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
submitEdit() {
|
||
|
|
const input = this.querySelector('#nameInput');
|
||
|
|
const name = input.value.trim();
|
||
|
|
|
||
|
|
if (name && this.app) {
|
||
|
|
this.app.editBuilding(this.currentX, this.currentY, name);
|
||
|
|
}
|
||
|
|
|
||
|
|
this.hide();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
customElements.define('context-menu', ContextMenu);
|