diff --git a/editor/js/ui/keyboard.js b/editor/js/ui/keyboard.js
index a7f815b0f..3316426ae 100644
--- a/editor/js/ui/keyboard.js
+++ b/editor/js/ui/keyboard.js
@@ -15,6 +15,8 @@
**/
RED.keyboard = (function() {
+ var isMac = /Mac/i.test(window.navigator.platform);
+
var handlers = {};
var partialState;
@@ -253,7 +255,6 @@ RED.keyboard = (function() {
var dialog = null;
- var isMac = /Mac/i.test(window.navigator.platform);
var cmdCtrlKey = ''+(isMac?'⌘':'Ctrl')+'';
function showKeyboardHelp() {
@@ -281,7 +282,7 @@ RED.keyboard = (function() {
'
'+cmdCtrlKey+' + f | '+RED._("keyboard.searchBox")+' |
'+
''+cmdCtrlKey+' + Shift + p | '+RED._("keyboard.managePalette")+' |
'+
' | |
'+
- '← ↑ → ↓ | '+RED._("keyboard.nudgeNode")+' |
'+
+ '← ↑ → ↓ | '+RED._("keyboard.nudgeNode")+' |
'+
'Shift + ← ↑ → ↓ | '+RED._("keyboard.moveNode")+' |
'+
' | |
'+
''+cmdCtrlKey+' + c | '+RED._("keyboard.copyNode")+' |
'+
@@ -303,6 +304,15 @@ RED.keyboard = (function() {
dialog.dialog("open");
}
+ function formatKey(key) {
+ var formattedKey = isMac?key.replace(/ctrl-?/,"⌘"):key;
+ formattedKey = formattedKey.replace(/shift-?/,"⇧")
+ formattedKey = formattedKey.replace(/left/,"←")
+ formattedKey = formattedKey.replace(/up/,"↑")
+ formattedKey = formattedKey.replace(/right/,"→")
+ formattedKey = formattedKey.replace(/down/,"↓")
+ return ''+formattedKey.split(" ").join(' ')+'';
+ }
return {
init: init,
@@ -310,7 +320,8 @@ RED.keyboard = (function() {
remove: removeHandler,
getShortcut: function(actionName) {
return actionToKeyMap[actionName];
- }
+ },
+ formatKey: formatKey
}
})();
diff --git a/editor/js/ui/tab-info.js b/editor/js/ui/tab-info.js
index 33216dd22..cf22367b6 100644
--- a/editor/js/ui/tab-info.js
+++ b/editor/js/ui/tab-info.js
@@ -67,6 +67,7 @@ RED.sidebar.info = (function() {
}
function refresh(node) {
+ tips.stop();
$(content).empty();
var table = $('');
var tableBody = $('').appendTo(table);
@@ -145,20 +146,76 @@ RED.sidebar.info = (function() {
});
}
- var infotimeout;
- function clear() {
- //$(content).html("");
- if (!infotimeout) {
- var r = parseInt(Math.random() * RED._("infotips:infoLength"));
- $(content).html(''+RED._("infotips:info.tip"+r)+'
');
- infotimeout = setTimeout(function() { infotimeout=null; }, 20000);
+
+ var tips = (function() {
+ var startDelay = 2000;
+ var cycleDelay = 10000;
+ var startTimeout;
+ var refreshTimeout;
+ var tipCount = -1;
+
+
+ function setTip() {
+
+ var r = Math.floor(Math.random() * tipCount);
+ var tip = RED._("infotips:info.tip"+r);
+
+ var m;
+ while ((m=/({{(.*?)}})/.exec(tip))) {
+ var shortcut = RED.keyboard.getShortcut(m[2]);
+ if (shortcut) {
+ tip = tip.replace(m[1],RED.keyboard.formatKey(shortcut.key));
+ } else {
+ return;
+ }
+ }
+ while ((m=/(\[(.*?)\])/.exec(tip))) {
+ tip = tip.replace(m[1],RED.keyboard.formatKey(m[2]));
+ }
+ $(''+tip+'
').appendTo(content).fadeIn(200);
+ if (startTimeout) {
+ startTimeout = null;
+ refreshTimeout = setInterval(cycleTips,cycleDelay);
+ }
}
+ function cycleTips() {
+ $(".node-info-tip").fadeOut(300,function() {
+ $(this).remove();
+ setTip();
+ })
+ }
+ return {
+ start: function() {
+ if (!startTimeout && !refreshTimeout) {
+ $(content).html("");
+ if (tipCount === -1) {
+ do {
+ tipCount++;
+ } while(RED._("infotips:info.tip"+tipCount)!=="infotips:info.tip"+tipCount);
+ }
+ startTimeout = setTimeout(setTip,startDelay);
+ }
+ },
+ stop: function() {
+ clearInterval(refreshTimeout);
+ clearTimeout(startTimeout);
+ refreshTimeout = null;
+ startTimeout = null;
+ }
+ }
+ })();
+
+ function clear() {
+ tips.start();
}
function set(html) {
+ tips.stop();
$(content).html(html);
}
+
+
RED.events.on("view:selection-changed",function(selection) {
if (selection.nodes) {
if (selection.nodes.length == 1) {
diff --git a/editor/sass/keyboard.scss b/editor/sass/keyboard.scss
index 6c05e5046..e355223f6 100644
--- a/editor/sass/keyboard.scss
+++ b/editor/sass/keyboard.scss
@@ -37,4 +37,6 @@
font-family: Courier, monospace;
box-shadow: #999 1px 1px 1px;
}
-
+.help-key-block {
+ white-space: nowrap;
+}
diff --git a/editor/sass/tab-info.scss b/editor/sass/tab-info.scss
index c7cf8e27e..eda9098c3 100644
--- a/editor/sass/tab-info.scss
+++ b/editor/sass/tab-info.scss
@@ -82,20 +82,17 @@ div.node-info {
}
}
.node-info-tip {
- margin: 10px;
- margin-top: 30px;
- border-radius: 6px;
- padding: 12px;
- font-size: 18px;
+ position: absolute;
+ top: 40%;
+ left:0;
+ right:0;
+ padding: 20px;
+ font-size: 16px;
text-align: center;
- color : #aaa;
+ line-height: 1.9em;
+ color : #bbb;
background-color: #fff;
- code {
- font-size: 16px;
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-weight: 700;
- padding: 3px 8px 3px 8px;
- border-radius: 4px;
- color: #aaa;
- }
+ @include disable-selection;
+ cursor: default;
+
}
diff --git a/red/api/locales/en-US/infotips.json b/red/api/locales/en-US/infotips.json
index cc7f68826..ca4fdf630 100644
--- a/red/api/locales/en-US/infotips.json
+++ b/red/api/locales/en-US/infotips.json
@@ -1,16 +1,32 @@
{
"info": {
- "tip0" : "Use the delete
key to remove a node.",
+ "tip0" : "You can remove the selected nodes or links with {{core:delete}}",
+ "tip1" : "Search for nodes using {{core:search}}",
+ "tip2" : "{{core:toggle-sidebar}} will toggle the view of this sidebar",
+ "tip3" : "You can manage your palette of nodes with {{core:manage-palette}}",
+ "tip4" : "Your flow configuration nodes are listed in the sidebar panel. It can been accessed from the menu or with {{core:show-config-tab}}",
+ "tip5" : "Enable or disable these tips from the option in the menu",
+ "tip6" : "Move the selected nodes using the [left] [up] [down] and [right] keys. Hold [shift] to nudge them further",
+ "tip7" : "Dragging a node onto a wire will splice it into the link",
+ "tip8" : "Export the selected nodes, or the current tab with {{core:export}}",
+ "tip9" : "Import a flow by dragging its JSON into the editor, or with {{core:import}}",
+ "tip10" : "[shift] [click] and drag on a node port to move all of the attached wires or just the selected one",
+ "tip11" : "Show the Info tab with {{core:show-info-tab}} or the Debug tab with {{core:show-debug-tab}}",
+ "tip12" : "[ctrl] [click] in the workspace to open the quick-add dialog",
+ "tip13" : "Hold down [ctrl] when you [click] on a node port to enable quick-wiring",
+ "tip14" : "Hold down [shift] when you [click] on a node to also select all of its connected nodes",
+ "tip15" : "Hold down [ctrl] when you [click] on a node to add or remove it from the current selection",
+ "tip16" : "Switch flow tabs with {{core:show-previous-tab}} and {{core:show-next-tab}}",
+ "tip17" : "You can confirm your changes in the node edit tray with {{core:confirm-edit-tray}} or cancel them with {{core:cancel-edit-tray}}"
+ },
+ "info-tbd": {
"tip1" : "Press the Deploy
button above to start the flow running. You can choose to deploy the whole flow or just the changes.",
"tip2" : "Options like Show grid and Snap to grid are under the menu icon
View",
- "tip3" : "ctrl .
or ⌘ .
can be used to search for nodes and tabs.",
"tip4" : " Manage palette can be used to find, add and remove extra nodes.",
"tip5" : "Nodes may install examples under
Import Examples",
"tip6" : "Lots of example flows can be found on flows.nodered.org
They can then be imported by drag and drop to the workspace.",
"tip7" : "Shift-click and drag on a connector to move all the attached wires in one go.",
"tip8" : "The Node-RED Dashboard package can be used to create simple User Interfaces.",
- "tip9" : "ctrl
space
will toggle the view of this sidebar.",
"tip10": "Got a question?
Join us on Slack
or the
Node-RED Google group"
- },
- "infoLength": "11"
+ }
}
diff --git a/red/runtime/i18n.js b/red/runtime/i18n.js
index 0d45b71e4..f555cb5fa 100644
--- a/red/runtime/i18n.js
+++ b/red/runtime/i18n.js
@@ -24,6 +24,13 @@ var defaultLang = "en-US";
var resourceMap = {};
var resourceCache = {};
+function registerMessageCatalogs(catalogs) {
+ var promises = catalogs.map(function(catalog) {
+ return registerMessageCatalog(catalog.namespace,catalog.dir,catalog.file);
+ });
+ return when.settle(promises);
+}
+
function registerMessageCatalog(namespace,dir,file) {
return when.promise(function(resolve,reject) {
resourceMap[namespace] = { basedir:dir, file:file};
@@ -109,6 +116,7 @@ function getCatalog(namespace,lang) {
var obj = module.exports = {
init: init,
registerMessageCatalog: registerMessageCatalog,
+ registerMessageCatalogs: registerMessageCatalogs,
catalog: getCatalog,
i: i18n,
defaultLang: defaultLang