/** * 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.palette = (function() { var exclusion = ['config','unknown','deprecated']; var coreCategories = [ 'subflows', 'common', 'function', 'network', 'input', 'output', 'sequence', 'parser', 'storage', 'analysis', 'social', 'advanced' ]; var categoryContainers = {}; var sidebarControls; function createCategory(originalCategory,rootCategory,category,ns) { if ($("#red-ui-palette-base-category-"+rootCategory).length === 0) { createCategoryContainer(originalCategory,rootCategory, ns+":palette.label."+rootCategory); } $("#red-ui-palette-container-"+rootCategory).show(); if ($("#red-ui-palette-"+category).length === 0) { $("#red-ui-palette-base-category-"+rootCategory).append('
'); } } function createCategoryContainer(originalCategory,category, labelId) { var label = RED._(labelId, {defaultValue:category}); label = (label || category).replace(/_/g, " "); var catDiv = $('
'+ '
'+label+'
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
').appendTo("#red-ui-palette-container"); catDiv.data('category',originalCategory); catDiv.data('label',label); categoryContainers[category] = { container: catDiv, close: function() { catDiv.removeClass("red-ui-palette-open"); catDiv.addClass("red-ui-palette-closed"); $("#red-ui-palette-base-category-"+category).slideUp(); $("#red-ui-palette-header-"+category+" i").removeClass("expanded"); }, open: function() { catDiv.addClass("red-ui-palette-open"); catDiv.removeClass("red-ui-palette-closed"); $("#red-ui-palette-base-category-"+category).slideDown(); $("#red-ui-palette-header-"+category+" i").addClass("expanded"); }, toggle: function() { if (catDiv.hasClass("red-ui-palette-open")) { categoryContainers[category].close(); } else { categoryContainers[category].open(); } } }; $("#red-ui-palette-header-"+category).on('click', function(e) { categoryContainers[category].toggle(); }); } function setLabel(type, el,label, info) { var nodeWidth = 82; var nodeHeight = 25; var lineHeight = 20; var portHeight = 10; el.attr("data-palette-label",label); label = RED.utils.sanitize(label); var words = label.split(/([ -]|\\n )/); var displayLines = []; var currentLine = ""; for (var i=0;i 0) { displayLines.push(currentLine); } while (true) { var wordWidth = RED.view.calculateTextWidth(word, "red-ui-palette-label"); if (wordWidth >= nodeWidth) { // break word if too wide for(var j = word.length; j > 0; j--) { var s = word.substring(0, j); var width = RED.view.calculateTextWidth(s, "red-ui-palette-label"); if (width < nodeWidth) { displayLines.push(s); word = word.substring(j); break; } } } else { currentLine = word; break; } } } } displayLines.push(currentLine); var lines = displayLines.join("
"); var multiLineNodeHeight = 8+(lineHeight*displayLines.length); el.css({height:multiLineNodeHeight+"px"}); var labelElement = el.find(".red-ui-palette-label"); labelElement.html(lines).attr('dir', RED.text.bidi.resolveBaseTextDir(lines)); el.find(".red-ui-palette-port").css({top:(multiLineNodeHeight/2-5)+"px"}); var popOverContent; try { var l = "

"+RED.text.bidi.enforceTextDirectionWithUCC(label)+"

"; popOverContent = $('
').append($(l+(info?info:RED.nodes.getNodeHelp(type)||"

"+RED._("palette.noInfo")+"

").trim()) .filter(function(n) { return (this.nodeType == 1 && this.nodeName == "P") || (this.nodeType == 3 && this.textContent.trim().length > 0) }).slice(0,2)); popOverContent.find("a").each(function(){ var linkText = $(this).text(); $(this).before(linkText); $(this).remove(); }); var typeInfo = RED.nodes.getType(type); if (typeInfo) { var metaData = ""; if (typeInfo && !/^subflow:/.test(type)) { metaData = typeInfo.set.module+" : "; } metaData += type; const safeType = type.replace(/'/g,"\\'"); const searchType = type.indexOf(' ') > -1 ? '"' + type + '"' : type if (/^subflow:/.test(type)) { $('').appendTo(popOverContent) } $('').appendTo(popOverContent) $('').appendTo(popOverContent) $('

',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent); } } catch(err) { // Malformed HTML may cause errors. TODO: need to understand what can break // NON-NLS: internal debug console.log("Error generating pop-over label for ",type); console.log(err.toString()); popOverContent = "

"+label+"

"+RED._("palette.noInfo")+"

"; } el.data('popover').setContent(popOverContent); } function setIcon(element,sf) { var icon_url = RED.utils.getNodeIcon(sf._def); var iconContainer = element.find(".red-ui-palette-icon-container"); var currentIcon = iconContainer.attr("data-palette-icon"); if (currentIcon !== icon_url) { iconContainer.attr("data-palette-icon", icon_url); RED.utils.createIconElement(icon_url, iconContainer, true); } } function getPaletteNode(type) { return $(".red-ui-palette-node[data-palette-type='"+type+"']"); } function escapeCategory(category) { return category.replace(/[\x00-\x2c\x2e-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]/g,"_"); } function addNodeType(nt,def) { if (getPaletteNode(nt).length) { return; } var nodeCategory = def.category; if (exclusion.indexOf(nodeCategory)===-1) { var originalCategory = nodeCategory; var category = escapeCategory(nodeCategory); var rootCategory = category.split("-")[0]; var d = $('
',{class:"red-ui-palette-node"}).attr("data-palette-type",nt).data('category',rootCategory); var label = RED.utils.getPaletteLabel(nt, def);///^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1]; $('
', { class: "red-ui-palette-label"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-label-right" : "") }).appendTo(d); if (def.icon) { var icon_url = RED.utils.getNodeIcon(def); var iconContainer = $('
', { class: "red-ui-palette-icon-container"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-icon-container-right" : "") }).appendTo(d); iconContainer.attr("data-palette-icon", icon_url); RED.utils.createIconElement(icon_url, iconContainer, true); } d.css("backgroundColor", RED.utils.getNodeColor(nt,def)); if (def.outputs > 0) { var portOut = document.createElement("div"); portOut.className = "red-ui-palette-port red-ui-palette-port-output"; d.append(portOut); } if (def.inputs > 0) { var portIn = document.createElement("div"); portIn.className = "red-ui-palette-port red-ui-palette-port-input"; d.append(portIn); } createCategory(nodeCategory,rootCategory,category,(coreCategories.indexOf(rootCategory) !== -1)?"node-red":def.set.id); $("#red-ui-palette-"+category).append(d); d.on("mousedown", function(e) { e.preventDefault();}); var popover = RED.popover.create({ target:d, trigger: "hover", interactive: true, width: "300px", content: "hi", delay: { show: 750, hide: 50 } }); d.data('popover',popover); var chart = $("#red-ui-workspace-chart"); var chartSVG = $("#red-ui-workspace-chart>svg").get(0); var activeSpliceLink; var mouseX; var mouseY; var spliceTimer; var groupTimer; var activeGroup; var hoverGroup; var paletteWidth; var paletteTop; var dropEnabled; $(d).draggable({ helper: 'clone', appendTo: '#red-ui-editor', revert: 'invalid', revertDuration: 200, containment:'#red-ui-main-container', start: function() { dropEnabled = !(RED.nodes.workspace(RED.workspaces.active())?.locked); paletteWidth = $("#red-ui-palette").width(); paletteTop = $("#red-ui-palette").parent().position().top + $("#red-ui-palette-container").position().top; hoverGroup = null; activeGroup = RED.view.getActiveGroup(); if (activeGroup) { document.getElementById("group_select_"+activeGroup.id).classList.add("red-ui-flow-group-active-hovered"); } RED.view.focus(); }, stop: function() { if (dropEnabled) { d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false); if (hoverGroup) { document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered"); } if (activeGroup) { document.getElementById("group_select_"+activeGroup.id).classList.remove("red-ui-flow-group-active-hovered"); } if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null; } if (groupTimer) { clearTimeout(groupTimer); groupTimer = null; } } }, drag: function(e,ui) { var paletteNode = getPaletteNode(nt); ui.originalPosition.left = paletteNode.offset().left; if (dropEnabled) { mouseX = ui.position.left - paletteWidth + (ui.helper.width()/2) + chart.scrollLeft(); mouseY = ui.position.top - paletteTop + (ui.helper.height()/2) + chart.scrollTop() + 10; if (!groupTimer) { groupTimer = setTimeout(function() { var mx = mouseX / RED.view.scale(); var my = mouseY / RED.view.scale(); var group = RED.view.getGroupAtPoint(mx,my); if (group !== hoverGroup) { if (hoverGroup) { document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered"); } if (group) { document.getElementById("group_select_"+group.id).classList.add("red-ui-flow-group-hovered"); } hoverGroup = group; if (hoverGroup) { $(ui.helper).data('group',hoverGroup); } else { $(ui.helper).removeData('group'); } } groupTimer = null; },200) } if (def.inputs > 0 && def.outputs > 0) { if (!spliceTimer) { spliceTimer = setTimeout(function() { var nodes = []; var bestDistance = Infinity; var bestLink = null; if (chartSVG.getIntersectionList) { var svgRect = chartSVG.createSVGRect(); svgRect.x = mouseX; svgRect.y = mouseY; svgRect.width = 1; svgRect.height = 1; nodes = chartSVG.getIntersectionList(svgRect,chartSVG); } else { // Firefox doesn't do getIntersectionList and that // makes us sad nodes = RED.view.getLinksAtPoint(mouseX,mouseY); } var mx = mouseX / RED.view.scale(); var my = mouseY / RED.view.scale(); for (var i=0;i 0) { var portIn = document.createElement("div"); portIn.className = "red-ui-palette-port red-ui-palette-port-input"; paletteNode.append(portIn); } else if (portInput.length !== 0 && sf.in.length === 0) { portInput.remove(); } if (portOutput.length === 0 && sf.out.length > 0) { var portOut = document.createElement("div"); portOut.className = "red-ui-palette-port red-ui-palette-port-output"; paletteNode.append(portOut); } else if (portOutput.length !== 0 && sf.out.length === 0) { portOutput.remove(); } var currentLabel = paletteNode.attr("data-palette-label"); var currentInfo = paletteNode.attr("data-palette-info"); if (currentLabel !== sf.name || currentInfo !== sf.info) { paletteNode.attr("data-palette-info",sf.info); setLabel(sf.type+":"+sf.id,paletteNode,sf.name,RED.utils.renderMarkdown(sf.info||"")); } setIcon(paletteNode,sf); var currentCategory = paletteNode.data('category'); var newCategory = (sf.category||"subflows"); if (currentCategory !== newCategory) { var category = escapeCategory(newCategory); createCategory(newCategory,category,category,"node-red"); var currentCategoryNode = paletteNode.closest(".red-ui-palette-category"); var newCategoryNode = $("#red-ui-palette-"+category); newCategoryNode.append(paletteNode); if (newCategoryNode.find(".red-ui-palette-node").length === 1) { categoryContainers[category].open(); } paletteNode.data('category',newCategory); if (currentCategoryNode.find(".red-ui-palette-node").length === 0) { if (currentCategoryNode.find("i").hasClass("expanded")) { currentCategoryNode.find(".red-ui-palette-content").slideToggle(); currentCategoryNode.find("i").toggleClass("expanded"); } currentCategoryNode.hide(); } } paletteNode.css("backgroundColor", sf.color); } function filterChange(val) { var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i'); $("#red-ui-palette-container .red-ui-palette-node").each(function(i,el) { var currentLabel = $(el).attr("data-palette-label"); var type = $(el).attr("data-palette-type"); if (val === "" || re.test(type) || re.test(currentLabel)) { $(this).show(); } else { $(this).hide(); } }); for (var category in categoryContainers) { if (categoryContainers.hasOwnProperty(category)) { if (categoryContainers[category].container .find(".red-ui-palette-node") .filter(function() { return $(this).css('display') !== 'none'}).length === 0) { categoryContainers[category].close(); categoryContainers[category].container.slideUp(); } else { categoryContainers[category].open(); categoryContainers[category].container.show(); } } } } function init() { $('').appendTo("#red-ui-palette"); $('').appendTo("#red-ui-palette"); $('
').appendTo("#red-ui-palette"); $('').appendTo("#red-ui-palette"); $('
').appendTo("#red-ui-palette"); $("#red-ui-palette > .red-ui-palette-spinner").show(); RED.events.on('registry:node-type-added', function(nodeType) { var def = RED.nodes.getType(nodeType); addNodeType(nodeType,def); if (def.onpaletteadd && typeof def.onpaletteadd === "function") { def.onpaletteadd.call(def); } }); RED.events.on('registry:node-type-removed', function(nodeType) { removeNodeType(nodeType); }); RED.events.on('registry:node-set-enabled', function(nodeSet) { for (var j=0;j
').appendTo($("#red-ui-palette")); RED.popover.tooltip(sidebarControls,RED._("keyboard.togglePalette"),"core:toggle-palette"); sidebarControls.on("click", function() { RED.menu.toggleSelected("menu-item-palette"); }) $("#red-ui-palette").on("mouseenter", function() { sidebarControls.toggle("slide", { direction: "left" }, 200); }) $("#red-ui-palette").on("mouseleave", function() { sidebarControls.stop(false,true); sidebarControls.hide(); }) var userCategories = []; if (RED.settings.paletteCategories) { userCategories = RED.settings.paletteCategories; } else if (RED.settings.theme('palette.categories')) { userCategories = RED.settings.theme('palette.categories'); } if (!Array.isArray(userCategories)) { userCategories = []; } var addedCategories = {}; userCategories.forEach(function(category){ addedCategories[category] = true; createCategoryContainer(category, escapeCategory(category), "palette.label."+escapeCategory(category)); }); coreCategories.forEach(function(category){ if (!addedCategories[category]) { createCategoryContainer(category, escapeCategory(category), "palette.label."+escapeCategory(category)); } }); var paletteFooterButtons = $('').appendTo("#red-ui-palette .red-ui-component-footer"); var paletteCollapseAll = $('').appendTo(paletteFooterButtons); paletteCollapseAll.on("click", function(e) { e.preventDefault(); for (var cat in categoryContainers) { if (categoryContainers.hasOwnProperty(cat)) { categoryContainers[cat].close(); } } }); RED.popover.tooltip(paletteCollapseAll,RED._('palette.actions.collapse-all')); var paletteExpandAll = $('').appendTo(paletteFooterButtons); paletteExpandAll.on("click", function(e) { e.preventDefault(); for (var cat in categoryContainers) { if (categoryContainers.hasOwnProperty(cat)) { categoryContainers[cat].open(); } } }); RED.popover.tooltip(paletteExpandAll,RED._('palette.actions.expand-all')); RED.actions.add("core:toggle-palette", function(state) { if (state === undefined) { RED.menu.toggleSelected("menu-item-palette"); } else { togglePalette(state); } }); } function togglePalette(state) { if (!state) { $("#red-ui-main-container").addClass("red-ui-palette-closed"); sidebarControls.hide(); sidebarControls.find("i").addClass("fa-chevron-right").removeClass("fa-chevron-left"); } else { $("#red-ui-main-container").removeClass("red-ui-palette-closed"); sidebarControls.find("i").removeClass("fa-chevron-right").addClass("fa-chevron-left"); } setTimeout(function() { $(window).trigger("resize"); } ,200); } function getCategories() { var categories = []; $("#red-ui-palette-container .red-ui-palette-category").each(function(i,d) { categories.push({id:$(d).data('category'),label:$(d).data('label')}); }) return categories; } return { init: init, add:addNodeType, remove:removeNodeType, hide:hideNodeType, show:showNodeType, refresh:refreshNodeTypes, getCategories: getCategories }; })();