diff options
Diffstat (limited to 'src/static')
-rw-r--r-- | src/static/css/base.css | 259 | ||||
-rw-r--r-- | src/static/css/detail_view.css | 39 | ||||
-rw-r--r-- | src/static/css/graph_common.css | 172 | ||||
-rw-r--r-- | src/static/js/dashboard.js | 300 |
4 files changed, 514 insertions, 256 deletions
diff --git a/src/static/css/base.css b/src/static/css/base.css index c51728c..9fec97e 100644 --- a/src/static/css/base.css +++ b/src/static/css/base.css @@ -1,3 +1,30 @@ +/* Sizing */ +#wrapper { + height: 100vh; +} + +/* Used for turning divs into square */ +.square-20 { + height: 20px; + width: 20px; +} + +/* Make links stay the same color with no underline */ +.discrete-a { + text-decoration: none; + color: inherit; +} + +.discrete-a:hover { + text-decoration: none; + color: inherit; +} + +/* Allow for sidebar to be small, but also resize on small screens */ +.sidebar { + min-width: 200px; +} + /* Rotating arrows when dropdown happens */ i.fas.rotate { transition: transform 0.3s ease-in-out; @@ -6,3 +33,235 @@ i.fas.rotate { a[aria-expanded="true"] > i.rotate { transform: rotate(180deg); } +/* End rotating arrows */ + +/* Start breadcrumbs for workflow */ +#topPagination .topcrumb { + flex: 1 1 0; + display: flex; + align-content: center; + justify-content: center; + border: 1px solid #dee2e6; + border-left: none; +} + +.topcrumb > span { + color: #343a40; + cursor: default; +} + +.topcrumb.active > span { + background: #007bff; + color: white; +} + +.topcrumb.disabled > span { + color: #6c757d; + background: #f8f9fa; +} + +/* Booking Node Styles */ +.selected_node { + border-color: #40c640; + box-shadow: 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(109, 243, 76, 0.6); + transition: border-color ease-in-out .1s,box-shadow ease-in-out .1s; +} + +/* Cursor effects */ +.not-allowed { + cursor: not-allowed; +} + +/* Used with position-absolute class to make a full height object */ +.topToBottom { + bottom: 0; + top: 0; +} + +.z-2 { + z-index: 2; +} + +.mh-30vh { + max-height: 30vh; +} + +.overflow-ellipsis { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +/* Graphing for networks */ +div.mxRubberband { + position: absolute; + overflow: hidden; + border-style: solid; + border-width: 1px; + border-color: #0000FF; + background: #0077FF; +} +.mxCellEditor { + background: url(data:image/gif;base64,R0lGODlhMAAwAIAAAP///wAAACH5BAEAAAAALAAAAAAwADAAAAIxhI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8egpAAA7); + _background: url('/static/img/mxgraph/transparent.gif'); + border-color: transparent; + border-style: solid; + display: inline-block; + position: absolute; + overflow: visible; + word-wrap: normal; + border-width: 0; + min-width: 1px; + resize: none; + padding: 0px; + margin: 0px; +} +.mxPlainTextEditor * { + padding: 0px; + margin: 0px; +} +div.mxWindow { + background: url('../img/mxgraph/window.gif'); + border:1px solid #c3c3c3; + position: absolute; + overflow: hidden; + z-index: 3; +} +table.mxWindow { + border-collapse: collapse; + table-layout: fixed; + font-family: Arial; + font-size: 8pt; +} +td.mxWindowTitle { + background: url('/static/img/mxgraph/window-title.gif') repeat-x; + text-overflow: ellipsis; + white-space: nowrap; + text-align: center; + font-weight: bold; + overflow: hidden; + height: 13px; + padding: 2px; + padding-top: 4px; + padding-bottom: 6px; + color: black; +} +td.mxWindowPane { + vertical-align: top; + padding: 0px; +} +div.mxWindowPane { + overflow: hidden; + position: relative; +} +td.mxWindowPane td { + font-family: Arial; + font-size: 8pt; +} +td.mxWindowPane input, td.mxWindowPane select, td.mxWindowPane textarea, td.mxWindowPane radio { + font-family: Arial; + font-size: 8pt; + padding: 1px; +} +td.mxWindowPane button { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; + display: inline-block; + margin: 2%; + font-size: 14px; + font-weight: 400; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +img.mxToolbarItem { + margin-right: 6px; + margin-bottom: 6px; + border-width: 1px; +} +select.mxToolbarCombo { + vertical-align: top; + border-style: inset; + border-width: 2px; +} +div.mxToolbarComboContainer { + padding: 2px; +} +img.mxToolbarMode { + margin: 2px; + margin-right: 4px; + margin-bottom: 4px; + border-width: 0px; +} +img.mxToolbarModeSelected { + margin: 0px; + margin-right: 2px; + margin-bottom: 2px; + border-width: 2px; + border-style: inset; +} +div.mxTooltip { + -webkit-box-shadow: 3px 3px 12px #C0C0C0; + -moz-box-shadow: 3px 3px 12px #C0C0C0; + box-shadow: 3px 3px 12px #C0C0C0; + background: #FFFFCC; + border-style: solid; + border-width: 1px; + border-color: black; + font-family: Arial; + font-size: 8pt; + position: absolute; + cursor: default; + padding: 4px; + color: black; +} +div.mxPopupMenu { + -webkit-box-shadow: 3px 3px 12px #C0C0C0; + -moz-box-shadow: 3px 3px 12px #C0C0C0; + box-shadow: 3px 3px 12px #C0C0C0; + background: url('/static/img/mxgraph/window.gif'); + position: absolute; + border-style: solid; + border-width: 1px; + border-color: black; +} +table.mxPopupMenu { + border-collapse: collapse; + margin-top: 1px; + margin-bottom: 1px; +} +tr.mxPopupMenuItem { + color: black; + cursor: pointer; +} +tr.mxPopupMenuItemHover { + background-color: #000066; + color: #FFFFFF; + cursor: pointer; +} +td.mxPopupMenuItem { + padding: 2px 30px 2px 10px; + white-space: nowrap; + font-family: Arial; + font-size: 8pt; +} +td.mxPopupMenuIcon { + background-color: #D0D0D0; + padding: 2px 4px 2px 4px; +} +.mxDisabled { + opacity: 0.2 !important; + cursor:default !important; +} diff --git a/src/static/css/detail_view.css b/src/static/css/detail_view.css deleted file mode 100644 index c3d0a4d..0000000 --- a/src/static/css/detail_view.css +++ /dev/null @@ -1,39 +0,0 @@ -.card_container { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; - grid-gap: 25px 25px; - justify-items: stretch; -} - -.card_container ul > li { - padding: 7px !important; - font-size: 16px; -} - -.detail_button_container .btn { - width: 49%; -} - -.detail_button_container .btn-danger { - float: right; -} - -#modal_warning { - transition: max-height 0.5s ease-out; - overflow: hidden; -} - -.detail_card { - border-radius: 5px; - border-top: 1px solid #ccc; - border-left: 1px solid #ccc; - border-right: 1px solid #ccc; - border-bottom: 1px solid #ccc; - margin: 5px; - padding-left: 25px; - padding-right: 25px; - padding-bottom: 15px; - display: flex; - flex-direction: column; - justify-content: space-between; -} diff --git a/src/static/css/graph_common.css b/src/static/css/graph_common.css deleted file mode 100644 index cff1516..0000000 --- a/src/static/css/graph_common.css +++ /dev/null @@ -1,172 +0,0 @@ -div.mxRubberband { - position: absolute; - overflow: hidden; - border-style: solid; - border-width: 1px; - border-color: #0000FF; - background: #0077FF; -} -.mxCellEditor { - background: url(data:image/gif;base64,R0lGODlhMAAwAIAAAP///wAAACH5BAEAAAAALAAAAAAwADAAAAIxhI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8egpAAA7); - _background: url('/static/img/mxgraph/transparent.gif'); - border-color: transparent; - border-style: solid; - display: inline-block; - position: absolute; - overflow: visible; - word-wrap: normal; - border-width: 0; - min-width: 1px; - resize: none; - padding: 0px; - margin: 0px; -} -.mxPlainTextEditor * { - padding: 0px; - margin: 0px; -} -div.mxWindow { - background: url('../img/mxgraph/window.gif'); - border:1px solid #c3c3c3; - position: absolute; - overflow: hidden; - z-index: 3; -} -table.mxWindow { - border-collapse: collapse; - table-layout: fixed; - font-family: Arial; - font-size: 8pt; -} -td.mxWindowTitle { - background: url('/static/img/mxgraph/window-title.gif') repeat-x; - text-overflow: ellipsis; - white-space: nowrap; - text-align: center; - font-weight: bold; - overflow: hidden; - height: 13px; - padding: 2px; - padding-top: 4px; - padding-bottom: 6px; - color: black; -} -td.mxWindowPane { - vertical-align: top; - padding: 0px; -} -div.mxWindowPane { - overflow: hidden; - position: relative; -} -td.mxWindowPane td { - font-family: Arial; - font-size: 8pt; -} -td.mxWindowPane input, td.mxWindowPane select, td.mxWindowPane textarea, td.mxWindowPane radio { - font-family: Arial; - font-size: 8pt; - padding: 1px; -} -td.mxWindowPane button { - color: #fff; - background-color: #337ab7; - border-color: #2e6da4; - display: inline-block; - margin: 2%; - font-size: 14px; - font-weight: 400; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -ms-touch-action: manipulation; - touch-action: manipulation; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -img.mxToolbarItem { - margin-right: 6px; - margin-bottom: 6px; - border-width: 1px; -} -select.mxToolbarCombo { - vertical-align: top; - border-style: inset; - border-width: 2px; -} -div.mxToolbarComboContainer { - padding: 2px; -} -img.mxToolbarMode { - margin: 2px; - margin-right: 4px; - margin-bottom: 4px; - border-width: 0px; -} -img.mxToolbarModeSelected { - margin: 0px; - margin-right: 2px; - margin-bottom: 2px; - border-width: 2px; - border-style: inset; -} -div.mxTooltip { - -webkit-box-shadow: 3px 3px 12px #C0C0C0; - -moz-box-shadow: 3px 3px 12px #C0C0C0; - box-shadow: 3px 3px 12px #C0C0C0; - background: #FFFFCC; - border-style: solid; - border-width: 1px; - border-color: black; - font-family: Arial; - font-size: 8pt; - position: absolute; - cursor: default; - padding: 4px; - color: black; -} -div.mxPopupMenu { - -webkit-box-shadow: 3px 3px 12px #C0C0C0; - -moz-box-shadow: 3px 3px 12px #C0C0C0; - box-shadow: 3px 3px 12px #C0C0C0; - background: url('/static/img/mxgraph/window.gif'); - position: absolute; - border-style: solid; - border-width: 1px; - border-color: black; -} -table.mxPopupMenu { - border-collapse: collapse; - margin-top: 1px; - margin-bottom: 1px; -} -tr.mxPopupMenuItem { - color: black; - cursor: pointer; -} -tr.mxPopupMenuItemHover { - background-color: #000066; - color: #FFFFFF; - cursor: pointer; -} -td.mxPopupMenuItem { - padding: 2px 30px 2px 10px; - white-space: nowrap; - font-family: Arial; - font-size: 8pt; -} -td.mxPopupMenuIcon { - background-color: #D0D0D0; - padding: 2px 4px 2px 4px; -} -.mxDisabled { - opacity: 0.2 !important; - cursor:default !important; -} diff --git a/src/static/js/dashboard.js b/src/static/js/dashboard.js index 84c3703..8e1250a 100644 --- a/src/static/js/dashboard.js +++ b/src/static/js/dashboard.js @@ -1,3 +1,190 @@ +/////////////////// +// Global Variables +/////////////////// + +form_submission_callbacks = []; //all runnables will be executed before form submission + +/////////////////// +// Global Functions +/////////////////// +function update_page(response) { + if( response.redirect ) + { + window.location.replace(response.redirect); + return; + } + draw_breadcrumbs(response.meta); + update_exit_button(response.meta); + update_side_buttons(response.meta); + $("#formContainer").html(response.content); +} + +function update_side_buttons(meta) { + const step = meta.active; + const page_count = meta.steps.length; + + const back_button = document.getElementById("gob"); + if (step == 0) { + back_button.classList.add("disabled"); + back_button.disabled = true; + } else { + back_button.classList.remove("disabled"); + back_button.disabled = false; + } + + const forward_btn = document.getElementById("gof"); + if (step == page_count - 1) { + forward_btn.classList.add("disabled"); + forward_btn.disabled = true; + } else { + forward_btn.classList.remove("disabled"); + forward_btn.disabled = false; + } +} + +function update_exit_button(meta) { + if (meta.workflow_count == 1) { + document.getElementById("cancel_btn").innerText = "Exit Workflow"; + } else { + document.getElementById("cancel_btn").innerText = "Return to Parent"; + } +} + +function draw_breadcrumbs(meta) { + $("#topPagination").children().not(".page-control").remove(); + + for (const i in meta.steps) { + const step_btn = create_step(meta.steps[i], i == meta["active"]); + $("#topPagination li:last-child").before(step_btn); + } +} + +function create_step(step_json, active) { + const step_dom = document.createElement("li"); + // First create the dom object depending on active or not + step_dom.className = "topcrumb"; + if (active) { + step_dom.classList.add("active"); + } + $(step_dom).html(`<span class="d-flex align-items-center justify-content-center text-capitalize w-100">${step_json['title']}</span>`) + + const code = step_json.valid; + + let stat = ""; + let msg = ""; + if (code < 100) { + $(step_dom).children().first().append("<i class='ml-2 far fa-square'></i>") + stat = ""; + msg = ""; + } else if (code < 200) { + $(step_dom).children().first().append("<i class='ml-2 fas fa-minus-square'></i>") + stat = "invalid"; + msg = step_json.message; + } else if (code < 300) { + $(step_dom).children().first().append("<i class='ml-2 far fa-check-square'></i>") + stat = "valid"; + msg = step_json.message; + } + + if (step_json.enabled == false) { + step_dom.classList.add("disabled"); + } + if (active) { + update_message(msg, stat); + } + + return step_dom; +} + +function update_description(title, desc) { + document.getElementById("view_title").innerText = title; + document.getElementById("view_desc").innerText = desc; +} + +function update_message(message, stepstatus) { + document.getElementById("view_message").innerText = message; + document.getElementById("view_message").className = "step_message"; + document.getElementById("view_message").classList.add("message_" + stepstatus); +} + +function submitStepForm(next_step = "current"){ + run_form_callbacks(); + const step_form_data = $("#step_form").serialize(); + const form_data = $.param({ + "step": next_step, + "step_form": step_form_data, + "csrfmiddlewaretoken": $("[name=csrfmiddlewaretoken]").val() + }); + $.post( + '/workflow/manager/', + form_data, + (data) => update_page(data), + 'json' + ).fail(() => alert("failure")); +} + +function run_form_callbacks(){ + for(f of form_submission_callbacks) + f(); + form_submission_callbacks = []; +} + +function create_workflow(type) { + $.ajax({ + type: "POST", + url: "/workflow/create/", + data: { + "workflow_type": type + }, + headers: { + "X-CSRFToken": $('input[name="csrfmiddlewaretoken"]').val() + } + }).done(function (data, textStatus, jqXHR) { + window.location = "/workflow/"; + }).fail(function (jqxHR, textstatus) { + alert("Something went wrong..."); + }); +} + +function add_workflow(type) { + data = $.ajax({ + type: "POST", + url: "/workflow/add/", + data: { + "workflow_type": type + }, + headers: { + "X-CSRFToken": $('input[name="csrfmiddlewaretoken"]').val() + } + }).done(function (data, textStatus, jqXHR) { + update_page(data); + }).fail(function (jqxHR, textstatus) { + alert("Something went wrong..."); + }); +} + +function pop_workflow() { + data = $.ajax({ + type: "POST", + url: "/workflow/pop/", + headers: { + "X-CSRFToken": $('input[name="csrfmiddlewaretoken"]').val() + } + }).done(function (data, textStatus, jqXHR) { + update_page(data); + }).fail(function (jqxHR, textstatus) { + alert("Something went wrong..."); + }); +} + +function continue_workflow() { + window.location.replace("/workflow/"); +} + +/////////////////// +//Class Definitions +/////////////////// + class MultipleSelectFilterWidget { constructor(neighbors, items, initial) { @@ -98,7 +285,7 @@ class MultipleSelectFilterWidget { select(node) { const elem = document.getElementById(node['id']); node['selected'] = true; - elem.classList.remove('disabled_node', 'cleared_node'); + elem.classList.remove('bg-white', 'not-allowed', 'bg-light'); elem.classList.add('selected_node'); } @@ -106,16 +293,16 @@ class MultipleSelectFilterWidget { const elem = document.getElementById(node['id']); node['selected'] = false; node['selectable'] = true; - elem.classList.add('cleared_node') - elem.classList.remove('disabled_node', 'selected_node'); + elem.classList.add('bg-white') + elem.classList.remove('not-allowed', 'bg-light', 'selected_node'); } disable_node(node) { const elem = document.getElementById(node['id']); node['selected'] = false; node['selectable'] = false; - elem.classList.remove('cleared_node', 'selected_node'); - elem.classList.add('disabled_node'); + elem.classList.remove('bg-white', 'selected_node'); + elem.classList.add('not-allowed', 'bg-light'); } processClick(id){ @@ -173,7 +360,7 @@ class MultipleSelectFilterWidget { const button = document.createElement("BUTTON"); button.type = "button"; button.appendChild(document.createTextNode("Remove")); - button.classList.add("btn", "btn-danger"); + button.classList.add("btn", "btn-danger", "d-inline-block"); const that = this; button.onclick = function(){ that.remove_dropdown(div.id, node.id); } return button; @@ -183,6 +370,7 @@ class MultipleSelectFilterWidget { const input = document.createElement("INPUT"); input.type = node.form.type; input.name = node.id + node.form.name + input.classList.add("form-control", "w-auto", "d-inline-block"); input.pattern = "(?=^.{1,253}$)(^([A-Za-z0-9-_]{1,62}\.)*[A-Za-z0-9-_]{1,63})"; input.title = "Only alphanumeric characters (a-z, A-Z, 0-9), underscore(_), and hyphen (-) are allowed" input.placeholder = node.form.placeholder; @@ -198,13 +386,18 @@ class MultipleSelectFilterWidget { add_item_prepopulate(node, prepopulate){ const div = document.createElement("DIV"); div.id = "dropdown_" + this.dropdown_count; - div.classList.add("dropdown_item"); + div.classList.add("card", "flex-row", "d-flex", "mb-2"); this.dropdown_count++; const label = document.createElement("H5") label.appendChild(document.createTextNode(node['name'])) + label.classList.add("p-1", "m-1"); div.appendChild(label); - div.appendChild(this.make_input(div, node, prepopulate)); - div.appendChild(this.make_remove_button(div, node)); + let input = this.make_input(div, node, prepopulate); + input.classList.add("flex-grow-1", "p-1", "m-1"); + div.appendChild(input); + let remove_btn = this.make_remove_button(div, node); + remove_btn.classList.add("p-1", "m-1"); + div.appendChild(remove_btn); document.getElementById("dropdown_wrapper").appendChild(div); return div; } @@ -756,21 +949,28 @@ class NetworkStep { } makeSidebarNetwork(net_name, color, net_id){ - const newNet = document.createElement("li"); const colorBlob = document.createElement("div"); - colorBlob.className = "colorblob"; - const textContainer = document.createElement("p"); - textContainer.className = "network_innertext"; - newNet.id = net_id; + colorBlob.className = "square-20 rounded-circle"; + colorBlob.style['background'] = color; + + const textContainer = document.createElement("span"); + textContainer.className = "ml-2"; + textContainer.appendChild(document.createTextNode(net_name)); + + const timesIcon = document.createElement("i"); + timesIcon.classList.add("fas", "fa-times"); + const deletebutton = document.createElement("button"); - deletebutton.className = "btn btn-danger"; - deletebutton.style = "float: right; height: 20px; line-height: 8px; vertical-align: middle; width: 20px; padding-left: 5px;"; - deletebutton.appendChild(document.createTextNode("X")); + deletebutton.className = "btn btn-danger ml-auto square-20 p-0 d-flex justify-content-center"; + deletebutton.appendChild(timesIcon); deletebutton.addEventListener("click", function() { this.createDeleteDialog(net_id); }.bind(this), false); - textContainer.appendChild(document.createTextNode(net_name)); - colorBlob.style['background'] = color; + + const newNet = document.createElement("li"); + newNet.classList.add("list-group-item", "d-flex", "bg-light"); + newNet.id = net_id; newNet.appendChild(colorBlob); newNet.appendChild(textContainer); + if( net_name != "public" ) { newNet.appendChild(deletebutton); } @@ -818,16 +1018,9 @@ class NetworkStep { this.graph.refresh(host); } - submitForm() { - const form = document.getElementById("xml_form"); + prepareForm() { const input_elem = document.getElementById("hidden_xml_input"); input_elem.value = this.encodeGraph(this.graph); - const req = new XMLHttpRequest(); - req.open("POST", "/wf/workflow/", false); - req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - req.onerror = function() { alert("problem with form submission"); } - const formData = $("#xml_form").serialize(); - req.send(formData); } } @@ -1048,18 +1241,19 @@ class SearchableSelectMultipleWidget { for( const id in ids ) { - const result_entry = document.createElement("li"); - const result_button = document.createElement("a"); const obj = this.items[id]; const result_text = this.generate_element_text(obj); - result_button.appendChild(document.createTextNode(result_text)); - result_button.onclick = function() { searchable_select_multiple_widget.select_item(obj.id); }; + const result_entry = document.createElement("a"); + result_entry.href = "#"; + result_entry.innerText = result_text; + result_entry.title = result_text; + result_entry.classList.add("list-group-item", "list-group-item-action", "overflow-ellipsis", "flex-shrink-0"); + result_entry.onclick = function() { searchable_select_multiple_widget.select_item(obj.id); }; const tooltip = document.createElement("span"); const tooltiptext = document.createTextNode(result_text); tooltip.appendChild(tooltiptext); - tooltip.setAttribute('class', 'entry_tooltip'); - result_button.appendChild(tooltip); - result_entry.appendChild(result_button); + tooltip.classList.add("d-none"); + result_entry.appendChild(tooltip); drop.appendChild(result_entry); } @@ -1112,23 +1306,39 @@ class SearchableSelectMultipleWidget { added_list.removeChild(added_list.firstChild); } - let list_html = ""; + const list_html = document.createElement("div"); + list_html.classList.add("list-group"); for( const item_id of this.added_items ) { - const item = this.items[item_id]; + const times = document.createElement("li"); + times.classList.add("fas", "fa-times"); + + const deleteButton = document.createElement("a"); + deleteButton.href = "#"; + deleteButton.innerHTML = "<i class='fas fa-times'></i>" + // Setting .onclick/.addEventListener does not work, + // which is why I took the setAttribute approach + // If anyone knows why, please let me know :] + deleteButton.setAttribute("onclick", `searchable_select_multiple_widget.remove_item(${item_id});`); + deleteButton.classList.add("btn"); + const deleteColumn = document.createElement("div"); + deleteColumn.classList.add("col-auto"); + deleteColumn.append(deleteButton); + const item = this.items[item_id]; const element_entry_text = this.generate_element_text(item); + const textColumn = document.createElement("div"); + textColumn.classList.add("col", "overflow-ellipsis"); + textColumn.innerText = element_entry_text; + textColumn.title = element_entry_text; + + const itemRow = document.createElement("div"); + itemRow.classList.add("list-group-item", "d-flex", "p-0", "align-items-center"); + itemRow.append(textColumn, deleteColumn); - list_html += '<div class="list_entry">' - + '<p class="added_entry_text">' - + element_entry_text - + '</p>' - + '<button onclick="searchable_select_multiple_widget.remove_item(' - + item_id - + ')" class="btn-remove btn">remove</button>'; - list_html += '</div>'; + list_html.append(itemRow); } - added_list.innerHTML = list_html; + added_list.innerHTML = list_html.innerHTML; } } |