Switch Ports Sortierung
-
Hallo @StefanP74,
das Thema "Sortierung" ist leider sehr schwierig, da es gefühlt keinen richtigen Weg gibt, der alle glücklich macht. Aktuell gibt es eine Reihe an Bedingungen für die Verkabelungsansicht:
- Um intern verkabelte Anschlüsse beieinander zu halten, werden diese so gut es geht zusammen sortiert (Eingang und Ausgang auf gleicher höhe)
- Intern nicht verkabelte Anschlüsse werden nach unten sortiert, damit die interne Verkabelung etwas ordentlicher wird
- Anschlussnamen werden aufgesplittet und numerisch sowie alphabetisch sortiert (sodass "Port 9" vor "Port 10" kommt)
Nachdem diese Regeln durchlaufen sind, bleibt es aber weiterhin so, dass wir von links nach rechts sortieren. In deinem Fall führt das leider zu einem unschönen Ergebnis, da die rechte Seite nicht weiter sortiert wird, um die vorherige Logik nicht zunichte zu machen.
Ich glaube, die einzige "saubere" Lösung wäre, eine optionale Sortierung pro Seite (Ein- und Ausgänge) anzubieten. Das ist jedoch mit erheblichem Aufwand verbunden Ich weiß nicht, ob wir das in nächster Zeit angehen werden.
Ich hoffe ich konnte zumindest etwas Licht ins Dunkle bringen
Viele Grüße
Leo -
Hallo @LFischer,
danke für die Info, ich verstehe es nur nicht ganz ... seitens der Programmierlogik.
Meine Gedanken zu dem Thema, vielleicht sehe ich das auch zu locker.Wenn ich einen Eingang mit einem Ausgang verbunden habe, dann ist nur die Sortierung der Eingänge (also links) nötig, da die beiden mit einander verbunden sind und der Ausgang entsprechend gereiht wird, anhand der Abhängigkeit zum Eingang.
Hat ein Eingang mehrere Ausgänge, dann werden zusätzlich die Ausgänge mit Abhängigkeit zum jeweiligen Eingang, ebenso sortiert.
Hat ein Eingang keine Abhängigkeit zu einem Ausgang, dann werden diese zB. unten, aber dennoch sortiert angezeigt, Eingang wie auch Ausgang.
LG Stefan
-
Hallo @StefanP74
ich glaube genau dieser Fall wird aktuell nicht berücksichtigt
Hat ein Eingang mehrere Ausgänge, dann werden zusätzlich die Ausgänge mit Abhängigkeit zum jeweiligen Eingang, ebenso sortiert.
Ich werde mir das aber noch mal lokal nachbauen und anschauen. Vielleicht lässt es sich ja doch noch irgendwie einbauen ohne etwas anderes kaputt zu machen
Viele Grüße
Leo -
Hallo @LFischer,
ich lege meine Hoffnung in deine Hände
Danke, wäre toll wenn das klappen würde.LG Stefan
-
Hey @StefanP74
ich glaube ich habe etwas gefunden - könntest du das vielleicht kurz bei dir ausprobieren und schauen ob es ggf. zu unerwünschten Seiteneffekten kommt? Ich habe das mit der Add-on Version 1.4 geprüft.
Dazu bitte in die folgende Datei navigieren (ausgehend vom i-doit Verzeichnis)
src/classes/modules/cabling/assets/js/cabling.js
Hier auf Zeile 254 steht folgendes:
// Then sort by "toIndex" to keep internally wired connectors near by each other. if (a.data.toIndex && b.data.toIndex) { return a.data.toIndex - b.data.toIndex }
Das bitte mal mit folgender kleinen Änderung anpassen:
// Then sort by "toIndex" to keep internally wired connectors near by each other. if (a.data.toIndex && b.data.toIndex && a.data.toIndex !== b.data.toIndex) { return a.data.toIndex - b.data.toIndex }
Das Problem ist nämlich das die Ausgänge alle auf den gleichen Eingang zeigen - bedeutet hier das der
a.data.toIndex
undb.data.toIndex
den identischen Wert beinhalten. Das Ergebnis der Sortierung ist in diesem Fall0
was so viel heißt wie: "Bleib wo du bist".In diesem Fall soll aber die Sortierung nach Namen übernehmen. Aus diesem Grund ergänzen wir die Bedingung um
a.data.toIndex ist ungleich b.data.toIndex
.Wenn das soweit passt würde ich das im Code übernehmen sodass diese Anpassung in der nächsten Version landet
Viele Grüße
Leo -
Hallo @LFischer,
best support ever!
Funktioniert hervorragend, sehr fein, danke.Super, danke.
Ich konnte bei den anderen Verbindungen (bis auf das noch bestehende Problem "chaotische Verkabelung", bei nachträglich angelegten Ports) nichts negatives feststellen.Problem chaotische Verkabelung:
Das ist wohl ein ganz anderes Thema.Danke jedenfalls für den super tollen raschen Fix.
Wenn du heute Abend das Gefühl hast "hääää was war das denn?" ... das war ich, ich habe ein paar Bier auf dich getrunkenLG Stefan
-
Hey @StefanP74
freut mich das ich dir damit weiterhelfen konnte Bzgl. dem "Chaotische Verkabelung" Problem - ist das erst durch den Fix geschehen? Denn genau den zuständigen Code habe ich angepasst...
Wäre natürlich schön wenn der Fix nur Probleme löst anstatt auch neue zu schaffen
Ich schaue mal ob ich auch dieses Problem nachvollziehen (und ggf. fixen) kann
VG Leo
edit
Okay, ich kann es nachstellen... Mal sehen ob ich das auch noch hinbekomme
edit 2
Ich glaube auch hier habe ich das Problem gefunden... Es ist aber etwa schwieriger zu lösen Es ist nämlich so dass die
toIndex
Werte vom Backend vorbereitet werden... Die Sortierung passiert dann aber im Frontend und ändert die Indexe, sodass diese dann nicht mehr korrekt sind.
Mal sehen wie ich das löse -
nein, das ist nicht neu dazugekommen.
Edit: Wäre genial wenn du das lösen könntest.
LG Stefan
-
Hey @StefanP74
ich war ein wenig fleißig und habe etwas erarbeitet Dieses mal betrifft es aber ein paar mehr Zeilen - ich glaube es ist einfacher die komplette Datei zu tauschen. Leider ist es im Forum nicht möglich die ganze Datei hochzuladen...
/** * i-doit cabling visualization javascript base class. * * @author Leonard Fischer <lfischer@i-doit.com> */ window.Cabling = Class.create({ $element: null, data: null, cache: null, svg: null, vis: null, zoom: null, options: {}, indexMapping: [], rootContainer: { height: 0, matching: [] }, getOptions: function () { return this.options; }, getOption: function (option) { return this.options[option]; }, setOption: function (option, value) { this.options[option] = value; return this; }, getSelectedElements: function () { // This method should be used to get all selected cable paths. // this.svg.selectAll('.selected'); }, initialize: function ($el, data, options) { var that = this; that.$element = $el; that.data = data || []; that.options = { authEdit: false, // Defines if the cabling view will allow any editing. minZoomLevel: 0.1, // Defines the minimal zoom level. maxZoomLevel: 1.5, // Defines the maximal zoom level. objectTypeData: {}, // JSON with all necessary object type data (name, color, ...). connectorTypeData: {}, // JSON with all necessary connector type data (name, color, ...). objectTypeFilter: [], // Array pf object types, that shall not be displayed. onAfterProcess: null, // 'Complete' event for when the rendering has finished. onObjSelect: null, // Click event for a object node. onObjUnselect: null, // Event for when a object gets unselected. onCableSelect: null, // Click event for a cable. onConnectorSelect: null, // Click event for a connector. onConnectorUnselect: null, // Event for when a connector gets unselected. onObjAcceptDrag: null, // Event for when a object gets unselected. onObjAbortDrag: null, // Event for when a object gets unselected. width: null, // This can be used to change the viewpoints width. The SVG element will always remain 100%x100%. height: null, // This can be used to change the viewpoints height. The SVG element will always remain 100%x100%. undefinedConnectorType: { color: '#fff', title: '-' }, // Default 'connector type' object. undefinedObjectType: { color: '#fff', title: '-' }, // Default 'object type' object. nodeWidth: 150, // Define the node width. nodeHeight: 20, // Define the node heigt. nodeMarginX: 25, // Define the horizontal margin between nodes. nodeMarginY: 25, // Define the vertical margin between nodes. displayWiring: false, // Define if the internal wiring shall be displayed (object boxes will get transparent). showCableLabels: false, // Define if cables shall be displayed. clickableConnectors: false // Define if connectors shall be clickable. }; that.rootContainer = { height: 0, matching: [] }; // Setting the default width and height. that.options.width = that.$element.getWidth(); that.options.height = that.$element.getHeight() + 16; Object.extend(that.options, options || {}); that.svg = d3.select($el).append('svg') .attr('width', that.options.width) .attr('height', that.options.height); that .svg.append('rect') .attr('width', that.options.width) .attr('height', that.options.height) .style('fill', 'none') .style('pointer-events', 'all'); // Here we set the <g> after the <rect>, this is necessary for dragging and zooming but still clicking elements inside <g>. that.vis = this.svg.append("g"); that.zoom = d3.zoom() .scaleExtent([ that.options.minZoomLevel, that.options.maxZoomLevel ]) .on('zoom', function () { that.vis.attr('transform', d3.event.transform); }); that.svg .call(that.zoom) .call(that.zoom.transform, d3.zoomIdentity.translate(that.options.width / 2, that.options.height / 2)); this.appendStyle(); return this; }, appendStyle: function () { // This method is necessary to include the SVG styles - this will be used in the SVG export. var defs = this.svg.select('defs'), isIE11 = !!window.MSInputMethodContext && !!document.documentMode; if (defs.node() === null) { defs = this.svg.append('defs'); defs.append('style').attr('type', 'text/css').text( ".cabling-object { \ fill: none;\ stroke: #444;\ stroke-width: 1px;\ }\ text {\ font-family: \"Helvetica Neue\", \"Lucida Grande\", \"Tahoma\", Arial, serif;\ font-size: 11px;\ paint-order: stroke;\ stroke: transparent;\ stroke-width: 0;\ fill: #000;\ }\ text.connector-left-title,\ text.connector-right-title {\ stroke-width: 5px;\ stroke: transparent;\ }\ text.connector-left-title.stroked,\ text.connector-right-title.stroked {\ " + (isIE11 ? "stroke-width: 0;" : "stroke-width: 5px;") + "\ stroke: #fff;\ }\ text.title,\ .linkname text,\ .linkname.clicked rect,\ .clicked rect.title {\ fill: #fff;\ }\ text.title {\ font-weight: bold;\ }\ .linkname rect,\ .linkname.clicked text {\ fill: #000;\ }\ rect.title,\ .clicked text.title {\ fill: #222;\ }\ circle.connector {\ stroke: rgba(0, 0, 0, 0.75);\ stroke-width: 1;\ }\ circle.connector-inner {\ fill: rgba(0, 0, 0, 0.75);\ stroke: none;\ }\ path {\ fill: none;\ stroke: #555;\ stroke-width: 2;\ }" ); } }, textFormat: function (text, width) { var result = text; if (width <= 0) { return ''; } d3.select(this).text(result); while (this.getComputedTextLength() > width) { result = result.substring(0, (result.length - 2)); d3.select(this).text(result); } if (result !== text && width > 2) { result += '..'; } return result; }, clearCanvas: function () { this.vis.selectAll('*').remove(); this.rootContainer = { height: 0, matching: [] }; }, responsive: function () { this.options.width = this.$element.getWidth(); this.options.height = this.$element.getHeight() + 16; return this; }, preProcess: function () { return this; }, process: function () { this.indexMapping = []; return this.preProcess().processSide('left').processSide('right').postProcess(); }, processSide: function (dir) { var that = this, invertX = (dir === 'right'), cache = this.data[dir]; // @see CABLING-49 Implement proper calculation for 'separation'. var tree = d3.tree() .separation((a, b) => Math.max(1, (a.children || []).length, (b.children || []).length)) .nodeSize([ (that.options.nodeHeight + that.options.nodeMarginY), (that.options.nodeWidth + that.options.nodeMarginX) ]); var root = d3.stratify()(cache) .sort(function (a, b) { // First sort by 'connected-index' to keep internally wired connectors near by each other. if (dir === 'right' && a.data.siblingId && b.data.siblingId && a.data.siblingId !== b.data.siblingId) { // @see CABLING-58 Use the newly created indexMapping to find the proper index. return this.indexMapping.findIndex((d) => d == a.data.siblingId) - this.indexMapping.findIndex((d) => d == b.data.siblingId); } // @see CABLING-36 Any "unconnected" connector will be moved down, so that no wires cross each other. if (a.data.siblingId && !b.data.siblingId) { return -1; } if (!a.data.siblingId && b.data.siblingId) { return 1; } // @see CABLING-19 Following code will try to sort the connectors in a more natural way! // First we split by "non-word" characters (like dots, slashes etc.). var aParts = a.data.title.split(/\W/), bParts = b.data.title.split(/\W/), minParts = Math.min(aParts.length, bParts.length), comparison, i; for (i = 0; i < minParts; i++) { if (isNumeric(aParts[i]) && isNumeric(bParts[i])) { comparison = aParts[i] - bParts[i]; } else { comparison = aParts[i].localeCompare(bParts[i]); } if (comparison !== 0) { return comparison; } } // If nothing worked out, use the default: return a.data.title.localeCompare(b.data.title); }.bind(this)); if (dir === 'left') { this.indexMapping = root.children.map((d) => d.data.id); } var connectorTranslate = function (d) { if (that.options.clickableConnectors) { if (d.parent === null || d.parent && d.parent.id === 'root') { return 'translate(' + (invertX ? 5 : -5) + ',0)'; } if (d.data.inner) { return 'translate(' + (invertX ? -5 : that.options.nodeWidth+5) + ',0)'; } else { return 'translate(' + (invertX ? that.options.nodeWidth+5 : -(that.options.nodeWidth+5)) + ',0)'; } } else { if (d.parent === null || d.parent && d.parent.id === 'root') { return 'translate(0,0)'; } if (d.data.inner) { return 'translate(' + (invertX ? 0 : that.options.nodeWidth) + ',0)'; } else { return 'translate(' + (invertX ? that.options.nodeWidth : -that.options.nodeWidth) + ',0)'; } } }; var linkData = tree(root).links(); var cable = that.vis .selectAll(".cable.cable-" + dir) .data(linkData); cable .enter().append("path") .style("opacity", 0) .attr("class", "cable cable-" + dir); // After the link data is assigned, we reduce the data to only hold cable information. linkData = linkData.filter(function (d) { return d.source.id !== 'root' && d.source.data.outer; }); // @see CABLING-35 Show internal cabling that.vis .selectAll('.internal-link.internal-link-' + dir) .data((root.children || []).filter((d) => d.data.wiredToItself)) .enter() .append("path") .style("opacity", 0) .attr('class', 'internal-link internal-link-' + dir) .attr('d', function (d) { const connection = (root.children || []).find(function (conn) { return conn.id == d.data.connectorId}); if (!connection) { return ''; } d.y -= 20; var xBetween = d.y + 30; const yBetween = ((d.x + connection.x) / 2); // Mirror the coordinates for the left side. if (dir === 'left') { d.y *= -1; xBetween *= -1; } return 'M' + d.y + ',' + d.x + ' C' + xBetween + ',' + d.x + ' ' + xBetween + ',' + yBetween + ' ' + xBetween + ',' + yBetween; }) .interrupt() .transition().duration(500) .transition().duration(250) .style("opacity", 1); var cableLabel = that.vis .selectAll(".linkname.linkname-" + dir) .data(linkData) .enter() .append("g") .style("opacity", 0) .attr("class", "linkname linkname-" + dir) .attr('data-id', function (d) { return d.source.data.cableId; }); that.vis .selectAll(".cable.cable-" + dir) .classed('cable-root', function (d) { return (d.source.id === 'root'); }) .interrupt().transition().duration(500) .attr("d", function (d) { var fromX = (d.source.y + (that.options.showCableLabels ? 50 : 125)), fromX2 = (fromX+20), fromX3 = (fromX+40), fromY = d.source.x, toX = (d.target.y + (that.options.showCableLabels ? 50 : 125)), toY = d.target.x; if (d.target.data.doubling) { toX += 20; } if (!invertX) { fromX *= -1; fromX2 *= -1; fromX3 *= -1; toX *= -1; } return "M" + fromX + "," + fromY + "C" + fromX2 + "," + fromY + " " + fromX2 + "," + toY + " " + fromX3 + "," + toY + "L" + toX + "," + toY; }) .transition().duration(250) .style("opacity", 1) .style('stroke-dasharray', function (d) { if (d.target.data.doubling) { return '2,2'; } return null; }); cable .exit() .interrupt().transition().duration(500) .style("opacity", 0) .remove(); cableLabel .append('rect') .attr('class', 'mouse-pointer') .attr('height', 14) .attr('width', 125) .attr('data-id', function (d) { return d.source.cableId }) .on('click', that.selectCableObject.bind(this)); cableLabel .append('text') .attr('class', 'mouse-pointer') .attr('dy', 10) .attr('x', 62.5) .style('text-anchor', 'middle') .text(function (d) { return d.source.data.cableTitle; }) .on('click', that.selectCableObject.bind(this)); that.vis .selectAll(".linkname.linkname-" + dir) .classed('hide', !that.options.showCableLabels) .interrupt().transition().duration(550) .style('opacity', (that.options.showCableLabels ? 1 : 0)) .attr('transform', function (d) { var translateX = d.source.y, translateY = d.source.x; if (invertX) { translateX = translateX + 85; } else { translateX = translateX + that.options.nodeWidth + 65; } if (d.source.parent.id === 'root') { translateX = translateX - 65; } return 'translate(' + (invertX ? '' : '-') + translateX + ',' + translateY + ')'; }); var node = that.vis .selectAll(".node.node-" + dir) .data(root.descendants()); var nodeEnter = node .enter().append("g") .style("opacity", 0) .attr("class", "node node-" + dir) .classed('root', function (d) { return d.parent === null; }) .attr('data-id', function (d) { return d.id; }); // This will append newly created and already existing nodes. this.vis .selectAll('.node.node-' + dir) .transition().duration(500) .style("opacity", 1) .attr("transform", function (d) { var translateX = d.y, translateY = d.x; if (d.parent === null) { return "translate(" + (invertX ? 0 : -that.options.nodeWidth) + "," + translateY + ")"; } if (d.parent && d.parent.id === 'root') { return "translate(" + (invertX ? that.options.nodeWidth : -that.options.nodeWidth) + "," + translateY + ")"; } if (d.data.inner) { if (!invertX) { translateX = -(translateX + that.options.nodeWidth); } } else { if (!invertX) { translateX = -(translateX + that.options.nodeWidth) + (that.options.nodeWidth + that.options.nodeMarginX); } else { translateX -= that.options.nodeMarginX; } } return "translate(" + translateX + "," + translateY + ")"; }); node.exit() .interrupt().transition().duration(500) .style("opacity", 0) .remove(); var container = nodeEnter .filter(function (d) { // Only draw boxes for the "root" element and "left" connectors. return d.parent === null || d.data.inner; }) .each(function (d) { // Prepare some data for each node. d.childNum = (d.children ? d.children.length : 1); d.minX = d.y; d.maxX = d.y + (that.options.nodeWidth * 2); if (d.children) { d.minY = d.children.first().x; d.maxY = d.children.last().x + that.options.nodeHeight; } else { d.minY = d.x; d.maxY = d.x + that.options.nodeHeight; } d.width = d.maxX - d.minX; d.height = d.maxY - d.minY; d.translateX = 0; d.translateY = -(d.height / 2); if (d.parent === null) { if (that.rootContainer.height < d.height) { that.rootContainer.height = d.height; that.rootContainer.translateX = d.translateX; that.rootContainer.translateY = d.translateY; } d.width = that.options.nodeWidth; } }); container .append('rect') .attr('class', 'title mouse-pointer') .attr('width', function (d) { return d.width; }) .attr('height', function (d) { return 20; }) .attr('data-object-id', function (d) { return d.data.objectId; }) .attr('transform', function (d) { var translateX = d.translateX, translateY = d.translateY; if (d.parent && d.parent !== 'root') { if (!invertX) { translateX = -that.options.nodeWidth; } } return 'translate(' + translateX + ',' + (translateY - 20) + ')'; }) .on('click', that.selectObject.bind(this)); container .append('rect') .attr('class', 'body') .attr('width', function (d) { return d.width; }) .attr('height', function (d) { return d.height; }) .attr('data-conn', function (d) { return d.data.title; }) .attr('transform', function (d) { var translateX = d.translateX, translateY = d.translateY; if (d.parent && d.parent !== 'root') { if (!invertX) { translateX = -that.options.nodeWidth; } } return 'translate(' + translateX + ',' + translateY + ')'; }) .attr('fill', function (d) { if (!that.options.objectTypeData.hasOwnProperty(d.data.objectTypeId)) { return that.options.undefinedObjectType.color; } return that.options.objectTypeData[d.data.objectTypeId].color || that.options.undefinedObjectType.color }); nodeEnter .filter(function (d) { return d.parent !== null; }) .append('circle') .attr('data-connector-id', function (d) { return d.data.id; }) .attr('class', 'connector connector-' + dir) .attr('transform', connectorTranslate) .on('click', that.selectConnector.bind(this)); nodeEnter .filter(function (d) { return d.parent !== null; }) .append('circle') .attr('data-connector-id', function (d) { return d.data.id; }) .style('opacity', 0) .attr('class', 'connector-inner hide connector-inner-' + dir) .attr('r', 4) .attr('transform', connectorTranslate) .on('click', that.selectConnector.bind(this)); that.vis .selectAll('circle.connector.connector-' + dir) .classed('mouse-pointer', that.options.clickableConnectors) .interrupt().transition().duration(500) .attr('r', (that.options.clickableConnectors ? 10: 5)) .attr('fill', function (d) { var connectorType = that.options.connectorTypeData[d.data.connectorType]; return connectorType ? connectorType.color : that.options.undefinedConnectorType.color; }) .attr('transform', connectorTranslate) .style('stroke-width', (that.options.clickableConnectors ? 3 : 1)); that.vis .selectAll('circle.connector-inner.connector-inner-' + dir) .classed('mouse-pointer', that.options.clickableConnectors) .interrupt().transition().duration(500) .attr('transform', connectorTranslate) .style('opacity', (that.options.clickableConnectors ? 1 : 0)); container .filter(function (d) { return (d.parent !== null || invertX); }) .append('text') .attr('class', 'title mouse-pointer') .attr("dy", function (d) { if (d.id === 'root') { return -((that.rootContainer.height / 2) + 7); } return -((d.height / 2) + 7); }) .attr("x", function (d) { if (d.parent === null) { return 0 } return invertX ? that.options.nodeWidth : 0; }) .style("text-anchor", 'middle') .text(function (d) { return d.data.objectTitle; }) .on('click', that.selectObject.bind(this)); nodeEnter .append("text") .attr('class', 'connector-' + dir + '-title') .attr("dy", 3) .attr("x", function (d) { if (d.parent !== null && d.parent.id === 'root') { return invertX ? -25 : 25; } if (d.data.outer) { return invertX ? that.options.nodeWidth-10 : -(that.options.nodeWidth-10); } return invertX ? 10 : (that.options.nodeWidth-10); }) .style("text-anchor", function (d) { if (d.parent !== null && d.parent.id === 'root' || d.data.outer) { return invertX ? 'end' : 'start'; } return invertX ? "start" : "end"; }) .text(function (d) { return that.textFormat.call(this, d.data.title, (that.options.nodeWidth - 15)); }); // @see CABLING-56 Show the full title when hovering connector. nodeEnter.append('title').text(d => d.data.title); // After all calculations have been done, we set the root height. this.vis.selectAll('g.root rect.title') .attr('transform', function (d) { return 'translate(' + that.rootContainer.translateX + ',' + (that.rootContainer.translateY - 20) + ')'; }); this.vis.selectAll('g.root rect.body') .attr('height', function () { return that.rootContainer.height; }) .attr('transform', function (d) { return 'translate(' + that.rootContainer.translateX + ',' + that.rootContainer.translateY + ')'; }); this.vis.selectAll('rect.body') .transition().duration(250) .style('opacity', (this.options.displayWiring ? 0.5 : 1)); this.vis .selectAll(".cable.cable-root.cable-" + dir) .each(function (d) { d.fromX = (invertX ? '' : '-') + 100; d.fromY = d.target.x; d.toX = (invertX ? '' : '-') + (d.target.y + (that.options.showCableLabels ? 50 : 125)); d.toY = d.target.x; // If a connector is internally wired, we draw the line to the middle (to visually "connect" them). if (d.target.data.wired) { d.fromX = 0; // -25; } // If a root connector is not connected, only show a small "stump". if (!d.target.children) { d.toX = parseInt((invertX ? '' : '-') + 200); } }) .attr('data-index', (d, i) => i) .interrupt().transition().delay(500).duration(250) .style('opacity', 1) .attr('d', function (d) { // @see CABLING-35 Cut the 'self wired' connectors more short if (d.target.data.wiredToItself || false) { if (dir === 'right') { d.toX -= 45; } else { d.toX += 45; } } if (invertX && d.target.data.wired) { const index = this.indexMapping.findIndex((i) => i == d.target.data.siblingId); const $selection = this.vis.select('[data-index="' + index + '"]'); if (index >= 0 && $selection.size()) { d.fromY = $selection.data()[0].fromY; return "M" + d.fromX + "," + d.fromY + "C" + (d.fromX+20) + "," + d.fromY + " " + (d.fromX+20) + "," + d.toY + " " + (d.fromX+40) + "," + d.toY + "L" + d.toX + "," + d.toY; } } return "M" + d.fromX + "," + d.fromY + "L" + d.toX + "," + d.toY; }.bind(this)); this.vis.selectAll('.connector-' + dir + '-title') .classed('stroked', this.options.displayWiring); return this; }, postProcess: function () { if (Object.isFunction(this.options.onAfterProcess)) { this.options.onAfterProcess.call(this); } return this; }, setData: function (data) { this.data = data; return this; }, selectObject: function (d) { var $object = this.vis.selectAll('[data-id="' + d.id + '"]'); if (!$object.classed('clicked')) { this.vis.selectAll('.clicked').classed('clicked', false); $object.classed('clicked', true); if (Object.isFunction(this.options.onObjSelect)) { this.options.onObjSelect.call(this, d); } } return this; }, selectCableObject: function (d) { var $object = this.vis.selectAll('[data-id="' + d.source.data.cableId + '"]'); if (!$object.classed('clicked')) { this.vis.selectAll('.clicked').classed('clicked', false); $object.classed('clicked', true); if (Object.isFunction(this.options.onCableSelect)) { this.options.onCableSelect.call(this, d); } } return this; }, selectConnector: function (d) { var $connector = this.vis.select('circle.connector-inner[data-connector-id="' + d.data.id + '"]'); if (! this.options.clickableConnectors) { return; } $connector.classed('hide', !$connector.classed('hide')); if (Object.isFunction(this.options.onConnectorSelect)) { this.options.onConnectorSelect.call(this, d); } return this; }, unselectConnectors: function (d) { var data = this.vis.selectAll('.connector-inner:not(.hide)').classed('hide', true).data(); if (Object.isFunction(this.options.onConnectorUnselect)) { this.options.onConnectorUnselect.call(this, data); } return this; }, unselectObject: function (data) { if (Object.isFunction(this.options.onObjUnselect)) { this.options.onObjUnselect.call(this, data); } return this; }, center: function () { var translateX = (this.options.width / 2), translateY = (this.options.height / 2); this.vis.attr('transform', "translate(" + translateX + "," + translateY + ")"); this.svg.select('rect').call(this.zoom.transform, d3.zoomIdentity.translate(translateX, translateY)); return this; } });
Die Datei müsste mit diesem neuen Inhalt überschrieben werden
Das dürfte weiterhelfen!
VG Leo
-
Servus @LFischer,
fantastico!
Vielen Dank, das ist perfekt.
Was für ein mächtiger Einsatz.LG Stefan