add draggable list custom element,

improve boot order list
This commit is contained in:
Arthur Lu 2023-08-14 23:42:02 +00:00
parent 7e01b5d730
commit 888e8bbc7e
3 changed files with 147 additions and 90 deletions

View File

@ -10,6 +10,7 @@
<link rel="stylesheet" href="css/nav.css"> <link rel="stylesheet" href="css/nav.css">
<link rel="stylesheet" href="css/form.css"> <link rel="stylesheet" href="css/form.css">
<script src="scripts/config.js" type="module"></script> <script src="scripts/config.js" type="module"></script>
<script src="scripts/draggable.js" type="module"></script>
</head> </head>
<body> <body>
<header> <header>
@ -55,15 +56,9 @@
</fieldset> </fieldset>
<fieldset class="w3-card w3-padding none" id="boot-card"> <fieldset class="w3-card w3-padding none" id="boot-card">
<legend>Boot Order</legend> <legend>Boot Order</legend>
<div id="enabled"> <draggable-container id="enabled"></draggable-container>
<label>Enabled</label> <hr style="padding: 0; margin: 0;">
<div class="drop-target spacer" id="enabled-spacer"></div> <draggable-container id="disabled"></draggable-container>
</div>
<hr style="margin: 0.5em 0px;">
<div id="disabled">
<label>Disabled</label>
<div class="drop-target spacer" id="disabled-spacer"></div>
</div>
</fieldset> </fieldset>
<div class="w3-container w3-center" id="form-actions"> <div class="w3-container w3-center" id="form-actions">
<button class="w3-button w3-margin" id="exit" type="button">EXIT</button> <button class="w3-button w3-margin" id="exit" type="button">EXIT</button>

View File

