| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2014 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -15,65 +16,65 @@ | |||
| **/ | |||
| 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 | |||
| } | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -14,72 +15,72 @@ | |||
| * limitations under the License. | |||
| **/ | |||
| 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(); | |||
| } | |||
| } | |||
| } | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -15,233 +16,234 @@ | |||
| **/ | |||
| 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"); | |||
| $.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 { | |||
| }; | |||
| })(); | |||
| @@ -16,43 +16,43 @@ | |||
| **/ | |||
| 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); | |||
| console.log("getID = " + str); | |||
| return str; | |||
| } | |||
| } | |||
| 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); | |||
| 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; | |||
| } | |||
| function createUniqueCppName(n) { | |||
| function createUniqueCppName(n) { | |||
| 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/, ""); | |||
| console.log("getUniqueCppName, using basename=" + basename); | |||
| @@ -66,423 +66,423 @@ RED.nodes = (function() { | |||
| } | |||
| console.log("getUniqueCppName, unique name=" + 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 | |||
| }; | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -15,54 +16,54 @@ | |||
| **/ | |||
| 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; } | |||
| } | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -14,354 +15,354 @@ | |||
| * limitations under the License. | |||
| **/ | |||
| 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 | |||
| } | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -14,46 +15,46 @@ | |||
| * limitations under the License. | |||
| **/ | |||
| 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; | |||
| } | |||
| })(); | |||
| @@ -17,154 +17,154 @@ | |||
| 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 | |||
| }; | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -15,139 +16,139 @@ | |||
| **/ | |||
| 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 | |||
| } | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -14,13 +15,13 @@ | |||
| * limitations under the License. | |||
| **/ | |||
| 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 | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -14,70 +15,70 @@ | |||
| * limitations under the License. | |||
| **/ | |||
| 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 | |||
| } | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -14,76 +15,76 @@ | |||
| * limitations under the License. | |||
| **/ | |||
| 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(""); | |||
| } | |||
| } | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -17,111 +18,111 @@ | |||
| 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 | |||
| } | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2014 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -16,171 +17,171 @@ | |||
| RED.touch = RED.touch||{}; | |||
| 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; | |||
| } | |||
| } | |||
| })(); | |||
| @@ -1,4 +1,5 @@ | |||
| /** | |||
| /** Modified from original Node-Red source, for audio system visualization | |||
| * vim: set ts=4: | |||
| * Copyright 2013 IBM Corp. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| @@ -14,6 +15,6 @@ | |||
| * limitations under the License. | |||
| **/ | |||
| 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);}} | |||
| }; | |||