diff --git a/DragDropExample.html b/DragDropExample.html new file mode 100644 index 0000000..d7e3236 --- /dev/null +++ b/DragDropExample.html @@ -0,0 +1,83 @@ + + + +Using Drag and Drop API to copy and move elements + + + + + +

Drag and Drop: Copy and Move elements with DataTransfer

+
+ Select this element and drag to the Copy Drop Zone. +
+
Copy Drop Zone
+
+ Select this element and drag to the Move Drop Zone. +
+
Move Drop Zone
+ + + \ No newline at end of file diff --git a/app.py b/app.py index 2942a50..08d5f14 100644 --- a/app.py +++ b/app.py @@ -23,6 +23,10 @@ def home(): username = "Test_Username" return render_template('home.html', items=items, testList=testList, username=username) +@app.route('/relative-rank-ai') +def rank_ai(): + return render_template('relative_rank_ai.html') + @app.route('/relative-rank') def rank(): return render_template('relative_rank.html') diff --git a/static/css/relative_rank.css b/static/css/relative_rank.css new file mode 100644 index 0000000..31448bc --- /dev/null +++ b/static/css/relative_rank.css @@ -0,0 +1,13 @@ +.item { + border: 1px solid black; + width: fit-content; + list-style: none; + padding: 5px; + margin: 5px 0; +} + +.flex-container { + display: flex; + flex-wrap: wrap; + justify-content: space-around; +} \ No newline at end of file diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..4e2f529 Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/js/ranking.js b/static/js/ranking.js index 01aba68..6a49477 100644 --- a/static/js/ranking.js +++ b/static/js/ranking.js @@ -1,97 +1,41 @@ -// Make items draggable -const itemsPool = document.getElementById("items-pool"); -const rankingArea = document.getElementById("ranking-area"); -const ranksPool = document.getElementById("ranks"); -const addItemBtn = document.getElementById("add-item-btn"); -const addRankBtn = document.getElementById("add-rank-btn"); -// Enable drag-and-drop between the pool and ranking area -const sortablePool = new Sortable(itemsPool, { - group: { - name: "shared", // Group name must match between lists - pull: true, // Allow items to be dragged out - put: true, // Allow items to be dropped in - }, - animation: 150, -}); - -const sortableRanking = new Sortable(rankingArea, { - group: { - name: "shared", // Same group name as itemsPool - pull: true, // Allow items to be dragged out - put: true, // Allow items to be dropped in - }, - animation: 150, -}); - -// Add new item functionality -addItemBtn.addEventListener("click", () => { - const newItemText = prompt("Enter new item name:"); - if (newItemText) { - const li = document.createElement("li"); - li.className = "list-group-item"; - li.textContent = newItemText; - li.draggable = true; - itemsPool.appendChild(li); +function dragstart_handler(ev) { + console.log("dragStart"); + // Change the source element's background color to signify drag has started + //ev.currentTarget.style.border = "dashed"; + // Add the id of the drag source element to the drag data payload so + // it is available when the drop event is fired + ev.dataTransfer.setData("text", ev.target.id); + // Tell the browser both copy and move are possible + ev.effectAllowed = "copyMove"; +} +function dragover_handler(ev) { + //console.log("dragOver"); + // Change the target element's border to signify a drag over event + // has occurred + ev.currentTarget.style.background = "lightblue"; + ev.preventDefault(); +} +function drop_handler(ev) { + //console.log("Drop"); + ev.preventDefault(); + // Get the id of drag source element (that was added to the drag data + // payload by the dragstart event handler) + var id = ev.dataTransfer.getData("text"); + // Only Move the element if the source and destination ids are both "move" + if (id == "src_move" && ev.target.id == "drop-target"){ + ev.target.appendChild(document.getElementById(id)); + ev.target.style.background = "white"; } -}); - -// Add new item functionality -addRankBtn.addEventListener("click", () => { - const newItemText = prompt("Enter new rank name:"); - if (newItemText) { - const li = document.createElement("li"); - li.className = "mb-2"; - label = document.createElement('label'); - label.innerHTML = newItemText; - input = document.createElement('input'); - input.setAttribute("type", "number"); - input.setAttribute("class", "form-control"); - input.setAttribute("placeholder", "Enter last rank for " + newItemText); - li.appendChild(label) - li.appendChild(input); - //li.draggable = true; - ranksPool.appendChild(li); + // Copy the element if the source and destination ids are both "copy" + if (id == "src_copy" && ev.target.id == "dest_copy") { + var nodeCopy = document.getElementById(id).cloneNode(true); + nodeCopy.id = "newId"; + ev.target.appendChild(nodeCopy); } -}); - -// Save rankings and tier ranges -document.getElementById("save-btn").addEventListener("click", () => { - // Get ranked items - const rankedItems = Array.from(rankingArea.children).map((item) => item.textContent.trim()); - const sTierEnd = parseInt(document.getElementById("s-tier-end").value || "0"); - const aTierEnd = parseInt(document.getElementById("a-tier-end").value || "0"); - - // Tier categories - const tiers = { - "S-Tier": rankedItems.slice(0, sTierEnd), - "A-Tier": rankedItems.slice(sTierEnd, aTierEnd), - "Other": rankedItems.slice(aTierEnd), - }; - - // Apply colors to items based on tiers - Array.from(rankingArea.children).forEach((item, index) => { - item.classList.remove("s-tier", "a-tier", "other-tier"); // Remove existing classes - if (index < sTierEnd) { - item.classList.add("s-tier"); - } else if (index < aTierEnd) { - item.classList.add("a-tier"); - } else { - item.classList.add("other-tier"); - } - }); - - // Disable dragging - sortableRanking.option("disabled", true); // Disable drag-and-drop for ranking area - sortablePool.option("disabled", true); // Optionally disable pool area too - - // Send rankings to the server - fetch("/save-rankings", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ rankedItems, tiers }), - }) - .then((response) => response.json()) - .catch((error) => console.error("Error:", error)); -}); +} +function dragend_handler(ev) { + //console.log("dragEnd"); + // Restore source's border + //ev.target.style.border = "solid black"; + ev.target.style.background = "white"; +} \ No newline at end of file diff --git a/static/js/ranking_ai.js b/static/js/ranking_ai.js new file mode 100644 index 0000000..01aba68 --- /dev/null +++ b/static/js/ranking_ai.js @@ -0,0 +1,97 @@ +// Make items draggable +const itemsPool = document.getElementById("items-pool"); +const rankingArea = document.getElementById("ranking-area"); +const ranksPool = document.getElementById("ranks"); +const addItemBtn = document.getElementById("add-item-btn"); +const addRankBtn = document.getElementById("add-rank-btn"); +// Enable drag-and-drop between the pool and ranking area +const sortablePool = new Sortable(itemsPool, { + group: { + name: "shared", // Group name must match between lists + pull: true, // Allow items to be dragged out + put: true, // Allow items to be dropped in + }, + animation: 150, +}); + +const sortableRanking = new Sortable(rankingArea, { + group: { + name: "shared", // Same group name as itemsPool + pull: true, // Allow items to be dragged out + put: true, // Allow items to be dropped in + }, + animation: 150, +}); + +// Add new item functionality +addItemBtn.addEventListener("click", () => { + const newItemText = prompt("Enter new item name:"); + if (newItemText) { + const li = document.createElement("li"); + li.className = "list-group-item"; + li.textContent = newItemText; + li.draggable = true; + itemsPool.appendChild(li); + } +}); + +// Add new item functionality +addRankBtn.addEventListener("click", () => { + const newItemText = prompt("Enter new rank name:"); + if (newItemText) { + const li = document.createElement("li"); + li.className = "mb-2"; + label = document.createElement('label'); + label.innerHTML = newItemText; + input = document.createElement('input'); + input.setAttribute("type", "number"); + input.setAttribute("class", "form-control"); + input.setAttribute("placeholder", "Enter last rank for " + newItemText); + li.appendChild(label) + li.appendChild(input); + //li.draggable = true; + ranksPool.appendChild(li); + } +}); + +// Save rankings and tier ranges +document.getElementById("save-btn").addEventListener("click", () => { + // Get ranked items + const rankedItems = Array.from(rankingArea.children).map((item) => item.textContent.trim()); + const sTierEnd = parseInt(document.getElementById("s-tier-end").value || "0"); + const aTierEnd = parseInt(document.getElementById("a-tier-end").value || "0"); + + // Tier categories + const tiers = { + "S-Tier": rankedItems.slice(0, sTierEnd), + "A-Tier": rankedItems.slice(sTierEnd, aTierEnd), + "Other": rankedItems.slice(aTierEnd), + }; + + // Apply colors to items based on tiers + Array.from(rankingArea.children).forEach((item, index) => { + item.classList.remove("s-tier", "a-tier", "other-tier"); // Remove existing classes + if (index < sTierEnd) { + item.classList.add("s-tier"); + } else if (index < aTierEnd) { + item.classList.add("a-tier"); + } else { + item.classList.add("other-tier"); + } + }); + + // Disable dragging + sortableRanking.option("disabled", true); // Disable drag-and-drop for ranking area + sortablePool.option("disabled", true); // Optionally disable pool area too + + // Send rankings to the server + fetch("/save-rankings", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ rankedItems, tiers }), + }) + .then((response) => response.json()) + .catch((error) => console.error("Error:", error)); +}); diff --git a/templates/base.html b/templates/base.html index 97f4a38..b687ef3 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,7 +8,7 @@ - + @@ -19,6 +19,7 @@ + diff --git a/templates/relative_rank.html b/templates/relative_rank.html index c367c1a..e359c8f 100644 --- a/templates/relative_rank.html +++ b/templates/relative_rank.html @@ -1,46 +1,20 @@ -{%extends "base.html"%} +{% extends "base.html" %} -{%block content%} -

Relative Ranking

-
- -
-

Items Pool

-