diff options
Diffstat (limited to 'static/index.js')
| -rw-r--r-- | static/index.js | 585 |
1 files changed, 0 insertions, 585 deletions
diff --git a/static/index.js b/static/index.js deleted file mode 100644 index ffc5532..0000000 --- a/static/index.js +++ /dev/null @@ -1,585 +0,0 @@ -/* - Offline Tierlist Maker - Copyright (C) 2022 silverweed - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. -*/ - -'use strict'; - -const MAX_NAME_LEN = 200; -const DEFAULT_TIERS = ['S', 'A', 'B', 'C', 'D', 'E', 'F']; -const TIER_COLORS = [ - '#ff6666', - '#f0a731', - '#f4d95b', - '#66ff66', - '#58c8f4', - '#5b76f4', - '#f45bed' -]; - -let unique_id = 0; - -let unsaved_changes = false; - -const LAYOUT_HORIZONTAL = 0; -const LAYOUT_VERTICAL = 1; -let cur_layout = LAYOUT_HORIZONTAL; - -// Contains [[header, input, label]] -let all_headers = []; -let headers_orig_min_width; - -// DOM elems -let untiered_images; -let tierlist_div; -let dragged_image; - -function reset_row(row) { - row.querySelectorAll('span.item').forEach((item) => { - for (let i = 0; i < item.children.length; ++i) { - let img = item.children[i]; - item.removeChild(img); - untiered_images.appendChild(img); - } - item.parentNode.removeChild(item); - }); -} - -function hard_reset_list() { - tierlist_div.innerHTML = ''; - untiered_images.innerHTML = ''; -} - -function soft_reset_list() { - tierlist_div.querySelectorAll('.row').forEach(reset_row); - unsaved_changes = true; -} - -window.addEventListener('load', () => { - untiered_images = document.querySelector('.images'); - tierlist_div = document.querySelector('.tierlist'); - - for (let i = 0; i < DEFAULT_TIERS.length; ++i) { - add_row(i, DEFAULT_TIERS[i]); - } - recompute_header_colors(); - - headers_orig_min_width = all_headers[0][0].clientWidth; - - make_accept_drop(document.querySelector('.images')); - - bind_title_events(); - - document.getElementById('load-img-input').addEventListener('input', (evt) => { - let images = document.querySelector('.images'); - for (let file of evt.target.files) { - let reader = new FileReader(); - reader.addEventListener('load', (load_evt) => { - let img = create_img_with_src(load_evt.target.result); - images.appendChild(img); - unsaved_changes = true; - }); - reader.readAsDataURL(file); - } - }); - - document.onpaste = (evt) => { - let clip_data = evt.clipboardData || evt.originalEvent.clipboardData; - let items = clip_data.items; - let images = document.querySelector('.images'); - for (let item of items) { - if (item.kind === 'file') { - let blob = item.getAsFile(); - let reader = new FileReader(); - reader.onload = (load_evt) => { - let img = create_img_with_src(load_evt.target.result); - images.appendChild(img); - unsaved_changes = true; - }; - reader.readAsDataURL(blob); - } - } - }; - - document.getElementById('reset-list-input').addEventListener('click', () => { - if (confirm('Reset Tierlist? (this will place all images back in the pool)')) { - soft_reset_list(); - } - }); - - document.getElementById('export-input').addEventListener('click', () => { - let name = prompt('Please give a name to this tierlist'); - if (name) { - save_tierlist(`${name}.json`); - } - }); - - document.getElementById('import-input').addEventListener('input', (evt) => { - if (!evt.target.files) { - return; - } - let file = evt.target.files[0]; - let reader = new FileReader(); - reader.addEventListener('load', (load_evt) => { - let raw = load_evt.target.result; - let parsed = JSON.parse(raw); - if (!parsed) { - alert("Failed to parse data"); - return; - } - hard_reset_list(); - load_tierlist(parsed); - }); - reader.readAsText(file); - }); - - bind_trash_events(); - bind_toggle_layout_events(); - - window.addEventListener('beforeunload', (evt) => { - if (!unsaved_changes) return null; - var msg = "You have unsaved changes. Leave anyway?"; - (evt || window.event).returnValue = msg; - return msg; - }); - - void try_load_tierlist_json(); - - const modal = document.getElementById('image-modal'); - const modalImg = document.getElementById('modal-img'); - const modalTitle = document.getElementById('modal-title'); - const modalDesc = document.getElementById('modal-description'); - const modalSave = document.getElementById('modal-save'); - const modalClose = document.querySelector('.modal .close'); - let currentModalImage = null; - - function showModal(img) { - currentModalImage = img; - document.body.style.overflow = 'hidden'; - modal.style.display = 'flex'; - modalImg.src = img.src; - modalTitle.value = img.dataset.title || ''; - modalDesc.value = img.dataset.description || ''; - } - - modalClose.addEventListener('click', () => { - modal.style.display = 'none'; - document.body.style.overflow = 'hidden'; - }); - - modalSave.addEventListener('click', () => { - if (currentModalImage) { - currentModalImage.dataset.title = modalTitle.value; - currentModalImage.dataset.description = modalDesc.value; - } - modal.style.display = 'none'; - document.body.style.overflow = 'hidden'; - }); - - window.addEventListener('click', (evt) => { - if (evt.target == modal) { - modal.style.display = 'none'; - document.body.style.overflow = 'hidden'; - } - }); - - tierlist_div.addEventListener('click', (evt) => { - if (evt.target.tagName.toUpperCase() === 'IMG') { - showModal(evt.target); - } - }); -}); - -function create_img_with_src(src) { - let img = document.createElement('img'); - img.src = src; - img.style.userSelect = 'none'; - img.classList.add('draggable'); - img.draggable = true; - - img.addEventListener("dragstart", (evt) => { - evt.dataTransfer.setData("text/plain", null); - dragged_image = evt.target; - dragged_image.classList.add("dragged"); - }); - - img.addEventListener("mouseenter", (evt) => { - const title = evt.target.dataset.title; - if (title) { - evt.target.title = title; - } - }); - - img.addEventListener("dragend", (evt) => { - if (dragged_image) { - dragged_image.classList.remove("dragged"); - } - dragged_image = null; - }); - - return img; -} - - -function save(filename, text) { - unsaved_changes = false; - - var el = document.createElement('a'); - el.setAttribute('href', 'data:text/html;charset=utf-8,' + encodeURIComponent(text)); - el.setAttribute('download', filename); - el.style.display = 'none'; - document.body.appendChild(el); - el.click(); - document.body.removeChild(el); -} - -function save_tierlist(filename) { - let serialized_tierlist = { - title: document.querySelector('.title-label').innerText, - rows: [], - }; - tierlist_div.querySelectorAll('.row').forEach((row, i) => { - serialized_tierlist.rows.push({ - name: row.querySelector('.header label').innerText.substr(0, MAX_NAME_LEN) - }); - serialized_tierlist.rows[i].imgs = []; - row.querySelectorAll('img').forEach((img) => { - serialized_tierlist.rows[i].imgs.push({ - src: img.src, - title: img.dataset.title || '', - description: img.dataset.description || '' - }); - }); - }); - - let untiered_imgs = document.querySelectorAll('.images img'); - if (untiered_imgs.length > 0) { - serialized_tierlist.untiered = []; - untiered_imgs.forEach((img) => { - serialized_tierlist.untiered.push({ - src: img.src, - title: img.dataset.title || '', - description: img.dataset.description || '' - }); - }); - } - - save(filename, JSON.stringify(serialized_tierlist)); -} - -function load_tierlist(serialized_tierlist) { - document.querySelector('.title-label').innerText = serialized_tierlist.title; - for (let idx in serialized_tierlist.rows) { - let ser_row = serialized_tierlist.rows[idx]; - let elem = add_row(idx, ser_row.name); - - for (let img_obj of ser_row.imgs ?? []) { - let img = create_img_with_src(img_obj.src); - img.dataset.title = img_obj.title || ''; - img.dataset.description = img_obj.description || ''; - let td = document.createElement('span'); - td.classList.add('item'); - td.appendChild(img); - let items_container = elem.querySelector('.items'); - items_container.appendChild(td); - } - - elem.querySelector('label').innerText = ser_row.name; - } - recompute_header_colors(); - - if (serialized_tierlist.untiered) { - let images = document.querySelector('.images'); - for (let img_obj of serialized_tierlist.untiered) { - let img = create_img_with_src(img_obj.src); - img.dataset.title = img_obj.title || ''; - img.dataset.description = img_obj.description || ''; - images.appendChild(img); - } - } - - resize_headers(); - - unsaved_changes = false; -} - -function end_drag(evt) { - if (dragged_image) { - dragged_image.classList.remove("dragged"); - } - dragged_image = null; -} - -window.addEventListener('mouseup', end_drag); -window.addEventListener('dragend', end_drag); - - -function make_accept_drop(elem) { - elem.classList.add('droppable'); - - elem.addEventListener('dragenter', (evt) => { - evt.preventDefault(); - evt.target.classList.add('drag-entered'); - }); - - elem.addEventListener('dragleave', (evt) => { - evt.target.classList.remove('drag-entered'); - }); - - elem.addEventListener('dragover', (evt) => { - evt.preventDefault(); - }); - - elem.addEventListener('drop', (evt) => { - evt.preventDefault(); - evt.target.classList.remove('drag-entered'); - - if (!dragged_image) { - return; - } - - let dragged_image_parent = dragged_image.parentNode; - if (dragged_image_parent.tagName.toUpperCase() === 'SPAN' && - dragged_image_parent.classList.contains('item')) { - let containing_tr = dragged_image_parent.parentNode; - containing_tr.removeChild(dragged_image_parent); - } else { - dragged_image_parent.removeChild(dragged_image); - } - - let td = document.createElement('span'); - td.classList.add('item'); - td.appendChild(dragged_image); - let items_container = elem.querySelector('.items'); - - if (!items_container) { - items_container = elem; - } - items_container.appendChild(td); - - dragged_image.draggable = true; - dragged_image.classList.remove("dragged"); - - dragged_image.addEventListener("dragstart", (e) => { - e.dataTransfer.setData("text/plain", null); - dragged_image.classList.add("dragged"); - }); - - unsaved_changes = true; - }); -} - - -function enable_edit_on_click(container, input, label) { - function change_label(evt) { - input.style.display = 'none'; - label.innerText = input.value; - label.style.display = 'inline'; - unsaved_changes = true; - } - - input.addEventListener('change', change_label); - input.addEventListener('focusout', change_label); - - container.addEventListener('click', (evt) => { - label.style.display = 'none'; - input.value = label.innerText.substr(0, MAX_NAME_LEN); - input.style.display = 'inline'; - input.select(); - }); -} - -function bind_title_events() { - let title_label = document.querySelector('.title-label'); - let title_input = document.getElementById('title-input'); - let title = document.querySelector('.title'); - - enable_edit_on_click(title, title_input, title_label); -} - -function create_label_input(row, row_idx, row_name) { - let input = document.createElement('input'); - input.id = `input-tier-${unique_id++}`; - input.type = 'text'; - input.addEventListener('change', resize_headers); - let label = document.createElement('label'); - label.htmlFor = input.id; - label.innerText = row_name; - - let header = row.querySelector('.header'); - all_headers.splice(row_idx, 0, [header, input, label]); - header.appendChild(label); - header.appendChild(input); - - enable_edit_on_click(header, input, label); -} - -function resize_headers() { - let max_width = headers_orig_min_width; - for (let [other_header, _i, label] of all_headers) { - max_width = Math.max(max_width, label.clientWidth); - } - - for (let [other_header, _i2, _l2] of all_headers) { - other_header.style.minWidth = `${max_width}px`; - } -} - -function add_row(index, name) { - let div = document.createElement('div'); - let header = document.createElement('span'); - let items = document.createElement('span'); - div.classList.add('row'); - header.classList.add('header'); - items.classList.add('items'); - div.appendChild(header); - div.appendChild(items); - let row_buttons = document.createElement('div'); - row_buttons.classList.add('row-buttons'); - let btn_plus_up = document.createElement('input'); - btn_plus_up.type = "button"; - btn_plus_up.value = '+'; - btn_plus_up.title = "Add row above"; - btn_plus_up.addEventListener('click', (evt) => { - let parent_div = evt.target.parentNode.parentNode; - let rows = Array.from(tierlist_div.children); - let idx = rows.indexOf(parent_div); - console.assert(idx >= 0); - add_row(idx, ''); - recompute_header_colors(); - }); - let btn_rm = document.createElement('input'); - btn_rm.type = "button"; - btn_rm.value = '-'; - btn_rm.title = "Remove row"; - btn_rm.addEventListener('click', (evt) => { - let rows = Array.from(tierlist_div.querySelectorAll('.row')); - if (rows.length < 2) return; - let parent_div = evt.target.parentNode.parentNode; - let idx = rows.indexOf(parent_div); - console.assert(idx >= 0); - if (rows[idx].querySelectorAll('img').length === 0 || - confirm(`Remove tier ${rows[idx].querySelector('.header label').innerText}? (This will move back all its content to the untiered pool)`)) { - rm_row(idx); - } - recompute_header_colors(); - }); - let btn_plus_down = document.createElement('input'); - btn_plus_down.type = "button"; - btn_plus_down.value = '+'; - btn_plus_down.title = "Add row below"; - btn_plus_down.addEventListener('click', (evt) => { - let parent_div = evt.target.parentNode.parentNode; - let rows = Array.from(tierlist_div.children); - let idx = rows.indexOf(parent_div); - console.assert(idx >= 0); - add_row(idx + 1, name); - recompute_header_colors(); - }); - row_buttons.appendChild(btn_plus_up); - row_buttons.appendChild(btn_rm); - row_buttons.appendChild(btn_plus_down); - div.appendChild(row_buttons); - - let rows = tierlist_div.children; - if (index === rows.length) { - tierlist_div.appendChild(div); - } else { - let nxt_child = rows[index]; - tierlist_div.insertBefore(div, nxt_child); - } - - make_accept_drop(div); - create_label_input(div, index, name); - - return div; -} - -function rm_row(idx) { - let row = tierlist_div.children[idx]; - reset_row(row); - tierlist_div.removeChild(row); -} - -function recompute_header_colors() { - tierlist_div.querySelectorAll('.row').forEach((row, row_idx) => { - let color = TIER_COLORS[row_idx % TIER_COLORS.length]; - row.querySelector('.header').style.backgroundColor = color; - }); -} - -function bind_trash_events() { - let trash = document.getElementById('trash'); - trash.classList.add('droppable'); - trash.addEventListener('dragenter', (evt) => { - evt.preventDefault(); - evt.target.src = '/static/img/trash-2.svg'; - }); - trash.addEventListener('dragexit', (evt) => { - evt.preventDefault(); - evt.target.src = '/static/img/trash.svg'; - }); - trash.addEventListener('dragover', (evt) => { - evt.preventDefault(); - }); - trash.addEventListener('drop', (evt) => { - evt.preventDefault(); - evt.target.src = '/static/img/trash.svg'; - if (dragged_image) { - let dragged_image_parent = dragged_image.parentNode; - if (dragged_image_parent.tagName.toUpperCase() === 'SPAN' && - dragged_image_parent.classList.contains('item')) { - let containing_tr = dragged_image_parent.parentNode; - containing_tr.removeChild(dragged_image_parent); - } - dragged_image.remove(); - } - }); -} - -function bind_toggle_layout_events() { - let toggle = document.getElementById('toggle-layout'); - toggle.addEventListener('click', () => { - set_layout((cur_layout + 1) % 2); - }); -} - -function set_layout(layout) { - let main = document.getElementsByClassName("main-content")[0]; - if (layout === LAYOUT_VERTICAL) { - main.classList.add("vertical"); - } else { - main.classList.remove("vertical"); - } - cur_layout = layout; -} - -function is_url(str) { - try { - new URL(str); - return true; - } catch (e) { - return false; - } -} - -async function try_load_tierlist_json() { - const load_from_url = new URLSearchParams(window.location.search).get('url'); - if (load_from_url !== null && is_url(load_from_url)) { - try { - let result = await fetch(load_from_url); - result = await result.json(); - hard_reset_list(); - load_tierlist(result); - } catch (e) { console.error(e); } - } -} |
