/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ RED.sidebar.info = (function() { marked.setOptions({ renderer: new marked.Renderer(), gfm: true, tables: true, breaks: false, pedantic: false, sanitize: true, smartLists: true, smartypants: false }); var content; var sections; var propertiesSection; var infoSection; var helpSection; var tipBox; var expandedSections = { "property": false }; function init() { content = document.createElement("div"); content.className = "red-ui-sidebar-info" RED.actions.add("core:show-info-tab",show); var stackContainer = $("
",{class:"red-ui-sidebar-info-stack"}).appendTo(content); sections = RED.stack.create({ container: stackContainer }).hide(); propertiesSection = sections.add({ title: RED._("sidebar.info.info"), collapsible: true }); propertiesSection.expand(); infoSection = sections.add({ title: RED._("sidebar.info.desc"), collapsible: true }); infoSection.expand(); infoSection.content.css("padding","6px"); helpSection = sections.add({ title: RED._("sidebar.info.nodeHelp"), collapsible: true }); helpSection.expand(); helpSection.content.css("padding","6px"); var tipContainer = $('
').appendTo(content); tipBox = $('
').appendTo(tipContainer); var tipButtons = $('
').appendTo(tipContainer); var tipRefresh = $('').appendTo(tipButtons); tipRefresh.on("click", function(e) { e.preventDefault(); tips.next(); }) var tipClose = $('').appendTo(tipButtons); tipClose.on("click", function(e) { e.preventDefault(); RED.actions.invoke("core:toggle-show-tips"); RED.notify(RED._("sidebar.info.showTips")); }); RED.sidebar.addTab({ id: "info", label: RED._("sidebar.info.label"), name: RED._("sidebar.info.name"), iconClass: "fa fa-info", action:"core:show-info-tab", content: content, pinned: true, enableOnEdit: true }); if (tips.enabled()) { tips.start(); } else { tips.stop(); } } function show() { RED.sidebar.show("info"); } // TODO: DRY - projects.js function addTargetToExternalLinks(el) { $(el).find("a").each(function(el) { var href = $(this).attr('href'); if (/^https?:/.test(href)) { $(this).attr('target','_blank'); } }); return el; } function refresh(node) { if (node === undefined) { refreshSelection(); return; } sections.show(); $(propertiesSection.content).empty(); $(infoSection.content).empty(); $(helpSection.content).empty(); infoSection.title.text(RED._("sidebar.info.desc")); var propRow; var table = $('
').appendTo(propertiesSection.content); var tableBody = $('').appendTo(table); var subflowNode; var subflowUserCount; var activeProject = RED.projects.getActiveProject(); if (activeProject) { propRow = $(''+ RED._("sidebar.project.name") + '').appendTo(tableBody); $(propRow.children()[1]).text(activeProject.name||""); $('').appendTo(tableBody); var editProjectButton = $('') .appendTo(propRow.children()[1]) .on("click", function(evt) { evt.preventDefault(); RED.projects.editProject(); }); RED.popover.tooltip(editProjectButton,RED._('sidebar.project.showProjectSettings')); } propertiesSection.container.show(); infoSection.container.show(); helpSection.container.show(); if (node === null) { return; } else if (Array.isArray(node)) { // Multiple things selected // - hide help and info sections var types = { nodes:0, flows:0, subflows:0 } node.forEach(function(n) { if (n.type === 'tab') { types.flows++; types.nodes += RED.nodes.filterNodes({z:n.id}).length; } else if (n.type === 'subflow') { types.subflows++; } else { types.nodes++; } }); helpSection.container.hide(); infoSection.container.hide(); // - show the count of selected nodes propRow = $(''+RED._("sidebar.info.selection")+"").appendTo(tableBody); var counts = $('
').appendTo($(propRow.children()[1])); if (types.flows > 0) { $('
').text(RED._("clipboard.flow",{count:types.flows})).appendTo(counts); } if (types.subflows > 0) { $('
').text(RED._("clipboard.subflow",{count:types.subflows})).appendTo(counts); } if (types.nodes > 0) { $('
').text(RED._("clipboard.node",{count:types.nodes})).appendTo(counts); } } else { // A single 'thing' selected. // Check to see if this is a subflow or subflow instance var m = /^subflow(:(.+))?$/.exec(node.type); if (m) { if (m[2]) { subflowNode = RED.nodes.subflow(m[2]); } else { subflowNode = node; } subflowUserCount = 0; var subflowType = "subflow:"+subflowNode.id; RED.nodes.eachNode(function(n) { if (n.type === subflowType) { subflowUserCount++; } }); } if (node.type === "tab" || node.type === "subflow") { // If nothing is selected, but we're on a flow or subflow tab. propRow = $(''+RED._("sidebar.info."+(node.type==='tab'?'flow':'subflow'))+'').appendTo(tableBody); RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]); propRow = $(''+RED._("sidebar.info.tabName")+"").appendTo(tableBody); $(propRow.children()[1]).text(node.label||node.name||""); if (node.type === "tab") { propRow = $(''+RED._("sidebar.info.status")+'').appendTo(tableBody); $(propRow.children()[1]).text((!!!node.disabled)?RED._("sidebar.info.enabled"):RED._("sidebar.info.disabled")) } } else { // An actual node is selected in the editor - build up its properties table propRow = $(''+RED._("sidebar.info.node")+"").appendTo(tableBody); RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]); if (node.type !== "subflow" && node.type !== "unknown" && node.name) { propRow = $(''+RED._("common.label.name")+'').appendTo(tableBody); $('').text(node.name).appendTo(propRow.children()[1]); } if (!m) { propRow = $(''+RED._("sidebar.info.type")+"").appendTo(tableBody); $(propRow.children()[1]).text((node.type === "unknown")?node._orig.type:node.type); if (node.type === "unknown") { $('').prependTo($(propRow.children()[1])) } } var count = 0; if (!m && node.type != "subflow") { var defaults; if (node.type === 'unknown') { defaults = {}; Object.keys(node._orig).forEach(function(k) { if (k !== 'type') { defaults[k] = {}; } }) } else if (node._def) { defaults = node._def.defaults; propRow = $(''+RED._("sidebar.info.module")+"").appendTo(tableBody); $(propRow.children()[1]).text(RED.nodes.getType(node.type).set.module); count++; } $('').appendTo(tableBody); if (defaults) { for (var n in defaults) { if (n != "name" && n != "info" && defaults.hasOwnProperty(n)) { var val = node[n]; var type = typeof val; count++; propRow = $(''+n+"").appendTo(tableBody); if (defaults[n].type) { var configNode = RED.nodes.node(val); if (!configNode) { RED.utils.createObjectElement(undefined).appendTo(propRow.children()[1]); } else { var configLabel = RED.utils.getNodeLabel(configNode,val); var container = propRow.children()[1]; var div = $('',{class:""}).appendTo(container); var nodeDiv = $('
',{class:"red-ui-palette-node red-ui-palette-node-small"}).appendTo(div); var colour = RED.utils.getNodeColor(configNode.type,configNode._def); var icon_url = RED.utils.getNodeIcon(configNode._def); nodeDiv.css({'backgroundColor':colour, "cursor":"pointer"}); var iconContainer = $('
',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv); $('
',{class:"red-ui-palette-icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer); var nodeContainer = $('').css({"verticalAlign":"top","marginLeft":"6px"}).text(configLabel).appendTo(container); nodeDiv.on('dblclick',function() { RED.editor.editConfig("", configNode.type, configNode.id); }) } } else { RED.utils.createObjectElement(val).appendTo(propRow.children()[1]); } } } } if (count > 0) { $(''+RED._("sidebar.info.showMore")+''+RED._("sidebar.info.showLess")+' ').appendTo(tableBody); } } if (node.type !== 'tab') { if (m) { $(''+RED._("sidebar.info.subflow")+'').appendTo(tableBody); $(''+RED._("common.label.name")+''+RED.utils.sanitize(subflowNode.name)+'').appendTo(tableBody); } } } if (m) { propRow = $(''+RED._("subflow.category")+'').appendTo(tableBody); var category = subflowNode.category||"subflows"; $(propRow.children()[1]).text(RED._("palette.label."+category,{defaultValue:category})) $(''+RED._("sidebar.info.instances")+""+subflowUserCount+'').appendTo(tableBody); } var helpText = ""; if (node.type === "tab" || node.type === "subflow") { $(helpSection.container).hide(); } else { $(helpSection.container).show(); if (subflowNode && node.type !== "subflow") { // Selected a subflow instance node. // - The subflow template info goes into help helpText = (marked(subflowNode.info||"")||(''+RED._("sidebar.info.none")+'')); } else { helpText = $("script[data-help-name='"+node.type+"']").html()||(''+RED._("sidebar.info.none")+''); } setInfoText(helpText, helpSection.content); } var infoText = ""; if (node._def && node._def.info) { var info = node._def.info; var textInfo = (typeof info === "function" ? info.call(node) : info); infoText = infoText + marked(textInfo); } if (node.info) { infoText = infoText + marked(node.info || "") } setInfoText(infoText, infoSection.content); $(".red-ui-sidebar-info-stack").scrollTop(0); $(".node-info-property-header").on("click", function(e) { e.preventDefault(); expandedSections["property"] = !expandedSections["property"]; $(this).toggleClass("expanded",expandedSections["property"]); $(".red-ui-help-info-property-row").toggle(expandedSections["property"]); }); } // $('').appendTo(tableBody); // propRow = $('Actions').appendTo(tableBody); // var actionBar = $(propRow.children()[1]); // // // var actionBar = $('
',{style:"background: #fefefe; padding: 3px;"}).appendTo(propertiesSection.content); // $('').appendTo(actionBar); // $('').appendTo(actionBar); // $('').appendTo(actionBar); // $('').appendTo(actionBar); } function setInfoText(infoText,target) { var info = addTargetToExternalLinks($('
'+infoText+'
')).appendTo(target); info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "" ); var foldingHeader = "H3"; info.find(foldingHeader).wrapInner('') .find("a").prepend('').on("click", function(e) { e.preventDefault(); var isExpanded = $(this).hasClass('expanded'); var el = $(this).parent().next(); while(el.length === 1 && el[0].nodeName !== foldingHeader) { el.toggle(!isExpanded); el = el.next(); } $(this).toggleClass('expanded',!isExpanded); }) } var tips = (function() { var enabled = true; var startDelay = 1000; var cycleDelay = 15000; var startTimeout; var refreshTimeout; var tipCount = -1; RED.actions.add("core:toggle-show-tips",function(state) { if (state === undefined) { RED.userSettings.toggle("view-show-tips"); } else { enabled = state; if (enabled) { startTips(); } else { stopTips(); } } }); 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])); } tipBox.html(tip).fadeIn(200); if (startTimeout) { startTimeout = null; refreshTimeout = setInterval(cycleTips,cycleDelay); } } function cycleTips() { tipBox.fadeOut(300,function() { setTip(); }) } function startTips() { $(".red-ui-sidebar-info").addClass('show-tips'); if (enabled) { if (!startTimeout && !refreshTimeout) { if (tipCount === -1) { do { tipCount++; } while(RED._("infotips:info.tip"+tipCount)!=="infotips:info.tip"+tipCount); } startTimeout = setTimeout(setTip,startDelay); } } } function stopTips() { $(".red-ui-sidebar-info").removeClass('show-tips'); clearInterval(refreshTimeout); clearTimeout(startTimeout); refreshTimeout = null; startTimeout = null; } function nextTip() { clearInterval(refreshTimeout); startTimeout = true; setTip(); } return { start: startTips, stop: stopTips, next: nextTip, enabled: function() { return enabled; } } })(); function clear() { // sections.hide(); refresh(null); } function set(html,title) { // tips.stop(); // sections.show(); refresh(null); propertiesSection.container.hide(); helpSection.container.hide(); infoSection.container.show(); infoSection.title.text(title||RED._("sidebar.info.desc")); setInfoText(html,infoSection.content); $(".red-ui-sidebar-info-stack").scrollTop(0); } function refreshSelection(selection) { if (selection === undefined) { selection = RED.view.selection(); } if (selection.nodes) { if (selection.nodes.length == 1) { var node = selection.nodes[0]; if (node.type === "subflow" && node.direction) { refresh(RED.nodes.subflow(node.z)); } else { refresh(node); } } else { refresh(selection.nodes); } } else if (selection.flows || selection.subflows) { refresh(selection.flows); } else { var activeWS = RED.workspaces.active(); var flow = RED.nodes.workspace(activeWS) || RED.nodes.subflow(activeWS); if (flow) { refresh(flow); } else { var workspace = RED.nodes.workspace(RED.workspaces.active()); if (workspace && workspace.info) { refresh(workspace); } else { refresh(null) // clear(); } } } } RED.events.on("view:selection-changed",refreshSelection); return { init: init, show: show, refresh: refresh, clear: clear, set: set } })();