smart-nodes
Version:
Controls light, shutters and more. Includes common used logic and statistic nodes to control your home.
290 lines (268 loc) • 11.9 kB
HTML
<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 resizeNodeList()
{
var rows = $("#dialog-form>div:not(.node-input-link-row)");
var height = $("#dialog-form").height();
for (var i = 0; i < rows.length; i++)
{
height -= $(rows[i]).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", Math.max(height, 200) + "px");
}
RED.nodes.registerType("smart_shutter-complex-control", {
category: "Smart Nodes",
paletteLabel: "Shutter complex control",
color: "#C882FF",
defaults: {
name: { value: "" },
exec_text_names: { value: "" },
max_time: { value: 60 },
max_time_up: { value: 60 },
max_time_down: { value: 60 },
revert_time_ms: { value: 100 },
alarm_action: { value: 'NOTHING' }, // NOTHING | UP | DOWN
alarm_off_action: { value: 'NOTHING' }, // NOTHING | ON | OFF | LAST
links: { value: [], type: "smart_central-control[]" }
},
inputs: 1,
outputs: 3,
outputLabels: ["Up", "Down", "Status Position"],
icon: "font-awesome/fa-align-justify",
label: function ()
{
return this.name || "Shutter complex control";
},
oneditprepare: function ()
{
let node = this;
onEditPrepare(this, ["smart_central-control"]);
initTreeList(node, ["smart_central-control"]);
$("#node-input-max_time_up")
.css("max-width", "4rem")
.spinner({
min: 1,
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_down")
.css("max-width", "4rem")
.spinner({
min: 1,
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);
}
});
// Backward compatibility
if (typeof node.max_time !== "undefined")
{
node.max_time_down = node.max_time;
node.max_time_up = node.max_time;
$("#node-input-max_time_down").val(node.max_time);
$("#node-input-max_time_up").val(node.max_time);
delete node.max_time;
}
$("#node-input-revert_time_ms")
.css("max-width", "4rem")
.spinner({
min: 1,
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-alarm_action")
.css("max-width", "70%")
.typedInput({
types: [{
default: "NOTHING",
value: "alarm_action",
options: [
{ value: "NOTHING", label: node._("shutter.ui.no_action") },
{ value: "UP", label: node._("shutter.ui.up") },
{ value: "DOWN", label: node._("shutter.ui.down") }
],
}],
});
$("#node-input-alarm_off_action")
.css("max-width", "70%")
.typedInput({
types: [{
value: "alarm_off_action",
default: "NOTHING",
options: [
{ value: "NOTHING", label: node._("shutter.ui.no_action") },
{ value: "UP", label: node._("shutter.ui.up") },
{ value: "DOWN", label: node._("shutter.ui.down") },
{ value: "LAST", label: node._("shutter.ui.last_position") }
],
}],
});
},
onadd: function ()
{
this.links = [];
},
oneditresize: resizeNodeList
});
})();
</script>
<script type="text/html" data-template-name="smart_shutter-complex-control">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="shutter.ui.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]shutter.ui.name" />
</div>
<div class="form-row">
<label for="node-input-exec_text_names"><i class="fa fa-comments-o"></i> <span data-i18n="shutter.ui.text"></span></label>
<input id="node-input-exec_text_names" type="text" />
<div style="max-width: 450px;" data-i18n="shutter.ui.controlled_by_words"></div>
</div>
<div class="form-row">
<label for="node-input-max_time_up"><i class="fa fa-clock-o"></i> <span data-i18n="shutter.ui.time_up"></span></label>
<input id="node-input-max_time_up" placeholder="Komplette Fahrt auf" /> s
</div>
<div class="form-row">
<label for="node-input-max_time_down"><i class="fa fa-clock-o"></i> <span data-i18n="shutter.ui.time_down"></span></label>
<input id="node-input-max_time_down" placeholder="Komplette Fahrt ab" /> s
</div>
<div class="form-row">
<label for="node-input-revert_time_ms"><i class="fa fa-clock-o"></i> <span data-i18n="shutter.ui.pause_change"></span></label>
<input id="node-input-revert_time_ms" placeholder="Pause zwischen Wechsel" /> ms
</div>
<div class="form-row">
<label for="node-input-alarm_action"><i class="fa fa-exclamation-triangle"></i> <span data-i18n="shutter.ui.alarm_on"></span></label>
<input id="node-input-alarm_action"/>
</div>
<div class="form-row">
<label for="node-input-alarm_off_action"><i class="fa fa-exclamation-triangle"></i> <span data-i18n="shutter.ui.alarm_off"></span></label>
<input id="node-input-alarm_off_action"/>
</div>
<span><i class="fa fa-link"></i> <span data-i18n="shutter.ui.controlled_by_central"></span></span>
<div class="form-row node-input-link-row node-input-link-rows"></div>
</script>