Line 1: |
Line 1: |
| $(document).ready(function() { | | $(document).ready(function() { |
− |
| |
| $.getScript('https://unpkg.com/vis-network/standalone/umd/vis-network.min.js').done(function() { | | $.getScript('https://unpkg.com/vis-network/standalone/umd/vis-network.min.js').done(function() { |
− | var pathId = 0;
| + | var pathId = 0; |
− | var newNodes = {};
| + | var newNodes = {}; |
− | var editNodes = {};
| + | var editNodes = {}; |
− | var editDeletedEdges = {};
| + | var editDeletedEdges = {}; |
− | var editDeletedNodes = {};
| + | var editDeletedNodes = {}; |
− |
| + | $(".InteractiveSemanticGraph").each(function(index) { |
− | $(".visNetworkGraph").each(function(index) {
| + | if ($('.InteractiveSemanticGraph').length) { //check if div element(s) exist |
− | if ($('.visNetworkGraph').length) { //check if div element(s) exist
| + | var input = JSON.parse(this.innerHTML); |
− | var input = JSON.parse(this.innerHTML);
| + | // create an array with nodes |
− |
| + | var nodes = new vis.DataSet([]); |
− | // create an array with nodes
| + | // create an array with edges |
− | var nodes = new vis.DataSet([]);
| + | var edges = new vis.DataSet([]); |
− | // create an array with edges
| + | //colors for the graph |
− | var edges = new vis.DataSet([]);
| + | var colors = []; |
− | //colors for the graph
| + | var oldGroups = {}; |
− | var colors = [];
| + | var givenDiv = this; |
− | var oldGroups = {};
| + | givenDiv.style.position = "relative"; |
− | var givenDiv = this;
| + | givenDiv.style.display = "inline-block"; |
− | givenDiv.style.position = "relative";
| |
− | givenDiv.style.display = "inline-block";
| |
− |
| |
| | | |
− |
| + | //Function for random colors |
− | function getColor() {
| + | var h = Math.random(); |
− | return "hsl(" + 360 * Math.random() + ',' + | + | var golden = 0.618033988749895; |
− | (25 + 70 * Math.random()) + '%,' +
| |
− | (85 + 10 * Math.random()) + '%)';
| |
− | }
| |
| | | |
− | var h = Math.random();
| + | function randomHSL() { |
− | var golden = 0.618033988749895;
| + | h += golden; |
− | function randomHSL() {
| + | h %= 1; |
− | h += golden;
| + | return "hsla(" + (360 * h) + "," + |
− | h %= 1;
| + | "70%," + |
− | //~~(360 * Math.random())
| + | "80%,1)"; |
− | return "hsla(" + (360 * h) + "," +
| + | } |
− | "70%," +
| + | for (var i = 0; i < input.properties.length; i++) { |
− | "80%,1)";
| + | colors.push(randomHSL()); |
− | }
| + | } |
| | | |
− | for (var i = 0; i < input.properties.length; i++) {
| + | function isLabelSet(id) { |
− | colors.push(randomHSL()); | + | node = nodes.get(id); |
− | }
| + | if (node === null) return false; |
− | | + | else return id; |
− | function isLabelSet(id) {
| + | } |
− | node = nodes.get(id);
| |
− | if (node === null) return false;
| |
− | else return id;
| |
− | }
| |
− | | |
− | //var colors = ['#ff7878', '#73ff77', '#e878ff', '#ffae57', '#80f8ff', '#ffff75', '#adadad', '#b482ff'];
| |
− | | |
− | nodes.add({
| |
− | id: input.root,
| |
− | label: input.root, //todo: query display title
| |
− | color: '#6dbfa9'
| |
− | });
| |
− | | |
− | //Creates API query Url with the given root and properties
| |
− | function createUrl(root, properties) {
| |
− | var url = `/w/api.php?action=ask&query=[[${encodeURIComponent(root)}]]`; | |
− | var propertiesVar = '';
| |
− | for (var i = 0; i < properties.length; i++) {
| |
− | propertiesVar += '|?' + encodeURIComponent(properties[i]);
| |
| | | |
| + | nodes.add({ |
| + | id: input.root, |
| + | label: input.root, //todo: query display title |
| + | color: '#6dbfa9' |
| + | }); |
| + | //Creates API query Url with the given root and properties |
| + | function createUrl(root, properties) { |
| + | if (properties[0] === "-Category") properties[0] = "Category"; |
| + | else if (root.startsWith("Category:")) root = ":" + root; //[[Category:X]] queries pages within this category, [[:Category:X]] the category itself |
| + | var url = `/w/api.php?action=ask&query=[[${encodeURIComponent(root)}]]`; |
| + | var propertiesVar = ''; |
| + | for (var i = 0; i < properties.length; i++) { |
| + | propertiesVar += '|?' + encodeURIComponent(properties[i]) + "=" + encodeURIComponent(properties[i]); //explicit label overwrites property display title. ToDo: extrakt label in result and get corresponding printout |
| + | propertiesVar += '|?' + encodeURIComponent(properties[i] + ".Display title of") + "=" + encodeURIComponent(properties[i] + ".Display title of"); //explicit query for display title due to slow update of the displaytitle page field |
| + | } |
| + | url = url + propertiesVar + '&format=json'; |
| + | return url; |
| } | | } |
| + | //Makes an API call with the given parameters and adds the results to the nodes and edges datasets. |
| + | //With a given nodeID the edges are set to the nodeID, else they are set to the root node. |
| + | function fetchData(root, properties, nodeID, setGroup, setColor) { |
| + | fetch(createUrl(root, properties)) |
| + | .then(response => response.json()) |
| + | .then(data => { |
| + | if (!nodeID && root) { //first query on root node |
| + | var rootNode = nodes.get(root); |
| + | rootNode.url = data.query.results[root].fullurl; |
| + | if (data.query.results[root].displaytitle) rootNode.label = data.query.results[root].displaytitle; |
| + | } |
| | | |
− | url = url + propertiesVar + '&format=json';
| + | for (var i = 0; i < properties.length; i++) { |
− | return url;
| |
− | }
| |
| | | |
− | //Makes an API call with the given parameters and adds the results to the nodes and edges datasets.
| + | for (var j = 0; j < data.query.results[root].printouts[properties[i]].length; j++) { |
− | //With a given nodeID the edges are set to the nodeID, else they are set to the root node.
| |
− | function fetchData(root, properties, nodeID, setGroup, setColor) {
| |
− | fetch(createUrl(root, properties))
| |
− | .then(response => response.json())
| |
− | .then(data => {
| |
− | if (!nodeID && root){ //first query on root node
| |
− | var rootNode = nodes.get(root);
| |
− | rootNode.url = data.query.results[root].fullurl;
| |
− | if (data.query.results[root].displaytitle) rootNode.label = data.query.results[root].displaytitle;
| |
− | }
| |
− | for (var i = 0; i < properties.length; i++) {
| |
− | for (var j = 0; j < data.query.results[root].printouts[properties[i]].length; j++) {
| |
− |
| |
− |
| |
− | //define colors
| |
− | if(!(properties[i] in legendColors) && setColor) {legendColors[properties[i]] = colors[i]; }
| |
− | else {setColor = legendColors[properties[i]]; colors[i] = legendColors[properties[i]]; colors[i] = legendColors[properties[i]];}
| |
− | //define id and label. use displaytitle if available. Use string representation of non-page properties
| |
− | var id = "";
| |
− | var label = "";
| |
− | if (data.query.results[root].printouts[properties[i]][j].fulltext) id = data.query.results[root].printouts[properties[i]][j].fulltext;
| |
− | else if(data.query.results[root].printouts[properties[i]][j].value) id = '' + data.query.results[root].printouts[properties[i]][j].value + ' ' + data.query.results[root].printouts[properties[i]][j].unit;
| |
− | else id = data.query.results[root].printouts[properties[i]][j].toString();
| |
− | if (data.query.results[root].printouts[properties[i]][j].displaytitle) label = data.query.results[root].printouts[properties[i]][j].displaytitle;
| |
− | if (label === "") label = id;
| |
− |
| |
− | if (isLabelSet(id) === false) {
| |
| | | |
− | if (setGroup && setColor) { | + | //define colors |
− | nodes.add({ | + | if (!(properties[i] in legendColors) && setColor) { |
− | id: id,
| + | legendColors[properties[i]] = colors[i]; |
− | label: label,
| |
− | color: setColor,
| |
− | group: setGroup[0],
| |
− | hidden: false,
| |
− | url: data.query.results[root].printouts[properties[i]][j].fullurl,
| |
− | oncontext: true,
| |
− | });
| |
− | oldGroups["" + id] = setGroup[0];
| |
| } else { | | } else { |
− | nodes.add({ | + | setColor = legendColors[properties[i]]; |
− | id: id,
| + | colors[i] = legendColors[properties[i]]; |
− | label: label,
| + | colors[i] = legendColors[properties[i]]; |
− | color: colors[i],
| |
− | group: properties[i],
| |
− | hidden: false,
| |
− | url: data.query.results[root].printouts[properties[i]][j].fullurl
| |
− | });
| |
− | oldGroups["" + id] = properties[i]; | |
| } | | } |
− | if (nodeID) { | + | //define id and label. use displaytitle if available. Use string representation of non-page properties |
| + | var id = ""; |
| + | var label = ""; |
| + | if (data.query.results[root].printouts[properties[i]][j].fulltext) id = data.query.results[root].printouts[properties[i]][j].fulltext; |
| + | else if (data.query.results[root].printouts[properties[i]][j].value) id = '' + data.query.results[root].printouts[properties[i]][j].value + ' ' + data.query.results[root].printouts[properties[i]][j].unit; |
| + | else id = data.query.results[root].printouts[properties[i]][j].toString(); |
| + | if (data.query.results[root].printouts[properties[i]][j].displaytitle) label = data.query.results[root].printouts[properties[i]][j].displaytitle; |
| + | if (data.query.results[root].printouts[properties[i] + ".Display title of"][j]) label = data.query.results[root].printouts[properties[i] + ".Display title of"][j]; //explicit use property display title due to slow update of the displaytitle page field |
| + | if (label === "") label = id; |
| + | if (isLabelSet(id) === false) { |
| + | if (setGroup && setColor) { |
| + | nodes.add({ |
| + | id: id, |
| + | label: label, |
| + | color: setColor, |
| + | group: setGroup[0], |
| + | hidden: false, |
| + | url: data.query.results[root].printouts[properties[i]][j].fullurl, |
| + | oncontext: true, |
| + | }); |
| + | oldGroups["" + id] = setGroup[0]; |
| + | } else { |
| + | nodes.add({ |
| + | id: id, |
| + | label: label, |
| + | color: colors[i], |
| + | group: properties[i], |
| + | hidden: false, |
| + | url: data.query.results[root].printouts[properties[i]][j].fullurl |
| + | }); |
| + | oldGroups["" + id] = properties[i]; |
| + | } |
| + | if (nodeID) { |
| + | edges.add({ |
| + | from: nodeID, |
| + | to: id, |
| + | label: properties[i], |
| + | color: colors[i], |
| + | group: properties[i] |
| + | }); |
| + | } else { |
| + | edges.add({ |
| + | from: input.root, |
| + | to: id, |
| + | label: properties[i], |
| + | color: colors[i], |
| + | group: properties[i] |
| + | }); |
| + | } |
| + | } else { |
| edges.add({ | | edges.add({ |
| from: nodeID, | | from: nodeID, |
− | to: id, | + | to: isLabelSet(id), |
| label: properties[i], | | label: properties[i], |
− | color: colors[i], | + | color: setColor, |
− | group: properties[i]
| |
− | });
| |
− | } else {
| |
− | edges.add({
| |
− | from: input.root,
| |
− | to: id,
| |
− | label: properties[i],
| |
− | color: colors[i],
| |
| group: properties[i] | | group: properties[i] |
| }); | | }); |
| } | | } |
− |
| |
− | } else {
| |
− | edges.add({
| |
− | from: nodeID,
| |
− | to: isLabelSet(id),
| |
− | label: properties[i],
| |
− | color: setColor,
| |
− | group: properties[i]
| |
− | });
| |
| } | | } |
| } | | } |
| + | network.setOptions(options); |
| + | network.body.emitter.emit('_dataChanged'); |
| + | network.redraw(); |
| + | }); |
| + | } |
| + | fetchData(input.root, input.properties); |
| + | // create a network |
| + | var container = this; //document.getElementById("InteractiveSemanticGraph"); |
| + | var data = { |
| + | nodes: nodes, |
| + | edges: edges, |
| + | }; |
| + | var options = { |
| + | width: "100%", |
| + | height: "100%", |
| + | interaction: { |
| + | hover: true |
| + | }, |
| + | manipulation: { |
| + | enabled: true, |
| + | editEdge: false, |
| + | deleteNode: function(data, callback) { |
| + | deleteSelectedNode(data, callback) |
| + | }.bind(this), |
| + | deleteEdge: function(data, callback) { |
| + | deleteSelectedEdge(data, callback) |
| + | }.bind(this), |
| + | addNode: function(data, callback) { |
| + | // filling in the popup DOM elements |
| + | document.getElementById("node-operation").innerText = "Add Node"; |
| + | dragElement(document.getElementById("node-popUp")); |
| + | editNode(data, clearNodePopUp, callback); |
| + | }, |
| + | addEdge: function(data, callback) { |
| + | if (data.from == data.to) { |
| + | var r = confirm("Do you want to connect the node to itself?"); |
| + | if (r != true) { |
| + | callback(null); |
| + | return; |
| + | } |
| + | } |
| + | document.getElementById("edge-operation").innerText = "Add Edge"; |
| + | dragElement(document.getElementById("edge-popUp")); |
| + | editEdgeWithoutDrag(data, callback); |
| + | }, |
| + | }, |
| + | edges: { |
| + | arrows: { |
| + | to: { |
| + | enabled: true |
| + | }, |
| + | //from:{enabled: true} |
| } | | } |
− | network.setOptions(options);
| + | }, |
− | network.body.emitter.emit('_dataChanged');
| + | groups: { |
− | network.redraw();
| + | useDefaultGroups: false |
− |
| + | }, |
− | }); | + | physics: { |
− | }
| + | stabilization: { |
− | fetchData(input.root, input.properties);
| + | enabled: true, |
− | // create a network
| + | }, |
− | var container = this; //document.getElementById("visNetworkGraph");
| + | barnesHut: { |
− | var data = {
| + | gravitationalConstant: -40000, |
− | nodes: nodes,
| + | centralGravity: 0, |
− | edges: edges,
| + | springLength: 0, |
− | };
| + | springConstant: 0.5, |
− | var options = {
| + | damping: 1, |
− | width: "100%",
| + | avoidOverlap: 0 |
− | height: "100%",
| |
− | interaction: {
| |
− | hover: true
| |
− | },
| |
− | manipulation: {
| |
− | enabled: true,
| |
− | editEdge: false,
| |
− | deleteNode: function (data, callback) {deleteSelectedNode(data, callback)}.bind(this),
| |
− | deleteEdge: function (data, callback) {deleteSelectedEdge(data, callback)}.bind(this),
| |
− | addNode: function (data, callback) {
| |
− |
| |
− | // filling in the popup DOM elements
| |
− | document.getElementById("node-operation").innerText = "Add Node";
| |
− | dragElement(document.getElementById("node-popUp"));
| |
− | editNode(data, clearNodePopUp, callback);
| |
− | },
| |
− | addEdge: function (data, callback) {
| |
− | if (data.from == data.to) {
| |
− | var r = confirm("Do you want to connect the node to itself?");
| |
− | if (r != true) {
| |
− | callback(null);
| |
− | return;
| |
− | }
| |
− | }
| |
− | document.getElementById("edge-operation").innerText = "Add Edge";
| |
− | dragElement(document.getElementById("edge-popUp"));
| |
− | editEdgeWithoutDrag(data, callback);
| |
− | },
| |
− | },
| |
− | edges: {
| |
− | arrows: {
| |
− | to: {
| |
− | enabled: true | |
| }, | | }, |
− | //from:{enabled: true} | + | maxVelocity: 5 |
− | }
| |
− | },
| |
− | groups: {
| |
− | useDefaultGroups: false
| |
− | },
| |
− | physics: {
| |
− | stabilization: {
| |
− | enabled: true,
| |
− | },
| |
− | barnesHut: {
| |
− | gravitationalConstant: -40000,
| |
− | centralGravity: 0,
| |
− | springLength: 0,
| |
− | springConstant: 0.5,
| |
− | damping: 1,
| |
− | avoidOverlap: 0
| |
| }, | | }, |
− | maxVelocity: 5
| |
− | },
| |
− |
| |
− | };
| |
− | //Creates groups in the options and sets them all to hidden:false.
| |
− | for (var i = 0; i < input.properties.length; i++) {
| |
− | options.groups[input.properties[i]] = {
| |
− | hidden: false
| |
| }; | | }; |
− | }
| + | //Creates groups in the options and sets them all to hidden:false. |
− | var network = new vis.Network(container, data, options);
| + | for (var i = 0; i < input.properties.length; i++) { |
− |
| + | options.groups[input.properties[i]] = { |
− | | + | hidden: false |
− | | + | }; |
− | | + | } |
− | function getAllEdgesBetween(node1,node2) { | + | var network = new vis.Network(container, data, options); |
− | return edges.get().filter(function (edge) {
| + | |
− | return (edge.from === node1 && edge.to === node2 )|| (edge.from === node2 && edge.to === node1);
| + | //The function getAllEdgesBetween() returns all edges between two nodes |
− | });
| + | function getAllEdgesBetween(node1, node2) { |
− | } | + | return edges.get().filter(function(edge) { |
− | | + | return (edge.from === node1 && edge.to === node2) || (edge.from === node2 && edge.to === node1); |
− | function getAllCombs(arrays){
| + | }); |
− | var numberOfCombs = 1;
| + | } |
− | for(var i=0; i<arrays.length; i++){
| |
− | numberOfCombs = numberOfCombs * arrays[i].length;
| |
− | }
| |
− | var allCombs = new Array(numberOfCombs);
| |
− | for(var i=0; i<allCombs.length; i++){
| |
− | allCombs[i] = new Array(arrays.length);
| |
− | }
| |
− |
| |
− | for(var i=0; i<arrays.length; i++){
| |
− | var current = arrays[i];
| |
− | for(var c=0; c<numberOfCombs; c++){
| |
− |
| |
− | for(var j=0; j<current.length; j++){
| |
− | allCombs[c][i] = current[c%current.length];
| |
| | | |
− | }
| + | //Cartesian Product of arrays |
− | }
| + | function cartesianProduct(arr) { |
− | }
| + | return arr.reduce(function(a,b){ |
− |
| + | return a.map(function(x){ |
− | return allCombs;
| + | return b.map(function(y){ |
− | } | + | return x.concat([y]); |
− | | + | }) |
− | function getEdgePathsForPath(path){ | + | }).reduce(function(a,b){ return a.concat(b) },[]) |
− | var arraysOfEdgesForNodeInPath = [];
| + | }, [[]]) |
− | for(var i=1; i<path.length; i++){
| + | } |
− | var edgesBetween = getAllEdgesBetween(path[i-1], path[i]);
| + | //Cartesian Product of given arrays |
− | var localedgesBetween = edgesBetween.slice();
| + | function getAllCombs(arrays) { |
− | arraysOfEdgesForNodeInPath.push(localedgesBetween);
| + | var allCombs = cartesianProduct(arrays); |
− | }
| + | return allCombs; |
− | var allEdgePaths = getAllCombs(arraysOfEdgesForNodeInPath);
| + | } |
− | return allEdgePaths; | + | //Gets Path array with nodes, returns Cartesian Product of edges |
− | } | + | function getEdgePathsForPath(path) { |
− | | + | var arraysOfEdgesForNodeInPath = []; |
− | function reverseLabel(label){ | + | for (var i = 1; i < path.length; i++) { |
− | if(label[0] == "-"){
| + | var edgesBetween = getAllEdgesBetween(path[i - 1], path[i]); |
− | return label.substring(1);
| + | var localedgesBetween = edgesBetween.slice(); |
− | }
| + | |
− | else{
| + | arraysOfEdgesForNodeInPath.push(localedgesBetween); |
− | return "-" + label;
| + | } |
− | }
| + | var allEdgePaths = getAllCombs(arraysOfEdgesForNodeInPath); |
− | } | + | return allEdgePaths; |
− | | + | } |
− | function getEdgeLabelStringsForPath(path){ | + | //Given Label is reversed with "-" or "-" is removed |
− | var allEdgePaths = getEdgePathsForPath(path);
| + | function reverseLabel(label) { |
− | var allStrings = new Array(allEdgePaths.length);
| + | if (label[0] == "-") { |
− | for(var i=0; i<allEdgePaths.length; i++){
| + | return label.substring(1); |
− | var s = "";
| + | } else { |
− | for(var j=0; j<allEdgePaths[i].length;j++){
| + | return "-" + label; |
− |
| + | } |
− | var edge = allEdgePaths[i][j];
| + | } |
− | var label = edge.label;
| + | //Gets Path array with nodes, returns all possible edge paths |
− | var nodeId1 = path[j];
| + | function getEdgeLabelStringsForPath(path) { |
− | var nodeId2 = path[j+1];
| + | var allEdgePaths = getEdgePathsForPath(path); |
− | if(edge.to == nodeId1 && edge.from == nodeId2){
| + | var allStrings = new Array(allEdgePaths.length); |
− | label = reverseLabel(label);
| + | for (var i = 0; i < allEdgePaths.length; i++) { |
− | }
| + | var s = ""; |
− | if(j == (allEdgePaths[i].length - 1)){
| + | for (var j = 0; j < allEdgePaths[i].length; j++) { |
− | s = s + label;
| + | var edge = allEdgePaths[i][j]; |
− | }
| + | var label = edge.label; |
− | else{
| + | var nodeId1 = path[j]; |
− | s = s + label + ".";
| + | var nodeId2 = path[j + 1]; |
− | }
| + | if (edge.to == nodeId1 && edge.from == nodeId2) { |
− |
| + | label = reverseLabel(label); |
− |
| + | } |
− | }
| + | if (j == (allEdgePaths[i].length - 1)) { |
− | allStrings[i] = s;
| + | s = s + label; |
− | }
| + | } else { |
− | return allStrings;
| + | s = s + label + "."; |
− | } | + | } |
− | | + | } |
− | function getAllStringsForAllPaths(paths){ | + | allStrings[i] = s; |
− | var arrayOfAllStrings = [];
| + | } |
− | for(var i=0; i<paths.length;i++){
| + | return allStrings; |
− | var path = paths[i];
| + | } |
− | var allStrings = getEdgeLabelStringsForPath(path);
| + | //Gets Path arrays with nodes, returns all possible edge paths |
− | arrayOfAllStrings.push(allStrings);
| + | function getAllStringsForAllPaths(paths) { |
− | }
| + | var arrayOfAllStrings = []; |
− | return arrayOfAllStrings; | + | for (var i = 0; i < paths.length; i++) { |
− | } | + | var path = paths[i]; |
− | | + | var allStrings = getEdgeLabelStringsForPath(path); |
− | | + | arrayOfAllStrings.push(allStrings); |
− | | + | } |
− | function removeItem(arr, value) { | + | return arrayOfAllStrings; |
− | var index = arr.indexOf(value);
| + | } |
− | if (index > -1) {
| + | //Removes the given value from the given array |
− | arr.splice(index, 1);
| + | function removeItem(arr, value) { |
− | }
| + | var index = arr.indexOf(value); |
− | return arr;
| + | if (index > -1) { |
− | } | + | arr.splice(index, 1); |
− | | + | } |
− | | + | return arr; |
− | | + | } |
− | | + | //Returns all paths between startNode and endNode |
− | function findAllPaths(startNode, endNode){ | + | function findAllPaths(startNode, endNode) { |
− | var visitedNodes = [];
| + | var visitedNodes = []; |
− | var currentPath = [];
| + | var currentPath = []; |
− | var allPaths = [];
| + | var allPaths = []; |
− | dfs(startNode, endNode, currentPath, allPaths, visitedNodes);
| + | dfs(startNode, endNode, currentPath, allPaths, visitedNodes); |
− | return allPaths;
| + | return allPaths; |
− | } | + | } |
− | | + | //Algorithm to search for all paths between two nodes |
− | function dfs(start, end, currentPath, allPaths, visitedNodes){ | + | function dfs(start, end, currentPath, allPaths, visitedNodes) { |
− | if(visitedNodes.includes(start)) return;
| + | if (visitedNodes.includes(start)) return; |
− | visitedNodes.push(start);
| + | visitedNodes.push(start); |
− | currentPath.push(start);
| + | currentPath.push(start); |
− | if(start == end){
| + | if (start == end) { |
− | var localCurrentPath = currentPath.slice();
| + | var localCurrentPath = currentPath.slice(); |
− | allPaths.push(localCurrentPath);
| + | allPaths.push(localCurrentPath); |
− | removeItem(visitedNodes, start);
| + | removeItem(visitedNodes, start); |
− | currentPath.pop();
| + | currentPath.pop(); |
− | return;
| + | return; |
− | }
| + | } |
− |
| + | var neighbours = network.getConnectedNodes(start); |
− | var neighbours = network.getConnectedNodes(start);
| + | for (var i = 0; i < neighbours.length; i++) { |
− | for(var i = 0; i < neighbours.length; i++){
| + | var current = neighbours[i]; |
− | var current = neighbours[i];
| + | dfs(current, end, currentPath, allPaths, visitedNodes); |
− | dfs(current, end, currentPath, allPaths, visitedNodes);
| + | } |
− | }
| + | currentPath.pop(); |
− | | + | removeItem(visitedNodes, start); |
− | currentPath.pop();
| |
− | removeItem(visitedNodes, start);
| |
− | | |
− | }
| |
− | | |
− | | |
− | | |
− | | |
− | | |
− |
| |
− |
| |
− | | |
− | //This function deletes all children of a given node.
| |
− | function getAllReachableNodesTo(nodeId, excludeIds, reachableNodes) {
| |
− | | |
− | if (reachableNodes.includes(nodeId) || excludeIds.includes(nodeId)) { return;}
| |
− | var children = network.getConnectedNodes(nodeId);
| |
− | reachableNodes.push(nodeId);
| |
− | for (var i = 0; i < children.length; i++) {
| |
− | getAllReachableNodesTo(children[i], excludeIds, reachableNodes);
| |
− | //if(excludeIds.includes(children[i]))continue;
| |
− | //reachableNodes.push(children[i]);
| |
| } | | } |
− | }
| + | //Algorithm that gets all nodes that are reachable from the given node in the graph |
− |
| + | function getAllReachableNodesTo(nodeId, excludeIds, reachableNodes) { |
− | function deleteNodesChildren(nodeId, deleteEdge) {
| + | if (reachableNodes.includes(nodeId) || excludeIds.includes(nodeId)) { |
− | var excludedIds = [];
| + | return; |
− | if(deleteEdge === true){
| + | } |
− | console.log("deleteEdge true")
| + | var children = network.getConnectedNodes(nodeId); |
− | }else{
| + | reachableNodes.push(nodeId); |
− | excludedIds.push(nodeId);
| + | for (var i = 0; i < children.length; i++) { |
| + | getAllReachableNodesTo(children[i], excludeIds, reachableNodes); |
| + | //if(excludeIds.includes(children[i]))continue; |
| + | //reachableNodes.push(children[i]); |
| + | } |
| } | | } |
− | var reachableNodesTo = []; | + | //This function deletes all children of a given node. |
− | getAllReachableNodesTo(input.root, excludedIds, reachableNodesTo);
| + | function deleteNodesChildren(nodeId, deleteEdge) { |
− | var nodesToDelete = [];
| + | var excludedIds = []; |
− | var allIds = nodes.getIds();
| + | if (deleteEdge === true) { |
− | | + | console.log("deleteEdge true") |
− | for (var i = 0; i < allIds.length; i++) {
| + | } else { |
− | if (reachableNodesTo.includes(allIds[i])) continue;
| + | excludedIds.push(nodeId); |
− | if (allIds[i] == nodeId) {
| + | } |
− | deleteEdges(nodeId);
| + | var reachableNodesTo = []; |
− | continue;
| + | getAllReachableNodesTo(input.root, excludedIds, reachableNodesTo); |
| + | var nodesToDelete = []; |
| + | var allIds = nodes.getIds(); |
| + | for (var i = 0; i < allIds.length; i++) { |
| + | if (reachableNodesTo.includes(allIds[i])) continue; |
| + | if (allIds[i] == nodeId) { |
| + | deleteEdges(nodeId); |
| + | continue; |
| + | } |
| + | nodesToDelete.push(allIds[i]); |
| + | deleteEdges(allIds[i]); |
| + | nodes.remove(allIds[i]); |
| + | delete oldGroups["" + allIds[i]]; |
| + | delete objClickedProps["" + allIds[i]]; |
| } | | } |
− | nodesToDelete.push(allIds[i]); | + | return nodesToDelete; |
− | deleteEdges(allIds[i]);
| |
− | nodes.remove(allIds[i]);
| |
− | delete oldGroups["" + allIds[i]];
| |
− | delete objClickedProps["" + allIds[i]];
| |
| } | | } |
− | | + | //Deletes all edges from given node |
− | return nodesToDelete; | + | function deleteEdges(nodeID) { |
− | }
| + | var fromEdges = edges.get({ |
− |
| + | filter: function(item) { |
− | function deleteEdges(nodeID){
| + | return item.from == nodeID; |
− | var fromEdges = edges.get({
| + | } |
− | filter: function (item) {
| + | }); |
− | return item.from == nodeID;
| + | for (var j = 0; j < fromEdges.length; j++) { |
| + | edges.remove(fromEdges[j]); |
| } | | } |
− | });
| |
− |
| |
− | for(var j = 0; j < fromEdges.length; j++){
| |
− | edges.remove(fromEdges[j]);
| |
− | }
| |
− | }
| |
− | var nodesClicked = [];
| |
− | var tip = '<p><strong>Hinweis:</strong> Um sich einen Pfad zwischen zwei Knoten ausgeben zu lassen, <em>Strg</em> gedrückt halten und die gewünschten zwei Knoten mit der <em>linken Maustaste</em> anklicken. </p>'
| |
− | this.insertAdjacentHTML('afterbegin', tip);
| |
− |
| |
− | network.on("click", function(params) {
| |
− |
| |
− | if (params.nodes[0] && params.event.srcEvent.ctrlKey) {
| |
− |
| |
− | if(nodesClicked.length < 2){
| |
− | nodesClicked.push(params.nodes[0]);
| |
− | }
| |
− | if(nodesClicked.length == 2 && nodesClicked[0] != nodesClicked[1]){
| |
− | var foundPaths = findAllPaths(nodesClicked[0],nodesClicked[1]);
| |
− | //.querySelector('[id^="poll-"]').id;
| |
− | if(document.querySelectorAll('[id^="fullPath"]')){
| |
− | for(var i=0; i < document.querySelectorAll('[id^="fullPath"]').length; i++){
| |
− | document.querySelectorAll('[id^="fullPath"]')[i].remove();
| |
− | }
| |
− | }
| |
− | var element = '<div id="fullPath'+ pathId +'"></div>'
| |
− | givenDiv.children[0].insertAdjacentHTML('afterend', element);
| |
− |
| |
− | var allStringsArray = getAllStringsForAllPaths(foundPaths);
| |
− |
| |
− | var stringDiv = givenDiv.querySelector('#fullPath' + pathId);
| |
− |
| |
− | if(foundPaths.length == 1){stringDiv.innerHTML = "<strong>Gefundener Pfad:</strong><br>"}else{stringDiv.innerHTML = "<strong>Gefundene Pfade:</strong><br>"}
| |
− |
| |
− | for(var s=0; s<foundPaths.length; s++){
| |
− | if(foundPaths.length == 1){var pathNumb = ""}else{var pathNumb = "<strong>" + (s+1) + ". Pfad:</strong> <br>"}
| |
− |
| |
− | stringDiv.innerHTML += pathNumb + "<strong>Knoten: </strong>";
| |
− | for(var t=0; t<foundPaths[s].length; t++){
| |
− | var currentFoundPath = foundPaths[s][t];
| |
− |
| |
− | if(t == (foundPaths[s].length - 1)){
| |
− | stringDiv.innerHTML = stringDiv.innerHTML + currentFoundPath + " ";
| |
− | }
| |
− | else{
| |
− | stringDiv.innerHTML = stringDiv.innerHTML + currentFoundPath + " - ";
| |
− | }
| |
− | }
| |
− | stringDiv.innerHTML += "<br>"
| |
− | stringDiv.innerHTML += "<strong>Kanten:</strong> "
| |
− | for(var t=0; t<allStringsArray[s].length; t++){
| |
− | var currentString = allStringsArray[s][t];
| |
− | var currentFoundPath = foundPaths[s][t];
| |
− | var stringDiv = givenDiv.querySelector('#fullPath' + pathId);
| |
− | stringDiv.innerHTML = stringDiv.innerHTML + currentString;
| |
− | }
| |
− | stringDiv.innerHTML += "<br>"
| |
− | }
| |
− |
| |
− | nodesClicked = [];
| |
− |
| |
− | }
| |
− | if(nodesClicked[0] === nodesClicked[1] || nodesClicked.length > 2){
| |
− | nodesClicked = [];
| |
− | }
| |
− |
| |
− |
| |
| } | | } |
− | pathId++;
| + | var nodesClicked = []; |
− | });
| + | var tip = '<p><strong>Hinweis:</strong> Um sich einen Pfad zwischen zwei Knoten ausgeben zu lassen, <em>Strg</em> gedrückt halten und die gewünschten zwei Knoten mit der <em>linken Maustaste</em> anklicken. </p>' |
− | | + | this.insertAdjacentHTML('afterbegin', tip); |
− | $(document).keyup(function(event) {
| + | //Ctrl and click on two nodes, puts out all possible paths between the two nodes under the tip |
− | if(!event.ctrlKey){
| + | network.on("click", function(params) { |
− | nodesClicked = [];
| + | if (params.nodes[0] && params.event.srcEvent.ctrlKey) { |
− | }
| + | if (nodesClicked.length < 2) { |
− | });
| + | nodesClicked.push(params.nodes[0]); |
− |
| + | } |
− |
| + | if (nodesClicked.length == 2 && nodesClicked[0] != nodesClicked[1]) { |
− |
| + | var foundPaths = findAllPaths(nodesClicked[0], nodesClicked[1]); |
− |
| + | //.querySelector('[id^="poll-"]').id; |
− |
| + | if (document.querySelectorAll('[id^="fullPath"]')) { |
− | | + | for (var i = 0; i < document.querySelectorAll('[id^="fullPath"]').length; i++) { |
− | var contextCreatedProps = [];
| + | document.querySelectorAll('[id^="fullPath"]')[i].remove(); |
− | | |
− | network.on("doubleClick", function(params) {
| |
− |
| |
− | if (params.nodes[0]) {
| |
− |
| |
− | var conManNodes = network.getConnectedNodes(params.nodes[0], 'to');
| |
− |
| |
− | var onlyConManNodes = true;
| |
− | for(var i = 0; i < conManNodes.length;i++){
| |
− |
| |
− |
| |
− | if(!(nodes.get(conManNodes[i]).oncontext || nodes.get(conManNodes[i]).manually)){
| |
− | onlyConManNodes = false;
| |
− | }
| |
− | }
| |
− |
| |
− | //Node is expanded -> delete it and all nodes related to its expansion
| |
− | if (network.getConnectedNodes(params.nodes[0]).length > 1 && onlyConManNodes == false) {
| |
− | deleteNodesChildren(params.nodes[0]);
| |
− | for (var i = 0; i < contextCreatedProps.length; i++) {
| |
− | var noNodesInNetwork = true;
| |
− | for (var j = 0; j < nodes.getIds().length; j++) {
| |
− | if (contextCreatedProps[i] == nodes.get(nodes.getIds()[j]).group) {
| |
− | noNodesInNetwork = false;
| |
| } | | } |
| } | | } |
− | if (noNodesInNetwork === true) { | + | var element = '<div id="fullPath' + pathId + '"></div>' |
− | givenDiv.querySelector('#' + contextCreatedProps[i]).remove();
| + | givenDiv.children[0].insertAdjacentHTML('afterend', element); |
− | contextCreatedProps.splice(contextCreatedProps.indexOf(contextCreatedProps[i]), 1);
| + | var allStringsArray = getAllStringsForAllPaths(foundPaths); |
− | i--; | + | var stringDiv = givenDiv.querySelector('#fullPath' + pathId); |
| + | if (foundPaths.length == 1) { |
| + | stringDiv.innerHTML = "<strong>Gefundener Pfad:</strong><br>" |
| + | } else { |
| + | stringDiv.innerHTML = "<strong>Gefundene Pfade:</strong><br>" |
| } | | } |
| + | for (var s = 0; s < foundPaths.length; s++) { |
| + | if (foundPaths.length == 1) { |
| + | var pathNumb = "" |
| + | } else { |
| + | var pathNumb = "<strong>" + (s + 1) + ". Pfad:</strong> <br>" |
| + | } |
| + | stringDiv.innerHTML += pathNumb + "<strong>Knoten: </strong>"; |
| + | for (var t = 0; t < foundPaths[s].length; t++) { |
| + | var currentFoundPath = foundPaths[s][t]; |
| + | if (t == (foundPaths[s].length - 1)) { |
| + | stringDiv.innerHTML = stringDiv.innerHTML + currentFoundPath + " "; |
| + | } else { |
| + | stringDiv.innerHTML = stringDiv.innerHTML + currentFoundPath + " - "; |
| + | } |
| + | } |
| + | stringDiv.innerHTML += "<br>" |
| + | stringDiv.innerHTML += "<strong>Kanten:</strong><br>" |
| + | for (var t = 0; t < allStringsArray[s].length; t++) { |
| + | var currentString = allStringsArray[s][t]; |
| + | var currentFoundPath = foundPaths[s][t]; |
| + | var stringDiv = givenDiv.querySelector('#fullPath' + pathId); |
| + | stringDiv.innerHTML = stringDiv.innerHTML + '● ' + currentString + '<br>'; |
| + | } |
| + | stringDiv.innerHTML += "<br>" |
| + | } |
| + | nodesClicked = []; |
| + | } |
| + | if (nodesClicked[0] === nodesClicked[1] || nodesClicked.length > 2) { |
| + | nodesClicked = []; |
| } | | } |
− | delete objClickedProps["" + params.nodes[0]];
| |
− |
| |
− | //nodesArray.splice(nodesArray.indexOf(params.nodes[0]), 1);
| |
− | } else {
| |
− | //Node is unexpanded -> expand it
| |
− | var nodeById = nodes.get(params.nodes[0]);
| |
− | fetchData(nodeById.id, input.properties, params.nodes[0]);
| |
− | //nodesArray.push(params.nodes[0]);
| |
| } | | } |
− | | + | pathId++; |
− | } | + | }); |
− | });
| + | $(document).keyup(function(event) { |
− |
| + | if (!event.ctrlKey) { |
− | function newGroup(node, legendGroup) {
| + | nodesClicked = []; |
| + | } |
| + | }); |
| + | var contextCreatedProps = []; |
| | | |
− | nodes.update({ | + | network.on("doubleClick", function(params) { |
− | id: node,
| + | if (params.nodes[0]) { |
− | group: legendGroup | + | //Checks if all node children are created from context menu or manually, if so it creates nodes for before defined properties else it deletes all children |
| + | var conManNodes = network.getConnectedNodes(params.nodes[0], 'to'); |
| + | var onlyConManNodes = true; |
| + | for (var i = 0; i < conManNodes.length; i++) { |
| + | if (!(nodes.get(conManNodes[i]).oncontext || nodes.get(conManNodes[i]).manually)) { |
| + | onlyConManNodes = false; |
| + | } |
| + | } |
| + | //Node is expanded -> delete it and all nodes related to its expansion |
| + | if (network.getConnectedNodes(params.nodes[0]).length > 1 && onlyConManNodes == false) { |
| + | deleteNodesChildren(params.nodes[0]); |
| + | for (var i = 0; i < contextCreatedProps.length; i++) { |
| + | var noNodesInNetwork = true; |
| + | for (var j = 0; j < nodes.getIds().length; j++) { |
| + | if (contextCreatedProps[i] == nodes.get(nodes.getIds()[j]).group) { |
| + | noNodesInNetwork = false; |
| + | } |
| + | } |
| + | if (noNodesInNetwork === true) { |
| + | givenDiv.querySelector('#' + contextCreatedProps[i]).remove(); |
| + | contextCreatedProps.splice(contextCreatedProps.indexOf(contextCreatedProps[i]), 1); |
| + | i--; |
| + | } |
| + | } |
| + | delete objClickedProps["" + params.nodes[0]]; |
| + | //nodesArray.splice(nodesArray.indexOf(params.nodes[0]), 1); |
| + | } else { |
| + | //Node is unexpanded -> expand it |
| + | var nodeById = nodes.get(params.nodes[0]); |
| + | fetchData(nodeById.id, input.properties, params.nodes[0]); |
| + | //nodesArray.push(params.nodes[0]); |
| + | } |
| + | } |
| }); | | }); |
| | | |
− | | + | function newGroup(node, legendGroup) { |
− | var connectedNodes = network.getConnectedNodes(node, 'to');
| + | nodes.update({ |
− | | + | id: node, |
− | for (var i = 0; i < connectedNodes.length; i++) {
| + | group: legendGroup |
− | newGroup(connectedNodes[i], legendGroup);
| + | }); |
| + | var connectedNodes = network.getConnectedNodes(node, 'to'); |
| + | for (var i = 0; i < connectedNodes.length; i++) { |
| + | newGroup(connectedNodes[i], legendGroup); |
| + | } |
| } | | } |
− | }
| + | //Checks, if a node has a path over visible edges to the root node. |
− | | + | //If not, the nodes gets hidden |
− | //Checks, if a node has a path over visible edges to the root node.
| + | function setNodeVisibilityByVisiblePath(nodeId, rootNodeId) { |
− | //If not, the nodes gets hidden
| + | if (nodeId == rootNodeId) return true; //root is always visible |
− | function setNodeVisibilityByVisiblePath(nodeId, rootNodeId){
| + | var node = nodes.get(nodeId); |
− | if (nodeId == rootNodeId) return true; //root is always visible
| + | if (node.visited) return !node.hidden //prevent circles. ToDo: Reuse results between runs |
− | var node = nodes.get(nodeId);
| + | node.visited = true; |
− | if (node.visited) return !node.hidden //prevent circles. ToDo: Reuse results between runs
| + | node.hidden = true; |
− | node.visited = true;
| + | var connectedEdgesIds = network.getConnectedEdges(nodeId); |
− | node.hidden = true;
| + | var connectedEdges = edges.get(connectedEdgesIds); |
− | var connectedEdgesIds = network.getConnectedEdges(nodeId);
| + | connectedEdges.forEach(function(edge) { |
− | var connectedEdges = edges.get(connectedEdgesIds);
| + | if (edge.hidden) return; //don't follow hidden edges |
− | connectedEdges.forEach(function(edge) {
| + | var connectedNodesIds = network.getConnectedNodes(edge.id); |
− | if (edge.hidden) return; //don't follow hidden edges
| + | var connectedNodes = nodes.get(connectedNodesIds); |
− | var connectedNodesIds = network.getConnectedNodes(edge.id);
| + | connectedNodes.forEach(function(connectedNode) { |
− | var connectedNodes = nodes.get(connectedNodesIds);
| + | if (connectedNode.id == nodeId) return; //prevent self evaluation |
− | connectedNodes.forEach(function(connectedNode) {
| + | if (setNodeVisibilityByVisiblePath(connectedNode.id, rootNodeId)) { |
− | if (connectedNode.id == nodeId) return; //prevent self evaluation
| + | node.hidden = false; //set node visible, if at least one connected node is visible |
− | if (setNodeVisibilityByVisiblePath(connectedNode.id, rootNodeId)) {
| + | } |
− | node.hidden = false; //set node visible, if at least one connected node is visible
| + | }); |
− | }
| |
| }); | | }); |
− | });
| + | node.physics = !node.hidden; //disable physics for hidden nodes |
− | node.physics = !node.hidden;//disable physics for hidden nodes
| + | return !node.hidden; |
− | return !node.hidden;
| + | } |
− | }
| |
| | | |
− | function legendFunctionality() {
| + | function legendFunctionality() { |
− | | + | var legendGroup; |
− | var legendGroup;
| + | var group; |
− | var group;
| + | var nodeChildren; |
− | var nodeChildren;
| + | legendGroup = this.parentNode.childNodes[1].innerHTML; |
− | legendGroup = this.parentNode.childNodes[1].innerHTML;
| + | var strategy = "strategy2" |
− |
| + | if (strategy == "strategy2") { |
− |
| + | //A node is visible if at least one path over visible edges to the root node exists. |
− | var strategy = "strategy2"
| + | options.groups[legendGroup].hidden = !options.groups[legendGroup].hidden; //toggle state |
− |
| + | if (options.groups[legendGroup].hidden) this.parentNode.childNodes[1].style.background = '#FFFFFF'; |
− | if (strategy == "strategy2"){
| + | else this.parentNode.childNodes[1].style.background = '#DEF'; |
− | //A node is visible if at least one path over visible edges to the root node exists.
| + | //update all edges |
− | options.groups[legendGroup].hidden = !options.groups[legendGroup].hidden; //toggle state
| + | edges.forEach(function(edge) { |
− | if(options.groups[legendGroup].hidden) this.parentNode.childNodes[1].style.background = '#FFFFFF';
| + | edge.hidden = options.groups[edge.label].hidden; |
− | else this.parentNode.childNodes[1].style.background = '#DEF';
| + | edge.physics = !edge.hidden; |
− | //update all edges
| + | }); |
− | edges.forEach(function(edge) {
| + | //reset nodes |
− | edge.hidden = options.groups[edge.label].hidden;
| + | nodes.forEach(function(node) { |
− | edge.physics = !edge.hidden;
| + | node.hidden = false; |
− | });
| + | node.physics = !node.hidden; |
− | //reset nodes
| + | node.visited = false; |
− | nodes.forEach(function(node) {
| + | }); |
− | node.hidden = false;
| + | //check each node |
− | node.physics = !node.hidden;
| + | nodes.forEach(function(node) { |
− | node.visited = false;
| + | setNodeVisibilityByVisiblePath(node.id, input.root) |
− | });
| + | //reset visited state. Todo: Reuse visited nodes between runs |
− | //check each node
| + | nodes.forEach(function(node) { |
− | nodes.forEach(function(node) {
| + | node.visited = false; |
− | setNodeVisibilityByVisiblePath(node.id, input.root)
| + | }); |
− | //reset visited state. Todo: Reuse visited nodes between runs
| + | }); |
− | nodes.forEach(function(node) {
| + | } |
− | node.visited = false;
| + | network.setOptions(options); |
− | });
| + | network.body.emitter.emit('_dataChanged'); |
| + | network.redraw(); |
| + | var allFalse = Object.keys(options.groups).every(function(k) { |
| + | if (k === 'useDefaultGroups') { |
| + | return true |
| + | } |
| + | return options.groups[k].hidden === false |
| }); | | }); |
− | }
| + | if (allFalse === true) { |
− |
| + | /*oldGroups = {};*/ |
− | network.setOptions(options);
| |
− | network.body.emitter.emit('_dataChanged');
| |
− | network.redraw();
| |
− | | |
− | var allFalse = Object.keys(options.groups).every(function(k) {
| |
− | if (k === 'useDefaultGroups') { | |
− | return true | |
| } | | } |
− | return options.groups[k].hidden === false
| + | }; |
− | }); | + | var legendDiv = document.createElement("div"); |
− | if (allFalse === true) { | + | this.append(legendDiv); |
− | /*oldGroups = {};*/ | + | legendDiv.style.width = '100%'; |
| + | legendDiv.style.position = 'relative'; |
| + | legendDiv.style.display = 'inline-block'; |
| + | legendDiv.id = "legendContainer"; |
| + | var legendColors = {}; |
| + | for (var i = 0; i < input.properties.length; i++) { |
| + | legendColors[input.properties[i]] = colors[i]; |
| + | var propertyContainer = document.createElement("div"); |
| + | var propertyColor = document.createElement("div"); |
| + | var propertyName = document.createElement("div"); |
| + | propertyContainer.className = "legend-element-container"; |
| + | propertyContainer.id = input.properties[i]; |
| + | propertyColor.className = "color-container"; |
| + | propertyName.className = "name-container"; |
| + | propertyColor.style.float = "left"; |
| + | propertyName.style.float = "left"; |
| + | propertyColor.style.border = "1px solid black"; |
| + | propertyName.style.border = "1px solid black"; |
| + | propertyColor.style.background = colors[i]; |
| + | propertyColor.innerHTML = ""; |
| + | propertyName.innerHTML = input.properties[i]; |
| + | propertyColor.style.width = "30px"; |
| + | propertyColor.style.height = "30px"; |
| + | propertyName.style.height = "30px"; |
| + | propertyName.style.background = '#DEF'; |
| + | //propertyName.text-align = 'center'; |
| + | propertyContainer.paddinng = '5px 5px 5px 5px'; |
| + | propertyName.addEventListener("click", legendFunctionality); |
| + | propertyColor.addEventListener("click", legendFunctionality); |
| + | legendDiv.append(propertyContainer); |
| + | propertyContainer.append(propertyColor); |
| + | propertyContainer.append(propertyName); |
| } | | } |
− | };
| + | var ul = document.createElement("ul"); |
− | | + | ul.className = 'custom-menu'; |
− | var legendDiv = document.createElement("div");
| + | document.body.append(ul); |
− | this.append(legendDiv);
| + | objClickedProps = {}; |
− | legendDiv.style.width = '100%';
| + | objColors = {}; |
− | legendDiv.style.position = 'relative';
| + | var start = 0; |
− | legendDiv.style.display = 'inline-block';
| + | //On a node right click it puts out all properties of the clicked node and a link to the node wiki-page |
− |
| + | network.on("oncontext", function(params) { |
− | legendDiv.id = "legendContainer";
| + | params.event.preventDefault(); |
− | var legendColors = {};
| + | var timeNow = Date.now(); |
− | for (var i = 0; i < input.properties.length; i++) {
| + | var timeDiff = timeNow - start |
− | legendColors[input.properties[i]] = colors[i];
| + | if (timeDiff > 300) { |
− | var propertyContainer = document.createElement("div");
| + | start = Date.now(); |
− | var propertyColor = document.createElement("div");
| + | //console.log(nodes.get(network.getNodeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y }))); |
− | var propertyName = document.createElement("div");
| + | //console.log(edges.get(network.getEdgeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y }))); |
− | | + | $('.custom-menu').each(function(index) { |
− | propertyContainer.className = "legend-element-container";
| + | while (this.lastElementChild) { |
− | propertyContainer.id = input.properties[i];
| + | this.removeChild(this.lastElementChild); |
− | | + | } |
− | propertyColor.className = "color-container";
| + | }); |
− | | + | if (!(network.getEdgeAt({ |
− | propertyName.className = "name-container";
| + | x: params.pointer.DOM.x, |
− | | + | y: params.pointer.DOM.y |
− | propertyColor.style.float = "left";
| + | }) && network.getNodeAt({ |
− | propertyName.style.float = "left";
| + | x: params.pointer.DOM.x, |
− | propertyColor.style.border = "1px solid black";
| + | y: params.pointer.DOM.y |
− | propertyName.style.border = "1px solid black";
| + | }))) { |
− | | + | if (edges.get(network.getEdgeAt({ |
− | propertyColor.style.background = colors[i];
| + | x: params.pointer.DOM.x, |
− | propertyColor.innerHTML = "";
| + | y: params.pointer.DOM.y |
− | propertyName.innerHTML = input.properties[i];
| + | })).from) { |
− | | + | params.event.preventDefault(); |
− | propertyColor.style.width = "30px";
| + | if (edges.get(network.getEdgeAt({ |
− | propertyColor.style.height = "30px";
| + | x: params.pointer.DOM.x, |
− | propertyName.style.height = "30px";
| + | y: params.pointer.DOM.y |
− | propertyName.style.background = '#DEF';
| + | })).label == 'Category') { |
− | | + | var li = document.createElement("li"); |
− | //propertyName.text-align = 'center';
| + | li.innerHTML = '' + '\uD83D\uDD17' + ' ' + edges.get(network.getEdgeAt({ |
− | propertyContainer.paddinng = '5px 5px 5px 5px';
| + | x: params.pointer.DOM.x, |
− | | + | y: params.pointer.DOM.y |
− | propertyName.addEventListener("click", legendFunctionality);
| + | })).to; |
− | propertyColor.addEventListener("click", legendFunctionality);
| + | li.addEventListener("click", function NewTab() { |
− | | + | window.open('/wiki/' + edges.get(network.getEdgeAt({ |
− | legendDiv.append(propertyContainer);
| + | x: params.pointer.DOM.x, |
− | propertyContainer.append(propertyColor);
| + | y: params.pointer.DOM.y |
− | propertyContainer.append(propertyName); | + | })).to); |
− | | + | }); |
− | }
| + | ul.prepend(li); |
− | | + | } else { |
− | var ul = document.createElement("ul");
| + | var li = document.createElement("li"); |
− | ul.className = 'custom-menu';
| + | li.innerHTML = '' + '\uD83D\uDD17' + ' ' + edges.get(network.getEdgeAt({ |
− | document.body.append(ul);
| + | x: params.pointer.DOM.x, |
− | objClickedProps = {};
| + | y: params.pointer.DOM.y |
− | objColors = {};
| + | })).label; |
− | var start = 0;
| + | li.addEventListener("click", function NewTab() { |
− |
| + | window.open('/wiki/' + 'Property:' + edges.get(network.getEdgeAt({ |
− | | + | x: params.pointer.DOM.x, |
− | network.on("oncontext", function(params) {
| + | y: params.pointer.DOM.y |
− | params.event.preventDefault();
| + | })).label); |
− | var timeNow = Date.now();
| + | }); |
− | var timeDiff = timeNow - start
| + | ul.prepend(li); |
− | if(timeDiff > 300){
| |
− | start = Date.now();
| |
− | console.log(nodes.get(network.getNodeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y })));
| |
− |
| |
− | //console.log(edges.get(network.getEdgeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y })));
| |
− |
| |
− | $('.custom-menu').each( function(index) {
| |
− | while (this.lastElementChild) {
| |
− | this.removeChild(this.lastElementChild);
| |
− | }});
| |
− | if(!(network.getEdgeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y }) && network.getNodeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y }))){
| |
− | if(edges.get(network.getEdgeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y })).from){
| |
− | params.event.preventDefault();
| |
− |
| |
− | if(edges.get(network.getEdgeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y })).label == 'Category'){
| |
− |
| |
− | var li = document.createElement("li");
| |
− | li.innerHTML = '' + '\uD83D\uDD17' + ' ' + edges.get(network.getEdgeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y })).to;
| |
− | | |
− | li.addEventListener("click", function NewTab() {
| |
− | window.open('/wiki/' + edges.get(network.getEdgeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y })).to);
| |
− | });
| |
− | ul.prepend(li);}else{
| |
− | var li = document.createElement("li");
| |
− | li.innerHTML = '' + '\uD83D\uDD17' + ' ' + edges.get(network.getEdgeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y })).label;
| |
− | | |
− | li.addEventListener("click", function NewTab() {
| |
− | window.open('/wiki/' + 'Property:' + edges.get(network.getEdgeAt({ x: params.pointer.DOM.x, y: params.pointer.DOM.y })).label);
| |
− | });
| |
− | ul.prepend(li);
| |
| } | | } |
− | $(".custom-menu").finish().toggle(100).css({
| + | $(".custom-menu").finish().toggle(100).css({ |
− | top: params.event.pageY + "px",
| + | top: params.event.pageY + "px", |
− | left: params.event.pageX + "px",
| + | left: params.event.pageX + "px", |
− | display: "block"
| + | display: "block" |
− | });
| |
− | }
| |
− | }
| |
− | if (network.getNodeAt({
| |
− | x: params.pointer.DOM.x,
| |
− | y: params.pointer.DOM.y
| |
− | })) {
| |
− | params.event.preventDefault();
| |
− |
| |
− | const nodeID = nodes.get(network.getNodeAt({x: params.pointer.DOM.x,y: params.pointer.DOM.y})).id;
| |
− | const subject = nodeID.split("#")[0];
| |
− | var subObject = "";
| |
− | if (nodeID.split("#")[1]) {
| |
− | subObject = nodeID.split("#")[1].replace(" ", "_");
| |
− | }
| |
− | //inverse properties are only available in html format
| |
− | const query = `/w/api.php?action=smwbrowse&browse=subject¶ms={"subject":"${encodeURIComponent(subject)}","subobject":"${subObject}","options":{"showAll":"true"}, "ns":0, "type":"html"}&format=json`;
| |
− | | |
− | fetch(query)
| |
− | .then(response => response.json())
| |
− | .then(data => {
| |
− | var selected_node = nodes.get(network.getNodeAt({
| |
− | x: params.pointer.DOM.x,
| |
− | y: params.pointer.DOM.y
| |
− | }));
| |
− | if (selected_node.url){
| |
− |
| |
− | var li = document.createElement("li");
| |
− | li.innerHTML = '' + '\uD83D\uDD17' + ' ' + selected_node.label;
| |
− | | |
− | li.addEventListener("click", function NewTab() {
| |
− | window.open(selected_node.url);
| |
| }); | | }); |
− | | + | } |
− | ul.prepend(li); | + | } |
− |
| + | if (network.getNodeAt({ |
− | }
| + | x: params.pointer.DOM.x, |
− | var page_properties = [];
| + | y: params.pointer.DOM.y |
− | $html = $(data.query);
| + | })) { |
− | $html.find("div.smwb-propvalue").each(function(){
| + | params.event.preventDefault(); |
− | $prop = $(this).find("div.smwb-prophead a");
| + | const nodeID = nodes.get(network.getNodeAt({ |
− | //var propName = $prop.text();
| + | x: params.pointer.DOM.x, |
− | //var propName = $prop.attr('title').replace("Property:", "");
| + | y: params.pointer.DOM.y |
− | var propName = "";
| + | })).id; |
− | if ($prop.attr('title') === "Special:Categories") propName += "Category";
| + | var subject = nodeID.split("#")[0]; |
− | else propName += $prop.attr('href').split("Property:")[1].split("&")[0];
| + | var subObject = ""; |
− | page_properties.push(propName);
| + | if (nodeID.split("#")[1]) { |
− | //console.log(propName);
| + | subObject = nodeID.split("#")[1].replace(" ", "_"); |
− | $(this).find("div.smwb-propval span.smwb-value").each(function(){
| + | } |
− | var value = $(this).find("a").attr("title");
| + | var namespace_id = 0; |
− | //console.log("-> " + value);
| + | if (subject.split(":")[1]) { |
− | });
| + | const namespace = subject.split(":")[0]; |
− | })
| + | subject = subject.split(":")[1]; |
− | $html.find("div.smwb-ipropvalue").each(function(){
| + | namespace_id = mw.config.get('wgNamespaceIds')[namespace.replaceAll(" ","_").toLowerCase()]; |
− | $prop = $(this).find("div.smwb-prophead a");
| + | //console.log(`Namespace ${namespace}, ID ${namespace_id}`); |
− | //var propName = $prop.text();
| + | } |
− | //var propName = $prop.attr('title').replace("Property:", "");
| + | |
− | var propName = "-";
| + | //inverse properties are only available in html format |
− | if ($prop.attr('title') === "Special:Categories") propName += "Category";
| + | const query = `/w/api.php?action=smwbrowse&browse=subject¶ms={"subject":"${encodeURIComponent(subject)}","subobject":"${subObject}","options":{"showAll":"true"}, "ns":${namespace_id}, "type":"html"}&format=json`; |
− | else propName += $prop.attr('href').split("Property:")[1].split("&")[0];
| + | fetch(query) |
− | page_properties.push(propName);
| + | .then(response => response.json()) |
− | //console.log(propName);
| + | .then(data => { |
− | $(this).find("div.smwb-propval span.smwb-ivalue").each(function(){
| + | var selected_node = nodes.get(network.getNodeAt({ |
− | var value = $(this).find("a").attr("title");
| + | x: params.pointer.DOM.x, |
− | //console.log("-> " + value);
| + | y: params.pointer.DOM.y |
− | });
| + | })); |
− | })
| + | if (selected_node.url) { |
− | for (var i = 0; i < page_properties.length; i++) {
| + | var li = document.createElement("li"); |
− | if (!page_properties[i].startsWith("_")) {
| + | li.innerHTML = '' + '\uD83D\uDD17' + ' ' + selected_node.label; |
− | var li = document.createElement("li");
| + | li.addEventListener("click", function NewTab() { |
− | li.dataset.action = page_properties[i].replaceAll('_',' ');
| + | window.open(selected_node.url); |
− | li.innerHTML = page_properties[i].replaceAll('_',' ');
| + | }); |
− | ul.append(li);
| + | ul.prepend(li); |
− | }
| + | } |
− | }
| + | var page_properties = []; |
− |
| + | $html = $(data.query); |
− | /* old: use json result */
| + | $html.find("div.smwb-propvalue").each(function() { |
− | /*
| + | $prop = $(this).find("div.smwb-prophead a"); |
| + | //var propName = $prop.text(); |
| + | //var propName = $prop.attr('title').replace("Property:", ""); |
| + | var propName = ""; |
| + | if ($prop.attr('title') === "Special:Categories") propName += "Category"; |
| + | else if ($prop.attr('title') === "Special:ListRedirects") return; |
| + | else if ($prop.attr('href')) propName += $prop.attr('href').split("Property:")[1].split("&")[0]; |
| + | else return; //empty property |
| + | page_properties.push(propName); |
| + | //console.log(propName); |
| + | $(this).find("div.smwb-propval span.smwb-value").each(function() { |
| + | var value = $(this).find("a").attr("title"); |
| + | //console.log("-> " + value); |
| + | }); |
| + | }) |
| + | $html.find("div.smwb-ipropvalue").each(function() { |
| + | $prop = $(this).find("div.smwb-prophead a"); |
| + | //var propName = $prop.text(); |
| + | //var propName = $prop.attr('title').replace("Property:", ""); |
| + | var propName = "-"; |
| + | if ($prop.attr('title') === "Special:Categories") propName += "Category"; |
| + | else if ($prop.attr('title') === "Special:ListRedirects") return; |
| + | else if ($prop.attr('href')) propName += $prop.attr('href').split("Property:")[1].split("&")[0]; |
| + | else return; //empty property |
| + | page_properties.push(propName); |
| + | //console.log(propName); |
| + | $(this).find("div.smwb-propval span.smwb-ivalue").each(function() { |
| + | var value = $(this).find("a").attr("title"); |
| + | //console.log("-> " + value); |
| + | }); |
| + | }) |
| + | for (var i = 0; i < page_properties.length; i++) { |
| + | if (!page_properties[i].startsWith("_")) { |
| + | var li = document.createElement("li"); |
| + | li.dataset.action = page_properties[i].replaceAll('_', ' '); |
| + | li.innerHTML = page_properties[i].replaceAll('_', ' '); |
| + | ul.append(li); |
| + | } |
| + | } |
| + | /* old: use json result */ |
| + | /* |
| var page_properties = data.query.data; //normal page | | var page_properties = data.query.data; //normal page |
| if (selected_node.id.includes('#')) { //subobject | | if (selected_node.id.includes('#')) { //subobject |
Line 828: |
Line 771: |
| } | | } |
| }*/ | | }*/ |
− | | + | //On left click on one of the properties it creates nodes for the clicked property and if the legend doesnt have that property as a legend entry it is created |
− | $(".custom-menu li").click(function() {
| + | $(".custom-menu li").click(function() { |
− | | + | var clickedProperty = [$(this).attr("data-action")] |
− | var clickedProperty = [$(this).attr("data-action")]
| + | var clickedPropertyColor = randomHSL(); |
− |
| + | if (!(clickedProperty in legendColors)) { |
− | var clickedPropertyColor = randomHSL();
| + | legendColors[clickedProperty] = clickedPropertyColor; |
− |
| + | } else { |
− | if(!(clickedProperty in legendColors)){legendColors[clickedProperty] = clickedPropertyColor; }else{clickedPropertyColor = legendColors[clickedProperty]; }
| + | clickedPropertyColor = legendColors[clickedProperty]; |
− | | + | } |
− |
| + | if (objColors[clickedProperty]) { |
− | | + | clickedPropertyColor = objColors[clickedProperty] |
− | if (objColors[clickedProperty]) {
| + | } else { |
− | clickedPropertyColor = objColors[clickedProperty]
| + | objColors[clickedProperty] = clickedPropertyColor; |
− | } else {
| + | } |
− | objColors[clickedProperty] = clickedPropertyColor;
| + | if (!objClickedProps[nodes.get(network.getNodeAt({ |
− | }
| + | x: params.pointer.DOM.x, |
− | | + | y: params.pointer.DOM.y |
− | | + | })).id]) { |
− | if (!objClickedProps[nodes.get(network.getNodeAt({
| + | objClickedProps[nodes.get(network.getNodeAt({ |
− | x: params.pointer.DOM.x,
| + | x: params.pointer.DOM.x, |
− | y: params.pointer.DOM.y
| + | y: params.pointer.DOM.y |
− | })).id]) {
| + | })).id] = new Array(); |
− | objClickedProps[nodes.get(network.getNodeAt({
| + | } |
− | x: params.pointer.DOM.x,
| + | if (!objClickedProps["" + nodes.get(network.getNodeAt({ |
− | y: params.pointer.DOM.y
| + | x: params.pointer.DOM.x, |
− | })).id] = new Array();
| + | y: params.pointer.DOM.y |
− | }
| + | })).id].includes(clickedProperty[0])) { |
− | | + | fetchData(nodes.get(network.getNodeAt({ |
− | | + | x: params.pointer.DOM.x, |
− | | + | y: params.pointer.DOM.y |
− | if (!objClickedProps["" + nodes.get(network.getNodeAt({
| + | })).id, clickedProperty, nodes.get(network.getNodeAt({ |
− | x: params.pointer.DOM.x,
| + | x: params.pointer.DOM.x, |
− | y: params.pointer.DOM.y
| + | y: params.pointer.DOM.y |
− | })).id].includes(clickedProperty[0])) {
| + | })).id, clickedProperty, clickedPropertyColor) |
− | fetchData(nodes.get(network.getNodeAt({
| + | objClickedProps["" + nodes.get(network.getNodeAt({ |
− | x: params.pointer.DOM.x,
| + | x: params.pointer.DOM.x, |
− | y: params.pointer.DOM.y
| + | y: params.pointer.DOM.y |
− | })).id, clickedProperty, nodes.get(network.getNodeAt({
| + | })).id].push(clickedProperty[0]); |
− | x: params.pointer.DOM.x,
| + | } |
− | y: params.pointer.DOM.y
| + | if (!(contextCreatedProps.includes(clickedProperty[0]) || input.properties.includes(clickedProperty[0]) /*|| legendColors[clickedProperty[0]]*/ )) { |
− | })).id, clickedProperty, clickedPropertyColor)
| + | contextCreatedProps.push(clickedProperty[0]); |
− | objClickedProps["" + nodes.get(network.getNodeAt({
| + | options.groups[clickedProperty] = { |
− | x: params.pointer.DOM.x,
| + | hidden: false |
− | y: params.pointer.DOM.y
| + | }; |
− | })).id].push(clickedProperty[0]);
| + | var propertyContainer = document.createElement("div"); |
− | }
| + | var propertyColor = document.createElement("div"); |
− | | + | var propertyName = document.createElement("div"); |
− | if (!(contextCreatedProps.includes(clickedProperty[0]) || input.properties.includes(clickedProperty[0]) /*|| legendColors[clickedProperty[0]]*/ )) {
| + | propertyContainer.className = "legend-element-container"; |
− | | + | propertyContainer.id = clickedProperty; |
− | contextCreatedProps.push(clickedProperty[0]);
| + | propertyColor.className = "color-container"; |
− | | + | propertyName.className = "name-container"; |
− | options.groups[clickedProperty] = {
| + | propertyColor.style.float = "left"; |
− | hidden: false
| + | propertyName.style.float = "left"; |
− | };
| + | propertyColor.style.border = "1px solid black"; |
− | | + | propertyName.style.border = "1px solid black"; |
− | var propertyContainer = document.createElement("div");
| + | propertyContainer.style = "margin-right: 5px"; |
− | var propertyColor = document.createElement("div");
| + | propertyColor.style.background = clickedPropertyColor; |
− | var propertyName = document.createElement("div");
| + | propertyColor.innerHTML = ""; |
− |
| + | propertyName.innerHTML = clickedProperty; |
− | | + | propertyColor.style.width = "30px"; |
− | propertyContainer.className = "legend-element-container";
| + | propertyColor.style.height = "30px"; |
− | propertyContainer.id = clickedProperty;
| + | propertyName.style.height = "30px"; |
− | | + | propertyName.style.background = '#DEF'; |
− | propertyColor.className = "color-container";
| + | //propertyName.text-align = 'center'; |
− | | + | propertyName.margin = 'auto 5px auto 5px'; |
− | propertyName.className = "name-container";
| + | propertyName.addEventListener("click", legendFunctionality); |
− | | + | propertyColor.addEventListener("click", legendFunctionality); |
− | propertyColor.style.float = "left";
| + | legendDiv.append(propertyContainer); |
− | propertyName.style.float = "left";
| + | propertyContainer.append(propertyColor); |
− | propertyColor.style.border = "1px solid black";
| + | propertyContainer.append(propertyName); |
− | propertyName.style.border = "1px solid black";
| + | } |
− | propertyContainer.style = "margin-right: 5px";
| + | $(".custom-menu").hide(100); |
− | | + | }); |
− | | + | }); |
− | propertyColor.style.background = clickedPropertyColor;
| + | $(".custom-menu").finish().toggle(100).css({ |
− | propertyColor.innerHTML = "";
| + | top: params.event.pageY + "px", |
− | propertyName.innerHTML = clickedProperty;
| + | left: params.event.pageX + "px", |
− | | + | display: "block" |
− | propertyColor.style.width = "30px";
| + | }); |
− | propertyColor.style.height = "30px";
| + | } |
− | propertyName.style.height = "30px";
| + | } |
− | propertyName.style.background = '#DEF';
| + | }); |
− | | + | // If the document is clicked somewhere it hides the context menu |
− | //propertyName.text-align = 'center';
| + | $(document).bind("mousedown", function(e) { |
− | propertyName.margin = 'auto 5px auto 5px';
| + | // If the clicked element is not the menu |
− | | + | if (!$(e.target).parents(".custom-menu").length > 0) { |
− | propertyName.addEventListener("click", legendFunctionality);
| + | // Hide it |
− | propertyColor.addEventListener("click", legendFunctionality);
| + | $(".custom-menu").hide(100); |
− | | + | } |
− | | + | }); |
− | legendDiv.append(propertyContainer);
| + | //Add Node popup |
− | propertyContainer.append(propertyColor);
| + | function editNode(data, cancelAction, callback) { |
− | propertyContainer.append(propertyName);
| + | var newNodeActive = true; |
− | | + | document.getElementById("node-label").value = data.label; |
− | } | + | document.getElementById("node-saveButton").onclick = saveNodeData.bind( |
− | | + | this, |
− | $(".custom-menu").hide(100); | + | data, |
| + | callback |
| + | ); |
| + | document.getElementById("node-cancelButton").onclick = cancelAction.bind( |
| + | this, |
| + | callback |
| + | ); |
| + | //document.getElementById("node-popUp") |
| + | $('canvas').on('click', function(e) { |
| + | if (newNodeActive === true) { |
| + | $("#node-popUp").css({ |
| + | top: e.pageY + "px", |
| + | left: e.pageX + "px", |
| + | display: "block" |
| }); | | }); |
− | }); | + | } |
− | | + | newNodeActive = false; |
− | $(".custom-menu").finish().toggle(100).css({
| |
− | top: params.event.pageY + "px", | |
− | left: params.event.pageX + "px",
| |
− | display: "block"
| |
| }); | | }); |
| } | | } |
− | }
| + | |
− | });
| + | function clearNodePopUp() { |
− | // If the document is clicked somewhere
| + | document.getElementById("node-saveButton").onclick = null; |
− | $(document).bind("mousedown", function(e) {
| + | document.getElementById("node-cancelButton").onclick = null; |
| + | document.getElementById("node-popUp").style.display = "none"; |
| + | } |
| | | |
− | // If the clicked element is not the menu | + | function cancelNodeEdit(callback) { |
− | if (!$(e.target).parents(".custom-menu").length > 0) { | + | clearNodePopUp(); |
− | | + | callback(null); |
− | // Hide it | + | } |
− | $(".custom-menu").hide(100); | + | //saveNodeData to the graph |
| + | function saveNodeData(data, callback) { |
| + | data.label = document.getElementById("node-label").value; |
| + | data.id = document.getElementById("node-label").value; |
| + | data.hidden = false; |
| + | data.physics = false; |
| + | document.getElementById("node-label").value = ""; |
| + | clearNodePopUp(); |
| + | callback(data); |
| } | | } |
− | });
| + | //addEdge popup |
− |
| + | function editEdgeWithoutDrag(data, callback) { |
− | function editNode(data, cancelAction, callback) {
| + | var newEdgeActive = true; |
− | var newNodeActive = true;
| + | // filling in the popup DOM elements |
− | document.getElementById("node-label").value = data.label;
| + | document.getElementById("edge-label").value = data.label; |
− | document.getElementById("node-saveButton").onclick = saveNodeData.bind(
| + | |
− | this,
| + | document.getElementById("edge-saveButton").onclick = saveEdgeData.bind( |
− | data,
| + | this, |
− | callback
| + | data, |
− | );
| + | callback |
− | document.getElementById("node-cancelButton").onclick = cancelAction.bind(
| + | ); |
− | this,
| + | document.getElementById("edge-cancelButton").onclick = cancelEdgeEdit.bind( |
− | callback
| + | this, |
− | );
| + | callback |
− | //document.getElementById("node-popUp")
| + | ); |
− | | + | $('canvas').on('click', function(e) { |
− |
| + | if (newEdgeActive === true) { |
− | $('canvas').on('click', function(e) {
| + | $("#edge-popUp").css({ |
− | if(newNodeActive === true){
| + | top: e.pageY + "px", |
− | $("#node-popUp").css({
| + | left: e.pageX + "px", |
− | top: e.pageY + "px",
| + | display: "block" |
− | left: e.pageX + "px",
| + | }); |
− | display: "block"
| + | } |
− | });}
| |
− | newNodeActive = false;
| |
− |
| |
− | });
| |
− | | |
− | }
| |
− | | |
− | // Callback passed as parameter is ignored
| |
− | function clearNodePopUp() {
| |
− | document.getElementById("node-saveButton").onclick = null;
| |
− | document.getElementById("node-cancelButton").onclick = null;
| |
− | document.getElementById("node-popUp").style.display = "none";
| |
− | }
| |
− | | |
− | function cancelNodeEdit(callback) {
| |
− | clearNodePopUp();
| |
− | callback(null);
| |
− | }
| |
− | | |
− | function saveNodeData(data, callback) {
| |
− | data.label = document.getElementById("node-label").value;
| |
− | data.id = document.getElementById("node-label").value;
| |
− | data.hidden = false;
| |
− | data.physics = false;
| |
− | document.getElementById("node-label").value = "";
| |
− | clearNodePopUp();
| |
− | callback(data);
| |
− | }
| |
− | | |
− | function editEdgeWithoutDrag(data, callback) { | |
− | var newEdgeActive = true;
| |
− | // filling in the popup DOM elements
| |
− | document.getElementById("edge-label").value = data.label;
| |
− | /*if(data.from === "H.1"){
| |
− | console.log("here");
| |
− | return;}*/
| |
− | document.getElementById("edge-saveButton").onclick = saveEdgeData.bind(
| |
− | this,
| |
− | data,
| |
− | callback
| |
− | );
| |
− | document.getElementById("edge-cancelButton").onclick = cancelEdgeEdit.bind(
| |
− | this,
| |
− | callback
| |
− | );
| |
− |
| |
− | $('canvas').on('click', function(e) {
| |
− | if(newEdgeActive === true){
| |
− | $("#edge-popUp").css({
| |
− | top: e.pageY + "px",
| |
− | left: e.pageX + "px",
| |
− | display: "block"
| |
− | });}
| |
| newEdgeActive = false; | | newEdgeActive = false; |
− | }); | + | }); |
− | //document.getElementById("edge-popUp").style.display = "block";
| + | //document.getElementById("edge-popUp").style.display = "block"; |
− | } | + | } |
| | | |
− | function clearEdgePopUp() { | + | function clearEdgePopUp() { |
− | document.getElementById("edge-saveButton").onclick = null;
| + | document.getElementById("edge-saveButton").onclick = null; |
− | document.getElementById("edge-cancelButton").onclick = null;
| + | document.getElementById("edge-cancelButton").onclick = null; |
− | document.getElementById("edge-popUp").style.display = "none";
| + | document.getElementById("edge-popUp").style.display = "none"; |
− | } | + | } |
| | | |
− | function cancelEdgeEdit(callback) { | + | function cancelEdgeEdit(callback) { |
− | clearEdgePopUp();
| + | clearEdgePopUp(); |
− | callback(null);
| + | callback(null); |
− | } | + | } |
| | | |
− | function isLabelReversed(label){ | + | function isLabelReversed(label) { |
− | if(label[0] == "-"){
| + | if (label[0] == "-") { |
− | return true;
| + | return true; |
− | }
| + | } else { |
− | else{
| + | return false; |
− | return false;
| + | } |
− | }
| + | } |
− | } | + | var pageBool; |
− | | + | //Checks if page exists in the wiki |
− | | + | async function pageExists(id) { |
− | | + | await fetch('/w/api.php?action=parse&page=' + id + '&prop=wikitext&format=json') |
− | | |
− | | |
− | | |
− | var pageBool; | |
− | async function pageExists(id){ | |
− |
| |
− | await fetch('/w/api.php?action=parse&page='+ id +'&prop=wikitext&format=json')
| |
| .then(response => response.json()) | | .then(response => response.json()) |
| .then(data => { | | .then(data => { |
− |
| + | if (data.error) { |
− | if(data.error){
| + | pageBool = false; |
− | pageBool = false;
| + | } else { |
− | }else{
| + | pageBool = true; |
− | pageBool = true;
| + | } |
− | }
| |
− |
| |
| }) | | }) |
− | return pageBool;
| + | return pageBool; |
− | } | + | } |
− | | + | var wikiText = ""; |
− | var wikiText = ""; | + | var semantic = ""; |
− | var semantic = ""; | + | //Splits Wikitext and Semantic/Element or Semantic/Link |
− | async function editWikiText(node){ | + | async function editWikiText(node) { |
− | await fetch('/w/api.php?action=parse&page='+ node +'&prop=wikitext&format=json')
| + | await fetch('/w/api.php?action=parse&page=' + node + '&prop=wikitext&format=json') |
| .then(response => response.json()) | | .then(response => response.json()) |
| .then(data => { | | .then(data => { |
− | wikiText = data.parse.wikitext['*'];
| + | wikiText = data.parse.wikitext['*']; |
− | semantic = "";
| + | semantic = ""; |
− | if(wikiText.search(/(\{\{Semantic\/[^}]*[\r\n]*\}[\r\n]*\})/g) >= 0){
| + | if (wikiText.search(/(\{\{Semantic\/[^}]*[\r\n]*\}[\r\n]*\})/g) >= 0) { |
− | //var edgeStringFound = wikiText.search(re) >= 0;
| + | //var edgeStringFound = wikiText.search(re) >= 0; |
− | const found = wikiText.match(/(\{\{Semantic\/[^}]*[\r\n]*\}[\r\n]*\})/g);
| + | const found = wikiText.match(/(\{\{Semantic\/[^}]*[\r\n]*\}[\r\n]*\})/g); |
− |
| + | var newWikiText = wikiText; |
− | var newWikiText = wikiText;
| + | for (var i = 0; i < found.length; i++) { |
− | for(var i=0; i<found.length;i++){
| + | if (i == found.length - 1) { |
− | if(i == found.length-1){
| + | semantic += found[i]; |
− | semantic += found[i];
| + | newWikiText = newWikiText.replace(/(\{\{Semantic\/[^}]*[\r\n]*\}[\r\n]*\}[\r\n]*\}[\r\n]*\})/g, ""); |
− | newWikiText = newWikiText.replace(/(\{\{Semantic\/[^}]*[\r\n]*\}[\r\n]*\}[\r\n]*\}[\r\n]*\})/g, "");
| + | newWikiText = newWikiText.replace(/(\{\{Semantic\/Link[^}]*[\r\n]*\}[\r\n]*\})/g, ""); |
− | }else{
| + | } else { |
− | semantic += found[i];
| + | semantic += found[i]; |
− | newWikiText = newWikiText.replace(found[i], "");
| + | newWikiText = newWikiText.replace(found[i], ""); |
− | }
| + | } |
− | }
| |
− | wikiText = newWikiText;
| |
− |
| |
− |
| |
− | | |
− | | |
− | }
| |
− | });
| |
− | return [semantic, wikiText];
| |
− | }
| |
− | | |
− | | |
− | | |
− | async function saveEdgeData(data, callback) {
| |
− | if (typeof data.to === "object") data.to = data.to.id;
| |
− | if (typeof data.from === "object") data.from = data.from.id;
| |
− |
| |
− | data.label = document.getElementById("edge-label").value;
| |
− | options.groups[data.label] = {hidden: false};
| |
− | var toNode = nodes.get(data.to);
| |
− | var fromNode = nodes.get(data.from);
| |
− | fromNode.physics = true;
| |
− | toNode.physics = true;
| |
− | delete fromNode.x;
| |
− | delete fromNode.y;
| |
− | delete toNode.x;
| |
− | delete toNode.y;
| |
− | if(!toNode.group){toNode.group = data.label}
| |
− | if(!fromNode.group){fromNode.group = data.label}
| |
− | if(legendColors[data.label]){data.color = legendColors[data.label];}else{data.color = randomHSL(); }
| |
− | if(!toNode.color){toNode.color = data.color; toNode.manually = true;}
| |
− | if(!fromNode.color){fromNode.color = data.color; fromNode.manually = true;}
| |
− |
| |
− | if(!(contextCreatedProps.includes(data.label) || input.properties.includes(data.label))){
| |
− | contextCreatedProps.push(data.label);
| |
− | var propertyContainer = document.createElement("div");
| |
− | var propertyColor = document.createElement("div");
| |
− | var propertyName = document.createElement("div");
| |
− |
| |
− | | |
− | propertyContainer.className = "legend-element-container";
| |
− | propertyContainer.id = data.label;
| |
− | | |
− | propertyColor.className = "color-container";
| |
− | | |
− | propertyName.className = "name-container";
| |
− | | |
− | propertyColor.style.float = "left";
| |
− | propertyName.style.float = "left";
| |
− | propertyColor.style.border = "1px solid black";
| |
− | propertyName.style.border = "1px solid black";
| |
− | propertyContainer.style = "margin-right: 5px";
| |
− | | |
− | | |
− | propertyColor.style.background = data.color;
| |
− | propertyColor.innerHTML = "";
| |
− | propertyName.innerHTML = data.label;
| |
− | | |
− | propertyColor.style.width = "30px";
| |
− | propertyColor.style.height = "30px";
| |
− | propertyName.style.height = "30px";
| |
− | propertyName.style.background = '#DEF';
| |
− | | |
− | //propertyName.text-align = 'center';
| |
− | propertyName.margin = 'auto 5px auto 5px';
| |
− | | |
− | propertyName.addEventListener("click", legendFunctionality);
| |
− | propertyColor.addEventListener("click", legendFunctionality);
| |
− | | |
− | | |
− | legendDiv.append(propertyContainer);
| |
− | propertyContainer.append(propertyColor);
| |
− | propertyContainer.append(propertyName);
| |
− | legendColors[data.label] = data.color;
| |
− | }
| |
− | if(isLabelReversed(data.label)){
| |
− | if(await pageExists(fromNode.id) === false){
| |
− | if(!(newNodes[fromNode.id])){
| |
− | newNodes[fromNode.id] = '' + '{{Semantic/Element' +
| |
− | '|label=' + fromNode.label +
| |
− | '|description=test' +
| |
− | '|relations=';
| |
− | }
| |
− |
| |
− | }
| |
− | | |
− | if(await pageExists(toNode.id) === true){
| |
− | var splitWikiText = await editWikiText(toNode.id);
| |
− | if(editNodes[toNode.id]){
| |
− | editNodes[toNode.id] += '' + '{{Semantic/Link'+
| |
− | '|property=' + reverseLabel(data.label) +
| |
− | '|value=' + fromNode.id +
| |
− | '}}' + '';
| |
− |
| |
− | }else{
| |
− | if(splitWikiText[0]){
| |
− | editNodes[toNode.id] = splitWikiText[1] + splitWikiText[0] + '{{Semantic/Link'+
| |
− | '|property=' + reverseLabel(data.label) +
| |
− | '|value=' + fromNode.id +
| |
− | '}}' + '';
| |
− | }else{
| |
− | editNodes[toNode.id] = splitWikiText[1] + '{{Semantic/Element' +
| |
− | '|label=' + toNode.label +
| |
− | '|description=test' +
| |
− | '|relations='+
| |
− | '{{Semantic/Link'+
| |
− | '|property=' + reverseLabel(data.label) +
| |
− | '|value=' + fromNode.id +
| |
− | '}}' + '';
| |
− | }
| |
− | }
| |
− | }else{
| |
− | if(newNodes[toNode.id]){
| |
− | newNodes[toNode.id] += '' + '{{Semantic/Link'+
| |
− | '|property=' + reverseLabel(data.label) +
| |
− | '|value=' + fromNode.id +
| |
− | '}}' + '';
| |
− | }else{
| |
− | newNodes[toNode.id] = '' + '{{Semantic/Element' +
| |
− | '|label=' + toNode.label +
| |
− | '|description=test' +
| |
− | '|relations={{Semantic/Link'+
| |
− | '|property=' + reverseLabel(data.label) +
| |
− | '|value=' + fromNode.id +
| |
− | '}}'+
| |
− | '';
| |
− | }
| |
− | }
| |
− | | |
− | }else{
| |
− |
| |
− | if(await pageExists(toNode.id) === false){
| |
− | if(!(newNodes[toNode.id])){
| |
− | newNodes[toNode.id] = '' + '{{Semantic/Element' +
| |
− | '|label=' + toNode.label +
| |
− | '|description=test' +
| |
− | '|relations=';
| |
− | }
| |
− | }
| |
− | if(await pageExists(fromNode.id) === true){
| |
− | var splitWikiText = await editWikiText(fromNode.id);
| |
− | if(editNodes[fromNode.id]){
| |
− | editNodes[fromNode.id] += '' + '{{Semantic/Link'+
| |
− | '|property=' + data.label +
| |
− | '|value=' + toNode.id +
| |
− | '}}' + '';
| |
− | }else{
| |
− | if(splitWikiText[0]){
| |
− | editNodes[fromNode.id] = splitWikiText[1] + splitWikiText[0] + '{{Semantic/Link'+
| |
− | '|property=' + data.label +
| |
− | '|value=' + toNode.id +
| |
− | '}}' + '';
| |
− | }else{
| |
− | editNodes[fromNode.id] = splitWikiText[1] + '{{Semantic/Element' +
| |
− | '|label=' + fromNode.label +
| |
− | '|description=test' +
| |
− | '|relations='+
| |
− | '{{Semantic/Link'+
| |
− | '|property=' + data.label +
| |
− | '|value=' + toNode.id +
| |
− | '}}' + '';
| |
− | }
| |
− | }
| |
− | }else{
| |
− | if(newNodes[fromNode.id]){
| |
− | newNodes[fromNode.id] += '' + '{{Semantic/Link'+
| |
− | '|property=' + data.label +
| |
− | '|value=' + toNode.id +
| |
− | '}}' + '';
| |
− |
| |
− | }else{
| |
− | newNodes[fromNode.id] = '' + '{{Semantic/Element' +
| |
− | '|label=' + fromNode.label +
| |
− | '|description=test' +
| |
− | '|relations={{Semantic/Link'+
| |
− | '|property=' + data.label +
| |
− | '|value=' + toNode.id +
| |
− | '}}'+
| |
− | '';
| |
− |
| |
− | }
| |
− | }
| |
− | | |
− | }
| |
− | | |
− | //console.log(toNode);
| |
− | //console.log(fromNode);
| |
− |
| |
− | console.log(editNodes);
| |
− | console.log(newNodes);
| |
− |
| |
− | clearEdgePopUp();
| |
− | callback(data);
| |
− | network.setOptions(options);
| |
− | network.body.emitter.emit('_dataChanged');
| |
− | network.redraw();
| |
− | }
| |
− | var saveBtn= document.createElement("button");
| |
− | saveBtn.addEventListener("click", saveGraphChanges);
| |
− | saveBtn.innerHTML = "Speichern";
| |
− | saveBtn.style.width = "auto";
| |
− | saveBtn.style.height = "auto";
| |
− | | |
− | givenDiv.appendChild(saveBtn);
| |
− | function saveGraphChanges() {
| |
− | var alertString = "";
| |
− | OO.ui.confirm( 'Änderungen übernehmen?' ).done( async function ( confirmed ) {
| |
− | if ( confirmed ) {
| |
− | for (const [key, value] of Object.entries(newNodes)) {
| |
− | var params = {
| |
− | action: 'edit',
| |
− | title: '' + key,
| |
− | appendtext: '' + value + '}}',
| |
− | format: 'json'
| |
− | },
| |
− | api = new mw.Api();
| |
− |
| |
− | await api.postWithToken( 'csrf', params ).done( function ( data ) {
| |
− | console.log( data );
| |
− | alertString += "Seite " + key + " erstellt!\r\n"
| |
− | } );
| |
− | }
| |
− |
| |
− | for (const [key, value] of Object.entries(editNodes)) {
| |
− | var params = {
| |
− | action: 'edit',
| |
− | title: '' + key,
| |
− | text: '' + value + '}}',
| |
− | format: 'json'
| |
− | },
| |
− | api = new mw.Api();
| |
− |
| |
− | await api.postWithToken( 'csrf', params ).done( function ( data ) {
| |
− | console.log( data );
| |
− | alertString += "Seite " + key + " bearbeitet!\r\n"
| |
− | } );
| |
− | }
| |
− |
| |
− | for (const [key, value] of Object.entries(editDeletedEdges)) {
| |
− | var params = {
| |
− | action: 'edit',
| |
− | title: '' + key,
| |
− | text: '' + value,
| |
− | format: 'json'
| |
− | },
| |
− | api = new mw.Api();
| |
− |
| |
− | await api.postWithToken( 'csrf', params ).done( function ( data ) {
| |
− | console.log( data );
| |
− | alertString += "Auf der Seite " + key + " wurde ein Attribut gelöscht!\r\n"
| |
− | } );
| |
− | }
| |
− |
| |
− | for (const [key, value] of Object.entries(editDeletedNodes)) {
| |
− | var params = {
| |
− | action: 'delete',
| |
− | title: '' + key,
| |
− | format: 'json'
| |
− | },
| |
− | api = new mw.Api();
| |
− | await api.postWithToken( 'csrf', params ).done( function ( data ) {
| |
− | console.log( data );
| |
− | alertString += "Seite " + key + " wurde gelöscht!\r\n"
| |
− | } );
| |
− | }
| |
− | console.log( alertString );
| |
− | // Example: Customize the displayed actions at the time the window is opened.
| |
− | var messageDialog = new OO.ui.MessageDialog();
| |
− |
| |
− | // Create and append a window manager.
| |
− | var windowManager = new OO.ui.WindowManager();
| |
− | $( 'body' ).append( windowManager.$element );
| |
− |
| |
− | // Add the dialog to the window manager.
| |
− | windowManager.addWindows( [ messageDialog ] );
| |
− |
| |
− | // Configure the message dialog when it is opened with the window manager's openWindow() method.
| |
− |
| |
− | windowManager.openWindow( messageDialog, {
| |
− | title: 'Folgende Änderugnen wurden übernommen:',
| |
− | message: '' + alertString,
| |
− | verbose: true,
| |
− | actions: [
| |
− | {
| |
− | action: 'accept',
| |
− | label: 'Okay',
| |
− | flags: 'primary'
| |
− | }
| |
− | ]
| |
− | });
| |
− | /*OO.ui.alert( "" + alertString ).done( function () {
| |
− | console.log( alertString );
| |
− | } );*/
| |
− |
| |
− | } else {
| |
− |
| |
− | }
| |
− |
| |
− | } );
| |
− |
| |
− | | |
− | }
| |
− |
| |
− | | |
− | | |
− | | |
− | function deleteSelectedNode(data, callback){
| |
− | console.log(contextCreatedProps);
| |
− | deleteNodesChildren(data.nodes[0]);
| |
− | nodes.remove(data.nodes[0]);
| |
− | for (var i = 0; i < contextCreatedProps.length; i++) {
| |
− | var noNodesInNetwork = true;
| |
− | for (var j = 0; j < nodes.getIds().length; j++) {
| |
− | if (contextCreatedProps[i] == nodes.get(nodes.getIds()[j]).group) {
| |
− |
| |
− | noNodesInNetwork = false; | |
| } | | } |
| + | wikiText = newWikiText; |
| } | | } |
− | if (noNodesInNetwork === true) {
| + | }); |
− |
| + | return [semantic, wikiText]; |
− | givenDiv.querySelector('#' + contextCreatedProps[i]).remove();
| + | } |
− | contextCreatedProps.splice(contextCreatedProps.indexOf(contextCreatedProps[i]), 1);
| + | //Save button on create edge popup |
− | i--; | + | async function saveEdgeData(data, callback) { |
| + | //Sets various options to the nodes that the edge gets connected |
| + | if (typeof data.to === "object") data.to = data.to.id; |
| + | if (typeof data.from === "object") data.from = data.from.id; |
| + | data.label = document.getElementById("edge-label").value; |
| + | options.groups[data.label] = { |
| + | hidden: false |
| + | }; |
| + | var toNode = nodes.get(data.to); |
| + | var fromNode = nodes.get(data.from); |
| + | fromNode.physics = true; |
| + | toNode.physics = true; |
| + | delete fromNode.x; |
| + | delete fromNode.y; |
| + | delete toNode.x; |
| + | delete toNode.y; |
| + | if (!toNode.group) { |
| + | toNode.group = data.label |
| + | } |
| + | if (!fromNode.group) { |
| + | fromNode.group = data.label |
| + | } |
| + | if (legendColors[data.label]) { |
| + | data.color = legendColors[data.label]; |
| + | } else { |
| + | data.color = randomHSL(); |
| + | } |
| + | if (!toNode.color) { |
| + | toNode.color = data.color; |
| + | toNode.manually = true; |
| + | } |
| + | if (!fromNode.color) { |
| + | fromNode.color = data.color; |
| + | fromNode.manually = true; |
| + | } |
| + | //If the given property is not set in the legend, a legend entry is created |
| + | if (!(contextCreatedProps.includes(data.label) || input.properties.includes(data.label))) { |
| + | contextCreatedProps.push(data.label); |
| + | var propertyContainer = document.createElement("div"); |
| + | var propertyColor = document.createElement("div"); |
| + | var propertyName = document.createElement("div"); |
| + | propertyContainer.className = "legend-element-container"; |
| + | propertyContainer.id = data.label; |
| + | propertyColor.className = "color-container"; |
| + | propertyName.className = "name-container"; |
| + | propertyColor.style.float = "left"; |
| + | propertyName.style.float = "left"; |
| + | propertyColor.style.border = "1px solid black"; |
| + | propertyName.style.border = "1px solid black"; |
| + | propertyContainer.style = "margin-right: 5px"; |
| + | propertyColor.style.background = data.color; |
| + | propertyColor.innerHTML = ""; |
| + | propertyName.innerHTML = data.label; |
| + | propertyColor.style.width = "30px"; |
| + | propertyColor.style.height = "30px"; |
| + | propertyName.style.height = "30px"; |
| + | propertyName.style.background = '#DEF'; |
| + | //propertyName.text-align = 'center'; |
| + | propertyName.margin = 'auto 5px auto 5px'; |
| + | propertyName.addEventListener("click", legendFunctionality); |
| + | propertyColor.addEventListener("click", legendFunctionality); |
| + | legendDiv.append(propertyContainer); |
| + | propertyContainer.append(propertyColor); |
| + | propertyContainer.append(propertyName); |
| + | legendColors[data.label] = data.color; |
| + | } |
| + | //Creates new wikitext that will be saved after the save button is clicked |
| + | if (isLabelReversed(data.label)) { |
| + | if (await pageExists(fromNode.id) === false) { |
| + | if (!(newNodes[fromNode.id])) { |
| + | newNodes[fromNode.id] = '' + '{{Semantic/Element' + |
| + | '|label=' + fromNode.label + |
| + | '|description=test' + |
| + | '|relations='; |
| } | | } |
| } | | } |
− | | + | if (await pageExists(toNode.id) === true) { |
− | | + | var splitWikiText = await editWikiText(toNode.id); |
− | delete oldGroups["" + data.nodes[0]];
| + | if (editNodes[toNode.id]) { |
− |
| + | editNodes[toNode.id] += '' + '{{Semantic/Link' + |
− | delete objClickedProps["" + data.nodes[0]];
| + | '|property=' + reverseLabel(data.label) + |
− | callback();
| + | '|value=' + fromNode.id + |
− | document.querySelector('.vis-delete').remove();
| + | '}}' + ''; |
− | editDeletedNodes[""+data.nodes[0]] = "";
| + | } else { |
− | delete newNodes[""+data.nodes[0]];
| + | if (splitWikiText[0].search(/(\{\{Semantic\/Element[^}]*[\r\n]*\}[\r\n]*\})/g) >= 0) { |
− | delete editNodes[""+data.nodes[0]];
| + | editNodes[toNode.id] = splitWikiText[1] + splitWikiText[0] + '{{Semantic/Link' + |
− | console.log(editDeletedNodes);
| + | '|property=' + reverseLabel(data.label) + |
− | | + | '|value=' + fromNode.id + |
− | } | + | '}}' + ''; |
− | | + | } else { |
− | async function deleteSelectedEdge(data, callback){
| + | editNodes[toNode.id] = splitWikiText[1] + '{{Semantic/Element' + |
− | var edgeToNode = edges.get(data.edges[0]).to;
| + | '|label=' + toNode.label + |
− | var edgeFromNode = edges.get(data.edges[0]).from;
| + | '|description=test' + |
− | var edgeLabel = edges.get(data.edges[0]).label;
| + | '|relations=' + |
− | console.log(edgeLabel);
| + | '{{Semantic/Link' + |
− | edges.remove(data.edges[0]);
| + | '|property=' + reverseLabel(data.label) + |
− | deleteNodesChildren(edgeToNode, true);
| + | '|value=' + fromNode.id + |
− | deleteNodesChildren(edgeFromNode, true);
| + | '}}' + '' + splitWikiText[0]; |
− |
| |
− | for (var i = 0; i < contextCreatedProps.length; i++) {
| |
− | var noNodesInNetwork = true;
| |
− | for (var j = 0; j < nodes.getIds().length; j++) {
| |
− | if (contextCreatedProps[i] == nodes.get(nodes.getIds()[j]).group) {
| |
− |
| |
− | noNodesInNetwork = false;
| |
| } | | } |
| } | | } |
− | if (noNodesInNetwork === true) { | + | } else { |
− |
| + | if (newNodes[toNode.id]) { |
− | givenDiv.querySelector('#' + contextCreatedProps[i]).remove(); | + | newNodes[toNode.id] += '' + '{{Semantic/Link' + |
− | contextCreatedProps.splice(contextCreatedProps.indexOf(contextCreatedProps[i]), 1); | + | '|property=' + reverseLabel(data.label) + |
− | i--;
| + | '|value=' + fromNode.id + |
| + | '}}' + ''; |
| + | } else { |
| + | newNodes[toNode.id] = '' + '{{Semantic/Element' + |
| + | '|label=' + toNode.label + |
| + | '|description=test' + |
| + | '|relations={{Semantic/Link' + |
| + | '|property=' + reverseLabel(data.label) + |
| + | '|value=' + fromNode.id + |
| + | '}}' + |
| + | ''; |
| } | | } |
| } | | } |
− |
| + | } else { |
− | if(edgeLabel[0] == "-"){
| + | if (await pageExists(toNode.id) === false) { |
− | if(await pageExists(edgeToNode) === true){
| + | if (!(newNodes[toNode.id])) { |
− | await fetch('/w/api.php?action=parse&page='+ edgeToNode +'&prop=wikitext&format=json')
| + | newNodes[toNode.id] = '' + '{{Semantic/Element' + |
− | .then(response => response.json())
| + | '|label=' + toNode.label + |
− | .then(data => {
| + | '|description=test' + |
− | var wikiText = data.parse.wikitext['*'];
| + | '|relations='; |
− | console.log(wikiText);
| + | } |
− |
| |
− | var edgeString = `(\{\{Semantic\/Link[\\r\\n]*\\|[\\r\\n]*property=`+reverseLabel(edgeLabel)+`[\\r\\n]*\\|[\\r\\n]*value=`+edgeFromNode+`[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*)`
| |
− | //var edgeString = '(\\{\\{Semantic\/Element[^}]*[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*[\\r\\n]*\\}[\\r\\n]*\\})'
| |
− | var re = new RegExp(edgeString,"g");
| |
− |
| |
− | var edgeStringFound = wikiText.search(re) >= 0;
| |
− |
| |
− | if(edgeStringFound){
| |
− | if(editDeletedEdges[""+ edgeToNode]){
| |
− | var newWikiText = editDeletedEdges[""+ edgeToNode].replace(re, "");
| |
− | editDeletedEdges[""+ edgeToNode] = newWikiText;
| |
− | }else{
| |
− | var newWikiText = wikiText.replace(re, "");
| |
− | console.log(newWikiText)
| |
− | editDeletedEdges[""+ edgeToNode] = newWikiText;
| |
− | }
| |
− |
| |
| } | | } |
− | | + | if (await pageExists(fromNode.id) === true) { |
− | if(newNodes[""+edgeToNode]){
| + | var splitWikiText = await editWikiText(fromNode.id); |
− |
| + | if (editNodes[fromNode.id]) { |
− | var newWikiText = newNodes[""+edgeToNode].replace(re, "");
| + | editNodes[fromNode.id] += '' + '{{Semantic/Link' + |
− | newNodes[""+edgeToNode] = newWikiText;
| + | '|property=' + data.label + |
− | | + | '|value=' + toNode.id + |
| + | '}}' + ''; |
| + | } else { |
| + | if (splitWikiText[0].search(/(\{\{Semantic\/Element[^}]*[\r\n]*\}[\r\n]*\})/g) >= 0) { |
| + | editNodes[fromNode.id] = splitWikiText[1] + splitWikiText[0] + '{{Semantic/Link' + |
| + | '|property=' + data.label + |
| + | '|value=' + toNode.id + |
| + | '}}' + ''; |
| + | } else { |
| + | editNodes[fromNode.id] = splitWikiText[1] + '{{Semantic/Element' + |
| + | '|label=' + fromNode.label + |
| + | '|description=test' + |
| + | '|relations=' + |
| + | '{{Semantic/Link' + |
| + | '|property=' + data.label + |
| + | '|value=' + toNode.id + |
| + | '}}' + '' + splitWikiText[0]; |
| + | } |
| + | } |
| + | } else { |
| + | if (newNodes[fromNode.id]) { |
| + | newNodes[fromNode.id] += '' + '{{Semantic/Link' + |
| + | '|property=' + data.label + |
| + | '|value=' + toNode.id + |
| + | '}}' + ''; |
| + | } else { |
| + | newNodes[fromNode.id] = '' + '{{Semantic/Element' + |
| + | '|label=' + fromNode.label + |
| + | '|description=test' + |
| + | '|relations={{Semantic/Link' + |
| + | '|property=' + data.label + |
| + | '|value=' + toNode.id + |
| + | '}}' + |
| + | ''; |
| + | } |
| } | | } |
− |
| + | } |
− | if(editNodes[""+edgeToNode]){ | + | //console.log(toNode); |
− |
| + | //console.log(fromNode); |
− | var newWikiText = editNodes[""+edgeToNode].replace(re, "");
| + | //console.log(editNodes); |
− | editNodes[""+edgeToNode] = newWikiText;
| + | //console.log(newNodes); |
− |
| + | clearEdgePopUp(); |
| + | callback(data); |
| + | network.setOptions(options); |
| + | network.body.emitter.emit('_dataChanged'); |
| + | network.redraw(); |
| + | } |
| + | //save button |
| + | var saveBtn = document.createElement("button"); |
| + | saveBtn.addEventListener("click", saveGraphChanges); |
| + | saveBtn.innerHTML = "Speichern"; |
| + | saveBtn.style.width = "auto"; |
| + | saveBtn.style.height = "auto"; |
| + | givenDiv.appendChild(saveBtn); |
| + | |
| + | //Called on save button click. Creates new wiki pages or edits them with the created wiki text. |
| + | function saveGraphChanges() { |
| + | var alertString = ""; |
| + | OO.ui.confirm('Änderungen übernehmen?').done(async function(confirmed) { |
| + | if (confirmed) { |
| + | for (const [key, value] of Object.entries(newNodes)) { |
| + | var params = { |
| + | action: 'edit', |
| + | title: '' + key, |
| + | appendtext: '' + value + '}}', |
| + | format: 'json' |
| + | }, |
| + | api = new mw.Api(); |
| + | await api.postWithToken('csrf', params).done(function(data) { |
| + | console.log(data); |
| + | alertString += "Seite " + key + " erstellt!\r\n" |
| + | }); |
| + | } |
| + | for (const [key, value] of Object.entries(editNodes)) { |
| + | var params = { |
| + | action: 'edit', |
| + | title: '' + key, |
| + | text: '' + value + '}}', |
| + | format: 'json' |
| + | }, |
| + | api = new mw.Api(); |
| + | await api.postWithToken('csrf', params).done(function(data) { |
| + | console.log(data); |
| + | alertString += "Seite " + key + " bearbeitet!\r\n" |
| + | }); |
| + | } |
| + | for (const [key, value] of Object.entries(editDeletedEdges)) { |
| + | var params = { |
| + | action: 'edit', |
| + | title: '' + key, |
| + | text: '' + value, |
| + | format: 'json' |
| + | }, |
| + | api = new mw.Api(); |
| + | await api.postWithToken('csrf', params).done(function(data) { |
| + | console.log(data); |
| + | alertString += "Auf der Seite " + key + " wurde ein Attribut gelöscht!\r\n" |
| + | }); |
| + | } |
| + | for (const [key, value] of Object.entries(editDeletedNodes)) { |
| + | var params = { |
| + | action: 'delete', |
| + | title: '' + key, |
| + | format: 'json' |
| + | }, |
| + | api = new mw.Api(); |
| + | await api.postWithToken('csrf', params).done(function(data) { |
| + | console.log(data); |
| + | alertString += "Seite " + key + " wurde gelöscht!\r\n" |
| + | }); |
| + | } |
| + | // Example: Customize the displayed actions at the time the window is opened. |
| + | var messageDialog = new OO.ui.MessageDialog(); |
| + | // Create and append a window manager. |
| + | var windowManager = new OO.ui.WindowManager(); |
| + | $('body').append(windowManager.$element); |
| + | // Add the dialog to the window manager. |
| + | windowManager.addWindows([messageDialog]); |
| + | // Configure the message dialog when it is opened with the window manager's openWindow() method. |
| + | windowManager.openWindow(messageDialog, { |
| + | title: 'Folgende Änderugnen wurden übernommen:', |
| + | message: '' + alertString, |
| + | verbose: true, |
| + | actions: [{ |
| + | action: 'accept', |
| + | label: 'Okay', |
| + | flags: 'primary' |
| + | }] |
| + | }); |
| + | /*OO.ui.alert( "" + alertString ).done( function () { |
| + | console.log( alertString ); |
| + | } );*/ |
| + | } else {} |
| + | }); |
| + | } |
| + | //Deletes node in manipulation mode and the wiki page. |
| + | function deleteSelectedNode(data, callback) { |
| + | deleteNodesChildren(data.nodes[0]); |
| + | nodes.remove(data.nodes[0]); |
| + | for (var i = 0; i < contextCreatedProps.length; i++) { |
| + | var noNodesInNetwork = true; |
| + | for (var j = 0; j < nodes.getIds().length; j++) { |
| + | if (contextCreatedProps[i] == nodes.get(nodes.getIds()[j]).group) { |
| + | noNodesInNetwork = false; |
| + | } |
| } | | } |
− | | + | if (noNodesInNetwork === true) { |
− | });}else{ | + | givenDiv.querySelector('#' + contextCreatedProps[i]).remove(); |
− | if(network.getConnectedNodes(edgeToNode).length == 0){
| + | contextCreatedProps.splice(contextCreatedProps.indexOf(contextCreatedProps[i]), 1); |
− | delete newNodes[""+edgeToNode];
| + | i--; |
− | }else{
| |
− | var edgeString = `(\{\{Semantic\/Link[\\r\\n]*\\|[\\r\\n]*property=`+reverseLabel(edgeLabel)+`[\\r\\n]*\\|[\\r\\n]*value=`+edgeFromNode+`[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*)`;
| |
− | | |
− | var re = new RegExp(edgeString,"g");
| |
− | var wikiText = newNodes[""+edgeToNode];
| |
− | var newWikiText = wikiText.replace(re,"");
| |
− | newNodes[""+edgeToNode] = newWikiText;
| |
− | }
| |
| } | | } |
− | }else{
| + | } |
− | if(await pageExists(edgeFromNode) === true){
| + | delete oldGroups["" + data.nodes[0]]; |
− | await fetch('/w/api.php?action=parse&page='+ edgeFromNode +'&prop=wikitext&format=json')
| + | delete objClickedProps["" + data.nodes[0]]; |
− | .then(response => response.json())
| + | callback(); |
− | .then(data => {
| + | document.querySelector('.vis-delete').remove(); |
− | var wikiText = data.parse.wikitext['*'];
| + | editDeletedNodes["" + data.nodes[0]] = ""; |
− | console.log(wikiText);
| + | delete newNodes["" + data.nodes[0]]; |
− |
| + | delete editNodes["" + data.nodes[0]]; |
− | var edgeString = `(\{\{Semantic\/Link[\\r\\n]*\\|[\\r\\n]*property=`+edgeLabel+`[\\r\\n]*\\|[\\r\\n]*value=`+edgeToNode+`[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*)`;
| + | } |
− | //var edgeString = '(\\{\\{Semantic\/Element[^}]*[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*[\\r\\n]*\\}[\\r\\n]*\\})'
| + | //Deletes edge in manipulation mode and deletes the property from the node wikipages |
− | var re = new RegExp(edgeString,"g");
| + | async function deleteSelectedEdge(data, callback) { |
− |
| + | var edgeToNode = edges.get(data.edges[0]).to; |
− | var edgeStringFound = wikiText.search(re) >= 0;
| + | var edgeFromNode = edges.get(data.edges[0]).from; |
− |
| + | var edgeLabel = edges.get(data.edges[0]).label; |
− | if(edgeStringFound){
| + | edges.remove(data.edges[0]); |
− | if(editDeletedEdges[""+ edgeFromNode]){
| + | deleteNodesChildren(edgeToNode, true); |
− | var newWikiText = editDeletedEdges[""+ edgeFromNode].replace(re, "");
| + | deleteNodesChildren(edgeFromNode, true); |
− | editDeletedEdges[""+ edgeFromNode] = newWikiText;
| + | for (var i = 0; i < contextCreatedProps.length; i++) { |
− | }else{
| + | var noNodesInNetwork = true; |
− | var newWikiText = wikiText.replace(re, "");
| + | for (var j = 0; j < nodes.getIds().length; j++) { |
− | console.log(newWikiText)
| + | if (contextCreatedProps[i] == nodes.get(nodes.getIds()[j]).group) { |
− | editDeletedEdges[""+ edgeFromNode] = newWikiText;
| + | noNodesInNetwork = false; |
− | }
| + | } |
− |
| |
| } | | } |
− |
| + | if (noNodesInNetwork === true) { |
− | if(newNodes[""+edgeFromNode]){ | + | givenDiv.querySelector('#' + contextCreatedProps[i]).remove(); |
− |
| + | contextCreatedProps.splice(contextCreatedProps.indexOf(contextCreatedProps[i]), 1); |
− | var newWikiText = newNodes[""+edgeFromNode].replace(re, "");
| + | i--; |
− | newNodes[""+edgeFromNode] = newWikiText;
| |
− | | |
| } | | } |
− | | + | } |
− | if(editNodes[""+edgeFromNode]){
| + | if (edgeLabel[0] == "-") { |
− |
| + | if (await pageExists(edgeToNode) === true) { |
− | var newWikiText = editNodes[""+edgeFromNode].replace(re, "");
| + | await fetch('/w/api.php?action=parse&page=' + edgeToNode + '&prop=wikitext&format=json') |
− | editNodes[""+edgeFromNode] = newWikiText;
| + | .then(response => response.json()) |
− |
| + | .then(data => { |
| + | var wikiText = data.parse.wikitext['*']; |
| + | var edgeString = `(\{\{Semantic\/Link[\\r\\n]*\\|[\\r\\n]*property=` + reverseLabel(edgeLabel) + `[\\r\\n]*\\|[\\r\\n]*value=` + edgeFromNode + `[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*)` |
| + | //var edgeString = '(\\{\\{Semantic\/Element[^}]*[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*[\\r\\n]*\\}[\\r\\n]*\\})' |
| + | var re = new RegExp(edgeString, "g"); |
| + | var edgeStringFound = wikiText.search(re) >= 0; |
| + | if (edgeStringFound) { |
| + | if (editDeletedEdges["" + edgeToNode]) { |
| + | var newWikiText = editDeletedEdges["" + edgeToNode].replace(re, ""); |
| + | editDeletedEdges["" + edgeToNode] = newWikiText; |
| + | } else { |
| + | var newWikiText = wikiText.replace(re, ""); |
| + | editDeletedEdges["" + edgeToNode] = newWikiText; |
| + | } |
| + | } |
| + | if (newNodes["" + edgeToNode]) { |
| + | var newWikiText = newNodes["" + edgeToNode].replace(re, ""); |
| + | newNodes["" + edgeToNode] = newWikiText; |
| + | } |
| + | if (editNodes["" + edgeToNode]) { |
| + | var newWikiText = editNodes["" + edgeToNode].replace(re, ""); |
| + | editNodes["" + edgeToNode] = newWikiText; |
| + | } |
| + | }); |
| + | } else { |
| + | if (network.getConnectedNodes(edgeToNode).length == 0) { |
| + | delete newNodes["" + edgeToNode]; |
| + | } else { |
| + | var edgeString = `(\{\{Semantic\/Link[\\r\\n]*\\|[\\r\\n]*property=` + reverseLabel(edgeLabel) + `[\\r\\n]*\\|[\\r\\n]*value=` + edgeFromNode + `[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*)`; |
| + | var re = new RegExp(edgeString, "g"); |
| + | var wikiText = newNodes["" + edgeToNode]; |
| + | var newWikiText = wikiText.replace(re, ""); |
| + | newNodes["" + edgeToNode] = newWikiText; |
| + | } |
| } | | } |
− | | + | } else { |
− |
| + | if (await pageExists(edgeFromNode) === true) { |
− | });}else{
| + | await fetch('/w/api.php?action=parse&page=' + edgeFromNode + '&prop=wikitext&format=json') |
− | if(network.getConnectedNodes(edgeFromNode).length == 0){
| + | .then(response => response.json()) |
− | delete newNodes[""+edgeFromNode];
| + | .then(data => { |
− | }else{
| + | var wikiText = data.parse.wikitext['*']; |
− | var edgeString = `(\{\{Semantic\/Link[\\r\\n]*\\|[\\r\\n]*property=`+edgeLabel+`[\\r\\n]*\\|[\\r\\n]*value=`+edgeToNode+`[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*)`;
| + | var edgeString = `(\{\{Semantic\/Link[\\r\\n]*\\|[\\r\\n]*property=` + edgeLabel + `[\\r\\n]*\\|[\\r\\n]*value=` + edgeToNode + `[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*)`; |
− | | + | //var edgeString = '(\\{\\{Semantic\/Element[^}]*[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*[\\r\\n]*\\}[\\r\\n]*\\})' |
− | var re = new RegExp(edgeString,"g");
| + | var re = new RegExp(edgeString, "g"); |
− | var wikiText = newNodes[""+edgeFromNode];
| + | var edgeStringFound = wikiText.search(re) >= 0; |
− | var newWikiText = wikiText.replace(re,"");
| + | if (edgeStringFound) { |
− | newNodes[""+edgeFromNode] = newWikiText;
| + | if (editDeletedEdges["" + edgeFromNode]) { |
− | }
| + | var newWikiText = editDeletedEdges["" + edgeFromNode].replace(re, ""); |
− | console.log(newNodes);
| + | editDeletedEdges["" + edgeFromNode] = newWikiText; |
| + | } else { |
| + | var newWikiText = wikiText.replace(re, ""); |
| + | editDeletedEdges["" + edgeFromNode] = newWikiText; |
| + | } |
| + | } |
| + | if (newNodes["" + edgeFromNode]) { |
| + | var newWikiText = newNodes["" + edgeFromNode].replace(re, ""); |
| + | newNodes["" + edgeFromNode] = newWikiText; |
| + | } |
| + | if (editNodes["" + edgeFromNode]) { |
| + | var newWikiText = editNodes["" + edgeFromNode].replace(re, ""); |
| + | editNodes["" + edgeFromNode] = newWikiText; |
| + | } |
| + | }); |
| + | } else { |
| + | if (network.getConnectedNodes(edgeFromNode).length == 0) { |
| + | delete newNodes["" + edgeFromNode]; |
| + | } else { |
| + | var edgeString = `(\{\{Semantic\/Link[\\r\\n]*\\|[\\r\\n]*property=` + edgeLabel + `[\\r\\n]*\\|[\\r\\n]*value=` + edgeToNode + `[\\r\\n]*\\}[\\r\\n]*\\}[\\r\\n]*)`; |
| + | var re = new RegExp(edgeString, "g"); |
| + | var wikiText = newNodes["" + edgeFromNode]; |
| + | var newWikiText = wikiText.replace(re, ""); |
| + | newNodes["" + edgeFromNode] = newWikiText; |
| + | } |
| } | | } |
− |
| + | } |
− | }
| + | //nodes.remove(edges.get(data.edges[0]).to); |
− |
| + | callback(data); |
− |
| + | document.querySelector('.vis-delete').remove(); |
− |
| + | } |
− |
| + | //HTML for the manipulation popups |
− | console.log(editDeletedEdges);
| + | var editHtml = '' + |
− | //nodes.remove(edges.get(data.edges[0]).to);
| + | '<div id="node-popUp">' + |
− |
| + | ' <span id="node-operation" style="cursor: move;">node</span> <br />' + |
− | callback(data);
| + | ' <table style="margin: auto">' + |
− | document.querySelector('.vis-delete').remove();
| + | ' <tbody>' + |
− | console.log(objClickedProps);
| + | ' <tr>' + |
− | console.log(oldGroups);
| + | ' <td>label</td>' + |
− | } | + | ' <td><input id="node-label" value="" /></td>' + |
| + | ' </tr>' + |
| + | ' </tbody>' + |
| + | ' </table>' + |
| + | ' <input type="button" value="save" id="node-saveButton" />' + |
| + | ' <input type="button" value="cancel" id="node-cancelButton" />' + |
| + | '</div>' + |
| + | '' + |
| + | '<div id="edge-popUp">' + |
| + | ' <span id="edge-operation" style="cursor: move;">edge</span> <br />' + |
| + | ' <table style="margin: auto">' + |
| + | ' <tbody>' + |
| + | ' <tr>' + |
| + | ' <td>label</td>' + |
| + | ' <td><input id="edge-label" value="" /></td>' + |
| + | ' </tr>' + |
| + | ' </tbody>' + |
| + | ' </table>' + |
| + | ' <input type="button" value="save" id="edge-saveButton" />' + |
| + | ' <input type="button" value="cancel" id="edge-cancelButton" />' + |
| + | '</div>' + |
| + | ''; |
| + | var editHtmlDiv = document.createElement("div"); |
| + | editHtmlDiv.innerHTML = editHtml; |
| + | document.body.appendChild(editHtmlDiv); |
| + | //dragElement(document.getElementById("node-popUp")); |
| + | //dragElement(document.getElementById("edge-popUp")); |
| + | |
| + | //function to make the manipulation popups draggable |
| + | function dragElement(elmnt) { |
| + | var pos1 = 0, |
| + | pos2 = 0, |
| + | pos3 = 0, |
| + | pos4 = 0; |
| + | if (document.getElementById(elmnt.id)) { |
| + | // if present, the header is where you move the DIV from: |
| + | document.getElementById("node-operation").onmousedown = dragMouseDown; |
| + | document.getElementById("edge-operation").onmousedown = dragMouseDown; |
| + | } else { |
| + | // otherwise, move the DIV from anywhere inside the DIV: |
| + | elmnt.onmousedown = dragMouseDown; |
| + | } |
| | | |
− | var editHtml = '' +
| + | function dragMouseDown(e) { |
| + | e = e || window.event; |
| + | e.preventDefault(); |
| + | // get the mouse cursor position at startup: |
| + | pos3 = e.clientX; |
| + | pos4 = e.clientY; |
| + | document.onmouseup = closeDragElement; |
| + | // call a function whenever the cursor moves: |
| + | document.onmousemove = elementDrag; |
| + | } |
| | | |
− | '<div id="node-popUp">' +
| + | function elementDrag(e) { |
− | ' <span id="node-operation" style="cursor: move;">node</span> <br />' +
| + | e = e || window.event; |
− | ' <table style="margin: auto">' +
| + | e.preventDefault(); |
− | ' <tbody>' +
| + | // calculate the new cursor position: |
− | ' <tr>' +
| + | pos1 = pos3 - e.clientX; |
− | ' <td>label</td>' +
| + | pos2 = pos4 - e.clientY; |
− | ' <td><input id="node-label" value="" /></td>' +
| + | pos3 = e.clientX; |
− | ' </tr>' +
| + | pos4 = e.clientY; |
− | ' </tbody>' +
| + | // set the element's new position: |
− | ' </table>' +
| + | elmnt.style.top = (elmnt.offsetTop - pos2) + "px"; |
− | ' <input type="button" value="save" id="node-saveButton" />' +
| + | elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; |
− | ' <input type="button" value="cancel" id="node-cancelButton" />' +
| + | } |
− | '</div>' +
| |
− | '' +
| |
− | '<div id="edge-popUp">' +
| |
− | ' <span id="edge-operation" style="cursor: move;">edge</span> <br />' +
| |
− | ' <table style="margin: auto">' +
| |
− | ' <tbody>' +
| |
− | ' <tr>' +
| |
− | ' <td>label</td>' +
| |
− | ' <td><input id="edge-label" value="" /></td>' +
| |
− | ' </tr>' +
| |
− | ' </tbody>' +
| |
− | ' </table>' +
| |
− | ' <input type="button" value="save" id="edge-saveButton" />' +
| |
− | ' <input type="button" value="cancel" id="edge-cancelButton" />' +
| |
− | '</div>' +
| |
− | '';
| |
| | | |
− | | + | function closeDragElement() { |
− | | + | // stop moving when mouse button is released: |
− | | + | document.onmouseup = null; |
− | var editHtmlDiv = document.createElement("div");
| + | document.onmousemove = null; |
− | editHtmlDiv.innerHTML = editHtml;
| + | } |
− | document.body.appendChild(editHtmlDiv);
| + | } |
− | | + | } |
− | | + | }); |
− | | |
− | | |
− | | |
− | | |
− | | |
− | //dragElement(document.getElementById("node-popUp"));
| |
− | //dragElement(document.getElementById("edge-popUp"));
| |
− | | |
− | function dragElement(elmnt) {
| |
− | var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
| |
− | if (document.getElementById(elmnt.id)) {
| |
− |
| |
− | // if present, the header is where you move the DIV from:
| |
− | document.getElementById("node-operation").onmousedown = dragMouseDown;
| |
− | document.getElementById("edge-operation").onmousedown = dragMouseDown;
| |
− | } else {
| |
− | // otherwise, move the DIV from anywhere inside the DIV:
| |
− | elmnt.onmousedown = dragMouseDown;
| |
− | }
| |
− | | |
− | function dragMouseDown(e) {
| |
− | e = e || window.event;
| |
− | e.preventDefault();
| |
− | // get the mouse cursor position at startup:
| |
− | pos3 = e.clientX;
| |
− | pos4 = e.clientY;
| |
− | document.onmouseup = closeDragElement;
| |
− | // call a function whenever the cursor moves:
| |
− | document.onmousemove = elementDrag;
| |
− | }
| |
− | | |
− | function elementDrag(e) {
| |
− | e = e || window.event;
| |
− | e.preventDefault();
| |
− | // calculate the new cursor position:
| |
− | pos1 = pos3 - e.clientX;
| |
− | pos2 = pos4 - e.clientY;
| |
− | pos3 = e.clientX;
| |
− | pos4 = e.clientY;
| |
− | // set the element's new position:
| |
− | elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
| |
− | elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
| |
− | }
| |
− | | |
− | function closeDragElement() {
| |
− | // stop moving when mouse button is released:
| |
− | document.onmouseup = null;
| |
− | document.onmousemove = null;
| |
− | }
| |
− | } | |
− | | |
− | | |
− | } | |
− | });
| |
| }); | | }); |
− |
| |
| }); | | }); |