145 lines
3.9 KiB
JavaScript
145 lines
3.9 KiB
JavaScript
let resolveLoaded;
|
|
const loaded = new Promise(resolve => resolveLoaded = resolve);
|
|
|
|
function e(unsafeText) {
|
|
let div = document.createElement('div');
|
|
div.innerText = unsafeText;
|
|
return div.innerHTML;
|
|
}
|
|
|
|
/**
|
|
* @type {import('../../src/lib/rpg/items').Item | null}
|
|
*/
|
|
let draggedItem = null;
|
|
/**
|
|
* @type {Record<string, import('../../src/lib/rpg/items').Items[]>}
|
|
*/
|
|
let itemLists = {};
|
|
|
|
function listToString(list) {
|
|
return list.map(stack => `${stack.item.id},${stack.quantity}`).join(';');
|
|
}
|
|
function updateString() {
|
|
document.querySelector('#recipe-string').innerText = [
|
|
listToString(itemLists['inputs'] || []),
|
|
listToString(itemLists['requirements'] || []),
|
|
listToString(itemLists['outputs'] || []),
|
|
].join('|');
|
|
}
|
|
|
|
/**
|
|
* @param {import('../../src/lib/rpg/items').Item} item
|
|
*/
|
|
function renderItem(item) {
|
|
const i = document.createElement('div');
|
|
i.innerHTML = `
|
|
<div class="icon">
|
|
${e(item.emoji)}
|
|
</div>
|
|
<div class="right">
|
|
<div class="name">${e(item.name)}</div>
|
|
<div class="description">${item.description ? e(item.description) : '<i>No description</i>'}</div>
|
|
</div>
|
|
`;
|
|
i.classList.add('item');
|
|
i.draggable = true;
|
|
i.addEventListener('dragstart', event => {
|
|
draggedItem = item;
|
|
event.target.classList.add('dragging');
|
|
});
|
|
i.addEventListener('dragend', event => {
|
|
draggedItem = null;
|
|
event.target.classList.remove('dragging');
|
|
});
|
|
return i;
|
|
}
|
|
function renderItemStack(item, quantity, type) {
|
|
const i = document.createElement('div');
|
|
i.innerHTML = `
|
|
<div class="icon">
|
|
${e(item.emoji)}
|
|
</div>
|
|
<div class="right">
|
|
x<b>${quantity}</b>
|
|
</div>
|
|
`;
|
|
i.classList.add('itemstack');
|
|
i.draggable = true;
|
|
i.addEventListener('dragstart', event => {
|
|
event.target.classList.add('dragging');
|
|
});
|
|
i.addEventListener('dragend', event => {
|
|
event.target.classList.remove('dragging');
|
|
itemLists[type] = itemLists[type] || [];
|
|
const items = itemLists[type];
|
|
const stackIdx = items.findIndex(n => n.item.id === item.id);
|
|
if (stackIdx !== -1) items.splice(stackIdx, 1);
|
|
document.querySelector(`.item-list[data-type="${type}"]`).replaceWith(renderItemList(items, type));
|
|
updateString();
|
|
});
|
|
return i;
|
|
}
|
|
function renderItemList(items, type) {
|
|
const i = document.createElement('div');
|
|
i.textContent = '';
|
|
items.forEach(itemStack => {
|
|
i.appendChild(renderItemStack(itemStack.item, itemStack.quantity, type));
|
|
});
|
|
i.dataset.type = type;
|
|
i.classList.add('item-list');
|
|
|
|
// prevent default to allow drop
|
|
i.addEventListener('dragover', (event) => event.preventDefault(), false);
|
|
|
|
i.addEventListener('dragenter', event => draggedItem && event.target.classList.add('dropping'));
|
|
i.addEventListener('dragleave', event => draggedItem && event.target.classList.remove('dropping'));
|
|
|
|
i.addEventListener('drop', (event) => {
|
|
event.preventDefault();
|
|
event.target.classList.remove('dropping');
|
|
|
|
if (!draggedItem) return;
|
|
|
|
itemLists[type] = itemLists[type] || [];
|
|
const items = itemLists[type];
|
|
|
|
const itemStack = items.find(v => v.item.id === draggedItem.id);
|
|
|
|
if (!itemStack) {
|
|
items.push({
|
|
item: draggedItem,
|
|
quantity: 1
|
|
});
|
|
} else {
|
|
itemStack.quantity = itemStack.quantity + 1;
|
|
}
|
|
|
|
updateString();
|
|
|
|
draggedItem = null;
|
|
|
|
event.target.replaceWith(renderItemList(items, type));
|
|
});
|
|
|
|
return i;
|
|
}
|
|
|
|
Promise.all([
|
|
fetch(`/api/items${document.location.search}`)
|
|
.then(res => res.json()),
|
|
loaded
|
|
]).then(([items]) => {
|
|
const itemsContainer = document.querySelector('.items');
|
|
itemsContainer.textContent = '';
|
|
items.forEach(item =>
|
|
itemsContainer.appendChild(renderItem(item))
|
|
);
|
|
document.querySelectorAll('.item-list').forEach(elem => {
|
|
const type = elem.dataset.type;
|
|
elem.replaceWith(renderItemList([], type));
|
|
});
|
|
|
|
updateString();
|
|
});
|
|
|
|
document.addEventListener('DOMContentLoaded', () => resolveLoaded()); |