/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2014 IBM Corp. | * Copyright 2014 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
**/ | **/ | ||||
RED.comms = (function() { | RED.comms = (function() { | ||||
var errornotification = null; | |||||
var subscriptions = {}; | |||||
var ws; | |||||
function connectWS() { | |||||
var path = location.hostname+":"+location.port+document.location.pathname; | |||||
path = path+(path.slice(-1) == "/"?"":"/")+"comms"; | |||||
path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path; | |||||
ws = new WebSocket(path); | |||||
ws.onopen = function() { | |||||
if (errornotification) { | |||||
errornotification.close(); | |||||
errornotification = null; | |||||
} | |||||
for (var t in subscriptions) { | |||||
if (subscriptions.hasOwnProperty(t)) { | |||||
ws.send(JSON.stringify({subscribe:t})); | |||||
} | |||||
} | |||||
} | |||||
ws.onmessage = function(event) { | |||||
var msg = JSON.parse(event.data); | |||||
if (msg.topic) { | |||||
for (var t in subscriptions) { | |||||
if (subscriptions.hasOwnProperty(t)) { | |||||
var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); | |||||
if (re.test(msg.topic)) { | |||||
var subscribers = subscriptions[t]; | |||||
if (subscribers) { | |||||
for (var i=0;i<subscribers.length;i++) { | |||||
subscribers[i](msg.topic,msg.data); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
}; | |||||
ws.onclose = function() { | |||||
if (errornotification == null) { | |||||
errornotification = RED.notify("<b>Error</b>: Lost connection to server","error",true); | |||||
} | |||||
setTimeout(connectWS,1000); | |||||
} | |||||
} | |||||
function subscribe(topic,callback) { | |||||
if (subscriptions[topic] == null) { | |||||
subscriptions[topic] = []; | |||||
} | |||||
subscriptions[topic].push(callback); | |||||
if (ws && ws.readyState == 1) { | |||||
ws.send(JSON.stringify({subscribe:topic})); | |||||
} | |||||
} | |||||
return { | |||||
connect: connectWS, | |||||
subscribe: subscribe | |||||
} | |||||
var errornotification = null; | |||||
var subscriptions = {}; | |||||
var ws; | |||||
function connectWS() { | |||||
var path = location.hostname+":"+location.port+document.location.pathname; | |||||
path = path+(path.slice(-1) == "/"?"":"/")+"comms"; | |||||
path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path; | |||||
ws = new WebSocket(path); | |||||
ws.onopen = function() { | |||||
if (errornotification) { | |||||
errornotification.close(); | |||||
errornotification = null; | |||||
} | |||||
for (var t in subscriptions) { | |||||
if (subscriptions.hasOwnProperty(t)) { | |||||
ws.send(JSON.stringify({subscribe:t})); | |||||
} | |||||
} | |||||
} | |||||
ws.onmessage = function(event) { | |||||
var msg = JSON.parse(event.data); | |||||
if (msg.topic) { | |||||
for (var t in subscriptions) { | |||||
if (subscriptions.hasOwnProperty(t)) { | |||||
var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); | |||||
if (re.test(msg.topic)) { | |||||
var subscribers = subscriptions[t]; | |||||
if (subscribers) { | |||||
for (var i=0;i<subscribers.length;i++) { | |||||
subscribers[i](msg.topic,msg.data); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
}; | |||||
ws.onclose = function() { | |||||
if (errornotification == null) { | |||||
errornotification = RED.notify("<b>Error</b>: Lost connection to server","error",true); | |||||
} | |||||
setTimeout(connectWS,1000); | |||||
} | |||||
} | |||||
function subscribe(topic,callback) { | |||||
if (subscriptions[topic] == null) { | |||||
subscriptions[topic] = []; | |||||
} | |||||
subscriptions[topic].push(callback); | |||||
if (ws && ws.readyState == 1) { | |||||
ws.send(JSON.stringify({subscribe:topic})); | |||||
} | |||||
} | |||||
return { | |||||
connect: connectWS, | |||||
subscribe: subscribe | |||||
} | |||||
})(); | })(); |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* limitations under the License. | * limitations under the License. | ||||
**/ | **/ | ||||
RED.history = (function() { | RED.history = (function() { | ||||
var undo_history = []; | |||||
return { | |||||
//TODO: this function is a placeholder until there is a 'save' event that can be listened to | |||||
markAllDirty: function() { | |||||
for (var i=0;i<undo_history.length;i++) { | |||||
undo_history[i].dirty = true; | |||||
} | |||||
}, | |||||
depth: function() { | |||||
return undo_history.length; | |||||
}, | |||||
push: function(ev) { | |||||
undo_history.push(ev); | |||||
}, | |||||
pop: function() { | |||||
var ev = undo_history.pop(); | |||||
var i; | |||||
if (ev) { | |||||
if (ev.t == 'add') { | |||||
for (i=0;i<ev.nodes.length;i++) { | |||||
RED.nodes.remove(ev.nodes[i]); | |||||
} | |||||
for (i=0;i<ev.links.length;i++) { | |||||
RED.nodes.removeLink(ev.links[i]); | |||||
} | |||||
for (i=0;i<ev.workspaces.length;i++) { | |||||
RED.nodes.removeWorkspace(ev.workspaces[i].id); | |||||
RED.view.removeWorkspace(ev.workspaces[i]); | |||||
} | |||||
} else if (ev.t == "delete") { | |||||
for (i=0;i<ev.workspaces.length;i++) { | |||||
RED.nodes.addWorkspace(ev.workspaces[i]); | |||||
RED.view.addWorkspace(ev.workspaces[i]); | |||||
} | |||||
for (i=0;i<ev.nodes.length;i++) { | |||||
RED.nodes.add(ev.nodes[i]); | |||||
} | |||||
for (i=0;i<ev.links.length;i++) { | |||||
RED.nodes.addLink(ev.links[i]); | |||||
} | |||||
} else if (ev.t == "move") { | |||||
for (i=0;i<ev.nodes.length;i++) { | |||||
var n = ev.nodes[i]; | |||||
n.n.x = n.ox; | |||||
n.n.y = n.oy; | |||||
n.n.dirty = true; | |||||
} | |||||
} else if (ev.t == "edit") { | |||||
for (i in ev.changes) { | |||||
if (ev.changes.hasOwnProperty(i)) { | |||||
ev.node[i] = ev.changes[i]; | |||||
} | |||||
} | |||||
RED.editor.updateNodeProperties(ev.node); | |||||
for (i=0;i<ev.links.length;i++) { | |||||
RED.nodes.addLink(ev.links[i]); | |||||
} | |||||
RED.editor.validateNode(ev.node); | |||||
ev.node.dirty = true; | |||||
ev.node.changed = ev.changed; | |||||
} | |||||
RED.view.dirty(ev.dirty); | |||||
RED.view.redraw(); | |||||
} | |||||
} | |||||
} | |||||
var undo_history = []; | |||||
return { | |||||
//TODO: this function is a placeholder until there is a 'save' event that can be listened to | |||||
markAllDirty: function() { | |||||
for (var i=0;i<undo_history.length;i++) { | |||||
undo_history[i].dirty = true; | |||||
} | |||||
}, | |||||
depth: function() { | |||||
return undo_history.length; | |||||
}, | |||||
push: function(ev) { | |||||
undo_history.push(ev); | |||||
}, | |||||
pop: function() { | |||||
var ev = undo_history.pop(); | |||||
var i; | |||||
if (ev) { | |||||
if (ev.t == 'add') { | |||||
for (i=0;i<ev.nodes.length;i++) { | |||||
RED.nodes.remove(ev.nodes[i]); | |||||
} | |||||
for (i=0;i<ev.links.length;i++) { | |||||
RED.nodes.removeLink(ev.links[i]); | |||||
} | |||||
for (i=0;i<ev.workspaces.length;i++) { | |||||
RED.nodes.removeWorkspace(ev.workspaces[i].id); | |||||
RED.view.removeWorkspace(ev.workspaces[i]); | |||||
} | |||||
} else if (ev.t == "delete") { | |||||
for (i=0;i<ev.workspaces.length;i++) { | |||||
RED.nodes.addWorkspace(ev.workspaces[i]); | |||||
RED.view.addWorkspace(ev.workspaces[i]); | |||||
} | |||||
for (i=0;i<ev.nodes.length;i++) { | |||||
RED.nodes.add(ev.nodes[i]); | |||||
} | |||||
for (i=0;i<ev.links.length;i++) { | |||||
RED.nodes.addLink(ev.links[i]); | |||||
} | |||||
} else if (ev.t == "move") { | |||||
for (i=0;i<ev.nodes.length;i++) { | |||||
var n = ev.nodes[i]; | |||||
n.n.x = n.ox; | |||||
n.n.y = n.oy; | |||||
n.n.dirty = true; | |||||
} | |||||
} else if (ev.t == "edit") { | |||||
for (i in ev.changes) { | |||||
if (ev.changes.hasOwnProperty(i)) { | |||||
ev.node[i] = ev.changes[i]; | |||||
} | |||||
} | |||||
RED.editor.updateNodeProperties(ev.node); | |||||
for (i=0;i<ev.links.length;i++) { | |||||
RED.nodes.addLink(ev.links[i]); | |||||
} | |||||
RED.editor.validateNode(ev.node); | |||||
ev.node.dirty = true; | |||||
ev.node.changed = ev.changed; | |||||
} | |||||
RED.view.dirty(ev.dirty); | |||||
RED.view.redraw(); | |||||
} | |||||
} | |||||
} | |||||
})(); | })(); |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
**/ | **/ | ||||
var RED = (function() { | var RED = (function() { | ||||
$('#btn-keyboard-shortcuts').click(function(){showHelp();}); | |||||
function hideDropTarget() { | |||||
$("#dropTarget").hide(); | |||||
RED.keyboard.remove(/* ESCAPE */ 27); | |||||
} | |||||
$('#chart').on("dragenter",function(event) { | |||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { | |||||
$("#dropTarget").css({display:'table'}); | |||||
RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget); | |||||
} | |||||
}); | |||||
$('#dropTarget').on("dragover",function(event) { | |||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { | |||||
event.preventDefault(); | |||||
} | |||||
}) | |||||
.on("dragleave",function(event) { | |||||
hideDropTarget(); | |||||
}) | |||||
.on("drop",function(event) { | |||||
var data = event.originalEvent.dataTransfer.getData("text/plain"); | |||||
hideDropTarget(); | |||||
RED.view.importNodes(data); | |||||
event.preventDefault(); | |||||
}); | |||||
function save(force) { | |||||
if (RED.view.dirty()) { | |||||
if (!force) { | |||||
var invalid = false; | |||||
var unknownNodes = []; | |||||
RED.nodes.eachNode(function(node) { | |||||
invalid = invalid || !node.valid; | |||||
if (node.type === "unknown") { | |||||
if (unknownNodes.indexOf(node.name) == -1) { | |||||
unknownNodes.push(node.name); | |||||
} | |||||
invalid = true; | |||||
} | |||||
}); | |||||
if (invalid) { | |||||
if (unknownNodes.length > 0) { | |||||
$( "#node-dialog-confirm-deploy-config" ).hide(); | |||||
$( "#node-dialog-confirm-deploy-unknown" ).show(); | |||||
var list = "<li>"+unknownNodes.join("</li><li>")+"</li>"; | |||||
$( "#node-dialog-confirm-deploy-unknown-list" ).html(list); | |||||
} else { | |||||
$( "#node-dialog-confirm-deploy-config" ).show(); | |||||
$( "#node-dialog-confirm-deploy-unknown" ).hide(); | |||||
} | |||||
$( "#node-dialog-confirm-deploy" ).dialog( "open" ); | |||||
return; | |||||
} | |||||
} | |||||
var nns = RED.nodes.createCompleteNodeSet(); | |||||
$("#btn-icn-deploy").removeClass('icon-upload'); | |||||
$("#btn-icn-deploy").addClass('spinner'); | |||||
RED.view.dirty(false); | |||||
console.log(JSON.stringify(nns)); | |||||
$.ajax({ | |||||
url:"flows", | |||||
type: "POST", | |||||
data: JSON.stringify(nns), | |||||
contentType: "application/json; charset=utf-8" | |||||
}).done(function(data,textStatus,xhr) { | |||||
RED.notify("Successfully deployed","success"); | |||||
RED.nodes.eachNode(function(node) { | |||||
if (node.changed) { | |||||
node.dirty = true; | |||||
node.changed = false; | |||||
} | |||||
if(node.credentials) { | |||||
delete node.credentials; | |||||
} | |||||
}); | |||||
RED.nodes.eachConfig(function (confNode) { | |||||
if (confNode.credentials) { | |||||
delete confNode.credentials; | |||||
} | |||||
}); | |||||
// Once deployed, cannot undo back to a clean state | |||||
RED.history.markAllDirty(); | |||||
RED.view.redraw(); | |||||
}).fail(function(xhr,textStatus,err) { | |||||
RED.view.dirty(true); | |||||
if (xhr.responseText) { | |||||
RED.notify("<strong>Error</strong>: "+xhr.responseText,"error"); | |||||
} else { | |||||
RED.notify("<strong>Error</strong>: no response from server","error"); | |||||
} | |||||
}).always(function() { | |||||
$("#btn-icn-deploy").removeClass('spinner'); | |||||
$("#btn-icn-deploy").addClass('icon-upload'); | |||||
}); | |||||
} | |||||
} | |||||
$('#btn-deploy').click(function() { save(); }); | |||||
$( "#node-dialog-confirm-deploy" ).dialog({ | |||||
title: "Confirm deploy", | |||||
modal: true, | |||||
autoOpen: false, | |||||
width: 530, | |||||
height: 230, | |||||
buttons: [ | |||||
{ | |||||
text: "Confirm deploy", | |||||
click: function() { | |||||
save(true); | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
}, | |||||
{ | |||||
text: "Cancel", | |||||
click: function() { | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
} | |||||
] | |||||
}); | |||||
function loadSettings() { | |||||
$('#btn-keyboard-shortcuts').click(function(){showHelp();}); | |||||
function hideDropTarget() { | |||||
$("#dropTarget").hide(); | |||||
RED.keyboard.remove(/* ESCAPE */ 27); | |||||
} | |||||
$('#chart').on("dragenter",function(event) { | |||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { | |||||
$("#dropTarget").css({display:'table'}); | |||||
RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget); | |||||
} | |||||
}); | |||||
$('#dropTarget').on("dragover",function(event) { | |||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { | |||||
event.preventDefault(); | |||||
} | |||||
}) | |||||
.on("dragleave",function(event) { | |||||
hideDropTarget(); | |||||
}) | |||||
.on("drop",function(event) { | |||||
var data = event.originalEvent.dataTransfer.getData("text/plain"); | |||||
hideDropTarget(); | |||||
RED.view.importNodes(data); | |||||
event.preventDefault(); | |||||
}); | |||||
function save(force) { | |||||
if (RED.view.dirty()) { | |||||
if (!force) { | |||||
var invalid = false; | |||||
var unknownNodes = []; | |||||
RED.nodes.eachNode(function(node) { | |||||
invalid = invalid || !node.valid; | |||||
if (node.type === "unknown") { | |||||
if (unknownNodes.indexOf(node.name) == -1) { | |||||
unknownNodes.push(node.name); | |||||
} | |||||
invalid = true; | |||||
} | |||||
}); | |||||
if (invalid) { | |||||
if (unknownNodes.length > 0) { | |||||
$( "#node-dialog-confirm-deploy-config" ).hide(); | |||||
$( "#node-dialog-confirm-deploy-unknown" ).show(); | |||||
var list = "<li>"+unknownNodes.join("</li><li>")+"</li>"; | |||||
$( "#node-dialog-confirm-deploy-unknown-list" ).html(list); | |||||
} else { | |||||
$( "#node-dialog-confirm-deploy-config" ).show(); | |||||
$( "#node-dialog-confirm-deploy-unknown" ).hide(); | |||||
} | |||||
$( "#node-dialog-confirm-deploy" ).dialog( "open" ); | |||||
return; | |||||
} | |||||
} | |||||
var nns = RED.nodes.createCompleteNodeSet(); | |||||
$("#btn-icn-deploy").removeClass('icon-upload'); | |||||
$("#btn-icn-deploy").addClass('spinner'); | |||||
RED.view.dirty(false); | |||||
console.log(JSON.stringify(nns)); | |||||
$.ajax({ | |||||
url:"flows", | |||||
type: "POST", | |||||
data: JSON.stringify(nns), | |||||
contentType: "application/json; charset=utf-8" | |||||
}).done(function(data,textStatus,xhr) { | |||||
RED.notify("Successfully deployed","success"); | |||||
RED.nodes.eachNode(function(node) { | |||||
if (node.changed) { | |||||
node.dirty = true; | |||||
node.changed = false; | |||||
} | |||||
if(node.credentials) { | |||||
delete node.credentials; | |||||
} | |||||
}); | |||||
RED.nodes.eachConfig(function (confNode) { | |||||
if (confNode.credentials) { | |||||
delete confNode.credentials; | |||||
} | |||||
}); | |||||
// Once deployed, cannot undo back to a clean state | |||||
RED.history.markAllDirty(); | |||||
RED.view.redraw(); | |||||
}).fail(function(xhr,textStatus,err) { | |||||
RED.view.dirty(true); | |||||
if (xhr.responseText) { | |||||
RED.notify("<strong>Error</strong>: "+xhr.responseText,"error"); | |||||
} else { | |||||
RED.notify("<strong>Error</strong>: no response from server","error"); | |||||
} | |||||
}).always(function() { | |||||
$("#btn-icn-deploy").removeClass('spinner'); | |||||
$("#btn-icn-deploy").addClass('icon-upload'); | |||||
}); | |||||
} | |||||
} | |||||
$('#btn-deploy').click(function() { save(); }); | |||||
$( "#node-dialog-confirm-deploy" ).dialog({ | |||||
title: "Confirm deploy", | |||||
modal: true, | |||||
autoOpen: false, | |||||
width: 530, | |||||
height: 230, | |||||
buttons: [ | |||||
{ | |||||
text: "Confirm deploy", | |||||
click: function() { | |||||
save(true); | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
}, | |||||
{ | |||||
text: "Cancel", | |||||
click: function() { | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
} | |||||
] | |||||
}); | |||||
function loadSettings() { | |||||
/* | /* | ||||
$.get('settings', function(data) { | |||||
RED.settings = data; | |||||
console.log("Node-RED: "+data.version); | |||||
loadNodes(); | |||||
}); | |||||
$.get('settings', function(data) { | |||||
RED.settings = data; | |||||
console.log("Node-RED: "+data.version); | |||||
loadNodes(); | |||||
}); | |||||
*/ | */ | ||||
loadNodes(); | |||||
} | |||||
function loadNodes() { | |||||
loadNodes(); | |||||
} | |||||
function loadNodes() { | |||||
console.log("loadNodes"); | console.log("loadNodes"); | ||||
$.get('list.html', function(data) { | |||||
console.log("loadNodes complete"); | |||||
$("body").append(data); | |||||
$(".palette-spinner").hide(); | |||||
$(".palette-scroll").show(); | |||||
$("#palette-search").show(); | |||||
//loadFlows(); | |||||
}, "html"); | |||||
} | |||||
function loadFlows() { | |||||
$.getJSON("flows",function(nodes) { | |||||
RED.nodes.import(nodes); | |||||
RED.view.dirty(false); | |||||
RED.view.redraw(); | |||||
RED.comms.subscribe("status/#",function(topic,msg) { | |||||
var parts = topic.split("/"); | |||||
var node = RED.nodes.node(parts[1]); | |||||
if (node) { | |||||
node.status = msg; | |||||
if (statusEnabled) { | |||||
node.dirty = true; | |||||
RED.view.redraw(); | |||||
} | |||||
} | |||||
}); | |||||
RED.comms.subscribe("node/#",function(topic,msg) { | |||||
var i; | |||||
if (topic == "node/added") { | |||||
for (i=0;i<msg.length;i++) { | |||||
var m = msg[i]; | |||||
var id = m.id; | |||||
$.get('nodes/'+id, function(data) { | |||||
$("body").append(data); | |||||
var typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>"; | |||||
RED.notify("Node"+(m.types.length!=1 ? "s":"")+" added to palette:"+typeList,"success"); | |||||
}); | |||||
} | |||||
} else if (topic == "node/removed") { | |||||
if (msg.types) { | |||||
for (i=0;i<msg.types.length;i++) { | |||||
RED.palette.remove(msg.types[i]); | |||||
} | |||||
var typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; | |||||
RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" removed from palette:"+typeList,"success"); | |||||
} | |||||
} | |||||
}); | |||||
}); | |||||
} | |||||
$('#btn-node-status').click(function() {toggleStatus();}); | |||||
var statusEnabled = false; | |||||
function toggleStatus() { | |||||
var btnStatus = $("#btn-node-status"); | |||||
statusEnabled = btnStatus.toggleClass("active").hasClass("active"); | |||||
RED.view.status(statusEnabled); | |||||
} | |||||
function showHelp() { | |||||
var dialog = $('#node-help'); | |||||
//$("#node-help").draggable({ | |||||
// handle: ".modal-header" | |||||
//}); | |||||
dialog.on('show',function() { | |||||
RED.keyboard.disable(); | |||||
}); | |||||
dialog.on('hidden',function() { | |||||
RED.keyboard.enable(); | |||||
}); | |||||
dialog.modal(); | |||||
} | |||||
$(function() { | |||||
RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); | |||||
loadSettings(); | |||||
RED.comms.connect(); | |||||
}); | |||||
return { | |||||
}; | |||||
$.get('list.html', function(data) { | |||||
console.log("loadNodes complete"); | |||||
$("body").append(data); | |||||
$(".palette-spinner").hide(); | |||||
$(".palette-scroll").show(); | |||||
$("#palette-search").show(); | |||||
//loadFlows(); | |||||
}, "html"); | |||||
} | |||||
function loadFlows() { | |||||
$.getJSON("flows",function(nodes) { | |||||
RED.nodes.import(nodes); | |||||
RED.view.dirty(false); | |||||
RED.view.redraw(); | |||||
RED.comms.subscribe("status/#",function(topic,msg) { | |||||
var parts = topic.split("/"); | |||||
var node = RED.nodes.node(parts[1]); | |||||
if (node) { | |||||
node.status = msg; | |||||
if (statusEnabled) { | |||||
node.dirty = true; | |||||
RED.view.redraw(); | |||||
} | |||||
} | |||||
}); | |||||
RED.comms.subscribe("node/#",function(topic,msg) { | |||||
var i; | |||||
if (topic == "node/added") { | |||||
for (i=0;i<msg.length;i++) { | |||||
var m = msg[i]; | |||||
var id = m.id; | |||||
$.get('nodes/'+id, function(data) { | |||||
$("body").append(data); | |||||
var typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>"; | |||||
RED.notify("Node"+(m.types.length!=1 ? "s":"")+" added to palette:"+typeList,"success"); | |||||
}); | |||||
} | |||||
} else if (topic == "node/removed") { | |||||
if (msg.types) { | |||||
for (i=0;i<msg.types.length;i++) { | |||||
RED.palette.remove(msg.types[i]); | |||||
} | |||||
var typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; | |||||
RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" removed from palette:"+typeList,"success"); | |||||
} | |||||
} | |||||
}); | |||||
}); | |||||
} | |||||
$('#btn-node-status').click(function() {toggleStatus();}); | |||||
var statusEnabled = false; | |||||
function toggleStatus() { | |||||
var btnStatus = $("#btn-node-status"); | |||||
statusEnabled = btnStatus.toggleClass("active").hasClass("active"); | |||||
RED.view.status(statusEnabled); | |||||
} | |||||
function showHelp() { | |||||
var dialog = $('#node-help'); | |||||
//$("#node-help").draggable({ | |||||
// handle: ".modal-header" | |||||
//}); | |||||
dialog.on('show',function() { | |||||
RED.keyboard.disable(); | |||||
}); | |||||
dialog.on('hidden',function() { | |||||
RED.keyboard.enable(); | |||||
}); | |||||
dialog.modal(); | |||||
} | |||||
$(function() { | |||||
RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); | |||||
loadSettings(); | |||||
RED.comms.connect(); | |||||
}); | |||||
return { | |||||
}; | |||||
})(); | })(); |
**/ | **/ | ||||
RED.nodes = (function() { | RED.nodes = (function() { | ||||
var node_defs = {}; | |||||
var nodes = []; | |||||
var configNodes = {}; | |||||
var links = []; | |||||
var defaultWorkspace; | |||||
var workspaces = {}; | |||||
var node_defs = {}; | |||||
var nodes = []; | |||||
var configNodes = {}; | |||||
var links = []; | |||||
var defaultWorkspace; | |||||
var workspaces = {}; | |||||
function registerType(nt,def) { | |||||
node_defs[nt] = def; | |||||
// TODO: too tightly coupled into palette UI | |||||
RED.palette.add(nt,def); | |||||
} | |||||
function registerType(nt,def) { | |||||
node_defs[nt] = def; | |||||
// TODO: too tightly coupled into palette UI | |||||
RED.palette.add(nt,def); | |||||
} | |||||
function getID() { | |||||
function getID() { | |||||
var str = (1+Math.random()*4294967295).toString(16); | var str = (1+Math.random()*4294967295).toString(16); | ||||
console.log("getID = " + str); | console.log("getID = " + str); | ||||
return str; | return str; | ||||
} | |||||
} | |||||
function checkID(name) { | function checkID(name) { | ||||
var i; | |||||
for (i=0;i<nodes.length;i++) { | |||||
var i; | |||||
for (i=0;i<nodes.length;i++) { | |||||
console.log("checkID, nodes[i].id = " + nodes[i].id); | console.log("checkID, nodes[i].id = " + nodes[i].id); | ||||
if (nodes[i].id == name) return true; | if (nodes[i].id == name) return true; | ||||
} | |||||
} | |||||
/* | /* | ||||
for (i in workspaces) { | |||||
if (workspaces.hasOwnProperty(i)) { } | |||||
} | |||||
for (i in configNodes) { | |||||
if (configNodes.hasOwnProperty(i)) { } | |||||
} | |||||
for (i in workspaces) { | |||||
if (workspaces.hasOwnProperty(i)) { } | |||||
} | |||||
for (i in configNodes) { | |||||
if (configNodes.hasOwnProperty(i)) { } | |||||
} | |||||
*/ | */ | ||||
return false; | return false; | ||||
} | } | ||||
function createUniqueCppName(n) { | |||||
function createUniqueCppName(n) { | |||||
console.log("getUniqueCppName, n.type=" + n.type + ", n._def.shortName=" + n._def.shortName); | console.log("getUniqueCppName, n.type=" + n.type + ", n._def.shortName=" + n._def.shortName); | ||||
var basename = (n._def.shortName) ? n._def.shortName : n.type.replace(/^Analog/, ""); | var basename = (n._def.shortName) ? n._def.shortName : n.type.replace(/^Analog/, ""); | ||||
console.log("getUniqueCppName, using basename=" + basename); | console.log("getUniqueCppName, using basename=" + basename); | ||||
} | } | ||||
console.log("getUniqueCppName, unique name=" + name); | console.log("getUniqueCppName, unique name=" + name); | ||||
return name; | return name; | ||||
} | |||||
} | |||||
function getType(type) { | |||||
return node_defs[type]; | |||||
} | |||||
function getType(type) { | |||||
return node_defs[type]; | |||||
} | |||||
function addNode(n) { | |||||
if (n._def.category == "config") { | |||||
configNodes[n.id] = n; | |||||
RED.sidebar.config.refresh(); | |||||
} else { | |||||
n.dirty = true; | |||||
nodes.push(n); | |||||
var updatedConfigNode = false; | |||||
for (var d in n._def.defaults) { | |||||
if (n._def.defaults.hasOwnProperty(d)) { | |||||
var property = n._def.defaults[d]; | |||||
if (property.type) { | |||||
var type = getType(property.type) | |||||
if (type && type.category == "config") { | |||||
var configNode = configNodes[n[d]]; | |||||
if (configNode) { | |||||
updatedConfigNode = true; | |||||
configNode.users.push(n); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
if (updatedConfigNode) { | |||||
RED.sidebar.config.refresh(); | |||||
} | |||||
} | |||||
} | |||||
function addLink(l) { | |||||
links.push(l); | |||||
} | |||||
function addConfig(c) { | |||||
configNodes[c.id] = c; | |||||
} | |||||
function addNode(n) { | |||||
if (n._def.category == "config") { | |||||
configNodes[n.id] = n; | |||||
RED.sidebar.config.refresh(); | |||||
} else { | |||||
n.dirty = true; | |||||
nodes.push(n); | |||||
var updatedConfigNode = false; | |||||
for (var d in n._def.defaults) { | |||||
if (n._def.defaults.hasOwnProperty(d)) { | |||||
var property = n._def.defaults[d]; | |||||
if (property.type) { | |||||
var type = getType(property.type) | |||||
if (type && type.category == "config") { | |||||
var configNode = configNodes[n[d]]; | |||||
if (configNode) { | |||||
updatedConfigNode = true; | |||||
configNode.users.push(n); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
if (updatedConfigNode) { | |||||
RED.sidebar.config.refresh(); | |||||
} | |||||
} | |||||
} | |||||
function addLink(l) { | |||||
links.push(l); | |||||
} | |||||
function addConfig(c) { | |||||
configNodes[c.id] = c; | |||||
} | |||||
function getNode(id) { | |||||
if (id in configNodes) { | |||||
return configNodes[id]; | |||||
} else { | |||||
for (var n in nodes) { | |||||
if (nodes[n].id == id) { | |||||
return nodes[n]; | |||||
} | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
function getNode(id) { | |||||
if (id in configNodes) { | |||||
return configNodes[id]; | |||||
} else { | |||||
for (var n in nodes) { | |||||
if (nodes[n].id == id) { | |||||
return nodes[n]; | |||||
} | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
function removeNode(id) { | |||||
var removedLinks = []; | |||||
if (id in configNodes) { | |||||
delete configNodes[id]; | |||||
RED.sidebar.config.refresh(); | |||||
} else { | |||||
var node = getNode(id); | |||||
if (node) { | |||||
nodes.splice(nodes.indexOf(node),1); | |||||
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); }); | |||||
removedLinks.map(function(l) {links.splice(links.indexOf(l), 1); }); | |||||
} | |||||
var updatedConfigNode = false; | |||||
for (var d in node._def.defaults) { | |||||
if (node._def.defaults.hasOwnProperty(d)) { | |||||
var property = node._def.defaults[d]; | |||||
if (property.type) { | |||||
var type = getType(property.type) | |||||
if (type && type.category == "config") { | |||||
var configNode = configNodes[node[d]]; | |||||
if (configNode) { | |||||
updatedConfigNode = true; | |||||
var users = configNode.users; | |||||
users.splice(users.indexOf(node),1); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
if (updatedConfigNode) { | |||||
RED.sidebar.config.refresh(); | |||||
} | |||||
} | |||||
return removedLinks; | |||||
} | |||||
function removeNode(id) { | |||||
var removedLinks = []; | |||||
if (id in configNodes) { | |||||
delete configNodes[id]; | |||||
RED.sidebar.config.refresh(); | |||||
} else { | |||||
var node = getNode(id); | |||||
if (node) { | |||||
nodes.splice(nodes.indexOf(node),1); | |||||
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); }); | |||||
removedLinks.map(function(l) {links.splice(links.indexOf(l), 1); }); | |||||
} | |||||
var updatedConfigNode = false; | |||||
for (var d in node._def.defaults) { | |||||
if (node._def.defaults.hasOwnProperty(d)) { | |||||
var property = node._def.defaults[d]; | |||||
if (property.type) { | |||||
var type = getType(property.type) | |||||
if (type && type.category == "config") { | |||||
var configNode = configNodes[node[d]]; | |||||
if (configNode) { | |||||
updatedConfigNode = true; | |||||
var users = configNode.users; | |||||
users.splice(users.indexOf(node),1); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
if (updatedConfigNode) { | |||||
RED.sidebar.config.refresh(); | |||||
} | |||||
} | |||||
return removedLinks; | |||||
} | |||||
function removeLink(l) { | |||||
var index = links.indexOf(l); | |||||
if (index != -1) { | |||||
links.splice(index,1); | |||||
} | |||||
} | |||||
function removeLink(l) { | |||||
var index = links.indexOf(l); | |||||
if (index != -1) { | |||||
links.splice(index,1); | |||||
} | |||||
} | |||||
function refreshValidation() { | |||||
for (var n=0;n<nodes.length;n++) { | |||||
RED.editor.validateNode(nodes[n]); | |||||
} | |||||
} | |||||
function refreshValidation() { | |||||
for (var n=0;n<nodes.length;n++) { | |||||
RED.editor.validateNode(nodes[n]); | |||||
} | |||||
} | |||||
function addWorkspace(ws) { | |||||
workspaces[ws.id] = ws; | |||||
} | |||||
function getWorkspace(id) { | |||||
return workspaces[id]; | |||||
} | |||||
function removeWorkspace(id) { | |||||
delete workspaces[id]; | |||||
var removedNodes = []; | |||||
var removedLinks = []; | |||||
var n; | |||||
for (n=0;n<nodes.length;n++) { | |||||
var node = nodes[n]; | |||||
if (node.z == id) { | |||||
removedNodes.push(node); | |||||
} | |||||
} | |||||
for (n=0;n<removedNodes.length;n++) { | |||||
var rmlinks = removeNode(removedNodes[n].id); | |||||
removedLinks = removedLinks.concat(rmlinks); | |||||
} | |||||
return {nodes:removedNodes,links:removedLinks}; | |||||
} | |||||
function addWorkspace(ws) { | |||||
workspaces[ws.id] = ws; | |||||
} | |||||
function getWorkspace(id) { | |||||
return workspaces[id]; | |||||
} | |||||
function removeWorkspace(id) { | |||||
delete workspaces[id]; | |||||
var removedNodes = []; | |||||
var removedLinks = []; | |||||
var n; | |||||
for (n=0;n<nodes.length;n++) { | |||||
var node = nodes[n]; | |||||
if (node.z == id) { | |||||
removedNodes.push(node); | |||||
} | |||||
} | |||||
for (n=0;n<removedNodes.length;n++) { | |||||
var rmlinks = removeNode(removedNodes[n].id); | |||||
removedLinks = removedLinks.concat(rmlinks); | |||||
} | |||||
return {nodes:removedNodes,links:removedLinks}; | |||||
} | |||||
function getAllFlowNodes(node) { | |||||
var visited = {}; | |||||
visited[node.id] = true; | |||||
var nns = [node]; | |||||
var stack = [node]; | |||||
while(stack.length !== 0) { | |||||
var n = stack.shift(); | |||||
var childLinks = links.filter(function(d) { return (d.source === n) || (d.target === n);}); | |||||
for (var i=0;i<childLinks.length;i++) { | |||||
var child = (childLinks[i].source === n)?childLinks[i].target:childLinks[i].source; | |||||
if (!visited[child.id]) { | |||||
visited[child.id] = true; | |||||
nns.push(child); | |||||
stack.push(child); | |||||
} | |||||
} | |||||
} | |||||
return nns; | |||||
} | |||||
function getAllFlowNodes(node) { | |||||
var visited = {}; | |||||
visited[node.id] = true; | |||||
var nns = [node]; | |||||
var stack = [node]; | |||||
while(stack.length !== 0) { | |||||
var n = stack.shift(); | |||||
var childLinks = links.filter(function(d) { return (d.source === n) || (d.target === n);}); | |||||
for (var i=0;i<childLinks.length;i++) { | |||||
var child = (childLinks[i].source === n)?childLinks[i].target:childLinks[i].source; | |||||
if (!visited[child.id]) { | |||||
visited[child.id] = true; | |||||
nns.push(child); | |||||
stack.push(child); | |||||
} | |||||
} | |||||
} | |||||
return nns; | |||||
} | |||||
/** | |||||
* Converts a node to an exportable JSON Object | |||||
**/ | |||||
function convertNode(n, exportCreds) { | |||||
exportCreds = exportCreds || false; | |||||
var node = {}; | |||||
node.id = n.id; | |||||
node.type = n.type; | |||||
for (var d in n._def.defaults) { | |||||
if (n._def.defaults.hasOwnProperty(d)) { | |||||
node[d] = n[d]; | |||||
} | |||||
} | |||||
if(exportCreds && n.credentials) { | |||||
node.credentials = {}; | |||||
for (var cred in n._def.credentials) { | |||||
if (n._def.credentials.hasOwnProperty(cred)) { | |||||
if (n.credentials[cred] != null) { | |||||
node.credentials[cred] = n.credentials[cred]; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
if (n._def.category != "config") { | |||||
node.x = n.x; | |||||
node.y = n.y; | |||||
node.z = n.z; | |||||
node.wires = []; | |||||
for(var i=0;i<n.outputs;i++) { | |||||
node.wires.push([]); | |||||
} | |||||
var wires = links.filter(function(d){return d.source === n;}); | |||||
for (var j=0;j<wires.length;j++) { | |||||
var w = wires[j]; | |||||
node.wires[w.sourcePort].push(w.target.id); | |||||
} | |||||
} | |||||
return node; | |||||
} | |||||
/** | |||||
* Converts a node to an exportable JSON Object | |||||
**/ | |||||
function convertNode(n, exportCreds) { | |||||
exportCreds = exportCreds || false; | |||||
var node = {}; | |||||
node.id = n.id; | |||||
node.type = n.type; | |||||
for (var d in n._def.defaults) { | |||||
if (n._def.defaults.hasOwnProperty(d)) { | |||||
node[d] = n[d]; | |||||
} | |||||
} | |||||
if(exportCreds && n.credentials) { | |||||
node.credentials = {}; | |||||
for (var cred in n._def.credentials) { | |||||
if (n._def.credentials.hasOwnProperty(cred)) { | |||||
if (n.credentials[cred] != null) { | |||||
node.credentials[cred] = n.credentials[cred]; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
if (n._def.category != "config") { | |||||
node.x = n.x; | |||||
node.y = n.y; | |||||
node.z = n.z; | |||||
node.wires = []; | |||||
for(var i=0;i<n.outputs;i++) { | |||||
node.wires.push([]); | |||||
} | |||||
var wires = links.filter(function(d){return d.source === n;}); | |||||
for (var j=0;j<wires.length;j++) { | |||||
var w = wires[j]; | |||||
node.wires[w.sourcePort].push(w.target.id); | |||||
} | |||||
} | |||||
return node; | |||||
} | |||||
/** | |||||
* Converts the current node selection to an exportable JSON Object | |||||
**/ | |||||
function createExportableNodeSet(set) { | |||||
var nns = []; | |||||
var exportedConfigNodes = {}; | |||||
for (var n=0;n<set.length;n++) { | |||||
var node = set[n].n; | |||||
var convertedNode = RED.nodes.convertNode(node); | |||||
for (var d in node._def.defaults) { | |||||
if (node._def.defaults[d].type && node[d] in configNodes) { | |||||
var confNode = configNodes[node[d]]; | |||||
var exportable = getType(node._def.defaults[d].type).exportable; | |||||
if ((exportable == null || exportable)) { | |||||
if (!(node[d] in exportedConfigNodes)) { | |||||
exportedConfigNodes[node[d]] = true; | |||||
nns.unshift(RED.nodes.convertNode(confNode)); | |||||
} | |||||
} else { | |||||
convertedNode[d] = ""; | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Converts the current node selection to an exportable JSON Object | |||||
**/ | |||||
function createExportableNodeSet(set) { | |||||
var nns = []; | |||||
var exportedConfigNodes = {}; | |||||
for (var n=0;n<set.length;n++) { | |||||
var node = set[n].n; | |||||
var convertedNode = RED.nodes.convertNode(node); | |||||
for (var d in node._def.defaults) { | |||||
if (node._def.defaults[d].type && node[d] in configNodes) { | |||||
var confNode = configNodes[node[d]]; | |||||
var exportable = getType(node._def.defaults[d].type).exportable; | |||||
if ((exportable == null || exportable)) { | |||||
if (!(node[d] in exportedConfigNodes)) { | |||||
exportedConfigNodes[node[d]] = true; | |||||
nns.unshift(RED.nodes.convertNode(confNode)); | |||||
} | |||||
} else { | |||||
convertedNode[d] = ""; | |||||
} | |||||
} | |||||
} | |||||
nns.push(convertedNode); | |||||
} | |||||
return nns; | |||||
} | |||||
nns.push(convertedNode); | |||||
} | |||||
return nns; | |||||
} | |||||
//TODO: rename this (createCompleteNodeSet) | |||||
function createCompleteNodeSet() { | |||||
var nns = []; | |||||
var i; | |||||
for (i in workspaces) { | |||||
if (workspaces.hasOwnProperty(i)) { | |||||
nns.push(workspaces[i]); | |||||
} | |||||
} | |||||
for (i in configNodes) { | |||||
if (configNodes.hasOwnProperty(i)) { | |||||
nns.push(convertNode(configNodes[i], true)); | |||||
} | |||||
} | |||||
for (i=0;i<nodes.length;i++) { | |||||
var node = nodes[i]; | |||||
nns.push(convertNode(node, true)); | |||||
} | |||||
return nns; | |||||
} | |||||
//TODO: rename this (createCompleteNodeSet) | |||||
function createCompleteNodeSet() { | |||||
var nns = []; | |||||
var i; | |||||
for (i in workspaces) { | |||||
if (workspaces.hasOwnProperty(i)) { | |||||
nns.push(workspaces[i]); | |||||
} | |||||
} | |||||
for (i in configNodes) { | |||||
if (configNodes.hasOwnProperty(i)) { | |||||
nns.push(convertNode(configNodes[i], true)); | |||||
} | |||||
} | |||||
for (i=0;i<nodes.length;i++) { | |||||
var node = nodes[i]; | |||||
nns.push(convertNode(node, true)); | |||||
} | |||||
return nns; | |||||
} | |||||
function importNodes(newNodesObj,createNewIds) { | |||||
try { | |||||
var i; | |||||
var n; | |||||
var newNodes; | |||||
if (typeof newNodesObj === "string") { | |||||
if (newNodesObj === "") { | |||||
return; | |||||
} | |||||
newNodes = JSON.parse(newNodesObj); | |||||
} else { | |||||
newNodes = newNodesObj; | |||||
} | |||||
function importNodes(newNodesObj,createNewIds) { | |||||
try { | |||||
var i; | |||||
var n; | |||||
var newNodes; | |||||
if (typeof newNodesObj === "string") { | |||||
if (newNodesObj === "") { | |||||
return; | |||||
} | |||||
newNodes = JSON.parse(newNodesObj); | |||||
} else { | |||||
newNodes = newNodesObj; | |||||
} | |||||
if (!$.isArray(newNodes)) { | |||||
newNodes = [newNodes]; | |||||
} | |||||
var unknownTypes = []; | |||||
for (i=0;i<newNodes.length;i++) { | |||||
n = newNodes[i]; | |||||
// TODO: remove workspace in next release+1 | |||||
if (n.type != "workspace" && n.type != "tab" && !getType(n.type)) { | |||||
// TODO: get this UI thing out of here! (see below as well) | |||||
n.name = n.type; | |||||
n.type = "unknown"; | |||||
if (unknownTypes.indexOf(n.name)==-1) { | |||||
unknownTypes.push(n.name); | |||||
} | |||||
if (n.x == null && n.y == null) { | |||||
// config node - remove it | |||||
newNodes.splice(i,1); | |||||
i--; | |||||
} | |||||
} | |||||
} | |||||
if (unknownTypes.length > 0) { | |||||
var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>"; | |||||
var type = "type"+(unknownTypes.length > 1?"s":""); | |||||
RED.notify("<strong>Imported unrecognised "+type+":</strong>"+typeList,"error",false,10000); | |||||
//"DO NOT DEPLOY while in this state.<br/>Either, add missing types to Node-RED, restart and then reload page,<br/>or delete unknown "+n.name+", rewire as required, and then deploy.","error"); | |||||
} | |||||
if (!$.isArray(newNodes)) { | |||||
newNodes = [newNodes]; | |||||
} | |||||
var unknownTypes = []; | |||||
for (i=0;i<newNodes.length;i++) { | |||||
n = newNodes[i]; | |||||
// TODO: remove workspace in next release+1 | |||||
if (n.type != "workspace" && n.type != "tab" && !getType(n.type)) { | |||||
// TODO: get this UI thing out of here! (see below as well) | |||||
n.name = n.type; | |||||
n.type = "unknown"; | |||||
if (unknownTypes.indexOf(n.name)==-1) { | |||||
unknownTypes.push(n.name); | |||||
} | |||||
if (n.x == null && n.y == null) { | |||||
// config node - remove it | |||||
newNodes.splice(i,1); | |||||
i--; | |||||
} | |||||
} | |||||
} | |||||
if (unknownTypes.length > 0) { | |||||
var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>"; | |||||
var type = "type"+(unknownTypes.length > 1?"s":""); | |||||
RED.notify("<strong>Imported unrecognised "+type+":</strong>"+typeList,"error",false,10000); | |||||
//"DO NOT DEPLOY while in this state.<br/>Either, add missing types to Node-RED, restart and then reload page,<br/>or delete unknown "+n.name+", rewire as required, and then deploy.","error"); | |||||
} | |||||
for (i=0;i<newNodes.length;i++) { | |||||
n = newNodes[i]; | |||||
// TODO: remove workspace in next release+1 | |||||
if (n.type === "workspace" || n.type === "tab") { | |||||
if (n.type === "workspace") { | |||||
n.type = "tab"; | |||||
} | |||||
if (defaultWorkspace == null) { | |||||
defaultWorkspace = n; | |||||
} | |||||
addWorkspace(n); | |||||
RED.view.addWorkspace(n); | |||||
} | |||||
} | |||||
if (defaultWorkspace == null) { | |||||
defaultWorkspace = { type:"tab", id:getID(), label:"Sheet 1" }; | |||||
addWorkspace(defaultWorkspace); | |||||
RED.view.addWorkspace(defaultWorkspace); | |||||
} | |||||
for (i=0;i<newNodes.length;i++) { | |||||
n = newNodes[i]; | |||||
// TODO: remove workspace in next release+1 | |||||
if (n.type === "workspace" || n.type === "tab") { | |||||
if (n.type === "workspace") { | |||||
n.type = "tab"; | |||||
} | |||||
if (defaultWorkspace == null) { | |||||
defaultWorkspace = n; | |||||
} | |||||
addWorkspace(n); | |||||
RED.view.addWorkspace(n); | |||||
} | |||||
} | |||||
if (defaultWorkspace == null) { | |||||
defaultWorkspace = { type:"tab", id:getID(), label:"Sheet 1" }; | |||||
addWorkspace(defaultWorkspace); | |||||
RED.view.addWorkspace(defaultWorkspace); | |||||
} | |||||
var node_map = {}; | |||||
var new_nodes = []; | |||||
var new_links = []; | |||||
var node_map = {}; | |||||
var new_nodes = []; | |||||
var new_links = []; | |||||
for (i=0;i<newNodes.length;i++) { | |||||
n = newNodes[i]; | |||||
// TODO: remove workspace in next release+1 | |||||
if (n.type !== "workspace" && n.type !== "tab") { | |||||
var def = getType(n.type); | |||||
if (def && def.category == "config") { | |||||
if (!RED.nodes.node(n.id)) { | |||||
var configNode = {id:n.id,type:n.type,users:[]}; | |||||
for (var d in def.defaults) { | |||||
if (def.defaults.hasOwnProperty(d)) { | |||||
configNode[d] = n[d]; | |||||
} | |||||
} | |||||
configNode.label = def.label; | |||||
configNode._def = def; | |||||
RED.nodes.add(configNode); | |||||
} | |||||
} else { | |||||
var node = {x:n.x,y:n.y,z:n.z,type:0,wires:n.wires,changed:false}; | |||||
if (createNewIds) { | |||||
node.z = RED.view.getWorkspace(); | |||||
node.id = getID(); | |||||
} else { | |||||
node.id = n.id; | |||||
if (node.z == null || !workspaces[node.z]) { | |||||
node.z = RED.view.getWorkspace(); | |||||
} | |||||
} | |||||
node.type = n.type; | |||||
node._def = def; | |||||
if (!node._def) { | |||||
node._def = { | |||||
color:"#fee", | |||||
defaults: {}, | |||||
label: "unknown: "+n.type, | |||||
labelStyle: "node_label_italic", | |||||
outputs: n.outputs||n.wires.length | |||||
} | |||||
} | |||||
node.outputs = n.outputs||node._def.outputs; | |||||
for (i=0;i<newNodes.length;i++) { | |||||
n = newNodes[i]; | |||||
// TODO: remove workspace in next release+1 | |||||
if (n.type !== "workspace" && n.type !== "tab") { | |||||
var def = getType(n.type); | |||||
if (def && def.category == "config") { | |||||
if (!RED.nodes.node(n.id)) { | |||||
var configNode = {id:n.id,type:n.type,users:[]}; | |||||
for (var d in def.defaults) { | |||||
if (def.defaults.hasOwnProperty(d)) { | |||||
configNode[d] = n[d]; | |||||
} | |||||
} | |||||
configNode.label = def.label; | |||||
configNode._def = def; | |||||
RED.nodes.add(configNode); | |||||
} | |||||
} else { | |||||
var node = {x:n.x,y:n.y,z:n.z,type:0,wires:n.wires,changed:false}; | |||||
if (createNewIds) { | |||||
node.z = RED.view.getWorkspace(); | |||||
node.id = getID(); | |||||
} else { | |||||
node.id = n.id; | |||||
if (node.z == null || !workspaces[node.z]) { | |||||
node.z = RED.view.getWorkspace(); | |||||
} | |||||
} | |||||
node.type = n.type; | |||||
node._def = def; | |||||
if (!node._def) { | |||||
node._def = { | |||||
color:"#fee", | |||||
defaults: {}, | |||||
label: "unknown: "+n.type, | |||||
labelStyle: "node_label_italic", | |||||
outputs: n.outputs||n.wires.length | |||||
} | |||||
} | |||||
node.outputs = n.outputs||node._def.outputs; | |||||
for (var d2 in node._def.defaults) { | |||||
if (node._def.defaults.hasOwnProperty(d2)) { | |||||
node[d2] = n[d2]; | |||||
} | |||||
} | |||||
for (var d2 in node._def.defaults) { | |||||
if (node._def.defaults.hasOwnProperty(d2)) { | |||||
node[d2] = n[d2]; | |||||
} | |||||
} | |||||
addNode(node); | |||||
RED.editor.validateNode(node); | |||||
node_map[n.id] = node; | |||||
new_nodes.push(node); | |||||
} | |||||
} | |||||
} | |||||
for (i=0;i<new_nodes.length;i++) { | |||||
n = new_nodes[i]; | |||||
for (var w1=0;w1<n.wires.length;w1++) { | |||||
var wires = (n.wires[w1] instanceof Array)?n.wires[w1]:[n.wires[w1]]; | |||||
for (var w2=0;w2<wires.length;w2++) { | |||||
if (wires[w2] in node_map) { | |||||
var link = {source:n,sourcePort:w1,target:node_map[wires[w2]]}; | |||||
addLink(link); | |||||
new_links.push(link); | |||||
} | |||||
} | |||||
} | |||||
delete n.wires; | |||||
} | |||||
return [new_nodes,new_links]; | |||||
} catch(error) { | |||||
//TODO: get this UI thing out of here! (see above as well) | |||||
RED.notify("<strong>Error</strong>: "+error,"error"); | |||||
return null; | |||||
} | |||||
addNode(node); | |||||
RED.editor.validateNode(node); | |||||
node_map[n.id] = node; | |||||
new_nodes.push(node); | |||||
} | |||||
} | |||||
} | |||||
for (i=0;i<new_nodes.length;i++) { | |||||
n = new_nodes[i]; | |||||
for (var w1=0;w1<n.wires.length;w1++) { | |||||
var wires = (n.wires[w1] instanceof Array)?n.wires[w1]:[n.wires[w1]]; | |||||
for (var w2=0;w2<wires.length;w2++) { | |||||
if (wires[w2] in node_map) { | |||||
var link = {source:n,sourcePort:w1,target:node_map[wires[w2]]}; | |||||
addLink(link); | |||||
new_links.push(link); | |||||
} | |||||
} | |||||
} | |||||
delete n.wires; | |||||
} | |||||
return [new_nodes,new_links]; | |||||
} catch(error) { | |||||
//TODO: get this UI thing out of here! (see above as well) | |||||
RED.notify("<strong>Error</strong>: "+error,"error"); | |||||
return null; | |||||
} | |||||
} | |||||
} | |||||
return { | |||||
registerType: registerType, | |||||
getType: getType, | |||||
convertNode: convertNode, | |||||
add: addNode, | |||||
addLink: addLink, | |||||
remove: removeNode, | |||||
removeLink: removeLink, | |||||
addWorkspace: addWorkspace, | |||||
removeWorkspace: removeWorkspace, | |||||
workspace: getWorkspace, | |||||
eachNode: function(cb) { | |||||
for (var n=0;n<nodes.length;n++) { | |||||
cb(nodes[n]); | |||||
} | |||||
}, | |||||
eachLink: function(cb) { | |||||
for (var l=0;l<links.length;l++) { | |||||
cb(links[l]); | |||||
} | |||||
}, | |||||
eachConfig: function(cb) { | |||||
for (var id in configNodes) { | |||||
if (configNodes.hasOwnProperty(id)) { | |||||
cb(configNodes[id]); | |||||
} | |||||
} | |||||
}, | |||||
node: getNode, | |||||
import: importNodes, | |||||
refreshValidation: refreshValidation, | |||||
getAllFlowNodes: getAllFlowNodes, | |||||
createExportableNodeSet: createExportableNodeSet, | |||||
createCompleteNodeSet: createCompleteNodeSet, | |||||
id: getID, | |||||
cppName: createUniqueCppName, | |||||
nodes: nodes, // TODO: exposed for d3 vis | |||||
links: links // TODO: exposed for d3 vis | |||||
}; | |||||
return { | |||||
registerType: registerType, | |||||
getType: getType, | |||||
convertNode: convertNode, | |||||
add: addNode, | |||||
addLink: addLink, | |||||
remove: removeNode, | |||||
removeLink: removeLink, | |||||
addWorkspace: addWorkspace, | |||||
removeWorkspace: removeWorkspace, | |||||
workspace: getWorkspace, | |||||
eachNode: function(cb) { | |||||
for (var n=0;n<nodes.length;n++) { | |||||
cb(nodes[n]); | |||||
} | |||||
}, | |||||
eachLink: function(cb) { | |||||
for (var l=0;l<links.length;l++) { | |||||
cb(links[l]); | |||||
} | |||||
}, | |||||
eachConfig: function(cb) { | |||||
for (var id in configNodes) { | |||||
if (configNodes.hasOwnProperty(id)) { | |||||
cb(configNodes[id]); | |||||
} | |||||
} | |||||
}, | |||||
node: getNode, | |||||
import: importNodes, | |||||
refreshValidation: refreshValidation, | |||||
getAllFlowNodes: getAllFlowNodes, | |||||
createExportableNodeSet: createExportableNodeSet, | |||||
createCompleteNodeSet: createCompleteNodeSet, | |||||
id: getID, | |||||
cppName: createUniqueCppName, | |||||
nodes: nodes, // TODO: exposed for d3 vis | |||||
links: links // TODO: exposed for d3 vis | |||||
}; | |||||
})(); | })(); |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
**/ | **/ | ||||
RED.keyboard = (function() { | RED.keyboard = (function() { | ||||
var active = true; | |||||
var handlers = {}; | |||||
var active = true; | |||||
var handlers = {}; | |||||
d3.select(window).on("keydown",function() { | |||||
if (!active) { return; } | |||||
var handler = handlers[d3.event.keyCode]; | |||||
if (handler && handler.ondown) { | |||||
if (!handler.modifiers || | |||||
((!handler.modifiers.shift || d3.event.shiftKey) && | |||||
(!handler.modifiers.ctrl || d3.event.ctrlKey ) && | |||||
(!handler.modifiers.alt || d3.event.altKey ) )) { | |||||
handler.ondown(); | |||||
} | |||||
} | |||||
}); | |||||
d3.select(window).on("keyup",function() { | |||||
if (!active) { return; } | |||||
var handler = handlers[d3.event.keyCode]; | |||||
if (handler && handler.onup) { | |||||
if (!handler.modifiers || | |||||
((!handler.modifiers.shift || d3.event.shiftKey) && | |||||
(!handler.modifiers.ctrl || d3.event.ctrlKey ) && | |||||
(!handler.modifiers.alt || d3.event.altKey ) )) { | |||||
handler.onup(); | |||||
} | |||||
} | |||||
}); | |||||
function addHandler(key,modifiers,ondown,onup) { | |||||
var mod = modifiers; | |||||
var cbdown = ondown; | |||||
var cbup = onup; | |||||
d3.select(window).on("keydown",function() { | |||||
if (!active) { return; } | |||||
var handler = handlers[d3.event.keyCode]; | |||||
if (handler && handler.ondown) { | |||||
if (!handler.modifiers || | |||||
((!handler.modifiers.shift || d3.event.shiftKey) && | |||||
(!handler.modifiers.ctrl || d3.event.ctrlKey ) && | |||||
(!handler.modifiers.alt || d3.event.altKey ) )) { | |||||
handler.ondown(); | |||||
} | |||||
} | |||||
}); | |||||
d3.select(window).on("keyup",function() { | |||||
if (!active) { return; } | |||||
var handler = handlers[d3.event.keyCode]; | |||||
if (handler && handler.onup) { | |||||
if (!handler.modifiers || | |||||
((!handler.modifiers.shift || d3.event.shiftKey) && | |||||
(!handler.modifiers.ctrl || d3.event.ctrlKey ) && | |||||
(!handler.modifiers.alt || d3.event.altKey ) )) { | |||||
handler.onup(); | |||||
} | |||||
} | |||||
}); | |||||
function addHandler(key,modifiers,ondown,onup) { | |||||
var mod = modifiers; | |||||
var cbdown = ondown; | |||||
var cbup = onup; | |||||
if (typeof modifiers == "function") { | |||||
mod = {}; | |||||
cbdown = modifiers; | |||||
cbup = ondown; | |||||
} | |||||
handlers[key] = {modifiers:mod, ondown:cbdown, onup:cbup}; | |||||
} | |||||
function removeHandler(key) { | |||||
delete handlers[key]; | |||||
} | |||||
if (typeof modifiers == "function") { | |||||
mod = {}; | |||||
cbdown = modifiers; | |||||
cbup = ondown; | |||||
} | |||||
handlers[key] = {modifiers:mod, ondown:cbdown, onup:cbup}; | |||||
} | |||||
function removeHandler(key) { | |||||
delete handlers[key]; | |||||
} | |||||
return { | |||||
add: addHandler, | |||||
remove: removeHandler, | |||||
disable: function(){ active = false;}, | |||||
enable: function(){ active = true; } | |||||
} | |||||
return { | |||||
add: addHandler, | |||||
remove: removeHandler, | |||||
disable: function(){ active = false;}, | |||||
enable: function(){ active = true; } | |||||
} | |||||
})(); | })(); |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* limitations under the License. | * limitations under the License. | ||||
**/ | **/ | ||||
RED.library = (function() { | RED.library = (function() { | ||||
function loadFlowLibrary() { | |||||
$.getJSON("library/flows",function(data) { | |||||
//console.log(data); | |||||
function loadFlowLibrary() { | |||||
$.getJSON("library/flows",function(data) { | |||||
//console.log(data); | |||||
var buildMenu = function(data,root) { | |||||
var i; | |||||
var li; | |||||
var a; | |||||
var ul = document.createElement("ul"); | |||||
ul.className = "dropdown-menu"; | |||||
if (data.d) { | |||||
for (i in data.d) { | |||||
if (data.d.hasOwnProperty(i)) { | |||||
li = document.createElement("li"); | |||||
li.className = "dropdown-submenu pull-left"; | |||||
a = document.createElement("a"); | |||||
a.href="#"; | |||||
a.innerHTML = i; | |||||
li.appendChild(a); | |||||
li.appendChild(buildMenu(data.d[i],root+(root!==""?"/":"")+i)); | |||||
ul.appendChild(li); | |||||
} | |||||
} | |||||
} | |||||
if (data.f) { | |||||
for (i in data.f) { | |||||
if (data.f.hasOwnProperty(i)) { | |||||
li = document.createElement("li"); | |||||
a = document.createElement("a"); | |||||
a.href="#"; | |||||
a.innerHTML = data.f[i]; | |||||
a.flowName = root+(root!==""?"/":"")+data.f[i]; | |||||
a.onclick = function() { | |||||
$.get('library/flows/'+this.flowName, function(data) { | |||||
RED.view.importNodes(data); | |||||
}); | |||||
}; | |||||
li.appendChild(a); | |||||
ul.appendChild(li); | |||||
} | |||||
} | |||||
} | |||||
return ul; | |||||
}; | |||||
var menu = buildMenu(data,""); | |||||
$("#flow-menu-parent>ul").replaceWith(menu); | |||||
}); | |||||
} | |||||
loadFlowLibrary(); | |||||
var buildMenu = function(data,root) { | |||||
var i; | |||||
var li; | |||||
var a; | |||||
var ul = document.createElement("ul"); | |||||
ul.className = "dropdown-menu"; | |||||
if (data.d) { | |||||
for (i in data.d) { | |||||
if (data.d.hasOwnProperty(i)) { | |||||
li = document.createElement("li"); | |||||
li.className = "dropdown-submenu pull-left"; | |||||
a = document.createElement("a"); | |||||
a.href="#"; | |||||
a.innerHTML = i; | |||||
li.appendChild(a); | |||||
li.appendChild(buildMenu(data.d[i],root+(root!==""?"/":"")+i)); | |||||
ul.appendChild(li); | |||||
} | |||||
} | |||||
} | |||||
if (data.f) { | |||||
for (i in data.f) { | |||||
if (data.f.hasOwnProperty(i)) { | |||||
li = document.createElement("li"); | |||||
a = document.createElement("a"); | |||||
a.href="#"; | |||||
a.innerHTML = data.f[i]; | |||||
a.flowName = root+(root!==""?"/":"")+data.f[i]; | |||||
a.onclick = function() { | |||||
$.get('library/flows/'+this.flowName, function(data) { | |||||
RED.view.importNodes(data); | |||||
}); | |||||
}; | |||||
li.appendChild(a); | |||||
ul.appendChild(li); | |||||
} | |||||
} | |||||
} | |||||
return ul; | |||||
}; | |||||
var menu = buildMenu(data,""); | |||||
$("#flow-menu-parent>ul").replaceWith(menu); | |||||
}); | |||||
} | |||||
loadFlowLibrary(); | |||||
function createUI(options) { | |||||
var libraryData = {}; | |||||
var selectedLibraryItem = null; | |||||
var libraryEditor = null; | |||||
function buildFileListItem(item) { | |||||
var li = document.createElement("li"); | |||||
li.onmouseover = function(e) { $(this).addClass("list-hover"); }; | |||||
li.onmouseout = function(e) { $(this).removeClass("list-hover"); }; | |||||
return li; | |||||
} | |||||
function buildFileList(root,data) { | |||||
var ul = document.createElement("ul"); | |||||
var li; | |||||
for (var i=0;i<data.length;i++) { | |||||
var v = data[i]; | |||||
if (typeof v === "string") { | |||||
// directory | |||||
li = buildFileListItem(v); | |||||
li.onclick = (function () { | |||||
var dirName = v; | |||||
return function(e) { | |||||
var bcli = $('<li class="active"><span class="divider">/</span> <a href="#">'+dirName+'</a></li>'); | |||||
$("a",bcli).click(function(e) { | |||||
$(this).parent().nextAll().remove(); | |||||
$.getJSON("library/"+options.url+root+dirName,function(data) { | |||||
$("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data)); | |||||
}); | |||||
e.stopPropagation(); | |||||
}); | |||||
var bc = $("#node-dialog-library-breadcrumbs"); | |||||
$(".active",bc).removeClass("active"); | |||||
bc.append(bcli); | |||||
$.getJSON("library/"+options.url+root+dirName,function(data) { | |||||
$("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data)); | |||||
}); | |||||
} | |||||
})(); | |||||
li.innerHTML = '<i class="icon-folder-close"></i> '+v+"</i>"; | |||||
ul.appendChild(li); | |||||
} else { | |||||
// file | |||||
li = buildFileListItem(v); | |||||
li.innerHTML = v.name; | |||||
li.onclick = (function() { | |||||
var item = v; | |||||
return function(e) { | |||||
$(".list-selected",ul).removeClass("list-selected"); | |||||
$(this).addClass("list-selected"); | |||||
$.get("library/"+options.url+root+item.fn, function(data) { | |||||
console.log(data); | |||||
selectedLibraryItem = item; | |||||
libraryEditor.setText(data); | |||||
}); | |||||
} | |||||
})(); | |||||
ul.appendChild(li); | |||||
} | |||||
} | |||||
return ul; | |||||
} | |||||
$('#node-input-name').addClass('input-append-left').css("width","65%").after( | |||||
'<div class="btn-group" style="margin-left: -5px;">'+ | |||||
'<button id="node-input-'+options.type+'-lookup" class="btn input-append-right" data-toggle="dropdown"><i class="icon-book"></i> <span class="caret"></span></button>'+ | |||||
'<ul class="dropdown-menu pull-right" role="menu">'+ | |||||
'<li><a id="node-input-'+options.type+'-menu-open-library" tabindex="-1" href="#">Open Library...</a></li>'+ | |||||
'<li><a id="node-input-'+options.type+'-menu-save-library" tabindex="-1" href="#">Save to Library...</a></li>'+ | |||||
'</ul></div>' | |||||
); | |||||
$('#node-input-'+options.type+'-menu-open-library').click(function(e) { | |||||
$("#node-select-library").children().remove(); | |||||
var bc = $("#node-dialog-library-breadcrumbs"); | |||||
bc.children().first().nextAll().remove(); | |||||
libraryEditor.setText(''); | |||||
$.getJSON("library/"+options.url,function(data) { | |||||
$("#node-select-library").append(buildFileList("/",data)); | |||||
$("#node-dialog-library-breadcrumbs a").click(function(e) { | |||||
$(this).parent().nextAll().remove(); | |||||
$("#node-select-library").children().first().replaceWith(buildFileList("/",data)); | |||||
e.stopPropagation(); | |||||
}); | |||||
$( "#node-dialog-library-lookup" ).dialog( "open" ); | |||||
}); | |||||
e.preventDefault(); | |||||
}); | |||||
$('#node-input-'+options.type+'-menu-save-library').click(function(e) { | |||||
//var found = false; | |||||
var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,""); | |||||
function createUI(options) { | |||||
var libraryData = {}; | |||||
var selectedLibraryItem = null; | |||||
var libraryEditor = null; | |||||
function buildFileListItem(item) { | |||||
var li = document.createElement("li"); | |||||
li.onmouseover = function(e) { $(this).addClass("list-hover"); }; | |||||
li.onmouseout = function(e) { $(this).removeClass("list-hover"); }; | |||||
return li; | |||||
} | |||||
function buildFileList(root,data) { | |||||
var ul = document.createElement("ul"); | |||||
var li; | |||||
for (var i=0;i<data.length;i++) { | |||||
var v = data[i]; | |||||
if (typeof v === "string") { | |||||
// directory | |||||
li = buildFileListItem(v); | |||||
li.onclick = (function () { | |||||
var dirName = v; | |||||
return function(e) { | |||||
var bcli = $('<li class="active"><span class="divider">/</span> <a href="#">'+dirName+'</a></li>'); | |||||
$("a",bcli).click(function(e) { | |||||
$(this).parent().nextAll().remove(); | |||||
$.getJSON("library/"+options.url+root+dirName,function(data) { | |||||
$("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data)); | |||||
}); | |||||
e.stopPropagation(); | |||||
}); | |||||
var bc = $("#node-dialog-library-breadcrumbs"); | |||||
$(".active",bc).removeClass("active"); | |||||
bc.append(bcli); | |||||
$.getJSON("library/"+options.url+root+dirName,function(data) { | |||||
$("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data)); | |||||
}); | |||||
} | |||||
})(); | |||||
li.innerHTML = '<i class="icon-folder-close"></i> '+v+"</i>"; | |||||
ul.appendChild(li); | |||||
} else { | |||||
// file | |||||
li = buildFileListItem(v); | |||||
li.innerHTML = v.name; | |||||
li.onclick = (function() { | |||||
var item = v; | |||||
return function(e) { | |||||
$(".list-selected",ul).removeClass("list-selected"); | |||||
$(this).addClass("list-selected"); | |||||
$.get("library/"+options.url+root+item.fn, function(data) { | |||||
console.log(data); | |||||
selectedLibraryItem = item; | |||||
libraryEditor.setText(data); | |||||
}); | |||||
} | |||||
})(); | |||||
ul.appendChild(li); | |||||
} | |||||
} | |||||
return ul; | |||||
} | |||||
$('#node-input-name').addClass('input-append-left').css("width","65%").after( | |||||
'<div class="btn-group" style="margin-left: -5px;">'+ | |||||
'<button id="node-input-'+options.type+'-lookup" class="btn input-append-right" data-toggle="dropdown"><i class="icon-book"></i> <span class="caret"></span></button>'+ | |||||
'<ul class="dropdown-menu pull-right" role="menu">'+ | |||||
'<li><a id="node-input-'+options.type+'-menu-open-library" tabindex="-1" href="#">Open Library...</a></li>'+ | |||||
'<li><a id="node-input-'+options.type+'-menu-save-library" tabindex="-1" href="#">Save to Library...</a></li>'+ | |||||
'</ul></div>' | |||||
); | |||||
$('#node-input-'+options.type+'-menu-open-library').click(function(e) { | |||||
$("#node-select-library").children().remove(); | |||||
var bc = $("#node-dialog-library-breadcrumbs"); | |||||
bc.children().first().nextAll().remove(); | |||||
libraryEditor.setText(''); | |||||
$.getJSON("library/"+options.url,function(data) { | |||||
$("#node-select-library").append(buildFileList("/",data)); | |||||
$("#node-dialog-library-breadcrumbs a").click(function(e) { | |||||
$(this).parent().nextAll().remove(); | |||||
$("#node-select-library").children().first().replaceWith(buildFileList("/",data)); | |||||
e.stopPropagation(); | |||||
}); | |||||
$( "#node-dialog-library-lookup" ).dialog( "open" ); | |||||
}); | |||||
e.preventDefault(); | |||||
}); | |||||
$('#node-input-'+options.type+'-menu-save-library').click(function(e) { | |||||
//var found = false; | |||||
var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,""); | |||||
//var buildPathList = function(data,root) { | |||||
// var paths = []; | |||||
// if (data.d) { | |||||
// for (var i in data.d) { | |||||
// var dn = root+(root==""?"":"/")+i; | |||||
// var d = { | |||||
// label:dn, | |||||
// files:[] | |||||
// }; | |||||
// for (var f in data.d[i].f) { | |||||
// d.files.push(data.d[i].f[f].fn.split("/").slice(-1)[0]); | |||||
// } | |||||
// paths.push(d); | |||||
// paths = paths.concat(buildPathList(data.d[i],root+(root==""?"":"/")+i)); | |||||
// } | |||||
// } | |||||
// return paths; | |||||
//}; | |||||
$("#node-dialog-library-save-folder").attr("value",""); | |||||
//var buildPathList = function(data,root) { | |||||
// var paths = []; | |||||
// if (data.d) { | |||||
// for (var i in data.d) { | |||||
// var dn = root+(root==""?"":"/")+i; | |||||
// var d = { | |||||
// label:dn, | |||||
// files:[] | |||||
// }; | |||||
// for (var f in data.d[i].f) { | |||||
// d.files.push(data.d[i].f[f].fn.split("/").slice(-1)[0]); | |||||
// } | |||||
// paths.push(d); | |||||
// paths = paths.concat(buildPathList(data.d[i],root+(root==""?"":"/")+i)); | |||||
// } | |||||
// } | |||||
// return paths; | |||||
//}; | |||||
$("#node-dialog-library-save-folder").attr("value",""); | |||||
var filename = name.replace(/[^\w-]/g,"-"); | |||||
if (filename === "") { | |||||
filename = "unnamed-"+options.type; | |||||
} | |||||
$("#node-dialog-library-save-filename").attr("value",filename+".js"); | |||||
var filename = name.replace(/[^\w-]/g,"-"); | |||||
if (filename === "") { | |||||
filename = "unnamed-"+options.type; | |||||
} | |||||
$("#node-dialog-library-save-filename").attr("value",filename+".js"); | |||||
//var paths = buildPathList(libraryData,""); | |||||
//$("#node-dialog-library-save-folder").autocomplete({ | |||||
// minLength: 0, | |||||
// source: paths, | |||||
// select: function( event, ui ) { | |||||
// $("#node-dialog-library-save-filename").autocomplete({ | |||||
// minLength: 0, | |||||
// source: ui.item.files | |||||
// }); | |||||
// } | |||||
//}); | |||||
//var paths = buildPathList(libraryData,""); | |||||
//$("#node-dialog-library-save-folder").autocomplete({ | |||||
// minLength: 0, | |||||
// source: paths, | |||||
// select: function( event, ui ) { | |||||
// $("#node-dialog-library-save-filename").autocomplete({ | |||||
// minLength: 0, | |||||
// source: ui.item.files | |||||
// }); | |||||
// } | |||||
//}); | |||||
$( "#node-dialog-library-save" ).dialog( "open" ); | |||||
e.preventDefault(); | |||||
}); | |||||
require(["orion/editor/edit"], function(edit) { | |||||
libraryEditor = edit({ | |||||
parent:document.getElementById('node-select-library-text'), | |||||
lang:"js", | |||||
readonly: true | |||||
}); | |||||
}); | |||||
$( "#node-dialog-library-lookup" ).dialog({ | |||||
title: options.type+" library", | |||||
modal: true, | |||||
autoOpen: false, | |||||
width: 800, | |||||
height: 450, | |||||
buttons: [ | |||||
{ | |||||
text: "Ok", | |||||
click: function() { | |||||
if (selectedLibraryItem) { | |||||
for (var i=0;i<options.fields.length;i++) { | |||||
var field = options.fields[i]; | |||||
$("#node-input-"+field).val(selectedLibraryItem[field]); | |||||
} | |||||
options.editor.setText(libraryEditor.getText()); | |||||
} | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
}, | |||||
{ | |||||
text: "Cancel", | |||||
click: function() { | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
} | |||||
], | |||||
open: function(e) { | |||||
var form = $("form",this); | |||||
form.height(form.parent().height()-30); | |||||
$("#node-select-library-text").height("100%"); | |||||
$(".form-row:last-child",form).children().height(form.height()-60); | |||||
}, | |||||
resize: function(e) { | |||||
var form = $("form",this); | |||||
form.height(form.parent().height()-30); | |||||
$(".form-row:last-child",form).children().height(form.height()-60); | |||||
} | |||||
}); | |||||
function saveToLibrary(overwrite) { | |||||
var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,""); | |||||
if (name === "") { | |||||
name = "Unnamed "+options.type; | |||||
} | |||||
var filename = $("#node-dialog-library-save-filename").val().replace(/(^\s*)|(\s*$)/g,""); | |||||
var pathname = $("#node-dialog-library-save-folder").val().replace(/(^\s*)|(\s*$)/g,""); | |||||
if (filename === "" || !/.+\.js$/.test(filename)) { | |||||
RED.notify("Invalid filename","warning"); | |||||
return; | |||||
} | |||||
var fullpath = pathname+(pathname===""?"":"/")+filename; | |||||
if (!overwrite) { | |||||
//var pathnameParts = pathname.split("/"); | |||||
//var exists = false; | |||||
//var ds = libraryData; | |||||
//for (var pnp in pathnameParts) { | |||||
// if (ds.d && pathnameParts[pnp] in ds.d) { | |||||
// ds = ds.d[pathnameParts[pnp]]; | |||||
// } else { | |||||
// ds = null; | |||||
// break; | |||||
// } | |||||
//} | |||||
//if (ds && ds.f) { | |||||
// for (var f in ds.f) { | |||||
// if (ds.f[f].fn == fullpath) { | |||||
// exists = true; | |||||
// break; | |||||
// } | |||||
// } | |||||
//} | |||||
//if (exists) { | |||||
// $("#node-dialog-library-save-type").html(options.type); | |||||
// $("#node-dialog-library-save-name").html(fullpath); | |||||
// $("#node-dialog-library-save-confirm").dialog( "open" ); | |||||
// return; | |||||
//} | |||||
} | |||||
var queryArgs = []; | |||||
for (var i=0;i<options.fields.length;i++) { | |||||
var field = options.fields[i]; | |||||
if (field == "name") { | |||||
queryArgs.push("name="+encodeURIComponent(name)); | |||||
} else { | |||||
queryArgs.push(encodeURIComponent(field)+"="+encodeURIComponent($("#node-input-"+field).val())); | |||||
} | |||||
} | |||||
var queryString = queryArgs.join("&"); | |||||
var text = options.editor.getText(); | |||||
$.post("library/"+options.url+'/'+fullpath+"?"+queryString,text,function() { | |||||
RED.notify("Saved "+options.type,"success"); | |||||
}); | |||||
} | |||||
$( "#node-dialog-library-save-confirm" ).dialog({ | |||||
title: "Save to library", | |||||
modal: true, | |||||
autoOpen: false, | |||||
width: 530, | |||||
height: 230, | |||||
buttons: [ | |||||
{ | |||||
text: "Ok", | |||||
click: function() { | |||||
saveToLibrary(true); | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
}, | |||||
{ | |||||
text: "Cancel", | |||||
click: function() { | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
} | |||||
] | |||||
}); | |||||
$( "#node-dialog-library-save" ).dialog({ | |||||
title: "Save to library", | |||||
modal: true, | |||||
autoOpen: false, | |||||
width: 530, | |||||
height: 230, | |||||
buttons: [ | |||||
{ | |||||
text: "Ok", | |||||
click: function() { | |||||
saveToLibrary(false); | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
}, | |||||
{ | |||||
text: "Cancel", | |||||
click: function() { | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
} | |||||
] | |||||
}); | |||||
$( "#node-dialog-library-save" ).dialog( "open" ); | |||||
e.preventDefault(); | |||||
}); | |||||
require(["orion/editor/edit"], function(edit) { | |||||
libraryEditor = edit({ | |||||
parent:document.getElementById('node-select-library-text'), | |||||
lang:"js", | |||||
readonly: true | |||||
}); | |||||
}); | |||||
$( "#node-dialog-library-lookup" ).dialog({ | |||||
title: options.type+" library", | |||||
modal: true, | |||||
autoOpen: false, | |||||
width: 800, | |||||
height: 450, | |||||
buttons: [ | |||||
{ | |||||
text: "Ok", | |||||
click: function() { | |||||
if (selectedLibraryItem) { | |||||
for (var i=0;i<options.fields.length;i++) { | |||||
var field = options.fields[i]; | |||||
$("#node-input-"+field).val(selectedLibraryItem[field]); | |||||
} | |||||
options.editor.setText(libraryEditor.getText()); | |||||
} | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
}, | |||||
{ | |||||
text: "Cancel", | |||||
click: function() { | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
} | |||||
], | |||||
open: function(e) { | |||||
var form = $("form",this); | |||||
form.height(form.parent().height()-30); | |||||
$("#node-select-library-text").height("100%"); | |||||
$(".form-row:last-child",form).children().height(form.height()-60); | |||||
}, | |||||
resize: function(e) { | |||||
var form = $("form",this); | |||||
form.height(form.parent().height()-30); | |||||
$(".form-row:last-child",form).children().height(form.height()-60); | |||||
} | |||||
}); | |||||
function saveToLibrary(overwrite) { | |||||
var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,""); | |||||
if (name === "") { | |||||
name = "Unnamed "+options.type; | |||||
} | |||||
var filename = $("#node-dialog-library-save-filename").val().replace(/(^\s*)|(\s*$)/g,""); | |||||
var pathname = $("#node-dialog-library-save-folder").val().replace(/(^\s*)|(\s*$)/g,""); | |||||
if (filename === "" || !/.+\.js$/.test(filename)) { | |||||
RED.notify("Invalid filename","warning"); | |||||
return; | |||||
} | |||||
var fullpath = pathname+(pathname===""?"":"/")+filename; | |||||
if (!overwrite) { | |||||
//var pathnameParts = pathname.split("/"); | |||||
//var exists = false; | |||||
//var ds = libraryData; | |||||
//for (var pnp in pathnameParts) { | |||||
// if (ds.d && pathnameParts[pnp] in ds.d) { | |||||
// ds = ds.d[pathnameParts[pnp]]; | |||||
// } else { | |||||
// ds = null; | |||||
// break; | |||||
// } | |||||
//} | |||||
//if (ds && ds.f) { | |||||
// for (var f in ds.f) { | |||||
// if (ds.f[f].fn == fullpath) { | |||||
// exists = true; | |||||
// break; | |||||
// } | |||||
// } | |||||
//} | |||||
//if (exists) { | |||||
// $("#node-dialog-library-save-type").html(options.type); | |||||
// $("#node-dialog-library-save-name").html(fullpath); | |||||
// $("#node-dialog-library-save-confirm").dialog( "open" ); | |||||
// return; | |||||
//} | |||||
} | |||||
var queryArgs = []; | |||||
for (var i=0;i<options.fields.length;i++) { | |||||
var field = options.fields[i]; | |||||
if (field == "name") { | |||||
queryArgs.push("name="+encodeURIComponent(name)); | |||||
} else { | |||||
queryArgs.push(encodeURIComponent(field)+"="+encodeURIComponent($("#node-input-"+field).val())); | |||||
} | |||||
} | |||||
var queryString = queryArgs.join("&"); | |||||
var text = options.editor.getText(); | |||||
$.post("library/"+options.url+'/'+fullpath+"?"+queryString,text,function() { | |||||
RED.notify("Saved "+options.type,"success"); | |||||
}); | |||||
} | |||||
$( "#node-dialog-library-save-confirm" ).dialog({ | |||||
title: "Save to library", | |||||
modal: true, | |||||
autoOpen: false, | |||||
width: 530, | |||||
height: 230, | |||||
buttons: [ | |||||
{ | |||||
text: "Ok", | |||||
click: function() { | |||||
saveToLibrary(true); | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
}, | |||||
{ | |||||
text: "Cancel", | |||||
click: function() { | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
} | |||||
] | |||||
}); | |||||
$( "#node-dialog-library-save" ).dialog({ | |||||
title: "Save to library", | |||||
modal: true, | |||||
autoOpen: false, | |||||
width: 530, | |||||
height: 230, | |||||
buttons: [ | |||||
{ | |||||
text: "Ok", | |||||
click: function() { | |||||
saveToLibrary(false); | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
}, | |||||
{ | |||||
text: "Cancel", | |||||
click: function() { | |||||
$( this ).dialog( "close" ); | |||||
} | |||||
} | |||||
] | |||||
}); | |||||
} | |||||
return { | |||||
create: createUI, | |||||
loadFlowLibrary: loadFlowLibrary | |||||
} | |||||
} | |||||
return { | |||||
create: createUI, | |||||
loadFlowLibrary: loadFlowLibrary | |||||
} | |||||
})(); | })(); | ||||
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* limitations under the License. | * limitations under the License. | ||||
**/ | **/ | ||||
RED.notify = (function() { | RED.notify = (function() { | ||||
var currentNotifications = []; | |||||
var c = 0; | |||||
return function(msg,type,fixed,timeout) { | |||||
if (currentNotifications.length > 4) { | |||||
var ll = currentNotifications.length; | |||||
for (var i = 0;ll > 4 && i<currentNotifications.length;i+=1) { | |||||
var notifiction = currentNotifications[i]; | |||||
if (!notifiction.fixed) { | |||||
window.clearTimeout(notifiction.timeoutid); | |||||
notifiction.close(); | |||||
ll -= 1; | |||||
} | |||||
} | |||||
} | |||||
var n = document.createElement("div"); | |||||
n.id="red-notification-"+c; | |||||
n.className = "alert"; | |||||
n.fixed = fixed; | |||||
if (type) { | |||||
n.className = "alert alert-"+type; | |||||
} | |||||
n.style.display = "none"; | |||||
n.innerHTML = msg; | |||||
$("#notifications").append(n); | |||||
$(n).slideDown(300); | |||||
n.close = (function() { | |||||
var nn = n; | |||||
return function() { | |||||
currentNotifications.splice(currentNotifications.indexOf(nn),1); | |||||
$(nn).slideUp(300, function() { | |||||
nn.parentNode.removeChild(nn); | |||||
}); | |||||
}; | |||||
})(); | |||||
if (!fixed) { | |||||
n.timeoutid = window.setTimeout(n.close,timeout||3000); | |||||
} | |||||
currentNotifications.push(n); | |||||
c+=1; | |||||
return n; | |||||
} | |||||
var currentNotifications = []; | |||||
var c = 0; | |||||
return function(msg,type,fixed,timeout) { | |||||
if (currentNotifications.length > 4) { | |||||
var ll = currentNotifications.length; | |||||
for (var i = 0;ll > 4 && i<currentNotifications.length;i+=1) { | |||||
var notifiction = currentNotifications[i]; | |||||
if (!notifiction.fixed) { | |||||
window.clearTimeout(notifiction.timeoutid); | |||||
notifiction.close(); | |||||
ll -= 1; | |||||
} | |||||
} | |||||
} | |||||
var n = document.createElement("div"); | |||||
n.id="red-notification-"+c; | |||||
n.className = "alert"; | |||||
n.fixed = fixed; | |||||
if (type) { | |||||
n.className = "alert alert-"+type; | |||||
} | |||||
n.style.display = "none"; | |||||
n.innerHTML = msg; | |||||
$("#notifications").append(n); | |||||
$(n).slideDown(300); | |||||
n.close = (function() { | |||||
var nn = n; | |||||
return function() { | |||||
currentNotifications.splice(currentNotifications.indexOf(nn),1); | |||||
$(nn).slideUp(300, function() { | |||||
nn.parentNode.removeChild(nn); | |||||
}); | |||||
}; | |||||
})(); | |||||
if (!fixed) { | |||||
n.timeoutid = window.setTimeout(n.close,timeout||3000); | |||||
} | |||||
currentNotifications.push(n); | |||||
c+=1; | |||||
return n; | |||||
} | |||||
})(); | })(); | ||||
RED.palette = (function() { | RED.palette = (function() { | ||||
var exclusion = ['config','unknown','deprecated']; | |||||
var core = ['input', 'output', 'mixer', 'play', 'record', 'synth', 'effect', 'filter', 'analyze']; | |||||
function createCategoryContainer(category){ | |||||
var exclusion = ['config','unknown','deprecated']; | |||||
var core = ['input', 'output', 'mixer', 'play', 'record', 'synth', 'effect', 'filter', 'analyze']; | |||||
function createCategoryContainer(category){ | |||||
$("#palette-container").append('<div class="palette-category">'+ | |||||
'<div id="header-'+category+'" class="palette-header"><i class="expanded icon-chevron-down"></i><span>'+category+'</span></div>'+ | |||||
'<div class="palette-content" id="palette-base-category-'+category+'">'+ | |||||
'<div id="palette-'+category+'-input"></div>'+ | |||||
'<div id="palette-'+category+'-output"></div>'+ | |||||
'<div id="palette-'+category+'-function"></div>'+ | |||||
'</div>'+ | |||||
'</div>'); | |||||
} | |||||
core.forEach(createCategoryContainer); | |||||
function addNodeType(nt,def) { | |||||
if ($("#palette_node_"+nt).length) { | |||||
return; | |||||
} | |||||
if (exclusion.indexOf(def.category)===-1) { | |||||
var category = def.category.split("-"); | |||||
var d = document.createElement("div"); | |||||
d.id = "palette_node_"+nt; | |||||
d.type = nt; | |||||
$("#palette-container").append('<div class="palette-category">'+ | |||||
'<div id="header-'+category+'" class="palette-header"><i class="expanded icon-chevron-down"></i><span>'+category+'</span></div>'+ | |||||
'<div class="palette-content" id="palette-base-category-'+category+'">'+ | |||||
'<div id="palette-'+category+'-input"></div>'+ | |||||
'<div id="palette-'+category+'-output"></div>'+ | |||||
'<div id="palette-'+category+'-function"></div>'+ | |||||
'</div>'+ | |||||
'</div>'); | |||||
} | |||||
core.forEach(createCategoryContainer); | |||||
function addNodeType(nt,def) { | |||||
if ($("#palette_node_"+nt).length) { | |||||
return; | |||||
} | |||||
if (exclusion.indexOf(def.category)===-1) { | |||||
var category = def.category.split("-"); | |||||
var d = document.createElement("div"); | |||||
d.id = "palette_node_"+nt; | |||||
d.type = nt; | |||||
//var label = /^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1]; | |||||
var label = (def.shortName) ? def.shortName : nt; | |||||
//var label = /^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1]; | |||||
var label = (def.shortName) ? def.shortName : nt; | |||||
d.innerHTML = '<div class="palette_label">'+label+"</div>"; | |||||
d.className="palette_node"; | |||||
if (def.icon) { | |||||
d.style.backgroundImage = "url(icons/"+def.icon+")"; | |||||
if (def.align == "right") { | |||||
d.style.backgroundPosition = "95% 50%"; | |||||
} else if (def.inputs > 0) { | |||||
d.style.backgroundPosition = "10% 50%"; | |||||
} | |||||
} | |||||
d.style.backgroundColor = def.color; | |||||
if (def.outputs > 0) { | |||||
var portOut = document.createElement("div"); | |||||
portOut.className = "palette_port palette_port_output"; | |||||
d.appendChild(portOut); | |||||
} | |||||
if (def.inputs > 0) { | |||||
var portIn = document.createElement("div"); | |||||
portIn.className = "palette_port"; | |||||
d.appendChild(portIn); | |||||
} | |||||
if ($("#palette-base-category-"+category[0]).length === 0){ | |||||
createCategoryContainer(category[0]); | |||||
} | |||||
if ($("#palette-"+def.category).length === 0) { | |||||
$("#palette-base-category-"+category[0]).append('<div id="palette-'+def.category+'"></div>'); | |||||
} | |||||
$("#palette-"+def.category).append(d); | |||||
d.onmousedown = function(e) { e.preventDefault(); } | |||||
$(d).popover({ | |||||
title:d.type, | |||||
placement:"right", | |||||
trigger: "hover", | |||||
delay: { show: 750, hide: 50 }, | |||||
html: true, | |||||
container:'body', | |||||
content: $(($("script[data-help-name|='"+nt+"']").html()||"<p>no information available</p>").trim())[0] | |||||
}); | |||||
$(d).click(function() { | |||||
var help = '<div class="node-help">'+($("script[data-help-name|='"+d.type+"']").html()||"")+"</div>"; | |||||
$("#tab-info").html(help); | |||||
}); | |||||
$(d).draggable({ | |||||
helper: 'clone', | |||||
appendTo: 'body', | |||||
revert: true, | |||||
revertDuration: 50 | |||||
}); | |||||
$("#header-"+category[0]).off('click').on('click', function(e) { | |||||
$(this).next().slideToggle(); | |||||
$(this).children("i").toggleClass("expanded"); | |||||
}); | |||||
d.innerHTML = '<div class="palette_label">'+label+"</div>"; | |||||
d.className="palette_node"; | |||||
if (def.icon) { | |||||
d.style.backgroundImage = "url(icons/"+def.icon+")"; | |||||
if (def.align == "right") { | |||||
d.style.backgroundPosition = "95% 50%"; | |||||
} else if (def.inputs > 0) { | |||||
d.style.backgroundPosition = "10% 50%"; | |||||
} | |||||
} | |||||
d.style.backgroundColor = def.color; | |||||
if (def.outputs > 0) { | |||||
var portOut = document.createElement("div"); | |||||
portOut.className = "palette_port palette_port_output"; | |||||
d.appendChild(portOut); | |||||
} | |||||
if (def.inputs > 0) { | |||||
var portIn = document.createElement("div"); | |||||
portIn.className = "palette_port"; | |||||
d.appendChild(portIn); | |||||
} | |||||
if ($("#palette-base-category-"+category[0]).length === 0){ | |||||
createCategoryContainer(category[0]); | |||||
} | |||||
if ($("#palette-"+def.category).length === 0) { | |||||
$("#palette-base-category-"+category[0]).append('<div id="palette-'+def.category+'"></div>'); | |||||
} | |||||
$("#palette-"+def.category).append(d); | |||||
d.onmousedown = function(e) { e.preventDefault(); } | |||||
$(d).popover({ | |||||
title:d.type, | |||||
placement:"right", | |||||
trigger: "hover", | |||||
delay: { show: 750, hide: 50 }, | |||||
html: true, | |||||
container:'body', | |||||
content: $(($("script[data-help-name|='"+nt+"']").html()||"<p>no information available</p>").trim())[0] | |||||
}); | |||||
$(d).click(function() { | |||||
var help = '<div class="node-help">'+($("script[data-help-name|='"+d.type+"']").html()||"")+"</div>"; | |||||
$("#tab-info").html(help); | |||||
}); | |||||
$(d).draggable({ | |||||
helper: 'clone', | |||||
appendTo: 'body', | |||||
revert: true, | |||||
revertDuration: 50 | |||||
}); | |||||
$("#header-"+category[0]).off('click').on('click', function(e) { | |||||
$(this).next().slideToggle(); | |||||
$(this).children("i").toggleClass("expanded"); | |||||
}); | |||||
} | |||||
} | |||||
function removeNodeType(type) { | |||||
$("#palette_node_"+type).remove(); | |||||
} | |||||
function filterChange() { | |||||
var val = $("#palette-search-input").val(); | |||||
if (val === "") { | |||||
$("#palette-search-clear").hide(); | |||||
} else { | |||||
$("#palette-search-clear").show(); | |||||
} | |||||
var re = new RegExp(val); | |||||
$(".palette_node").each(function(i,el) { | |||||
if (val === "" || re.test(el.id)) { | |||||
$(this).show(); | |||||
} else { | |||||
$(this).hide(); | |||||
} | |||||
}); | |||||
} | |||||
$("#palette-search-input").focus(function(e) { | |||||
RED.keyboard.disable(); | |||||
}); | |||||
$("#palette-search-input").blur(function(e) { | |||||
RED.keyboard.enable(); | |||||
}); | |||||
$("#palette-search-clear").on("click",function(e) { | |||||
e.preventDefault(); | |||||
$("#palette-search-input").val(""); | |||||
filterChange(); | |||||
$("#palette-search-input").focus(); | |||||
}); | |||||
$("#palette-search-input").val(""); | |||||
$("#palette-search-input").on("keyup",function() { | |||||
filterChange(); | |||||
}); | |||||
} | |||||
} | |||||
function removeNodeType(type) { | |||||
$("#palette_node_"+type).remove(); | |||||
} | |||||
function filterChange() { | |||||
var val = $("#palette-search-input").val(); | |||||
if (val === "") { | |||||
$("#palette-search-clear").hide(); | |||||
} else { | |||||
$("#palette-search-clear").show(); | |||||
} | |||||
var re = new RegExp(val); | |||||
$(".palette_node").each(function(i,el) { | |||||
if (val === "" || re.test(el.id)) { | |||||
$(this).show(); | |||||
} else { | |||||
$(this).hide(); | |||||
} | |||||
}); | |||||
} | |||||
$("#palette-search-input").focus(function(e) { | |||||
RED.keyboard.disable(); | |||||
}); | |||||
$("#palette-search-input").blur(function(e) { | |||||
RED.keyboard.enable(); | |||||
}); | |||||
$("#palette-search-clear").on("click",function(e) { | |||||
e.preventDefault(); | |||||
$("#palette-search-input").val(""); | |||||
filterChange(); | |||||
$("#palette-search-input").focus(); | |||||
}); | |||||
$("#palette-search-input").val(""); | |||||
$("#palette-search-input").on("keyup",function() { | |||||
filterChange(); | |||||
}); | |||||
$("#palette-search-input").on("focus",function() { | |||||
$("body").one("mousedown",function() { | |||||
$("#palette-search-input").blur(); | |||||
}); | |||||
}); | |||||
return { | |||||
add:addNodeType, | |||||
remove:removeNodeType | |||||
}; | |||||
$("#palette-search-input").on("focus",function() { | |||||
$("body").one("mousedown",function() { | |||||
$("#palette-search-input").blur(); | |||||
}); | |||||
}); | |||||
return { | |||||
add:addNodeType, | |||||
remove:removeNodeType | |||||
}; | |||||
})(); | })(); |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
**/ | **/ | ||||
RED.sidebar = (function() { | RED.sidebar = (function() { | ||||
//$('#sidebar').tabs(); | |||||
var sidebar_tabs = RED.tabs.create({ | |||||
id:"sidebar-tabs", | |||||
onchange:function(tab) { | |||||
$("#sidebar-content").children().hide(); | |||||
$("#"+tab.id).show(); | |||||
}, | |||||
onremove: function(tab) { | |||||
$("#"+tab.id).remove(); | |||||
} | |||||
}); | |||||
function addTab(title,content,closeable) { | |||||
$("#sidebar-content").append(content); | |||||
$(content).hide(); | |||||
sidebar_tabs.addTab({id:"tab-"+title,label:title,closeable:closeable}); | |||||
//content.style.position = "absolute"; | |||||
//$('#sidebar').tabs("refresh"); | |||||
} | |||||
$('#btn-sidebar').click(function() {toggleSidebar();}); | |||||
RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){toggleSidebar();d3.event.preventDefault();}); | |||||
//$('#sidebar').tabs(); | |||||
var sidebar_tabs = RED.tabs.create({ | |||||
id:"sidebar-tabs", | |||||
onchange:function(tab) { | |||||
$("#sidebar-content").children().hide(); | |||||
$("#"+tab.id).show(); | |||||
}, | |||||
onremove: function(tab) { | |||||
$("#"+tab.id).remove(); | |||||
} | |||||
}); | |||||
function addTab(title,content,closeable) { | |||||
$("#sidebar-content").append(content); | |||||
$(content).hide(); | |||||
sidebar_tabs.addTab({id:"tab-"+title,label:title,closeable:closeable}); | |||||
//content.style.position = "absolute"; | |||||
//$('#sidebar').tabs("refresh"); | |||||
} | |||||
$('#btn-sidebar').click(function() {toggleSidebar();}); | |||||
RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){toggleSidebar();d3.event.preventDefault();}); | |||||
var sidebarSeparator = {}; | |||||
$("#sidebar-separator").draggable({ | |||||
axis: "x", | |||||
start:function(event,ui) { | |||||
sidebarSeparator.closing = false; | |||||
sidebarSeparator.opening = false; | |||||
var winWidth = $(window).width(); | |||||
sidebarSeparator.start = ui.position.left; | |||||
sidebarSeparator.chartWidth = $("#workspace").width(); | |||||
sidebarSeparator.chartRight = winWidth-$("#workspace").width()-$("#workspace").offset().left-2; | |||||
var sidebarSeparator = {}; | |||||
$("#sidebar-separator").draggable({ | |||||
axis: "x", | |||||
start:function(event,ui) { | |||||
sidebarSeparator.closing = false; | |||||
sidebarSeparator.opening = false; | |||||
var winWidth = $(window).width(); | |||||
sidebarSeparator.start = ui.position.left; | |||||
sidebarSeparator.chartWidth = $("#workspace").width(); | |||||
sidebarSeparator.chartRight = winWidth-$("#workspace").width()-$("#workspace").offset().left-2; | |||||
if (!btnSidebar.hasClass("active")) { | |||||
sidebarSeparator.opening = true; | |||||
var newChartRight = 15; | |||||
$("#sidebar").addClass("closing"); | |||||
$("#workspace").css("right",newChartRight); | |||||
$("#chart-zoom-controls").css("right",newChartRight+20); | |||||
$("#sidebar").width(0); | |||||
toggleSidebar(); | |||||
RED.view.resize(); | |||||
} | |||||
if (!btnSidebar.hasClass("active")) { | |||||
sidebarSeparator.opening = true; | |||||
var newChartRight = 15; | |||||
$("#sidebar").addClass("closing"); | |||||
$("#workspace").css("right",newChartRight); | |||||
$("#chart-zoom-controls").css("right",newChartRight+20); | |||||
$("#sidebar").width(0); | |||||
toggleSidebar(); | |||||
RED.view.resize(); | |||||
} | |||||
sidebarSeparator.width = $("#sidebar").width(); | |||||
}, | |||||
drag: function(event,ui) { | |||||
var d = ui.position.left-sidebarSeparator.start; | |||||
var newSidebarWidth = sidebarSeparator.width-d; | |||||
if (sidebarSeparator.opening) { | |||||
newSidebarWidth -= 13; | |||||
} | |||||
if (newSidebarWidth > 150) { | |||||
if (sidebarSeparator.chartWidth+d < 200) { | |||||
ui.position.left = 200+sidebarSeparator.start-sidebarSeparator.chartWidth; | |||||
d = ui.position.left-sidebarSeparator.start; | |||||
newSidebarWidth = sidebarSeparator.width-d; | |||||
} | |||||
} | |||||
if (newSidebarWidth < 150) { | |||||
if (!sidebarSeparator.closing) { | |||||
$("#sidebar").addClass("closing"); | |||||
sidebarSeparator.closing = true; | |||||
} | |||||
if (!sidebarSeparator.opening) { | |||||
newSidebarWidth = 150; | |||||
ui.position.left = sidebarSeparator.width-(150 - sidebarSeparator.start); | |||||
d = ui.position.left-sidebarSeparator.start; | |||||
} | |||||
} else if (newSidebarWidth > 150 && (sidebarSeparator.closing || sidebarSeparator.opening)) { | |||||
sidebarSeparator.closing = false; | |||||
$("#sidebar").removeClass("closing"); | |||||
} | |||||
sidebarSeparator.width = $("#sidebar").width(); | |||||
}, | |||||
drag: function(event,ui) { | |||||
var d = ui.position.left-sidebarSeparator.start; | |||||
var newSidebarWidth = sidebarSeparator.width-d; | |||||
if (sidebarSeparator.opening) { | |||||
newSidebarWidth -= 13; | |||||
} | |||||
if (newSidebarWidth > 150) { | |||||
if (sidebarSeparator.chartWidth+d < 200) { | |||||
ui.position.left = 200+sidebarSeparator.start-sidebarSeparator.chartWidth; | |||||
d = ui.position.left-sidebarSeparator.start; | |||||
newSidebarWidth = sidebarSeparator.width-d; | |||||
} | |||||
} | |||||
if (newSidebarWidth < 150) { | |||||
if (!sidebarSeparator.closing) { | |||||
$("#sidebar").addClass("closing"); | |||||
sidebarSeparator.closing = true; | |||||
} | |||||
if (!sidebarSeparator.opening) { | |||||
newSidebarWidth = 150; | |||||
ui.position.left = sidebarSeparator.width-(150 - sidebarSeparator.start); | |||||
d = ui.position.left-sidebarSeparator.start; | |||||
} | |||||
} else if (newSidebarWidth > 150 && (sidebarSeparator.closing || sidebarSeparator.opening)) { | |||||
sidebarSeparator.closing = false; | |||||
$("#sidebar").removeClass("closing"); | |||||
} | |||||
var newChartRight = sidebarSeparator.chartRight-d; | |||||
$("#workspace").css("right",newChartRight); | |||||
$("#chart-zoom-controls").css("right",newChartRight+20); | |||||
$("#sidebar").width(newSidebarWidth); | |||||
var newChartRight = sidebarSeparator.chartRight-d; | |||||
$("#workspace").css("right",newChartRight); | |||||
$("#chart-zoom-controls").css("right",newChartRight+20); | |||||
$("#sidebar").width(newSidebarWidth); | |||||
sidebar_tabs.resize(); | |||||
RED.view.resize(); | |||||
}, | |||||
stop:function(event,ui) { | |||||
RED.view.resize(); | |||||
if (sidebarSeparator.closing) { | |||||
$("#sidebar").removeClass("closing"); | |||||
toggleSidebar(); | |||||
if ($("#sidebar").width() < 180) { | |||||
$("#sidebar").width(180); | |||||
$("#workspace").css("right",208); | |||||
$("#chart-zoom-controls").css("right",228); | |||||
} | |||||
} | |||||
$("#sidebar-separator").css("left","auto"); | |||||
$("#sidebar-separator").css("right",($("#sidebar").width()+13)+"px"); | |||||
} | |||||
}); | |||||
var btnSidebar = $("#btn-sidebar"); | |||||
function toggleSidebar() { | |||||
//if ($('#sidebar').tabs( "option", "active" ) === false) { | |||||
// $('#sidebar').tabs( "option", "active",0); | |||||
//} | |||||
btnSidebar.toggleClass("active"); | |||||
if (!btnSidebar.hasClass("active")) { | |||||
$("#main-container").addClass("sidebar-closed"); | |||||
} else { | |||||
$("#main-container").removeClass("sidebar-closed"); | |||||
} | |||||
} | |||||
toggleSidebar(); | |||||
function showSidebar(id) { | |||||
if (!$("#btn-sidebar").hasClass("active")) { | |||||
toggleSidebar(); | |||||
} | |||||
sidebar_tabs.activateTab("tab-"+id); | |||||
} | |||||
function containsTab(id) { | |||||
return sidebar_tabs.contains("tab-"+id); | |||||
} | |||||
return { | |||||
addTab: addTab, | |||||
show: showSidebar, | |||||
containsTab: containsTab | |||||
} | |||||
sidebar_tabs.resize(); | |||||
RED.view.resize(); | |||||
}, | |||||
stop:function(event,ui) { | |||||
RED.view.resize(); | |||||
if (sidebarSeparator.closing) { | |||||
$("#sidebar").removeClass("closing"); | |||||
toggleSidebar(); | |||||
if ($("#sidebar").width() < 180) { | |||||
$("#sidebar").width(180); | |||||
$("#workspace").css("right",208); | |||||
$("#chart-zoom-controls").css("right",228); | |||||
} | |||||
} | |||||
$("#sidebar-separator").css("left","auto"); | |||||
$("#sidebar-separator").css("right",($("#sidebar").width()+13)+"px"); | |||||
} | |||||
}); | |||||
var btnSidebar = $("#btn-sidebar"); | |||||
function toggleSidebar() { | |||||
//if ($('#sidebar').tabs( "option", "active" ) === false) { | |||||
// $('#sidebar').tabs( "option", "active",0); | |||||
//} | |||||
btnSidebar.toggleClass("active"); | |||||
if (!btnSidebar.hasClass("active")) { | |||||
$("#main-container").addClass("sidebar-closed"); | |||||
} else { | |||||
$("#main-container").removeClass("sidebar-closed"); | |||||
} | |||||
} | |||||
toggleSidebar(); | |||||
function showSidebar(id) { | |||||
if (!$("#btn-sidebar").hasClass("active")) { | |||||
toggleSidebar(); | |||||
} | |||||
sidebar_tabs.activateTab("tab-"+id); | |||||
} | |||||
function containsTab(id) { | |||||
return sidebar_tabs.contains("tab-"+id); | |||||
} | |||||
return { | |||||
addTab: addTab, | |||||
show: showSidebar, | |||||
containsTab: containsTab | |||||
} | |||||
})(); | })(); |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* limitations under the License. | * limitations under the License. | ||||
**/ | **/ | ||||
RED.state = { | RED.state = { | ||||
DEFAULT: 0, | |||||
MOVING: 1, | |||||
JOINING: 2, | |||||
MOVING_ACTIVE: 3, | |||||
ADDING: 4, | |||||
EDITING: 5, | |||||
EXPORT: 6, | |||||
IMPORT: 7, | |||||
IMPORT_DRAGGING: 8 | |||||
DEFAULT: 0, | |||||
MOVING: 1, | |||||
JOINING: 2, | |||||
MOVING_ACTIVE: 3, | |||||
ADDING: 4, | |||||
EDITING: 5, | |||||
EXPORT: 6, | |||||
IMPORT: 7, | |||||
IMPORT_DRAGGING: 8 | |||||
} | } |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* limitations under the License. | * limitations under the License. | ||||
**/ | **/ | ||||
RED.sidebar.config = (function() { | RED.sidebar.config = (function() { | ||||
var content = document.createElement("div"); | |||||
content.id = "tab-config"; | |||||
content.style.paddingTop = "4px"; | |||||
content.style.paddingLeft = "4px"; | |||||
content.style.paddingRight = "4px"; | |||||
var list = $("<ul>",{class:"tab-config-list"}).appendTo(content); | |||||
$("#btn-config-nodes").click(function(){ | |||||
if (!RED.sidebar.containsTab("config")) { | |||||
RED.sidebar.addTab("config",content,true); | |||||
} | |||||
refresh(); | |||||
RED.sidebar.show("config"); | |||||
}); | |||||
function refresh() { | |||||
list.empty(); | |||||
RED.nodes.eachConfig(function(node) { | |||||
var li = list.find("#tab-config-list-type-"+node.type); | |||||
if (li.length === 0) { | |||||
li = $("<li>",{id:"tab-config-list-type-"+node.type}).appendTo(list); | |||||
$('<div class="tab-config-list-type">'+node.type+'</div>').appendTo(li); | |||||
} | |||||
var label = ""; | |||||
if (typeof node._def.label == "function") { | |||||
label = node._def.label.call(node); | |||||
} else { | |||||
label = node._def.label; | |||||
} | |||||
label = label || " "; | |||||
var entry = $('<div class="tab-config-list-entry"></div>').appendTo(li); | |||||
entry.on('dblclick',function(e) { | |||||
RED.editor.editConfig("", node.type, node.id); | |||||
}); | |||||
var userArray = node.users.map(function(n) { return n.id }); | |||||
entry.on('mouseover',function(e) { | |||||
RED.nodes.eachNode(function(node) { | |||||
if( userArray.indexOf(node.id) != -1) { | |||||
node.highlighted = true; | |||||
node.dirty = true; | |||||
} | |||||
}); | |||||
RED.view.redraw(); | |||||
}); | |||||
var content = document.createElement("div"); | |||||
content.id = "tab-config"; | |||||
content.style.paddingTop = "4px"; | |||||
content.style.paddingLeft = "4px"; | |||||
content.style.paddingRight = "4px"; | |||||
var list = $("<ul>",{class:"tab-config-list"}).appendTo(content); | |||||
$("#btn-config-nodes").click(function(){ | |||||
if (!RED.sidebar.containsTab("config")) { | |||||
RED.sidebar.addTab("config",content,true); | |||||
} | |||||
refresh(); | |||||
RED.sidebar.show("config"); | |||||
}); | |||||
function refresh() { | |||||
list.empty(); | |||||
RED.nodes.eachConfig(function(node) { | |||||
var li = list.find("#tab-config-list-type-"+node.type); | |||||
if (li.length === 0) { | |||||
li = $("<li>",{id:"tab-config-list-type-"+node.type}).appendTo(list); | |||||
$('<div class="tab-config-list-type">'+node.type+'</div>').appendTo(li); | |||||
} | |||||
var label = ""; | |||||
if (typeof node._def.label == "function") { | |||||
label = node._def.label.call(node); | |||||
} else { | |||||
label = node._def.label; | |||||
} | |||||
label = label || " "; | |||||
var entry = $('<div class="tab-config-list-entry"></div>').appendTo(li); | |||||
entry.on('dblclick',function(e) { | |||||
RED.editor.editConfig("", node.type, node.id); | |||||
}); | |||||
var userArray = node.users.map(function(n) { return n.id }); | |||||
entry.on('mouseover',function(e) { | |||||
RED.nodes.eachNode(function(node) { | |||||
if( userArray.indexOf(node.id) != -1) { | |||||
node.highlighted = true; | |||||
node.dirty = true; | |||||
} | |||||
}); | |||||
RED.view.redraw(); | |||||
}); | |||||
entry.on('mouseout',function(e) { | |||||
RED.nodes.eachNode(function(node) { | |||||
if(node.highlighted) { | |||||
node.highlighted = false; | |||||
node.dirty = true; | |||||
} | |||||
}); | |||||
RED.view.redraw(); | |||||
}); | |||||
$('<div class="tab-config-list-label">'+label+'</div>').appendTo(entry); | |||||
$('<div class="tab-config-list-users">'+node.users.length+'</div>').appendTo(entry); | |||||
}); | |||||
} | |||||
return { | |||||
refresh:refresh | |||||
} | |||||
entry.on('mouseout',function(e) { | |||||
RED.nodes.eachNode(function(node) { | |||||
if(node.highlighted) { | |||||
node.highlighted = false; | |||||
node.dirty = true; | |||||
} | |||||
}); | |||||
RED.view.redraw(); | |||||
}); | |||||
$('<div class="tab-config-list-label">'+label+'</div>').appendTo(entry); | |||||
$('<div class="tab-config-list-users">'+node.users.length+'</div>').appendTo(entry); | |||||
}); | |||||
} | |||||
return { | |||||
refresh:refresh | |||||
} | |||||
})(); | })(); |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* limitations under the License. | * limitations under the License. | ||||
**/ | **/ | ||||
RED.sidebar.info = (function() { | RED.sidebar.info = (function() { | ||||
var content = document.createElement("div"); | |||||
content.id = "tab-info"; | |||||
content.style.paddingTop = "4px"; | |||||
content.style.paddingLeft = "4px"; | |||||
content.style.paddingRight = "4px"; | |||||
var content = document.createElement("div"); | |||||
content.id = "tab-info"; | |||||
content.style.paddingTop = "4px"; | |||||
content.style.paddingLeft = "4px"; | |||||
content.style.paddingRight = "4px"; | |||||
RED.sidebar.addTab("info",content); | |||||
function jsonFilter(key,value) { | |||||
if (key === "") { | |||||
return value; | |||||
} | |||||
var t = typeof value; | |||||
if ($.isArray(value)) { | |||||
return "[array:"+value.length+"]"; | |||||
} else if (t === "object") { | |||||
return "[object]" | |||||
} else if (t === "string") { | |||||
if (value.length > 30) { | |||||
return value.substring(0,30)+" ..."; | |||||
} | |||||
} | |||||
return value; | |||||
} | |||||
function refresh(node) { | |||||
var table = '<table class="node-info"><tbody>'; | |||||
RED.sidebar.addTab("info",content); | |||||
function jsonFilter(key,value) { | |||||
if (key === "") { | |||||
return value; | |||||
} | |||||
var t = typeof value; | |||||
if ($.isArray(value)) { | |||||
return "[array:"+value.length+"]"; | |||||
} else if (t === "object") { | |||||
return "[object]" | |||||
} else if (t === "string") { | |||||
if (value.length > 30) { | |||||
return value.substring(0,30)+" ..."; | |||||
} | |||||
} | |||||
return value; | |||||
} | |||||
function refresh(node) { | |||||
var table = '<table class="node-info"><tbody>'; | |||||
table += "<tr><td>Type</td><td> "+node.type+"</td></tr>"; | |||||
table += "<tr><td>ID</td><td> "+node.id+"</td></tr>"; | |||||
table += '<tr class="blank"><td colspan="2"> Properties</td></tr>'; | |||||
for (var n in node._def.defaults) { | |||||
if (node._def.defaults.hasOwnProperty(n)) { | |||||
var val = node[n]||""; | |||||
var type = typeof val; | |||||
if (type === "string") { | |||||
if (val.length > 30) { | |||||
val = val.substring(0,30)+" ..."; | |||||
} | |||||
val = val.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); | |||||
} else if (type === "number") { | |||||
val = val.toString(); | |||||
} else if ($.isArray(val)) { | |||||
val = "[<br/>"; | |||||
for (var i=0;i<Math.min(node[n].length,10);i++) { | |||||
var vv = JSON.stringify(node[n][i],jsonFilter," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); | |||||
val += " "+i+": "+vv+"<br/>"; | |||||
} | |||||
if (node[n].length > 10) { | |||||
val += " ... "+node[n].length+" items<br/>"; | |||||
} | |||||
val += "]"; | |||||
} else { | |||||
val = JSON.stringify(val,jsonFilter," "); | |||||
val = val.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); | |||||
} | |||||
table += "<tr><td> "+n+"</td><td>"+val+"</td></tr>"; | |||||
} | |||||
} | |||||
table += "</tbody></table><br/>"; | |||||
table += '<div class="node-help">'+($("script[data-help-name|='"+node.type+"']").html()||"")+"</div>"; | |||||
$("#tab-info").html(table); | |||||
} | |||||
return { | |||||
refresh:refresh, | |||||
clear: function() { | |||||
$("#tab-info").html(""); | |||||
} | |||||
} | |||||
table += "<tr><td>Type</td><td> "+node.type+"</td></tr>"; | |||||
table += "<tr><td>ID</td><td> "+node.id+"</td></tr>"; | |||||
table += '<tr class="blank"><td colspan="2"> Properties</td></tr>'; | |||||
for (var n in node._def.defaults) { | |||||
if (node._def.defaults.hasOwnProperty(n)) { | |||||
var val = node[n]||""; | |||||
var type = typeof val; | |||||
if (type === "string") { | |||||
if (val.length > 30) { | |||||
val = val.substring(0,30)+" ..."; | |||||
} | |||||
val = val.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); | |||||
} else if (type === "number") { | |||||
val = val.toString(); | |||||
} else if ($.isArray(val)) { | |||||
val = "[<br/>"; | |||||
for (var i=0;i<Math.min(node[n].length,10);i++) { | |||||
var vv = JSON.stringify(node[n][i],jsonFilter," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); | |||||
val += " "+i+": "+vv+"<br/>"; | |||||
} | |||||
if (node[n].length > 10) { | |||||
val += " ... "+node[n].length+" items<br/>"; | |||||
} | |||||
val += "]"; | |||||
} else { | |||||
val = JSON.stringify(val,jsonFilter," "); | |||||
val = val.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); | |||||
} | |||||
table += "<tr><td> "+n+"</td><td>"+val+"</td></tr>"; | |||||
} | |||||
} | |||||
table += "</tbody></table><br/>"; | |||||
table += '<div class="node-help">'+($("script[data-help-name|='"+node.type+"']").html()||"")+"</div>"; | |||||
$("#tab-info").html(table); | |||||
} | |||||
return { | |||||
refresh:refresh, | |||||
clear: function() { | |||||
$("#tab-info").html(""); | |||||
} | |||||
} | |||||
})(); | })(); |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
RED.tabs = (function() { | RED.tabs = (function() { | ||||
function createTabs(options) { | |||||
var tabs = {}; | |||||
var ul = $("#"+options.id) | |||||
ul.addClass("red-ui-tabs"); | |||||
ul.children().first().addClass("active"); | |||||
ul.children().addClass("red-ui-tab"); | |||||
function onTabClick() { | |||||
activateTab($(this)); | |||||
return false; | |||||
} | |||||
function onTabDblClick() { | |||||
if (options.ondblclick) { | |||||
options.ondblclick(tabs[$(this).attr('href').slice(1)]); | |||||
} | |||||
return false; | |||||
} | |||||
function activateTab(link) { | |||||
if (typeof link === "string") { | |||||
link = ul.find("a[href='#"+link+"']"); | |||||
} | |||||
if (!link.parent().hasClass("active")) { | |||||
ul.children().removeClass("active"); | |||||
link.parent().addClass("active"); | |||||
if (options.onchange) { | |||||
options.onchange(tabs[link.attr('href').slice(1)]); | |||||
} | |||||
} | |||||
} | |||||
function updateTabWidths() { | |||||
var tabs = ul.find("li.red-ui-tab"); | |||||
var width = ul.width(); | |||||
var tabCount = tabs.size(); | |||||
var tabWidth = (width-6-(tabCount*7))/tabCount; | |||||
var pct = 100*tabWidth/width; | |||||
tabs.css({width:pct+"%"}); | |||||
} | |||||
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick); | |||||
updateTabWidths(); | |||||
function removeTab(id) { | |||||
var li = ul.find("a[href='#"+id+"']").parent(); | |||||
if (li.hasClass("active")) { | |||||
var tab = li.prev(); | |||||
if (tab.size() === 0) { | |||||
tab = li.next(); | |||||
} | |||||
activateTab(tab.find("a")); | |||||
} | |||||
li.remove(); | |||||
if (options.onremove) { | |||||
options.onremove(tabs[id]); | |||||
} | |||||
delete tabs[id]; | |||||
updateTabWidths(); | |||||
} | |||||
return { | |||||
addTab: function(tab) { | |||||
tabs[tab.id] = tab; | |||||
var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul); | |||||
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li); | |||||
link.html(tab.label); | |||||
link.on("click",onTabClick); | |||||
link.on("dblclick",onTabDblClick); | |||||
if (tab.closeable) { | |||||
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li); | |||||
closeLink.html('<i class="icon-remove" />'); | |||||
closeLink.on("click",function(event) { | |||||
removeTab(tab.id); | |||||
}); | |||||
} | |||||
updateTabWidths(); | |||||
if (options.onadd) { | |||||
options.onadd(tab); | |||||
} | |||||
link.attr("title",tab.label); | |||||
if (ul.find("li.red-ui-tab").size() == 1) { | |||||
activateTab(link); | |||||
} | |||||
}, | |||||
removeTab: removeTab, | |||||
activateTab: activateTab, | |||||
resize: updateTabWidths, | |||||
count: function() { | |||||
return ul.find("li.red-ui-tab").size(); | |||||
}, | |||||
contains: function(id) { | |||||
return ul.find("a[href='#"+id+"']").length > 0; | |||||
} | |||||
function createTabs(options) { | |||||
var tabs = {}; | |||||
var ul = $("#"+options.id) | |||||
ul.addClass("red-ui-tabs"); | |||||
ul.children().first().addClass("active"); | |||||
ul.children().addClass("red-ui-tab"); | |||||
function onTabClick() { | |||||
activateTab($(this)); | |||||
return false; | |||||
} | |||||
function onTabDblClick() { | |||||
if (options.ondblclick) { | |||||
options.ondblclick(tabs[$(this).attr('href').slice(1)]); | |||||
} | |||||
return false; | |||||
} | |||||
function activateTab(link) { | |||||
if (typeof link === "string") { | |||||
link = ul.find("a[href='#"+link+"']"); | |||||
} | |||||
if (!link.parent().hasClass("active")) { | |||||
ul.children().removeClass("active"); | |||||
link.parent().addClass("active"); | |||||
if (options.onchange) { | |||||
options.onchange(tabs[link.attr('href').slice(1)]); | |||||
} | |||||
} | |||||
} | |||||
function updateTabWidths() { | |||||
var tabs = ul.find("li.red-ui-tab"); | |||||
var width = ul.width(); | |||||
var tabCount = tabs.size(); | |||||
var tabWidth = (width-6-(tabCount*7))/tabCount; | |||||
var pct = 100*tabWidth/width; | |||||
tabs.css({width:pct+"%"}); | |||||
} | |||||
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick); | |||||
updateTabWidths(); | |||||
function removeTab(id) { | |||||
var li = ul.find("a[href='#"+id+"']").parent(); | |||||
if (li.hasClass("active")) { | |||||
var tab = li.prev(); | |||||
if (tab.size() === 0) { | |||||
tab = li.next(); | |||||
} | |||||
activateTab(tab.find("a")); | |||||
} | |||||
li.remove(); | |||||
if (options.onremove) { | |||||
options.onremove(tabs[id]); | |||||
} | |||||
delete tabs[id]; | |||||
updateTabWidths(); | |||||
} | |||||
return { | |||||
addTab: function(tab) { | |||||
tabs[tab.id] = tab; | |||||
var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul); | |||||
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li); | |||||
link.html(tab.label); | |||||
link.on("click",onTabClick); | |||||
link.on("dblclick",onTabDblClick); | |||||
if (tab.closeable) { | |||||
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li); | |||||
closeLink.html('<i class="icon-remove" />'); | |||||
closeLink.on("click",function(event) { | |||||
removeTab(tab.id); | |||||
}); | |||||
} | |||||
updateTabWidths(); | |||||
if (options.onadd) { | |||||
options.onadd(tab); | |||||
} | |||||
link.attr("title",tab.label); | |||||
if (ul.find("li.red-ui-tab").size() == 1) { | |||||
activateTab(link); | |||||
} | |||||
}, | |||||
removeTab: removeTab, | |||||
activateTab: activateTab, | |||||
resize: updateTabWidths, | |||||
count: function() { | |||||
return ul.find("li.red-ui-tab").size(); | |||||
}, | |||||
contains: function(id) { | |||||
return ul.find("a[href='#"+id+"']").length > 0; | |||||
} | |||||
} | |||||
} | |||||
return { | |||||
create: createTabs | |||||
} | |||||
} | |||||
} | |||||
return { | |||||
create: createTabs | |||||
} | |||||
})(); | })(); |
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2014 IBM Corp. | * Copyright 2014 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
RED.touch = RED.touch||{}; | RED.touch = RED.touch||{}; | ||||
RED.touch.radialMenu = (function() { | RED.touch.radialMenu = (function() { | ||||
var touchMenu = null; | |||||
var isActive = false; | |||||
var isOutside = false; | |||||
var activeOption = null; | |||||
var touchMenu = null; | |||||
var isActive = false; | |||||
var isOutside = false; | |||||
var activeOption = null; | |||||
function createRadial(obj,pos,options) { | |||||
isActive = true; | |||||
try { | |||||
var w = $("body").width(); | |||||
var h = $("body").height(); | |||||
touchMenu = d3.select("body").append("div") | |||||
.style({ | |||||
position:"absolute", | |||||
top: 0, | |||||
left:0, | |||||
bottom:0, | |||||
right:0, | |||||
"z-index": 1000 | |||||
}) | |||||
.on('touchstart',function() { | |||||
hide(); | |||||
d3.event.preventDefault(); | |||||
}); | |||||
function createRadial(obj,pos,options) { | |||||
isActive = true; | |||||
try { | |||||
var w = $("body").width(); | |||||
var h = $("body").height(); | |||||
touchMenu = d3.select("body").append("div") | |||||
.style({ | |||||
position:"absolute", | |||||
top: 0, | |||||
left:0, | |||||
bottom:0, | |||||
right:0, | |||||
"z-index": 1000 | |||||
}) | |||||
.on('touchstart',function() { | |||||
hide(); | |||||
d3.event.preventDefault(); | |||||
}); | |||||
var menu = touchMenu.append("div") | |||||
.style({ | |||||
position: "absolute", | |||||
top: (pos[1]-80)+"px", | |||||
left:(pos[0]-80)+"px", | |||||
"border-radius": "80px", | |||||
width: "160px", | |||||
height: "160px", | |||||
background: "rgba(255,255,255,0.6)", | |||||
border: "1px solid #666" | |||||
}); | |||||
var menuOpts = []; | |||||
var createMenuOpt = function(x,y,opt) { | |||||
opt.el = menu.append("div") | |||||
.style({ | |||||
position: "absolute", | |||||
top: (y+80-25)+"px", | |||||
left:(x+80-25)+"px", | |||||
"border-radius": "20px", | |||||
width: "50px", | |||||
height: "50px", | |||||
background: "#fff", | |||||
border: "2px solid #666", | |||||
"text-align": "center", | |||||
"line-height":"50px" | |||||
}); | |||||
if (opt.icon) { | |||||
opt.el.append("i").attr("class","icon "+opt.icon) | |||||
} else { | |||||
opt.el.html(opt.name); | |||||
} | |||||
if (opt.disabled) { | |||||
opt.el.style({"border-color":"#ccc",color:"#ccc"}); | |||||
} | |||||
opt.x = x; | |||||
opt.y = y; | |||||
menuOpts.push(opt); | |||||
opt.el.on('touchstart',function() { | |||||
opt.el.style("background","#999"); | |||||
d3.event.preventDefault(); | |||||
d3.event.stopPropagation(); | |||||
}); | |||||
opt.el.on('touchend',function() { | |||||
hide(); | |||||
opt.onselect(); | |||||
d3.event.preventDefault(); | |||||
d3.event.stopPropagation(); | |||||
}); | |||||
} | |||||
var n = options.length; | |||||
var dang = Math.max(Math.PI/(n-1),Math.PI/4); | |||||
var ang = Math.PI; | |||||
for (var i=0;i<n;i++) { | |||||
var x = Math.floor(Math.cos(ang)*80); | |||||
var y = Math.floor(Math.sin(ang)*80); | |||||
if (options[i].name) { | |||||
createMenuOpt(x,y,options[i]); | |||||
} | |||||
ang += dang; | |||||
} | |||||
var menu = touchMenu.append("div") | |||||
.style({ | |||||
position: "absolute", | |||||
top: (pos[1]-80)+"px", | |||||
left:(pos[0]-80)+"px", | |||||
"border-radius": "80px", | |||||
width: "160px", | |||||
height: "160px", | |||||
background: "rgba(255,255,255,0.6)", | |||||
border: "1px solid #666" | |||||
}); | |||||
var menuOpts = []; | |||||
var createMenuOpt = function(x,y,opt) { | |||||
opt.el = menu.append("div") | |||||
.style({ | |||||
position: "absolute", | |||||
top: (y+80-25)+"px", | |||||
left:(x+80-25)+"px", | |||||
"border-radius": "20px", | |||||
width: "50px", | |||||
height: "50px", | |||||
background: "#fff", | |||||
border: "2px solid #666", | |||||
"text-align": "center", | |||||
"line-height":"50px" | |||||
}); | |||||
if (opt.icon) { | |||||
opt.el.append("i").attr("class","icon "+opt.icon) | |||||
} else { | |||||
opt.el.html(opt.name); | |||||
} | |||||
if (opt.disabled) { | |||||
opt.el.style({"border-color":"#ccc",color:"#ccc"}); | |||||
} | |||||
opt.x = x; | |||||
opt.y = y; | |||||
menuOpts.push(opt); | |||||
opt.el.on('touchstart',function() { | |||||
opt.el.style("background","#999"); | |||||
d3.event.preventDefault(); | |||||
d3.event.stopPropagation(); | |||||
}); | |||||
opt.el.on('touchend',function() { | |||||
hide(); | |||||
opt.onselect(); | |||||
d3.event.preventDefault(); | |||||
d3.event.stopPropagation(); | |||||
}); | |||||
} | |||||
var n = options.length; | |||||
var dang = Math.max(Math.PI/(n-1),Math.PI/4); | |||||
var ang = Math.PI; | |||||
for (var i=0;i<n;i++) { | |||||
var x = Math.floor(Math.cos(ang)*80); | |||||
var y = Math.floor(Math.sin(ang)*80); | |||||
if (options[i].name) { | |||||
createMenuOpt(x,y,options[i]); | |||||
} | |||||
ang += dang; | |||||
} | |||||
var hide = function() { | |||||
isActive = false; | |||||
activeOption = null; | |||||
touchMenu.remove(); | |||||
touchMenu = null; | |||||
} | |||||
obj.on('touchend.radial',function() { | |||||
obj.on('touchend.radial',null); | |||||
obj.on('touchmenu.radial',null); | |||||
if (activeOption) { | |||||
try { | |||||
activeOption.onselect(); | |||||
} catch(err) { | |||||
RED._debug(err); | |||||
} | |||||
hide(); | |||||
} else if (isOutside) { | |||||
hide(); | |||||
} | |||||
}); | |||||
var hide = function() { | |||||
isActive = false; | |||||
activeOption = null; | |||||
touchMenu.remove(); | |||||
touchMenu = null; | |||||
} | |||||
obj.on('touchend.radial',function() { | |||||
obj.on('touchend.radial',null); | |||||
obj.on('touchmenu.radial',null); | |||||
if (activeOption) { | |||||
try { | |||||
activeOption.onselect(); | |||||
} catch(err) { | |||||
RED._debug(err); | |||||
} | |||||
hide(); | |||||
} else if (isOutside) { | |||||
hide(); | |||||
} | |||||
}); | |||||
obj.on('touchmove.radial',function() { | |||||
try { | |||||
var touch0 = d3.event.touches.item(0); | |||||
var p = [touch0.pageX - pos[0],touch0.pageY-pos[1]]; | |||||
for (var i=0;i<menuOpts.length;i++) { | |||||
var opt = menuOpts[i]; | |||||
if (!opt.disabled) { | |||||
if (p[0]>opt.x-30 && p[0]<opt.x+30 && p[1]>opt.y-30 && p[1]<opt.y+30) { | |||||
if (opt !== activeOption) { | |||||
opt.el.style("background","#999"); | |||||
activeOption = opt; | |||||
} | |||||
} else if (opt === activeOption) { | |||||
opt.el.style("background","#fff"); | |||||
activeOption = null; | |||||
} else { | |||||
opt.el.style("background","#fff"); | |||||
} | |||||
} | |||||
} | |||||
if (!activeOption) { | |||||
var d = Math.abs((p[0]*p[0])+(p[1]*p[1])); | |||||
isOutside = (d > 80*80); | |||||
} | |||||
} catch(err) { | |||||
RED._debug(err); | |||||
} | |||||
obj.on('touchmove.radial',function() { | |||||
try { | |||||
var touch0 = d3.event.touches.item(0); | |||||
var p = [touch0.pageX - pos[0],touch0.pageY-pos[1]]; | |||||
for (var i=0;i<menuOpts.length;i++) { | |||||
var opt = menuOpts[i]; | |||||
if (!opt.disabled) { | |||||
if (p[0]>opt.x-30 && p[0]<opt.x+30 && p[1]>opt.y-30 && p[1]<opt.y+30) { | |||||
if (opt !== activeOption) { | |||||
opt.el.style("background","#999"); | |||||
activeOption = opt; | |||||
} | |||||
} else if (opt === activeOption) { | |||||
opt.el.style("background","#fff"); | |||||
activeOption = null; | |||||
} else { | |||||
opt.el.style("background","#fff"); | |||||
} | |||||
} | |||||
} | |||||
if (!activeOption) { | |||||
var d = Math.abs((p[0]*p[0])+(p[1]*p[1])); | |||||
isOutside = (d > 80*80); | |||||
} | |||||
} catch(err) { | |||||
RED._debug(err); | |||||
} | |||||
}); | |||||
} catch(err) { | |||||
RED._debug(err); | |||||
} | |||||
} | |||||
}); | |||||
} catch(err) { | |||||
RED._debug(err); | |||||
} | |||||
} | |||||
return { | |||||
show: createRadial, | |||||
active: function() { | |||||
return isActive; | |||||
} | |||||
} | |||||
return { | |||||
show: createRadial, | |||||
active: function() { | |||||
return isActive; | |||||
} | |||||
} | |||||
})(); | })(); | ||||
/** | |||||
/** Modified from original Node-Red source, for audio system visualization | |||||
* vim: set ts=4: | |||||
* Copyright 2013 IBM Corp. | * Copyright 2013 IBM Corp. | ||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* limitations under the License. | * limitations under the License. | ||||
**/ | **/ | ||||
RED.validators = { | RED.validators = { | ||||
number: function(){return function(v) { return v!=='' && !isNaN(v);}}, | |||||
regex: function(re){return function(v) { return re.test(v);}} | |||||
number: function(){return function(v) { return v!=='' && !isNaN(v);}}, | |||||
regex: function(re){return function(v) { return re.test(v);}} | |||||
}; | }; |