/** * 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', 'input', 'output', 'function', 'social', 'mobile', 'storage', 'analysis', 'advanced']; var categoryContainers = {}; function createCategory(originalCategory,rootCategory,category,ns) { if ($("#palette-base-category-"+rootCategory).length === 0) { createCategoryContainer(originalCategory,rootCategory, ns+":palette.label."+rootCategory); } $("#palette-container-"+rootCategory).show(); if ($("#palette-"+category).length === 0) { $("#palette-base-category-"+rootCategory).append('
'); } } function createCategoryContainer(originalCategory,category, labelId) { var label = RED._(labelId, {defaultValue:category}); label = (label || category).replace(/_/g, " "); var catDiv = $(' ').appendTo("#palette-container"); catDiv.data('category',originalCategory); catDiv.data('label',label); categoryContainers[category] = { container: catDiv, close: function() { catDiv.removeClass("palette-open"); catDiv.addClass("palette-closed"); $("#palette-base-category-"+category).slideUp(); $("#palette-header-"+category+" i").removeClass("expanded"); }, open: function() { catDiv.addClass("palette-open"); catDiv.removeClass("palette-closed"); $("#palette-base-category-"+category).slideDown(); $("#palette-header-"+category+" i").addClass("expanded"); }, toggle: function() { if (catDiv.hasClass("palette-open")) { categoryContainers[category].close(); } else { categoryContainers[category].open(); } } }; $("#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; var words = label.split(/[ -]/); var displayLines = []; var currentLine = words[0]; var currentLineWidth = RED.view.calculateTextWidth(currentLine, "palette_label", 0); for (var i=1;i"+RED.text.bidi.enforceTextDirectionWithUCC(label)+"
"; if (label != type) { l = ""+RED.text.bidi.enforceTextDirectionWithUCC(label)+"
"+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); } 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 iconElement = element.find(".palette_icon"); var icon_url = RED.utils.getNodeIcon(sf._def,sf); iconElement.attr("style", "background-image: url("+icon_url+")"); } function escapeNodeType(nt) { return nt.replace(" ","_").replace(".","_").replace(":","_"); } function addNodeType(nt,def) { var nodeTypeId = escapeNodeType(nt); if ($("#palette_node_"+nodeTypeId).length) { return; } if (exclusion.indexOf(def.category)===-1) { var originalCategory = def.category; var category = def.category.replace(/ /g,"_"); var rootCategory = category.split("-")[0]; var d = document.createElement("div"); d.id = "palette_node_"+nodeTypeId; d.type = nt; var label = /^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1]; if (typeof def.paletteLabel !== "undefined") { try { label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||""; } catch(err) { console.log("Definition error: "+nt+".paletteLabel",err); } } $('',{class:"palette_label"+(def.align=="right"?" palette_label_right":"")}).appendTo(d); d.className="palette_node"; if (def.icon) { var icon_url = RED.utils.getNodeIcon(def); var iconContainer = $('',{class:"palette_icon_container"+(def.align=="right"?" palette_icon_container_right":"")}).appendTo(d); $('',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer); } d.style.backgroundColor = RED.utils.getNodeColor(nt,def); 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 palette_port_input"; d.appendChild(portIn); } createCategory(def.category,rootCategory,category,(coreCategories.indexOf(rootCategory) !== -1)?"node-red":def.set.id); $("#palette-"+category).append(d); $(d).data('category',rootCategory); d.onmousedown = function(e) { e.preventDefault(); }; 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, // placement:"right", // trigger: "hover", // delay: { show: 750, hide: 50 }, // html: true, // container:'body' // }); $(d).click(function() { RED.view.focus(); var helpText; if (nt.indexOf("subflow:") === 0) { helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"")||(''+RED._("sidebar.info.none")+''); } else { helpText = $("script[data-help-name='"+d.type+"']").html()||(''+RED._("sidebar.info.none")+''); } RED.sidebar.info.set(helpText,RED._("sidebar.info.nodeHelp")); }); var chart = $("#chart"); var chartOffset = chart.offset(); var chartSVG = $("#chart>svg").get(0); var activeSpliceLink; var mouseX; var mouseY; var spliceTimer; var paletteWidth; var paletteTop; $(d).draggable({ helper: 'clone', appendTo: 'body', revert: true, revertDuration: 50, containment:'#main-container', start: function() { paletteWidth = $("#palette").width(); paletteTop = $("#palette").parent().position().top + $("#palette-container").position().top; RED.view.focus(); }, stop: function() { d3.select('.link_splice').classed('link_splice',false); if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null;}}, drag: function(e,ui) { // TODO: this is the margin-left of palette node. Hard coding // it here makes me sad //console.log(ui.helper.position()); ui.position.left += 17.5; if (def.inputs > 0 && def.outputs > 0) { mouseX = ui.position.left-paletteWidth+(ui.helper.width()/2) - chartOffset.left + chart.scrollLeft(); mouseY = ui.position.top-paletteTop+(ui.helper.height()/2) - chartOffset.top + chart.scrollTop(); 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); mouseX /= RED.view.scale(); mouseY /= RED.view.scale(); } else { // Firefox doesn't do getIntersectionList and that // makes us sad mouseX /= RED.view.scale(); mouseY /= RED.view.scale(); nodes = RED.view.getLinksAtPoint(mouseX,mouseY); } for (var i=0;i