@ -754,25 +754,8 @@ async function handleDeviceAdd () {
async function populateBoot () { async function populateBoot () {
if (type === "qemu") { if (type === "qemu") {
document.querySelector("#boot-card").classList.remove("none"); document.querySelector("#boot-card").classList.remove("none");
document.querySelectorAll(".drop-target").forEach((element) => { document.querySelector("#enabled").title = "Enabled";
element.addEventListener("dragenter", (event) => { document.querySelector("#disabled").title = "Disabled";
event.target.style.borderTop = "1px dotted";
event.preventDefault();
});
element.addEventListener("dragleave", (event) => {
event.target.attributeStyleMap.clear();
event.preventDefault();
});
element.addEventListener("dragover", (event) => {
event.preventDefault();
});
element.addEventListener("drop", (event) => {
const data = event.dataTransfer.getData("text/plain");
event.target.attributeStyleMap.clear();
addBootLine(element.parentElement.id, JSON.parse(data), element);
event.preventDefault();
});
});
const order = config.data.boot.replace("order=", "").split(";"); const order = config.data.boot.replace("order=", "").split(";");
const bootable = { disabled: [] }; const bootable = { disabled: [] };
const eligible = bootMetaData.eligiblePrefixes; const eligible = bootMetaData.eligiblePrefixes;
@ -801,74 +784,22 @@ async function populateBoot () {
} }
function addBootLine (fieldset, bootable, before = null) { function addBootLine (fieldset, bootable, before = null) {
const box = document.createElement("div"); const item = document.createElement("draggable-item");
const icon = document.createElement("img"); item.bootable = bootable;
icon.src = bootMetaData[bootable.prefix].icon; item.innerHTML = `
box.append(icon); <img src="${bootMetaData[bootable.prefix].icon}">
const label = document.createElement("p"); <p style="margin: 0px;">${bootable.id}</p>
label.innerText = bootable.id; `;
label.style.margin = "0px"; item.draggable = true;
box.append(label); item.classList.add("drop-target");
box.draggable = true;
box.classList.add("flex");
box.classList.add("row");
box.classList.add("drop-target");
box.id = `boot-${bootable.id}`;
// setup draggable event listeners
box.addEventListener("dragstart", (event) => {
event.target.style.opacity = "0.5";
event.dataTransfer.setData("text/plain", JSON.stringify(bootable));
event.dataTransfer.effectAllowed = "move";
});
box.addEventListener("dragend", (event) => {
if (event.dataTransfer.dropEffect === "move") {
box.parentElement.removeChild(box);
}
else {
event.target.attributeStyleMap.clear();
}
});
box.addEventListener("dragenter", (event) => {
if (event.target.parentElement.classList.contains("drop-target")) {
event.target.parentElement.style.borderTop = "1px dotted";
}
event.preventDefault();
});
box.addEventListener("dragleave", (event) => {
if (event.target.parentElement.classList.contains("drop-target")) {
event.target.parentElement.style.borderTop = "";
}
event.preventDefault();
});
box.addEventListener("dragover", (event) => {
event.preventDefault();
});
box.addEventListener("drop", (event) => {
event.preventDefault();
const data = event.dataTransfer.getData("text/plain");
if (event.target.parentElement.classList.contains("drop-target")) {
event.target.parentElement.attributeStyleMap.clear();
}
addBootLine(box.parentElement.id, JSON.parse(data), box);
});
if (before) { if (before) {
document.querySelector(`#${fieldset}`).insertBefore(box, before); document.querySelector(`#${fieldset}`).insertBefore(item, before);
} }
else { else {
document.querySelector(`#${fieldset}`).append(box); document.querySelector(`#${fieldset}`).append(item);
} }
} }
class DraggableItem extends HTMLElement {
constructor () {
super();
}
}
customElements.define("draggable-item", DraggableItem);
window.customElement
async function handleFormExit () { async function handleFormExit () {
const body = { const body = {
cores: document.querySelector("#cores").value, cores: document.querySelector("#cores").value,

131
scripts/draggable.js Normal file
View File

@ -0,0 +1,131 @@
class DraggableContainer extends HTMLElement {
constructor () {
super();
this.attachShadow({ mode: "open" });
this.shadowRoot.innerHTML = `
<link rel="stylesheet" href="css/style.css">
<label id="title"></label>
<div id="wrapper">
<draggable-item id="bottom" class="drop-target"></draggable-item>
</div>
`;
this.content = this.shadowRoot.querySelector("#wrapper");
this.bottom = this.shadowRoot.querySelector("#bottom");
this.titleElem = this.shadowRoot.querySelector("#title");
}
get title () {
return this.titleElem.innerText;
}
set title (title) {
this.titleElem.innerText = title;
}
append (newNode) {
this.content.insertBefore(newNode, this.bottom);
}
insertBefore (newNode, referenceNode) {
this.content.insertBefore(newNode, referenceNode);
}
}
class DraggableItem extends HTMLElement {
constructor () {
super();
this.attachShadow({ mode: "open" });
this.shadowRoot.innerHTML = `
<link rel="stylesheet" href="css/style.css">
<style>
#wrapper {
min-height: 1.5em;
}
</style>
<div id="wrapper" class="flex row"></div>
`;
this.content = this.shadowRoot.querySelector("#wrapper");
// add drag and drop listeners
this.addEventListener("dragstart", (event) => {
this.content.style.opacity = "0.5";
event.dataTransfer.setData("application/json", JSON.stringify(this.data));
event.dataTransfer.setData("text/html", this.content.innerHTML);
event.dataTransfer.effectAllowed = "move";
});
this.addEventListener("dragend", (event) => {
if (event.dataTransfer.dropEffect === "move") {
this.parentElement.removeChild(this);
}
else {
this.content.attributeStyleMap.clear();
}
});
this.addEventListener("dragenter", (event) => {
if (event.target.classList.contains("drop-target")) {
event.target.classList.add("drag-over");
event.target.borderTop = true;
}
event.preventDefault();
});
this.addEventListener("dragleave", (event) => {
if (event.target.classList.contains("drag-over")) {
event.target.classList.remove("drag-over");
event.target.borderTop = false;
}
event.preventDefault();
});
this.addEventListener("dragover", (event) => {
event.preventDefault();
});
this.addEventListener("drop", (event) => {
if (event.target.classList.contains("drag-over")) {
event.target.classList.remove("drag-over");
event.target.borderTop = false;
}
if (event.target.classList.contains("drop-target")) {
const data = event.dataTransfer.getData("application/json");
const content = event.dataTransfer.getData("text/html");
const item = document.createElement("draggable-item");
item.bootable = data;
item.innerHTML = content;
item.draggable = true;
item.classList.add("drop-target");
event.target.parentElement.insertBefore(item, event.target);
}
this.content.attributeStyleMap.clear();
event.preventDefault();
});
}
get innerHTML () {
return this.content.innerHTML;
}
set innerHTML (innerHTML) {
this.content.innerHTML = innerHTML;
}
get bootable () {
return this.data;
}
set bootable (bootable) {
this.data = bootable;
}
get borderTop () {
return this.content.style.borderTop === "";
}
set borderTop (borderTop) {
if (borderTop) {
this.content.style.borderTop = "1px dotted";
}
else {
this.content.style.borderTop = "";
}
}
}
customElements.define("draggable-container", DraggableContainer);
customElements.define("draggable-item", DraggableItem);