Converted operation arguments to material design

This commit is contained in:
n1474335 2018-06-10 12:03:55 +01:00
parent 27b0505ede
commit 2bacd6424d
14 changed files with 186 additions and 262 deletions

View File

@ -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;
}

View File

@ -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;
});
}

View File

@ -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) +
" <span class='caret'></span>";
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;

View File

@ -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 ? "" : "<div class='clearfix'>&nbsp;</div>",
let html = "",
i, m;
/*html += "<div class='arg-group" + (inline ? " inline-args" : "") +
(this.type === "text" ? " arg-group-text" : "") + "'><label class='arg-label' for='" +
this.id + "'>" + this.name + "</label>";*/
switch (this.type) {
case "string":
case "binaryString":
@ -69,102 +57,149 @@ class HTMLIngredient {
break;
case "shortString":
case "binaryShortString":
html += "<input type='text' id='" + this.id +
"'class='arg arg-input short-string' arg-name='" + this.name + "'value='" +
this.value + "'" + (this.disabled ? " disabled='disabled'" : "") +
(this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + ">";
html += `<div class="form-group inline">
<label for="${this.id}" class="bmd-label-floating inline">${this.name}</label>
<input type="text"
class="form-control arg inline"
id="${this.id}"
arg-name="${this.name}"
value="${this.value}"
${this.disabled ? "disabled" : ""}>
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
</div>`;
break;
case "toggleString":
html += "<div class='input-group'><div class='input-group-btn'>\
<button type='button' class='btn btn-secondary dropdown-toggle' data-toggle='dropdown'\
aria-haspopup='true' aria-expanded='false'" +
(this.disabled ? " disabled='disabled'" : "") + ">" + this.toggleValues[0] +
" <span class='caret'></span></button><ul class='dropdown-menu'>";
html += `<div class="form-group input-group">
<div class="input-group-prepend">
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">${this.toggleValues[0]}</button>
<div class="dropdown-menu toggle-dropdown">`;
for (i = 0; i < this.toggleValues.length; i++) {
html += "<li><a href='#'>" + this.toggleValues[i] + "</a></li>";
html += `<a class="dropdown-item" href="#">${this.toggleValues[i]}</a>`;
}
html += "</ul></div><input type='text' class='arg arg-input toggle-string'" +
(this.disabled ? " disabled='disabled'" : "") +
(this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + "></div>";
html += `</div>
</div>
<div class="toggle-string">
<label for="${this.id}" class="bmd-label-floating toggle-string">${this.name}</label>
<input type="text"
class="form-control arg toggle-string"
id="${this.id}"
arg-name="${this.name}"
value="${this.value}"
${this.disabled ? "disabled" : ""}>
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
</div>
</div>`;
break;
case "number":
html += "<input type='number' id='" + this.id + "'class='arg arg-input' arg-name='" +
this.name + "'value='" + this.value + "'" +
(this.disabled ? " disabled='disabled'" : "") +
(this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + ">";
html += `<div class="form-group inline">
<label for="${this.id}" class="bmd-label-floating inline">${this.name}</label>
<input type="number"
class="form-control arg inline"
id="${this.id}"
arg-name="${this.name}"
value="${this.value}"
${this.disabled ? "disabled" : ""}>
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
</div>`;
break;
case "boolean":
html += `<label class="checkbox-inline">
<input type="checkbox"
id="${this.id}"
class="arg"
arg-name="${this.name}"
${this.value ? " checked='checked' " : ""}
${this.disabled ? " disabled='disabled'" : ""}
value="${this.name}"> ${this.name}
</label>`;
// html += "<input type='checkbox' id='" + this.id + "'class='arg' arg-name='" +
// this.name + "'" + (this.value ? " checked='checked' " : "") +
// (this.disabled ? " disabled='disabled'" : "") + ">";
if (this.disableArgs) {
this.manager.addDynamicListener("#" + this.id, "click", this.toggleDisableArgs, this);
}
html += `<div class="form-group inline">
<div class="checkbox">
<label>
<input type="checkbox"
class="arg"
id="${this.id}"
arg-name="${this.name}"
${this.value ? " checked='checked' " : ""}
${this.disabled ? " disabled='disabled'" : ""}
value="${this.name}"> ${this.name}
</label>
</div>
</div>`;
break;
case "option":
html += "<select class='arg' id='" + this.id + "'arg-name='" + this.name + "'" +
(this.disabled ? " disabled='disabled'" : "") + ">";
html += `<div class="form-group inline">
<label for="${this.id}" class="bmd-label-floating inline">${this.name}</label>
<select
class="form-control arg inline"
id="${this.id}"
arg-name="${this.name}"
${this.disabled ? "disabled" : ""}>`;
for (i = 0; i < this.value.length; i++) {
if ((m = this.value[i].match(/\[([a-z0-9 -()^]+)\]/i))) {
html += "<optgroup label='" + m[1] + "'>";
html += `<optgroup label="${m[1]}">`;
} else if ((m = this.value[i].match(/\[\/([a-z0-9 -()^]+)\]/i))) {
html += "</optgroup>";
} else {
html += "<option>" + this.value[i] + "</option>";
html += `<option>${this.value[i]}</option>`;
}
}
html += "</select>";
html += `</select>
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
</div>`;
break;
case "populateOption":
html += "<select class='arg' id='" + this.id + "'arg-name='" + this.name + "'" +
(this.disabled ? " disabled='disabled'" : "") + ">";
html += `<div class="form-group">
<label for="${this.id}" class="bmd-label-floating">${this.name}</label>
<select
class="form-control arg"
id="${this.id}"
arg-name="${this.name}"
${this.disabled ? "disabled" : ""}>`;
for (i = 0; i < this.value.length; i++) {
if ((m = this.value[i].name.match(/\[([a-z0-9 -()^]+)\]/i))) {
html += "<optgroup label='" + m[1] + "'>";
html += `<optgroup label="${m[1]}">`;
} else if ((m = this.value[i].name.match(/\[\/([a-z0-9 -()^]+)\]/i))) {
html += "</optgroup>";
} else {
html += "<option populate-value='" + this.value[i].value + "'>" +
this.value[i].name + "</option>";
html += `<option populate-value="${this.value[i].value}">${this.value[i].name}</option>`;
}
}
html += "</select>";
html += `</select>
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
</div>`;
this.manager.addDynamicListener("#" + this.id, "change", this.populateOptionChange, this);
break;
case "editableOption":
html += "<div class='editable-option'>";
html += "<select class='editable-option-select' id='sel-" + this.id + "'" +
(this.disabled ? " disabled='disabled'" : "") + ">";
html += `<div class="form-group input-group inline">
<label for="${this.id}" class="bmd-label-floating inline">${this.name}</label>
<input type="text"
class="form-control arg inline"
id="${this.id}"
arg-name="${this.name}"
value="${this.value[0].value}"
${this.disabled ? "disabled" : ""}>
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
<div class="input-group-append inline">
<button type="button"
class="btn btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown"
data-boundary="scrollParent"
aria-haspopup="true"
aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu editable-option-menu">`;
for (i = 0; i < this.value.length; i++) {
html += "<option value='" + this.value[i].value + "'>" + this.value[i].name + "</option>";
html += `<a class="dropdown-item" href="#" value="${this.value[i].value}">${this.value[i].name}</a>`;
}
html += "</select>";
html += "<input class='arg arg-input editable-option-input' id='" + this.id +
"'arg-name='" + this.name + "'" + " value='" + this.value[0].value + "'" +
(this.disabled ? " disabled='disabled'" : "") +
(this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + ">";
html += "</div>";
html += `</div>
</div>
</div>`;
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 += "<textarea id='" + this.id + "' class='arg' arg-name='" +
this.name + "'" + (this.disabled ? " disabled='disabled'" : "") +
(this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + ">" +
this.value + "</textarea>";
html += `<div class="form-group">
<label for="${this.id}" class="bmd-label-floating">${this.name}</label>
<textarea
class="form-control arg"
id="${this.id}"
arg-name="${this.name}"
${this.disabled ? "disabled" : ""}>${this.value}</textarea>
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
</div>`;
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();
}

View File

@ -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

View File

@ -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 + " <span class='caret'></span>";
const el = e.target;
const button = el.parentNode.parentNode.querySelector("button");
button.innerHTML = el.textContent;
this.ingChange();
}

View File

@ -188,13 +188,13 @@
<div class="title no-select">
Recipe
<span class="float-right">
<button type="button" class="btn btn-danger bmd-btn-icon" id="save" data-toggle="tooltip" title="Save recipe">
<button type="button" class="btn btn-primary bmd-btn-icon" id="save" data-toggle="tooltip" title="Save recipe">
<i class="material-icons">save</i>
</button>
<button type="button" class="btn btn-danger bmd-btn-icon" id="load" data-toggle="tooltip" title="Load recipe">
<button type="button" class="btn btn-primary bmd-btn-icon" id="load" data-toggle="tooltip" title="Load recipe">
<i class="material-icons">folder</i>
</button>
<button type="button" class="btn btn-danger bmd-btn-icon" id="clr-recipe" data-toggle="tooltip" title="Clear recipe">
<button type="button" class="btn btn-primary bmd-btn-icon" id="clr-recipe" data-toggle="tooltip" title="Clear recipe">
<i class="material-icons">delete</i>
</button>
</span>
@ -226,10 +226,10 @@
<div class="title no-select">
<label for="input-text">Input</label>
<span class="float-right">
<button type="button" class="btn btn-danger bmd-btn-icon" id="clr-io" data-toggle="tooltip" title="Clear input and output">
<button type="button" class="btn btn-primary bmd-btn-icon" id="clr-io" data-toggle="tooltip" title="Clear input and output">
<i class="material-icons">delete</i>
</button>
<button type="button" class="btn btn-info bmd-btn-icon" id="reset-layout" data-toggle="tooltip" title="Reset pane layout">
<button type="button" class="btn btn-primary bmd-btn-icon" id="reset-layout" data-toggle="tooltip" title="Reset pane layout">
<i class="material-icons">view_compact</i>
</button>
</span>
@ -261,19 +261,19 @@
<div class="title no-select">
<label for="output-text">Output</label>
<span class="float-right">
<button type="button" class="btn btn-danger bmd-btn-icon" id="save-to-file" data-toggle="tooltip" title="Save output to file">
<button type="button" class="btn btn-primary bmd-btn-icon" id="save-to-file" data-toggle="tooltip" title="Save output to file">
<i class="material-icons">save</i>
</button>
<button type="button" class="btn btn-danger bmd-btn-icon" id="copy-output" data-toggle="tooltip" title="Copy raw output to the clipboard">
<button type="button" class="btn btn-primary bmd-btn-icon" id="copy-output" data-toggle="tooltip" title="Copy raw output to the clipboard">
<i class="material-icons">content_copy</i>
</button>
<button type="button" class="btn btn-danger bmd-btn-icon" id="switch" data-toggle="tooltip" title="Move output to input">
<button type="button" class="btn btn-primary bmd-btn-icon" id="switch" data-toggle="tooltip" title="Move output to input">
<i class="material-icons">loop</i>
</button>
<button type="button" class="btn btn-warning bmd-btn-icon" id="undo-switch" data-toggle="tooltip" title="Undo" disabled="disabled">
<button type="button" class="btn btn-primary bmd-btn-icon" id="undo-switch" data-toggle="tooltip" title="Undo" disabled="disabled">
<i class="material-icons">undo</i>
</button>
<button type="button" class="btn btn-danger bmd-btn-icon" id="maximise-output" data-toggle="tooltip" title="Maximise output pane">
<button type="button" class="btn btn-primary bmd-btn-icon" id="maximise-output" data-toggle="tooltip" title="Maximise output pane">
<i class="material-icons">fullscreen</i>
</button>
</span>

View File

@ -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);

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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";