UNPKG

smart-nodes

Version:
481 lines (428 loc) 18.4 kB
<script type="text/javascript"> (function () { let treeList; let candidateNodesCount = 0; let flows = []; let flowMap = {}; function onEditPrepare(node, targetTypes) { if (!node.links) node.links = []; const activeSubflow = RED.nodes.subflow(node.z); treeList = $("<div>") .css({ width: "100%", height: "100%" }) .appendTo(".node-input-link-row") .treeList({ autoSelect: false }) .on("treelistitemmouseover", function (e, item) { if (item.node) { item.node.highlighted = true; item.node.dirty = true; RED.view.redraw(); } }) .on("treelistitemmouseout", function (e, item) { if (item.node) { item.node.highlighted = false; item.node.dirty = true; RED.view.redraw(); } }); flows = []; flowMap = {}; if (activeSubflow) { flowMap[activeSubflow.id] = { id: activeSubflow.id, class: "red-ui-palette-header", label: "Subflow : " + (activeSubflow.name || activeSubflow.id), expanded: true, children: [] }; flows.push(flowMap[activeSubflow.id]); } else { RED.nodes.eachWorkspace(function (ws) { if (!ws.disabled) { flowMap[ws.id] = { id: ws.id, class: "red-ui-palette-header", label: (ws.label || ws.id) + (node.z === ws.id ? " *" : ""), expanded: true, children: [] }; flows.push(flowMap[ws.id]); } }); } setTimeout(function () { treeList.treeList("show", node.z); }, 100); } function initTreeList(node, targetTypes) { candidateNodesCount = 0; for (const key in flowMap) { flowMap[key].children = []; } let candidateNodes = []; targetTypes.forEach(function (targetType) { candidateNodes = candidateNodes.concat(RED.nodes.filterNodes({ type: targetType })); }); candidateNodes.forEach(function (n) { if (flowMap[n.z]) { const isChecked = (node.links.indexOf(n.id) !== -1) || (n.links || []).indexOf(node.id) !== -1; if (isChecked) { flowMap[n.z].children.push({ id: n.id, node: n, label: n.name || n.id, selected: false, checkbox: false, radio: false }); candidateNodesCount++; } } }); for (const key in flowMap) { flowMap[key].children.sort((a, b) => a.label.localeCompare(b.label)); } const flowsFiltered = flows.filter(function (f) { return f.children.length > 0 }); treeList.treeList("empty"); treeList.treeList("data", flowsFiltered); } function resizeDialog(size) { size = size || { height: $(".red-ui-tray-content form").height() } var rowsScenes = $("#dialog-form > div:not(.node-input-property-scenes-row):visible"); var rowsOutputs = $("#dialog-form > div:not(.node-input-property-outputs-row):visible"); var rows = Math.max(rowsScenes, rowsOutputs); var height = size.height; for (var i = 0; i < rows.length; i++) { height -= $(rows[i]).outerHeight(true); } let sceneHeight = height; let outputHeight = height; var editorRow = $("#dialog-form > div.node-input-property-scenes-row"); sceneHeight -= (parseInt(editorRow.css("marginTop")) + parseInt(editorRow.css("marginBottom"))); sceneHeight += 16; $("#node-input-property-scenes").editableList("height", sceneHeight); var editorRow = $("#dialog-form > div.node-input-property-outputs-row"); outputHeight -= (parseInt(editorRow.css("marginTop")) + parseInt(editorRow.css("marginBottom"))); outputHeight += 16; $("#node-input-property-outputs").editableList("height", outputHeight); // links tree list var rows = $("#dialog-form>div:not(#light-control-scenes)"); var height = $("#dialog-form").height(); for (var i = 0; i < rows.length; i++) { height -= $(rows[i]).outerHeight(true); } var tabRow = $("#dialog-form div.scene-tabs-row"); height -= (parseInt(tabRow.css("marginTop")) + parseInt(tabRow.css("marginBottom"))) + tabRow.outerHeight(true); var editorRow = $("#dialog-form div.node-input-link-row"); height -= (parseInt(editorRow.css("marginTop")) + parseInt(editorRow.css("marginBottom"))); $(".node-input-link-row").css("height", height + "px"); } function getScenes(el) { var result = { scenes: [] } el.each(function (i) { var prop = $(this); result.scenes.push({ name: prop.find(".node-input-prop-name").val(), outputs: prop.find(".node-input-prop-outputs").typedInput("value") }); }); return result; } function getOutputs(el) { var result = { output_items: [] } el.each(function (i) { var prop = $(this); result.output_items.push({ name: prop.find(".node-input-prop-name").val(), }); }); return result; } function initScenesOutputs() { let outputs = getOutputs($("#node-input-property-outputs").editableList("items")); let options = []; for (let i = 0; i < outputs.output_items.length; i++) { const item = outputs.output_items[i]; options.push({ value: "" + (i + 1), label: item.name }); } let inputs = $(".node-input-prop-outputs"); for (let i = 0; i < inputs.length; i++) { let value = $(inputs[i]).typedInput("value"); $(inputs[i]).typedInput("types", [{ value: "output", multiple: true, options: options }]); $(inputs[i]).typedInput("value", value); } } RED.nodes.registerType("smart_scene-control", { category: "Smart Nodes", paletteLabel: "Scene control", color: "#C882FF", defaults: { name: { value: "" }, exec_text_names: { value: "" }, max_time_on: { value: "0" }, max_time_on_unit: { value: "s" }, outputs: { value: 1 }, output_items: { value: [{ name: "" }] }, scenes: { value: [{ name: "", outputs: "" }], }, links: { value: [], type: "smart_central-control[]" } }, inputs: 1, outputs: 1, outputLabels: function (index) { return this.output_items[index].name; }, icon: "font-awesome/fa-lightbulb-o", label: function () { return this.name || "Scene control"; }, oneditprepare: function () { let node = this; onEditPrepare(this, ["smart_central-control"]); initTreeList(node, ["smart_central-control"]); // Output list var outputList = $("#node-input-property-outputs").css("min-height", "120px").css("min-width", "445px"); outputList.editableList({ addItem: function (container, i, opt) { var prop = opt; if (!prop.hasOwnProperty("name")) { prop = { name: "" }; } container.css({ overflow: "hidden", whiteSpace: "nowrap" }); var row = $("<div/>").appendTo(container); // Output number $("<div/>", { style: "display:inline-block; padding:0px 6px;" }) .text((i + 1) + ":") .appendTo(row); // Output name var outputName = $("<input/>", { class: "node-input-prop-name", placeholder: node._("scene.ui.name"), type: "text" }) .css("width", "80%") .appendTo(row); outputName.val(prop.name); }, removable: true, }); // Default outputs if (!this.output_items) this.output_items = [{ name: "" }]; // Add existing outputs to list for (var i = 0; i < this.output_items.length; i++) { var item = this.output_items[i]; var newItem = { name: item.name }; outputList.editableList("addItem", newItem); } // Scene list var sceneList = $("#node-input-property-scenes").css("min-height", "120px").css("min-width", "445px"); sceneList.editableList({ addItem: function (container, i, opt) { var prop = opt; if (!prop.hasOwnProperty("name")) { prop = { name: "", outputs: "" }; } container.css({ overflow: "hidden", whiteSpace: "nowrap" }); var row = $("<div/>").appendTo(container); // Scene number $("<div/>", { style: "display:inline-block; padding:0px 6px;" }) .text((i + 1) + ":") .appendTo(row); // Scene name var sceneName = $("<input/>", { class: "node-input-prop-name", placeholder: node._("scene.ui.name"), type: "text" }) .css("width", "30%") .appendTo(row); // Arrow $("<div/>", { style: "display:inline-block; padding:0px 6px;" }) .text("=>") .appendTo(row); // Output select var outputs = $("<input/>", { class: "node-input-prop-outputs", type: "text" }) .css("width", "calc(70% - 55px)") .appendTo(row) .typedInput({ type: "output", types: [{ value: "output", multiple: true, options: [] }] }); // Fill values sceneName.val(prop.name); outputs.typedInput("value", prop.outputs); initScenesOutputs(); }, removable: true, }); // Default scenes if (!this.scenes) this.scenes = [{ name: "", outputs: "" }]; // Add existing scenes to list for (var i = 0; i < this.scenes.length; i++) { var scene = this.scenes[i]; var newScene = { name: scene.name, outputs: scene.outputs }; sceneList.editableList("addItem", newScene); } // Init tabs var tabs = RED.tabs.create({ id: "scene-tabs", onchange: function (tab) { if (tab.id == "scene-tab-scenes") initScenesOutputs(); $("#scene-tabs-content").children().hide(); $("#" + tab.id).show(); resizeDialog(); } }); tabs.addTab({ id: "scene-tab-outputs", iconClass: "fa fa-lightbulb-o", label: node._("scene.ui.outputs") }); tabs.addTab({ id: "scene-tab-scenes", iconClass: "fa fa-list-ul", label: node._("scene.ui.scenes") }); tabs.addTab({ id: "scene-tab-links", iconClass: "fa fa-links", label: node._("scene.ui.links") }); $("#scene-tabs").trigger("change"); $("#node-input-max_time_on") .css("max-width", "4rem") .spinner({ min: 0, change: function (event, ui) { var value = parseInt(this.value); value = isNaN(value) ? 0 : value; value = Math.max(value, parseInt($(this).attr("aria-valuemin"))); // value = Math.min(value, parseInt($(this).attr("aria-valuemax"))); if (value !== this.value) $(this).spinner("value", value); } }); $("#node-input-max_time_on_unit") .css("max-width", "10rem") .typedInput({ types: [{ default: "s", value: "max_time_on_unit", options: [ { value: "ms", label: node._("scene.ui.milliseconds") }, { value: "s", label: node._("scene.ui.seconds") }, { value: "min", label: node._("scene.ui.minutes") }, { value: "h", label: node._("scene.ui.hours") }, ], }], }); }, oneditsave: function () { let node = this; // Set scenes var items = $("#node-input-property-scenes").editableList("items"); var result = getScenes(items); this.scenes = result.scenes; // Set outputs var items = $("#node-input-property-outputs").editableList("items"); var result = getOutputs(items); this.output_items = result.output_items; this.outputs = this.output_items.length; }, onadd: function () { this.links = []; }, oneditresize: resizeDialog }); })(); </script> <script type="text/html" data-template-name="smart_scene-control"> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="scene.ui.name"></span></label> <input type="text" id="node-input-name" data-i18n="[placeholder]scene.ui.name" /> </div> <div class="form-row"> <label for="node-input-exec_text_names"><i class="fa fa-comments-o"></i> <span data-i18n="scene.ui.text"></span></label> <input id="node-input-exec_text_names" type="text" /> <div style="max-width: 450px;" data-i18n="scene.ui.controlled_by_words"></div> </div> <div class="form-row"> <label for="node-input-max_time_on"><i class="fa fa-clock-o"></i> <span data-i18n="scene.ui.time_on"></span></label> <input id="node-input-max_time_on" value="0" /> <input id="node-input-max_time_on_unit" /> </div> <div id="light-control-scenes"> <div class="form-row scene-tabs-row"> <ul style="min-width: 600px; margin-bottom: 20px;" id="scene-tabs"></ul> </div> <div id="scene-tabs-content"> <div id="scene-tab-outputs" style="display: none;"> <ol id="node-input-property-outputs"></ol> </div> <div id="scene-tab-scenes" style="display: none;"> <ol id="node-input-property-scenes"></ol> </div> <div id="scene-tab-links" style="display: none;"> <span><i class="fa fa-link"></i> <span data-i18n="scene.ui.controlled_by_central"></span></span> <div class="form-row node-input-link-row node-input-link-rows"></div> </div> </div> </div> </script>