diff --git a/editor/js/ui/clipboard.js b/editor/js/ui/clipboard.js
index 6db81f22e..72d06e2c6 100644
--- a/editor/js/ui/clipboard.js
+++ b/editor/js/ui/clipboard.js
@@ -270,10 +270,44 @@ RED.clipboard = (function() {
$("#dropTarget").hide();
RED.keyboard.remove("escape");
}
-
+ function copyText(value,element,msg) {
+ var truncated = false;
+ if (typeof value !== "string" ) {
+ value = JSON.stringify(value, function(key,value) {
+ if (value !== null && typeof value === 'object') {
+ if (value.__encoded__ && value.hasOwnProperty('data') && value.hasOwnProperty('length')) {
+ truncated = value.data.length !== value.length;
+ return value.data;
+ }
+ }
+ return value;
+ });
+ }
+ if (truncated) {
+ msg += "_truncated";
+ }
+ $("#clipboard-hidden").val(value).select();
+ var result = document.execCommand("copy");
+ if (result && element) {
+ var popover = RED.popover.create({
+ target: element,
+ direction: 'left',
+ size: 'small',
+ content: RED._(msg)
+ });
+ setTimeout(function() {
+ popover.close();
+ },1000);
+ popover.open();
+ }
+ return result;
+ }
return {
init: function() {
setupDialogs();
+
+ $('').appendTo("body");
+
RED.events.on("view:selection-changed",function(selection) {
if (!selection.nodes) {
RED.menu.setDisabled("menu-item-export",true);
@@ -339,6 +373,7 @@ RED.clipboard = (function() {
},
import: importNodes,
- export: exportNodes
+ export: exportNodes,
+ copyText: copyText
}
})();
diff --git a/editor/js/ui/common/popover.js b/editor/js/ui/common/popover.js
index 1ae3b8f45..df586f668 100644
--- a/editor/js/ui/common/popover.js
+++ b/editor/js/ui/common/popover.js
@@ -15,26 +15,61 @@
**/
RED.popover = (function() {
-
-
+ var deltaSizes = {
+ "default": {
+ top: 10,
+ leftRight: 17,
+ leftLeft: 25
+ },
+ "small": {
+ top: 5,
+ leftRight: 8,
+ leftLeft: 16
+ }
+ }
function createPopover(options) {
var target = options.target;
-
+ var direction = options.direction || "right";
+ var trigger = options.trigger;
var content = options.content;
var delay = options.delay;
+ var width = options.width||"auto";
+ var size = options.size||"default";
+ if (!deltaSizes[size]) {
+ throw new Error("Invalid RED.popover size value:",size);
+ }
+
var timer = null;
var active;
var div;
var openPopup = function() {
if (active) {
- div = $('
').html(content).appendTo("body");
+ div = $('').appendTo("body");
+ if (size !== "default") {
+ div.addClass("red-ui-popover-size-"+size);
+ }
+ if (typeof content === 'function') {
+ content.call(res).appendTo(div);
+ } else {
+ div.html(content);
+ }
+ if (width !== "auto") {
+ div.width(width);
+ }
+
+
var targetPos = target.offset();
var targetWidth = target.width();
var targetHeight = target.height();
var divHeight = div.height();
- div.css({top: targetPos.top+targetHeight/2-divHeight/2-10,left:targetPos.left+targetWidth+17});
+ var divWidth = div.width();
+ if (direction === 'right') {
+ div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left+targetWidth+deltaSizes[size].leftRight});
+ } else if (direction === 'left') {
+ div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left-deltaSizes[size].leftLeft-divWidth});
+ }
div.fadeIn("fast");
}
@@ -50,24 +85,45 @@ RED.popover = (function() {
}
}
- target.on('mouseenter',function(e) {
- clearTimeout(timer);
- active = true;
- timer = setTimeout(openPopup,delay.show);
- });
- target.on('mouseleave', function(e) {
- if (timer) {
+ if (trigger === 'hover') {
+
+ target.on('mouseenter',function(e) {
clearTimeout(timer);
- }
- active = false;
- setTimeout(closePopup,delay.hide);
- });
+ active = true;
+ timer = setTimeout(openPopup,delay.show);
+ });
+ target.on('mouseleave', function(e) {
+ if (timer) {
+ clearTimeout(timer);
+ }
+ active = false;
+ setTimeout(closePopup,delay.hide);
+ });
+ } else if (trigger === 'click') {
+ target.click(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ active = !active;
+ if (!active) {
+ closePopup();
+ } else {
+ openPopup();
+ }
+ });
+ }
var res = {
setContent: function(_content) {
content = _content;
+ },
+ open: function () {
+ active = true;
+ openPopup();
+ },
+ close: function () {
+ active = false;
+ closePopup();
}
}
- target.data('popover',res);
return res;
}
diff --git a/editor/js/ui/palette.js b/editor/js/ui/palette.js
index b657b101c..b7c1b58a5 100644
--- a/editor/js/ui/palette.js
+++ b/editor/js/ui/palette.js
@@ -185,11 +185,14 @@ RED.palette = (function() {
$("#palette-"+category).append(d);
d.onmousedown = function(e) { e.preventDefault(); };
- RED.popover.create({
+ var popover = RED.popover.create({
target:$(d),
+ trigger: "hover",
+ width: "300px",
content: "hi",
delay: { show: 750, hide: 50 }
});
+ $(d).data('popover',popover);
// $(d).popover({
// title:d.type,
diff --git a/editor/js/ui/utils.js b/editor/js/ui/utils.js
index 371698ac0..d7c151604 100644
--- a/editor/js/ui/utils.js
+++ b/editor/js/ui/utils.js
@@ -31,7 +31,7 @@ RED.utils = (function() {
result = $('null');
} else if (typeof value === 'object') {
if (value.hasOwnProperty('type') && value.type === 'Buffer' && value.hasOwnProperty('data')) {
- result = $('').html('buffer['+value.data.length+']');
+ result = $('').html('buffer['+value.length+']');
} else if (value.hasOwnProperty('type') && value.type === 'array' && value.hasOwnProperty('data')) {
result = $('').html('array['+value.length+']');
} else {
@@ -66,8 +66,22 @@ RED.utils = (function() {
e.preventDefault();
});
}
+ function addMessageControls(obj,key,msg) {
+ var tools = $('').appendTo(obj);
+ var copyPath = $('').appendTo(tools).click(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ RED.clipboard.copyText(key,copyPath,"clipboard.copyMessagePath");
+ })
+ var copyPayload = $('').appendTo(tools).click(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ RED.clipboard.copyText(msg,copyPayload,"clipboard.copyMessageValue");
+ })
- function buildMessageElement(obj,key,typeHint,hideKey) {
+ }
+
+ function buildMessageElement(obj,key,typeHint,hideKey,path) {
var i;
var e;
var entryObj;
@@ -75,15 +89,15 @@ RED.utils = (function() {
var headerHead;
var value;
var element = $('');
+ header = $('').appendTo(element);
+ addMessageControls(header,path,obj);
if (!key) {
element.addClass("debug-message-top-level");
- }
-
- header = $('').appendTo(element);
-
- if (key && !hideKey) {
- $('').text(key).appendTo(header);
- $(': ').appendTo(header);
+ } else {
+ if (!hideKey) {
+ $('').text(key).appendTo(header);
+ $(': ').appendTo(header);
+ }
}
entryObj = $('').appendTo(header);
@@ -166,6 +180,7 @@ RED.utils = (function() {
if (type === 'buffer') {
var stringRow = $('').appendTo(element);
var sr = $('').appendTo(stringRow);
+
var stringEncoding = "";
try {
stringEncoding = String.fromCharCode.apply(null, new Uint16Array(data))
@@ -190,7 +205,7 @@ RED.utils = (function() {
if (fullLength <= 10) {
for (i=0;i').appendTo(arrayRows);
- buildMessageElement(data[i],""+i,false).appendTo(row);
+ buildMessageElement(data[i],""+i,false,false,path+"["+i+"]").appendTo(row);
}
} else {
for (i=0;i').appendTo(parent);
- buildMessageElement(data[i],""+i,false).appendTo(row);
+ buildMessageElement(data[i],""+i,false,false,path+"["+i+"]").appendTo(row);
}
}
})());
@@ -249,7 +264,13 @@ RED.utils = (function() {
}
for (i=0;i').appendTo(element);
- buildMessageElement(obj[keys[i]],keys[i],false).appendTo(row);
+ var newPath = path;
+ if (/^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(keys[i])) {
+ newPath += "."+keys[i];
+ } else {
+ newPath += "[\""+keys[i].replace(/"/,"\\\"")+"\"]"
+ }
+ buildMessageElement(obj[keys[i]],keys[i],false,false,newPath).appendTo(row);
}
if (keys.length === 0) {
$('').text("empty").appendTo(element);
@@ -405,6 +426,6 @@ RED.utils = (function() {
createObjectElement: buildMessageElement,
validatePropertyExpression: validatePropertyExpression,
getNodeIcon: getNodeIcon,
- getNodeLabel: getNodeLabel
+ getNodeLabel: getNodeLabel,
}
})();
diff --git a/editor/sass/debug.scss b/editor/sass/debug.scss
index 0834c1e00..b211d77f3 100644
--- a/editor/sass/debug.scss
+++ b/editor/sass/debug.scss
@@ -46,11 +46,31 @@
}
.debug-message {
+ position: relative;
border-bottom: 1px solid #eee;
border-left: 8px solid #eee;
border-right: 8px solid #eee;
padding: 2px;
+ &.debug-message-hover {
+ border-right-color: #999;
+ &>.debug-message-meta .debug-message-tools {
+ display: inline-block;
+ }
+ }
}
+.debug-message-row .debug-message-tools .editor-button-small {
+ height: 16px;
+ line-height: 14px;
+ font-size: 8px;
+ border-radius: 1px;
+ padding: 0 3px;
+}
+.debug-message-row:hover {
+ &>.debug-message-tools {
+ display: inline-block;
+ }
+}
+
.debug-message-meta {
background: #fff;
font-size: 10px;
@@ -67,6 +87,12 @@
padding: 1px 5px;
color: #777;
}
+.debug-message-tools {
+ position: absolute;
+ top: 3px;
+ right: 1px;
+ display: none;
+}
.debug-message-payload {
display: block;
padding: 2px;
@@ -85,9 +111,8 @@
border-right-color: #f99;
}
.debug-message-object-entry {
+ position: relative;
padding-left: 15px;
- padding-bottom: 3px;
- padding-top: 3px;
}
.debug-message-element {
color: #333;
@@ -153,12 +178,17 @@
.debug-message-type-number { color: #2033d6; };
.debug-message-type-number-toggle { cursor: pointer;}
+.debug-message-row {
+ display: block;
+ padding: 4px 2px 2px;
+ position: relative;
+ &:hover {
+ background: #f3f3f3;
+ }
+}
.debug-message-expandable {
cursor: pointer;
}
-.debug-message-expandable:hover {
- background: #fefefe;
-}
.debug-message-expandable:hover .debug-message-object-handle {
color: #b72828 !important;
}
diff --git a/editor/sass/editor.scss b/editor/sass/editor.scss
index 261ca83ba..406fda74a 100644
--- a/editor/sass/editor.scss
+++ b/editor/sass/editor.scss
@@ -292,3 +292,8 @@
border-color: $primary-border-color;
}
}
+
+#clipboard-hidden {
+ position: absolute;
+ top: -3000px;
+}
diff --git a/editor/sass/popover.scss b/editor/sass/popover.scss
index 3a00dd4a3..d3c077e6d 100644
--- a/editor/sass/popover.scss
+++ b/editor/sass/popover.scss
@@ -15,39 +15,82 @@
**/
- .red-ui-popover {
- display: none;
- position: absolute;
- width: 300px;
- padding: 10px;
- height: auto;
- background: #fff;
-
- z-index: 1000;
- font-size: 14px;
- line-height: 1.4em;
- @include component-shadow;
- }
- .red-ui-popover:after, .red-ui-popover:before {
- right: 100%;
- top: 50%;
- border: solid transparent;
- content: " ";
- height: 0;
- width: 0;
- position: absolute;
- pointer-events: none;
- }
+.red-ui-popover {
+ display: none;
+ position: absolute;
+ width: auto;
+ padding: 10px;
+ height: auto;
+ background: #fff;
- .red-ui-popover:after {
- border-color: rgba(136, 183, 213, 0);
- border-right-color: #fff;
- border-width: 10px;
- margin-top: -10px;
- }
- .red-ui-popover:before {
- border-color: rgba(194, 225, 245, 0);
- border-right-color: $primary-border-color;
- border-width: 11px;
- margin-top: -11px;
- }
+ z-index: 1000;
+ font-size: 14px;
+ line-height: 1.4em;
+ @include component-shadow;
+}
+
+.red-ui-popover:after, .red-ui-popover:before {
+ top: 50%;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+}
+.red-ui-popover.red-ui-popover-right:after, .red-ui-popover.red-ui-popover-right:before {
+ right: 100%;
+}
+.red-ui-popover.red-ui-popover-left:after, .red-ui-popover.red-ui-popover-left:before {
+ left: 100%;
+}
+
+
+.red-ui-popover.red-ui-popover-right:after {
+ border-color: rgba(136, 183, 213, 0);
+ border-right-color: #fff;
+ border-width: 10px;
+ margin-top: -10px;
+}
+.red-ui-popover.red-ui-popover-right:before {
+ border-color: rgba(194, 225, 245, 0);
+ border-right-color: $primary-border-color;
+ border-width: 11px;
+ margin-top: -11px;
+}
+
+.red-ui-popover.red-ui-popover-left:after {
+ border-color: rgba(136, 183, 213, 0);
+ border-left-color: #fff;
+ border-width: 10px;
+ margin-top: -10px;
+}
+.red-ui-popover.red-ui-popover-left:before {
+ border-color: rgba(194, 225, 245, 0);
+ border-left-color: $primary-border-color;
+ border-width: 11px;
+ margin-top: -11px;
+}
+
+.red-ui-popover-size-small {
+ font-size: 11px;
+ padding: 5px;
+
+ &.red-ui-popover-right:after {
+ border-width: 5px;
+ margin-top: -5px;
+ }
+ &.red-ui-popover-right:before {
+ border-width: 6px;
+ margin-top: -6px;
+ }
+
+ &.red-ui-popover-left:after {
+ border-width: 5px;
+ margin-top: -5px;
+ }
+ &.red-ui-popover-left:before {
+ border-width: 6px;
+ margin-top: -6px;
+ }
+}
diff --git a/nodes/core/core/58-debug.js b/nodes/core/core/58-debug.js
index a49506d97..2a6958d14 100644
--- a/nodes/core/core/58-debug.js
+++ b/nodes/core/core/58-debug.js
@@ -90,10 +90,9 @@ module.exports = function(RED) {
msg.msg = msg.msg.toString('hex');
if (msg.msg.length > debuglength) {
msg.msg = msg.msg.substring(0,debuglength);
+ msg.modified = true;
}
} else if (msg.msg && typeof msg.msg === 'object') {
- var seen = [];
- var seenAts = [];
try {
msg.format = msg.msg.constructor.name || "Object";
// Handle special case of msg.req/res objects from HTTP In node
@@ -113,38 +112,54 @@ module.exports = function(RED) {
if (isArray) {
msg.format = "array["+msg.msg.length+"]";
if (msg.msg.length > debuglength) {
- msg.msg = msg.msg.slice(0,debuglength);
+ // msg.msg = msg.msg.slice(0,debuglength);
+ msg.msg = {
+ __encoded__: true,
+ type: "array",
+ data: msg.msg.slice(0,debuglength),
+ length: msg.msg.length
+ }
+ msg.modified = true;
}
}
if (isArray || (msg.format === "Object")) {
+ var modified = false;
msg.msg = safeJSONStringify(msg.msg, function(key, value) {
if (key === '_req' || key === '_res') {
- return "[internal]"
- }
- if (value instanceof Error) {
- return value.toString()
- }
- if (util.isArray(value) && value.length > debuglength) {
+ value = "[internal]"
+ } else if (value instanceof Error) {
+ value = value.toString()
+ } else if (util.isArray(value) && value.length > debuglength) {
value = {
__encoded__: true,
type: "array",
data: value.slice(0,debuglength),
length: value.length
}
- }
- if (typeof value === 'string') {
+ modified = true;
+ } else if (typeof value === 'string') {
if (value.length > debuglength) {
- return value.substring(0,debuglength)+"...";
+ modified = true;
+ value = value.substring(0,debuglength)+"...";
+ }
+ } else if (value !== null && typeof value === 'object' && value.type === "Buffer") {
+ value.__encoded__ = true;
+ value.length = value.data.length;
+ if (value.length > debuglength) {
+ value.data = value.data.slice(0,debuglength);
+ modified = true;
}
}
return value;
}," ");
+ if (modified) {
+ msg.modified = modified;
+ }
} else {
try { msg.msg = msg.msg.toString(); }
catch(e) { msg.msg = "[Type not printable]"; }
}
}
- seen = null;
} else if (typeof msg.msg === "boolean") {
msg.format = "boolean";
msg.msg = msg.msg.toString();
@@ -161,6 +176,7 @@ module.exports = function(RED) {
msg.format = "string["+msg.msg.length+"]";
if (msg.msg.length > debuglength) {
msg.msg = msg.msg.substring(0,debuglength)+"...";
+ msg.modified = true;
}
}
// if (msg.msg.length > debuglength) {
diff --git a/nodes/core/core/lib/debug/debug-utils.js b/nodes/core/core/lib/debug/debug-utils.js
index 9c9f48661..0b6f384bf 100644
--- a/nodes/core/core/lib/debug/debug-utils.js
+++ b/nodes/core/core/lib/debug/debug-utils.js
@@ -184,13 +184,13 @@ RED.debug = (function() {
var sourceNode = o._source;
msg.onmouseenter = function() {
- msg.style.borderRightColor = "#999";
+ $(msg).addClass('debug-message-hover');
if (o._source) {
config.messageMouseEnter(o._source.id);
}
};
msg.onmouseleave = function() {
- msg.style.borderRightColor = "";
+ $(msg).removeClass('debug-message-hover');
if (o._source) {
config.messageMouseLeave(o._source.id);
}
@@ -225,6 +225,9 @@ RED.debug = (function() {
$(msg).addClass('debug-message-level-' + errorLvl);
$('function : (' + errorLvlType + ')').appendTo(metaRow);
} else {
+ // var tools = $('').appendTo(metaRow);
+ // var filterMessage = $('').appendTo(tools);
+
$(''+
(o.topic?topic+' : ':'')+
(o.property?'msg.'+property:'msg')+" : "+format+
@@ -247,7 +250,8 @@ RED.debug = (function() {
}
}
var el = $('').appendTo(msg);
- RED.utils.createObjectElement(payload,/*true*/null,format).appendTo(el);
+ var path = (o.property?'msg.'+property:'msg');
+ RED.utils.createObjectElement(payload,/*true*/null,format,false,path).appendTo(el);
var atBottom = (sbc.scrollHeight-messageList.height()-sbc.scrollTop) < 5;
var m = {
el: msg
diff --git a/red/api/locales/en-US/editor.json b/red/api/locales/en-US/editor.json
index 023735b66..a0788cd28 100644
--- a/red/api/locales/en-US/editor.json
+++ b/red/api/locales/en-US/editor.json
@@ -112,7 +112,10 @@
"import": {
"import": "Import to",
"newFlow": "new flow"
- }
+ },
+ "copyMessagePath": "Path copied",
+ "copyMessageValue": "Value copied",
+ "copyMessageValue_truncated": "Truncated value copied"
},
"deploy": {
"deploy": "Deploy",