diff --git a/src/core/Ingredient.mjs b/src/core/Ingredient.mjs index e06b9a6a..02359014 100755 --- a/src/core/Ingredient.mjs +++ b/src/core/Ingredient.mjs @@ -24,6 +24,7 @@ class Ingredient { this.disabled = false; this.hint = ""; this.toggleValues = []; + this.target = null; if (ingredientConfig) { this._parseConfig(ingredientConfig); @@ -44,6 +45,7 @@ class Ingredient { this.disabled = !!ingredientConfig.disabled; this.hint = ingredientConfig.hint || false; this.toggleValues = ingredientConfig.toggleValues; + this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null; } diff --git a/src/core/Operation.mjs b/src/core/Operation.mjs index 23dac19b..cdeb9a73 100755 --- a/src/core/Operation.mjs +++ b/src/core/Operation.mjs @@ -179,6 +179,7 @@ class Operation { if (ing.toggleValues) conf.toggleValues = ing.toggleValues; if (ing.hint) conf.hint = ing.hint; if (ing.disabled) conf.disabled = ing.disabled; + if (ing.target) conf.target = ing.target; return conf; }); } diff --git a/src/web/App.mjs b/src/web/App.mjs index ef0bd3a8..bb2a5977 100755 --- a/src/web/App.mjs +++ b/src/web/App.mjs @@ -472,9 +472,8 @@ class App { } else if (args[j].classList.contains("toggle-string")) { // toggleString args[j].value = recipeConfig[i].args[j].string; - args[j].previousSibling.children[0].innerHTML = - Utils.escapeHtml(recipeConfig[i].args[j].option) + - " "; + args[j].parentNode.parentNode.querySelector("button").innerHTML = + Utils.escapeHtml(recipeConfig[i].args[j].option); } else { // all others args[j].value = recipeConfig[i].args[j]; @@ -705,42 +704,6 @@ class App { this.loadURIParams(); } - - /** - * Function to call an external API from this view. - */ - callApi(url, type, data, dataType, contentType) { - type = type || "POST"; - data = data || {}; - dataType = dataType || undefined; - contentType = contentType || "application/json"; - - let response = null, - success = false; - - $.ajax({ - url: url, - async: false, - type: type, - data: data, - dataType: dataType, - contentType: contentType, - success: function(data) { - success = true; - response = data; - }, - error: function(data) { - success = false; - response = data; - }, - }); - - return { - success: success, - response: response - }; - } - } export default App; diff --git a/src/web/HTMLIngredient.mjs b/src/web/HTMLIngredient.mjs index f45b4de4..88fd9781 100755 --- a/src/web/HTMLIngredient.mjs +++ b/src/web/HTMLIngredient.mjs @@ -24,7 +24,6 @@ class HTMLIngredient { this.type = config.type; this.value = config.value; this.disabled = config.disabled || false; - this.disableArgs = config.disableArgs || false; this.hint = config.hint || false; this.target = config.target; this.toggleValues = config.toggleValues; @@ -38,20 +37,9 @@ class HTMLIngredient { * @returns {string} */ toHtml() { - const inline = ( - this.type === "boolean" || - this.type === "number" || - this.type === "option" || - this.type === "shortString" || - this.type === "binaryShortString" - ); - let html = inline ? "" : "
 
", + let html = "", i, m; - /*html += "
";*/ - switch (this.type) { case "string": case "binaryString": @@ -69,102 +57,149 @@ class HTMLIngredient { break; case "shortString": case "binaryShortString": - html += ""; + html += `
+ + + ${this.hint ? "" + this.hint + "" : ""} +
`; break; case "toggleString": - html += "
\ -
"; + html += `
+ +
+ + + ${this.hint ? "" + this.hint + "" : ""} +
+ `; break; case "number": - html += ""; + html += `
+ + + ${this.hint ? "" + this.hint + "" : ""} +
`; break; case "boolean": - html += ``; - - // html += ""; - - if (this.disableArgs) { - this.manager.addDynamicListener("#" + this.id, "click", this.toggleDisableArgs, this); - } + html += `
+
+ +
+
`; break; case "option": - html += "`; for (i = 0; i < this.value.length; i++) { if ((m = this.value[i].match(/\[([a-z0-9 -()^]+)\]/i))) { - html += ""; + html += ``; } else if ((m = this.value[i].match(/\[\/([a-z0-9 -()^]+)\]/i))) { html += ""; } else { - html += ""; + html += ``; } } - html += ""; + html += ` + ${this.hint ? "" + this.hint + "" : ""} + `; break; case "populateOption": - html += "`; for (i = 0; i < this.value.length; i++) { if ((m = this.value[i].name.match(/\[([a-z0-9 -()^]+)\]/i))) { - html += ""; + html += ``; } else if ((m = this.value[i].name.match(/\[\/([a-z0-9 -()^]+)\]/i))) { html += ""; } else { - html += ""; + html += ``; } } - html += ""; + html += ` + ${this.hint ? "" + this.hint + "" : ""} + `; this.manager.addDynamicListener("#" + this.id, "change", this.populateOptionChange, this); break; case "editableOption": - html += "
"; - html += " + ${this.hint ? "" + this.hint + "" : ""} +
+ + "; + html += `
+
+ `; - - this.manager.addDynamicListener("#sel-" + this.id, "change", this.editableOptionChange, this); + this.manager.addDynamicListener(".editable-option-menu a", "click", this.editableOptionClick, this); break; case "text": - html += ""; + html += `
+ + + ${this.hint ? "" + this.hint + "" : ""} +
`; break; default: break; @@ -175,33 +210,6 @@ class HTMLIngredient { } - /** - * Handler for argument disable toggle. - * Toggles disabled state for all arguments in the disableArgs list for this ingredient. - * - * @param {event} e - */ - toggleDisableArgs(e) { - const el = e.target; - const op = el.parentNode.parentNode; - const args = op.querySelectorAll(".arg-group"); - - for (let i = 0; i < this.disableArgs.length; i++) { - const els = args[this.disableArgs[i]].querySelectorAll("input, select, button"); - - for (let j = 0; j < els.length; j++) { - if (els[j].getAttribute("disabled")) { - els[j].removeAttribute("disabled"); - } else { - els[j].setAttribute("disabled", "disabled"); - } - } - } - - this.manager.recipe.ingChange(); - } - - /** * Handler for populate option changes. * Populates the relevant argument with the specified value. @@ -211,25 +219,30 @@ class HTMLIngredient { populateOptionChange(e) { const el = e.target; const op = el.parentNode.parentNode; - const target = op.querySelectorAll(".arg-group")[this.target].querySelector("input, select, textarea"); + const target = op.querySelectorAll(".arg")[this.target]; target.value = el.childNodes[el.selectedIndex].getAttribute("populate-value"); + const evt = new Event("change"); + target.dispatchEvent(evt); this.manager.recipe.ingChange(); } /** - * Handler for editable option changes. + * Handler for editable option clicks. * Populates the input box with the selected value. * * @param {event} e */ - editableOptionChange(e) { - const select = e.target, - input = select.nextSibling; + editableOptionClick(e) { + e.preventDefault(); + e.stopPropagation(); - input.value = select.childNodes[select.selectedIndex].value; + const link = e.target, + input = link.parentNode.parentNode.parentNode.querySelector("input"); + + input.value = link.getAttribute("value"); this.manager.recipe.ingChange(); } diff --git a/src/web/Manager.mjs b/src/web/Manager.mjs index a779c13b..ffb3a8c3 100755 --- a/src/web/Manager.mjs +++ b/src/web/Manager.mjs @@ -137,7 +137,7 @@ class Manager { this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe); this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe); this.addDynamicListener("#rec-list li.operation > div", "dblclick", this.recipe.operationChildDblclick, this.recipe); - this.addDynamicListener("#rec-list .input-group .dropdown-menu a", "click", this.recipe.dropdownToggleClick, this.recipe); + this.addDynamicListener("#rec-list .dropdown-menu.toggle-dropdown a", "click", this.recipe.dropdownToggleClick, this.recipe); this.addDynamicListener("#rec-list", "operationremove", this.recipe.opRemove.bind(this.recipe)); // Input diff --git a/src/web/RecipeWaiter.mjs b/src/web/RecipeWaiter.mjs index a19ca6bc..cc5a2988 100755 --- a/src/web/RecipeWaiter.mjs +++ b/src/web/RecipeWaiter.mjs @@ -39,7 +39,7 @@ class RecipeWaiter { sort: true, animation: 0, delay: 0, - filter: ".arg-input,.arg", + filter: ".arg", preventOnFilter: false, setData: function(dataTransfer, dragEl) { dataTransfer.setData("Text", dragEl.querySelector(".op-title").textContent); @@ -305,7 +305,7 @@ class RecipeWaiter { } else if (ingList[j].classList.contains("toggle-string")) { // toggleString ingredients[j] = { - option: ingList[j].previousSibling.children[0].textContent.slice(0, -1), + option: ingList[j].parentNode.parentNode.querySelector("button").textContent, string: ingList[j].value }; } else if (ingList[j].getAttribute("type") === "number") { @@ -417,10 +417,13 @@ class RecipeWaiter { * @param {event} e */ dropdownToggleClick(e) { - const el = e.target; - const button = el.parentNode.parentNode.previousSibling; + e.stopPropagation(); + e.preventDefault(); - button.innerHTML = el.textContent + " "; + const el = e.target; + const button = el.parentNode.parentNode.querySelector("button"); + + button.innerHTML = el.textContent; this.ingChange(); } diff --git a/src/web/html/index.html b/src/web/html/index.html index 11fda1a2..5e37a994 100755 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -188,13 +188,13 @@
Recipe - - - @@ -226,10 +226,10 @@
- - @@ -261,19 +261,19 @@
- - - - - diff --git a/src/web/stylesheets/components/_operation.css b/src/web/stylesheets/components/_operation.css index 244d0f49..1ad9891e 100755 --- a/src/web/stylesheets/components/_operation.css +++ b/src/web/stylesheets/components/_operation.css @@ -18,111 +18,63 @@ border-right: none; } -/* .arg-group { - display: table; - width: 100%; - margin-top: 10px; -} */ - -/* .arg-group-text { - display: block; -} - -.inline-args { - float: left; - width: auto; - margin-right: 30px; - height: 34px; -} */ - -/* .inline-args input[type="checkbox"] { - margin-top: 10px; -} */ - -/* .inline-args input[type="number"] { - width: 100px; -} */ - .op-title { font-weight: var(--op-title-font-weight); } -/* .arg-input { - display: table-cell; - width: 100%; - padding: 6px 12px; - vertical-align: middle; - height: var(--arg-input-height); - font-size: var(--arg-input-font-size); - line-height: var(--arg-input-line-height); - color: var(--arg-font-colour); - background-color: var(--arg-background); - border: 1px solid var(--arg-border-colour); +.arg { font-family: var(--fixed-width-font-family); text-overflow: ellipsis; -} */ - -/* .short-string { - width: 150px; } -select { - display: block; - padding: 6px 8px; - height: 34px; - border: 1px solid var(--arg-border-colour); - background-color: var(--arg-background); - color: var(--arg-font-colour); -} - -.arg[disabled] { - cursor: not-allowed; - opacity: 1; - background-color: var(--arg-disabled-background); +select.arg { + font-family: var(--primary-font-family); + min-width: 100px; } textarea.arg { - width: 100%; - min-height: 50px; - height: 70px; - margin-top: 5px; - border: 1px solid var(--arg-border-colour); + min-height: 68px; resize: vertical; - color: var(--arg-font-colour); - background-color: var(--arg-background); - font-family: var(--fixed-width-font-family); } -.arg-label { - display: table-cell; - width: 1px; - padding-right: 10px; - font-weight: normal; - vertical-align: middle; - white-space: pre; +@media (min-width: 576px) { + .arg.inline { + display: inline-block; + width: auto; + vertical-align: middle; + } + + .form-group.inline { + display: inline-block; + margin-right: 20px; + width: unset; + } + + .input-group-append.inline { + display: inline-block; + } } -.editable-option { - position: relative; - display: inline-block; +div.toggle-string { + flex: 1; } -.editable-option-select { - min-width: 250px; +.bmd-form-group.is-filled div.toggle-string label.bmd-label-floating, +.bmd-form-group.is-focused div.toggle-string label.bmd-label-floating { + left: unset; } -.editable-option-input { - position: absolute; - top: 1px; - left: 1px; - width: calc(100% - 20px); - height: calc(100% - 2px) !important; - border: none !important; +.editable-option-menu { + height: auto; + max-height: 300px; + overflow-x: hidden; } -button.dropdown-toggle { - background-color: var(--secondary-background-colour); -} */ +.editable-option-menu .dropdown-item { + padding: 0.3rem 1rem 0.3rem 1rem; + min-height: 1.6rem; + max-width: 20rem; +} .register-list { background-color: var(--fc-operation-border-colour); diff --git a/src/web/stylesheets/layout/_modals.css b/src/web/stylesheets/layout/_modals.css index ac3f5e04..2a0462b3 100755 --- a/src/web/stylesheets/layout/_modals.css +++ b/src/web/stylesheets/layout/_modals.css @@ -24,11 +24,6 @@ height: 28px; padding: 3px 10px; vertical-align: middle; - font-size: calc(var(--arg-input-font-size) - 1px); - line-height: var(--arg-input-line-height); - color: var(--arg-font-colour); - background-color: var(--arg-background); - border: 1px solid var(--primary-border-colour); } .option-item select { diff --git a/src/web/stylesheets/themes/_classic.css b/src/web/stylesheets/themes/_classic.css index 3a9247b4..ba42d940 100755 --- a/src/web/stylesheets/themes/_classic.css +++ b/src/web/stylesheets/themes/_classic.css @@ -69,9 +69,6 @@ /* Operation arguments */ --op-title-font-weight: bold; - --arg-input-height: 34px; - --arg-input-line-height: 20px; - --arg-input-font-size: 15px; --arg-font-colour: #424242; --arg-background: #fff; --arg-border-colour: #ddd; diff --git a/src/web/stylesheets/themes/_dark.css b/src/web/stylesheets/themes/_dark.css index 4390e86d..7696de8a 100755 --- a/src/web/stylesheets/themes/_dark.css +++ b/src/web/stylesheets/themes/_dark.css @@ -65,9 +65,6 @@ /* Operation arguments */ --op-title-font-weight: bold; - --arg-input-height: 34px; - --arg-input-line-height: 20px; - --arg-input-font-size: 15px; --arg-font-colour: #bbb; --arg-background: #3c3c3c; --arg-border-colour: #3c3c3c; diff --git a/src/web/stylesheets/themes/_geocities.css b/src/web/stylesheets/themes/_geocities.css index fa3d8b76..cb7f0827 100755 --- a/src/web/stylesheets/themes/_geocities.css +++ b/src/web/stylesheets/themes/_geocities.css @@ -65,9 +65,6 @@ /* Operation arguments */ --op-title-font-weight: bold; - --arg-input-height: 34px; - --arg-input-line-height: 20px; - --arg-input-font-size: 15px; --arg-font-colour: white; --arg-background: black; --arg-border-colour: lime; diff --git a/src/web/stylesheets/utils/_overrides.css b/src/web/stylesheets/utils/_overrides.css index 323782a6..7f6301c1 100755 --- a/src/web/stylesheets/utils/_overrides.css +++ b/src/web/stylesheets/utils/_overrides.css @@ -32,6 +32,10 @@ -webkit-font-smoothing: antialiased; } +.form-group { + margin-bottom: 0; +} + /* button, a:focus { @@ -95,17 +99,16 @@ a:focus { border-radius: 0 !important; }*/ -.btn.dropdown-toggle { - height: 34px; -} input[type="search"] { -webkit-appearance: searchfield; + appearance: searchfield; box-shadow: none; } input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: searchfield-cancel-button; + appearance: searchfield-cancel-button; } .modal { diff --git a/src/web/stylesheets/vendors/bootstrap.scss b/src/web/stylesheets/vendors/bootstrap.scss index 3587c2cf..dbe1956a 100644 --- a/src/web/stylesheets/vendors/bootstrap.scss +++ b/src/web/stylesheets/vendors/bootstrap.scss @@ -20,5 +20,6 @@ $theme-colors: ( $bmd-label-color: $green-700; $bmd-label-color-inner-focus: $green-500; +$bmd-form-line-height: 1.25; @import "~bootstrap-material-design/scss/core";