components/modal: Updated modal to work with forms
This commit is contained in:
@@ -1,5 +1,111 @@
|
||||
module.exports = class {
|
||||
onCreate() {
|
||||
this.mounted = false
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
this.emit("close")
|
||||
|
||||
if (this.mounted) {
|
||||
window.removeEventListener("keydown", this.onPress)
|
||||
}
|
||||
}
|
||||
|
||||
onInput(input) {
|
||||
if (!this.mounted) {
|
||||
return
|
||||
}
|
||||
|
||||
if (input) {
|
||||
if (input.enabled && (!this.input || !this.input.enabled)) {
|
||||
this.emit("open")
|
||||
}
|
||||
|
||||
if (input.closable) {
|
||||
if (input.enabled && (!this.input || !this.input.enabled)) {
|
||||
window.addEventListener("keydown", this.onPress)
|
||||
} else if (!input.enabled && (this.input && this.input.enabled)) {
|
||||
window.removeEventListener("keydown", this.onPress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMount() {
|
||||
this.onPress = this.onPress.bind(this)
|
||||
this.mounted = true
|
||||
|
||||
if (this.input.enabled && this.input.closable) {
|
||||
window.addEventListener("keydown", this.onPress)
|
||||
}
|
||||
}
|
||||
|
||||
onUnmount() {
|
||||
if (this.input.enabled) {
|
||||
window.removeEventListener("keydown", this.onPress)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {KeyboardEvent} ev
|
||||
*/
|
||||
onPress(ev) {
|
||||
if (ev.key === "Escape" && ev.ctrlKey ) {
|
||||
this.closeModal()
|
||||
}
|
||||
}
|
||||
|
||||
getValues() {
|
||||
/** @type {HTMLElement[]} */
|
||||
const elems = this.findInputs()
|
||||
const map = {}
|
||||
|
||||
for (const component of this.getComponents()) {
|
||||
if (component.getFormData != null) {
|
||||
Object.assign(map, component.getFormData() || {})
|
||||
}
|
||||
}
|
||||
|
||||
return elems.reduce((map, elem) => {
|
||||
let path = elem.getAttribute("name").split(".")
|
||||
let node = map
|
||||
for (const part of path.slice(0, -1)) {
|
||||
if (node[part] == null) {
|
||||
node[part] = {}
|
||||
}
|
||||
|
||||
node = node[part]
|
||||
}
|
||||
|
||||
node[path[path.length - 1]] = elem.value;
|
||||
return map
|
||||
}, map)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} elem
|
||||
*/
|
||||
findInputs(elem = this.getEl()) {
|
||||
let results = []
|
||||
|
||||
if (elem.childNodes.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
for (let i = 0; i < elem.children.length; ++i) {
|
||||
const child = elem.children.item(i)
|
||||
if (child.dataset.formboundary != null) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (child.nodeName === "INPUT" || child.nodeName === "TEXTAREA") {
|
||||
results.push(child)
|
||||
} else {
|
||||
results = results.concat(this.findInputs(child))
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
<if(input.enabled)>
|
||||
<div class=["overlay", (input.notification ? "notification-overlay" : "normal-overlay")]>
|
||||
<div class="overlay-options color-menu">
|
||||
<div if(input.closable) on-click("closeModal")>X</div>
|
||||
<div if(input.closable) on-click("closeModal")>Close</div>
|
||||
</div>
|
||||
<div class="modal color-text">
|
||||
<div class=input.class>
|
||||
<include(input.renderBody) />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,12 +4,12 @@ div.overlay {
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
padding-top: 4em;
|
||||
padding-top: 1em;
|
||||
z-index: 999;
|
||||
|
||||
background-color: rgba(0, 0, 0, 0.75);
|
||||
background-color: rgba(0, 0, 0, 0.90);
|
||||
|
||||
overflow-y: auto;
|
||||
overflow-y: scroll;
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
@@ -19,6 +19,70 @@ div.overlay {
|
||||
width: 60ch;
|
||||
max-width: 95%;
|
||||
margin: auto;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0 0.5ch;
|
||||
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
background: none;
|
||||
outline: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
input.big {
|
||||
font-size: 1.5em;
|
||||
padding: 0 0.3333ch;
|
||||
}
|
||||
|
||||
textarea {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 8em;
|
||||
padding: 0 0.5ch;
|
||||
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
background: none;
|
||||
outline: none;
|
||||
opacity: 0.5;
|
||||
|
||||
resize: none;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
textarea.tall {
|
||||
height: 24em;
|
||||
}
|
||||
|
||||
input:focus, textarea:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
button {
|
||||
border: 1px solid;
|
||||
background-color: rgba(0, 0, 0, 0.75);
|
||||
margin: 2em auto;
|
||||
display: block;
|
||||
padding: 0.5em 4ch;
|
||||
|
||||
opacity: 0.75;
|
||||
}
|
||||
button:hover {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
div.modal.nolabel {
|
||||
input, textarea {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
div.overlay-options {
|
||||
|
||||
Reference in New Issue
Block a user