-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from SoopSASM/feature/dropdown-node
[add] dropdown node
- Loading branch information
Showing
2 changed files
with
516 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,319 @@ | ||
<style></style> | ||
<script type="text/javascript"> | ||
RED.nodes.registerType("soop_dropdown", { | ||
category: "soop-dashboard", | ||
color: "rgb(255, 189, 27)", | ||
defaults: { | ||
name: { | ||
value: "", | ||
}, | ||
label: { | ||
value: "dropdown", | ||
}, | ||
tooltip: { | ||
value: "", | ||
}, | ||
place: { value: "Select" }, | ||
group: { | ||
type: "soop_group", | ||
required: true, | ||
}, | ||
order: { | ||
value: 0, | ||
}, | ||
width: { | ||
value: 0, | ||
validate: function (v) { | ||
var width = v || 0; | ||
var currentGroup = $("#node-input-group").val() || this.group; | ||
var groupNode = RED.nodes.node(currentGroup); | ||
var valid = !groupNode || +width <= +groupNode.width; | ||
$("#node-input-size").toggleClass("input-error", !valid); | ||
return valid; | ||
}, | ||
}, | ||
height: { | ||
value: 0, | ||
validate: function (v) { | ||
var height = v || 0; | ||
var currentGroup = $("#node-input-group").val() || this.group; | ||
var groupNode = RED.nodes.node(currentGroup); | ||
var valid = !groupNode || +height <= +groupNode.height; | ||
$("#node-input-size").toggleClass("input-error", !valid); | ||
return valid; | ||
}, | ||
}, | ||
options: { | ||
value: [{ value: "", label: "" }], | ||
validate: function (v) { | ||
var unique = new Set( | ||
v.map(function (o) { | ||
return o.value; | ||
}) | ||
); | ||
return v.length == unique.size; | ||
}, | ||
}, | ||
payload: { value: "" }, | ||
topic: { | ||
value: "topic", | ||
validate: RED.validators.hasOwnProperty("typedInput") | ||
? RED.validators.typedInput("topicType") | ||
: function (v) { | ||
return true; | ||
}, | ||
}, | ||
passthru: { value: true }, | ||
multipleSelect: { value: false }, | ||
topicType: { | ||
value: "msg", | ||
}, | ||
}, | ||
inputs: 1, | ||
outputs: 1, | ||
icon: "ui_switch.png", | ||
paletteLabel: "dropdown", | ||
outputLabels: function () { | ||
return this.min + " - " + this.max; | ||
}, | ||
label: function () { | ||
return ( | ||
this.name || | ||
(~this.label.indexOf("{{") ? null : this.label) || | ||
"dropdown" | ||
); | ||
}, | ||
labelStyle: function () { | ||
return this.name ? "node_label_italic" : ""; | ||
}, | ||
oneditprepare: function () { | ||
if (this.multiple === undefined) { | ||
$("#node-input-multiple").prop("checked", false); | ||
} | ||
$("#node-input-size").elementSizer({ | ||
width: "#node-input-width", | ||
height: "#node-input-height", | ||
group: "#node-input-group", | ||
}); | ||
var un = new Set( | ||
this.options.map(function (o) { | ||
return o.value; | ||
}) | ||
); | ||
if (this.options.length == un.size) { | ||
$("#valWarning").hide(); | ||
} else { | ||
$("#valWarning").show(); | ||
} | ||
|
||
function generateOption(i, option) { | ||
var container = $("<li/>", { | ||
style: | ||
"background: #fff; margin:0; padding:8px 0px 0px; border-bottom: 1px solid #ccc;", | ||
}); | ||
var row = $("<div/>").appendTo(container); | ||
var row2 = $("<div/>", { | ||
style: "padding-top:5px; padding-left:175px;", | ||
}).appendTo(container); | ||
var row3 = $("<div/>", { | ||
style: "padding-top:5px; padding-left:120px;", | ||
}).appendTo(container); | ||
|
||
$( | ||
'<i style="color:#eee; cursor:move; margin-left:3px;" class="node-input-option-handle fa fa-bars"></i>' | ||
).appendTo(row); | ||
|
||
var valueField = $("<input/>", { | ||
class: "node-input-option-value", | ||
type: "text", | ||
style: "margin-left:7px; width:calc(50% - 32px);", | ||
placeholder: "Value", | ||
value: option.value, | ||
}) | ||
.appendTo(row) | ||
.typedInput({ | ||
default: option.type || "str", | ||
types: ["str", "num", "bool"], | ||
}); | ||
var labelField = $("<input/>", { | ||
class: "node-input-option-label", | ||
type: "text", | ||
style: "margin-left:7px; width:calc(50% - 32px);", | ||
placeholder: "Label", | ||
value: option.label, | ||
}).appendTo(row); | ||
|
||
var finalspan = $("<span/>", { | ||
style: "float:right; margin-right:8px;", | ||
}).appendTo(row); | ||
var deleteButton = $("<a/>", { | ||
href: "#", | ||
class: "editor-button editor-button-small", | ||
style: "margin-top:7px; margin-left:5px;", | ||
}).appendTo(finalspan); | ||
$("<i/>", { class: "fa fa-remove" }).appendTo(deleteButton); | ||
|
||
deleteButton.click(function () { | ||
container.css({ background: "#fee" }); | ||
container.fadeOut(300, function () { | ||
$(this).remove(); | ||
}); | ||
}); | ||
|
||
$("#node-input-option-container").append(container); | ||
} | ||
|
||
$("#node-input-add-option").click(function () { | ||
generateOption( | ||
$("#node-input-option-container").children().length + 1, | ||
{} | ||
); | ||
$("#node-input-option-container-div").scrollTop( | ||
$("#node-input-option-container-div").get(0).scrollHeight | ||
); | ||
}); | ||
|
||
for (var i = 0; i < this.options.length; i++) { | ||
var option = this.options[i]; | ||
generateOption(i + 1, option); | ||
} | ||
|
||
$("#node-input-option-container").sortable({ | ||
axis: "y", | ||
handle: ".node-input-option-handle", | ||
cursor: "move", | ||
}); | ||
|
||
$("#node-input-topic").typedInput({ | ||
default: "str", | ||
typeField: $("#node-input-topicType"), | ||
types: ["str", "msg", "flow", "global"], | ||
}); | ||
}, | ||
oneditsave: function () { | ||
var options = $("#node-input-option-container").children(); | ||
var node = this; | ||
node.options = []; | ||
options.each(function (i) { | ||
var option = $(this); | ||
var o = { | ||
label: option.find(".node-input-option-label").val(), | ||
value: option.find(".node-input-option-value").typedInput("value"), | ||
type: option.find(".node-input-option-value").typedInput("type"), | ||
}; | ||
if ( | ||
option.find(".node-input-option-value").typedInput("type") === "num" | ||
) { | ||
o.value = Number(o.value); | ||
} | ||
if ( | ||
option.find(".node-input-option-value").typedInput("type") === "bool" | ||
) { | ||
o.value = o.value == "true"; | ||
} | ||
node.options.push(o); | ||
}); | ||
}, | ||
oneditresize: function () {}, | ||
}); | ||
</script> | ||
|
||
<script type="text/html" data-template-name="soop_dropdown"> | ||
<div class="form-row"> | ||
<label for="node-input-group"><i class="fa fa-table"></i> Group</label> | ||
<input type="text" id="node-input-group" /> | ||
</div> | ||
<div class="form-row"> | ||
<label><i class="fa fa-object-group"></i> Size</label> | ||
<input type="hidden" id="node-input-width" /> | ||
<input type="hidden" id="node-input-height" /> | ||
<button class="editor-button" id="node-input-size"></button> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-label"><i class="fa fa-tag"></i> Label</label> | ||
<input type="text" id="node-input-label" placeholder="optional label" /> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-tooltip" | ||
><i class="fa fa-info-circle"></i> Tooltip</label | ||
> | ||
<input type="text" id="node-input-tooltip" placeholder="optional tooltip" /> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-place"><i class="fa fa-tag"></i> Placeholder</label> | ||
<input | ||
type="text" | ||
id="node-input-place" | ||
placeholder="optional placeholder" | ||
/> | ||
</div> | ||
<div | ||
class="form-row node-input-option-container-row" | ||
style="margin-bottom: 0px;width: 100%" | ||
> | ||
<label for="node-input-width" style="vertical-align:top" | ||
><i class="fa fa-list-alt"></i> Options</label | ||
> | ||
<div | ||
id="node-input-option-container-div" | ||
style="box-sizing:border-box; border-radius:5px; height:257px; padding:5px; border:1px solid #ccc; overflow-y:scroll; display:inline-block; width:calc(70% + 15px);" | ||
> | ||
<span id="valWarning" style="color:#910000" | ||
><b>All Values must be unique.</b></span | ||
> | ||
<ol | ||
id="node-input-option-container" | ||
style="list-style-type:none; margin:0;" | ||
></ol> | ||
</div> | ||
</div> | ||
<div class="form-row"> | ||
<a | ||
href="#" | ||
class="editor-button editor-button-small" | ||
id="node-input-add-option" | ||
style="margin-top:4px; margin-left:103px;" | ||
><i class="fa fa-plus"></i> <span>option</span></a | ||
> | ||
</div> | ||
<div class="form-row"> | ||
<label style="width:auto" for="node-input-multiple" | ||
><i class="fa fa-th-list"></i> Allow multiple selections from list: | ||
</label> | ||
<input | ||
type="checkbox" | ||
checked | ||
id="node-input-multiple" | ||
style="display:inline-block; width:auto; vertical-align:top;" | ||
/> | ||
</div> | ||
<div class="form-row"> | ||
<label style="width:auto" for="node-input-passthru" | ||
><i class="fa fa-arrow-right"></i> If <code>msg</code> arrives on input, | ||
pass through to output: | ||
</label> | ||
<input | ||
type="checkbox" | ||
checked | ||
id="node-input-passthru" | ||
style="display:inline-block; width:auto; vertical-align:top;" | ||
/> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label> | ||
<input type="text" id="node-input-topic" placeholder="optional msg.topic" /> | ||
<input type="hidden" id="node-input-topicType" /> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-className"><i class="fa fa-code"></i> Class</label> | ||
<input | ||
type="text" | ||
id="node-input-className" | ||
placeholder="Optional CSS class name(s) for widget" | ||
/> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label> | ||
<input type="text" id="node-input-name" /> | ||
</div> | ||
</script> |
Oops, something went wrong.