├── README.md ├── bootstrap.min.css ├── img ├── add-line.png ├── add-node.pdn ├── add-node.png ├── bg.png ├── delete-line.pdn ├── delete-line.png ├── delete-node.pdn ├── delete-node.png ├── favicon.PNG ├── favicon.ico ├── move-node.pdn └── move-node.png ├── index.html ├── js ├── algorithms.js ├── jquery-3.4.1.slim.min.js └── scripts.js └── styles.css /README.md: -------------------------------------------------------------------------------- 1 | # Graph-Node-Generator 2 | Generate graphs from nodes using graph theorem and graph traversal algorithms 3 | 4 | ## Screenshot: 5 | ![image](https://user-images.githubusercontent.com/64016811/139532039-54ef093b-a796-496f-976a-fb31afefc5e5.png) 6 | 7 | ## Tech Stack: 8 | - HTML 9 | - CSS 10 | - JavaScript 11 | - Bootstrap 12 | 13 | ## Overview: 14 | Used to generate, add or delete nodes, link the nodes using a GUI based approach and form graphs. Then one can find the shortest path between a start node and an end node as specified by the user through the input boxes. A build log is also displayed on the right sidebar of the application. This contains the instructions to guide an user and also the calculations of the shortest path. If a possible path doesn't exist between any pair of nodes that falls in the path of calculation, then shortest path length is displayed as null. 15 | 16 | ## Idea: 17 | - Uses graph traversal algorithms. 18 | - The nodes are numbered using a memory based approach. 19 | - Uses backtracking algorithm while finding the shortest path. 20 | - Node numbers and calculations based on the path traced are dynamic. 21 | 22 | ## Creator of the Project: 23 | 24 |
25 |
26 | Mainak Chaudhuri
27 |
28 | -------------------------------------------------------------------------------- /img/add-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/add-line.png -------------------------------------------------------------------------------- /img/add-node.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/add-node.pdn -------------------------------------------------------------------------------- /img/add-node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/add-node.png -------------------------------------------------------------------------------- /img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/bg.png -------------------------------------------------------------------------------- /img/delete-line.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/delete-line.pdn -------------------------------------------------------------------------------- /img/delete-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/delete-line.png -------------------------------------------------------------------------------- /img/delete-node.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/delete-node.pdn -------------------------------------------------------------------------------- /img/delete-node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/delete-node.png -------------------------------------------------------------------------------- /img/favicon.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/favicon.PNG -------------------------------------------------------------------------------- /img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/favicon.ico -------------------------------------------------------------------------------- /img/move-node.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/move-node.pdn -------------------------------------------------------------------------------- /img/move-node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MainakRepositor/Graph-Node-Generator/d74e440356f78bb339f1641e6fce1256c4d732f3/img/move-node.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Node Graphs 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |

NODE GRAPH GENERATOR

20 |
21 |
22 |
New node
23 |
Delete node
24 |
New line
25 |
Delete line
26 |
Move node
27 |

Shortest Path:

28 |
29 |
30 |
31 |
32 | 33 | 36 |
37 |
38 |
39 |
40 | 41 | 44 |
45 |
46 |
47 |
48 | 49 |
50 |
51 |
52 |
53 | 60 |
61 |

Made by : Mainak

62 |
63 | 64 | -------------------------------------------------------------------------------- /js/algorithms.js: -------------------------------------------------------------------------------- 1 | //all functions here assume nodes and edges have been created 2 | 3 | function print() { 4 | console.log(nodes); 5 | console.log(edges); 6 | } 7 | 8 | 9 | //0 -> empty 1 -> neighbor 10 | function buildAdjacencyMatrix(nodes, edges) { 11 | var adjacencyMatrix = []; 12 | for(var i = 0; i < nodes.length; i++) { 13 | var row = []; 14 | for(var j = 0; j < nodes.length; j++) { 15 | row.push(0); 16 | } 17 | adjacencyMatrix.push(row); 18 | } 19 | 20 | for(var i = 0; i < edges.length; i++) { 21 | var edge= edges[i]; 22 | for(var j = 0; j < nodes.length; j++) { 23 | var node = nodes[j]; 24 | if(edge.a.is(node.elem)) { 25 | for(var k = 0; k < nodes.length; k++) { 26 | // console.log("at edge " + i + " with node " + k + "as a, testing node " + k + "to see if it's b"); 27 | var node2 = nodes[k]; 28 | if(edge.b.is(node2.elem)) { 29 | adjacencyMatrix[j][k] = 1; 30 | adjacencyMatrix[k][j] = 1; 31 | } 32 | } 33 | } 34 | } 35 | } 36 | return adjacencyMatrix; 37 | } 38 | 39 | function getNeighbors(vertex, vertices, adjacencyMatrix) { 40 | // console.log(vertex, vertices, adjacencyMatrix); 41 | var neighbors = []; 42 | var arr = adjacencyMatrix[vertex.name]; 43 | for(var i = 0; i < arr.length; i++) { 44 | if(arr[i] == 1) { 45 | neighbors.push(vertices[i]); 46 | // console.log(i); 47 | } 48 | } 49 | // console.log(neighbors); 50 | return neighbors; 51 | } 52 | 53 | function nextUnvisitedNeighbor(vertex, vertices, adjacencyMatrix) { 54 | var neighbors = getNeighbors(vertex, vertices, adjacencyMatrix); 55 | for(var ind = 0; ind < neighbors.length; ind++) { 56 | var neighbor = neighbors[ind]; 57 | if(!neighbor.visited) { 58 | // console.log(neighbor.name); 59 | return neighbor; 60 | } 61 | } 62 | return null; 63 | } 64 | 65 | //takes two numbers 66 | function shortestPath(startVertex, endVertex) { 67 | //setup 68 | // startVertex = labelToNodeNum(startVertex); 69 | // endVertex = labelToNodeNum(endVertex); 70 | var result = {process:[], length:null}; 71 | var vertices = nodes; 72 | for(var ind = 0; ind < vertices.length; ind++) { 73 | var vertex = vertices[ind]; 74 | vertex.name = ind; 75 | vertex.length = null; 76 | vertex.prevVertex = null; 77 | vertex.visited = false; 78 | vertex.nextVertex = null; 79 | } 80 | startVertex = vertices[startVertex]; 81 | endVertex = vertices[endVertex]; 82 | var unvisitedVertices = []; 83 | 84 | var adjacencyMatrix = buildAdjacencyMatrix(nodes, edges); 85 | // console.log(nextUnvisitedNeighbor(vertices[0], vertices, adjacencyMatrix)); 86 | //console.log(getNeighbors(vertices[0], vertices, adjacencyMatrix)); 87 | 88 | 89 | var done = false; 90 | startVertex.visited = true; 91 | startVertex.length = 0; 92 | unvisitedVertices.push(startVertex); 93 | // console.log(startVertex, endVertex, unvisitedVertices); 94 | while(!done && unvisitedVertices.length != 0) { 95 | var frontVertex = unvisitedVertices[0]; 96 | unvisitedVertices.shift(); 97 | var processEntry = [frontVertex.name, []]; 98 | console.log("removed vertice " + frontVertex.name + " adding vertices: "); 99 | while(!done && nextUnvisitedNeighbor(frontVertex, vertices, adjacencyMatrix) != null) { 100 | var nextNeighbor = nextUnvisitedNeighbor(frontVertex, vertices, adjacencyMatrix); 101 | if(nextNeighbor.visited == false) { 102 | nextNeighbor.visited = true; 103 | nextNeighbor.length = 1 + frontVertex.length; 104 | nextNeighbor.prevVertex = frontVertex; 105 | unvisitedVertices.push(nextNeighbor); 106 | processEntry[1].push(nextNeighbor.name); 107 | console.log(nextNeighbor.name); 108 | } 109 | if(nextNeighbor.name == endVertex.name) { 110 | console.log("added vertice " + endVertex.name + ", search over"); 111 | done = true; 112 | } 113 | } 114 | result.process.push(processEntry); 115 | } 116 | result.length = endVertex.length; 117 | console.log("Path Length: " + endVertex.length); 118 | console.log(vertices); 119 | console.log(result); 120 | 121 | //print array 122 | 123 | return result; 124 | } -------------------------------------------------------------------------------- /js/jquery-3.4.1.slim.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.4.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector | (c) JS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(g,e){"use strict";var t=[],v=g.document,r=Object.getPrototypeOf,s=t.slice,y=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,m=n.hasOwnProperty,a=m.toString,l=a.call(Object),b={},x=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},w=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function C(e,t,n){var r,i,o=(n=n||v).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function T(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector",E=function(e,t){return new E.fn.init(e,t)},d=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function p(e){var t=!!e&&"length"in e&&e.length,n=T(e);return!x(e)&&!w(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+R+")"+R+"*"),U=new RegExp(R+"|>"),V=new RegExp(W),X=new RegExp("^"+B+"$"),Q={ID:new RegExp("^#("+B+")"),CLASS:new RegExp("^\\.("+B+")"),TAG:new RegExp("^("+B+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+R+"*(even|odd|(([+-]|)(\\d*)n|)"+R+"*(?:([+-]|)"+R+"*(\\d+)|))"+R+"*\\)|)","i"),bool:new RegExp("^(?:"+I+")$","i"),needsContext:new RegExp("^"+R+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+R+"*((?:-\\d)?\\d*)"+R+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,G=/^(?:input|select|textarea|button)$/i,K=/^h\d$/i,J=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+R+"?|("+R+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){C()},ae=xe(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{O.apply(t=P.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){O={apply:t.length?function(e,t){q.apply(e,P.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,d=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==d&&9!==d&&11!==d)return n;if(!r&&((e?e.ownerDocument||e:m)!==T&&C(e),e=e||T,E)){if(11!==d&&(u=Z.exec(t)))if(i=u[1]){if(9===d){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return O.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&p.getElementsByClassName&&e.getElementsByClassName)return O.apply(n,e.getElementsByClassName(i)),n}if(p.qsa&&!S[t+" "]&&(!v||!v.test(t))&&(1!==d||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===d&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=N),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+be(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return O.apply(n,f.querySelectorAll(c)),n}catch(e){S(t,!0)}finally{s===N&&e.removeAttribute("id")}}}return g(t.replace(F,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>x.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[N]=!0,e}function ce(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)x.attrHandle[n[r]]=t}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pe(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in p=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},C=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==T&&9===r.nodeType&&r.documentElement&&(a=(T=r).documentElement,E=!i(T),m!==T&&(n=T.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),p.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),p.getElementsByTagName=ce(function(e){return e.appendChild(T.createComment("")),!e.getElementsByTagName("*").length}),p.getElementsByClassName=J.test(T.getElementsByClassName),p.getById=ce(function(e){return a.appendChild(e).id=N,!T.getElementsByName||!T.getElementsByName(N).length}),p.getById?(x.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},x.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(x.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},x.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),x.find.TAG=p.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):p.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},x.find.CLASS=p.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(p.qsa=J.test(T.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+R+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+R+"*(?:value|"+I+")"),e.querySelectorAll("[id~="+N+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+N+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=T.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+R+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(p.matchesSelector=J.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){p.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",W)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=J.test(a.compareDocumentPosition),y=t||J.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!p.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument===m&&y(m,e)?-1:t===T||t.ownerDocument===m&&y(m,t)?1:u?H(u,e)-H(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===T?-1:t===T?1:i?-1:o?1:u?H(u,e)-H(u,t):0;if(i===o)return de(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?de(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),T},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==T&&C(e),p.matchesSelector&&E&&!S[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||p.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){S(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&V.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=d[e+" "];return t||(t=new RegExp("(^|"+R+")"+e+"("+R+"|$)"))&&d(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function L(e,n,r){return x(n)?E.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?E.grep(e,function(e){return e===n!==r}):"string"!=typeof n?E.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(E.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof E?t[0]:t,E.merge(this,E.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:v,!0)),D.test(r[1])&&E.isPlainObject(t))for(r in t)x(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=v.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):x(e)?void 0!==n.ready?n.ready(e):e(E):E.makeArray(e,this)}).prototype=E.fn,j=E(v);var O=/^(?:parents|prev(?:Until|All))/,P={children:!0,contents:!0,next:!0,prev:!0};function H(e,t){while((e=e[t])&&1!==e.nodeType);return e}E.fn.extend({has:function(e){var t=E(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,pe=/^$|^module$|\/(?:java|ecma)script/i,he={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ge(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&S(e,t)?E.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;nx",b.noCloneChecked=!!ye.cloneNode(!0).lastChild.defaultValue;var we=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Te=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function Ne(){return!1}function Ae(e,t){return e===function(){try{return v.activeElement}catch(e){}}()==("focus"===t)}function ke(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)ke(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Ne;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return E().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=E.guid++)),e.each(function(){E.event.add(this,t,i,r,n)})}function Se(e,i,o){o?(G.set(e,i,!1),E.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=G.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(E.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),G.set(this,i,r),t=o(this,i),this[i](),r!==(n=G.get(this,i))||t?G.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(G.set(this,i,{value:E.event.trigger(E.extend(r[0],E.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===G.get(e,i)&&E.event.add(e,i,Ee)}E.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,v=G.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&E.find.matchesSelector(ie,i),n.guid||(n.guid=E.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof E&&E.event.triggered!==e.type?E.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(I)||[""]).length;while(l--)p=g=(s=Te.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),p&&(f=E.event.special[p]||{},p=(i?f.delegateType:f.bindType)||p,f=E.event.special[p]||{},c=E.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&E.expr.match.needsContext.test(i),namespace:h.join(".")},o),(d=u[p])||((d=u[p]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(p,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,c):d.push(c),E.event.global[p]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,v=G.hasData(e)&&G.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(I)||[""]).length;while(l--)if(p=g=(s=Te.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),p){f=E.event.special[p]||{},d=u[p=(r?f.delegateType:f.bindType)||p]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=d.length;while(o--)c=d[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(d.splice(o,1),c.selector&&d.delegateCount--,f.remove&&f.remove.call(e,c));a&&!d.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||E.removeEvent(e,p,v.handle),delete u[p])}else for(p in u)E.event.remove(e,p+t[l],n,r,!0);E.isEmptyObject(u)&&G.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=E.event.fix(e),u=new Array(arguments.length),l=(G.get(this,"events")||{})[s.type]||[],c=E.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,Le=/\s*$/g;function Oe(e,t){return S(e,"table")&&S(11!==t.nodeType?t:t.firstChild,"tr")&&E(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Ie(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(G.hasData(e)&&(o=G.access(e),a=G.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(b.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||E.isXMLDoc(e)))for(a=ge(c),r=0,i=(o=ge(e)).length;r
",2===pt.childNodes.length),E.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(b.createHTMLDocument?((r=(t=v.implementation.createHTMLDocument("")).createElement("base")).href=v.location.href,t.head.appendChild(r)):t=v),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&E(o).remove(),E.merge([],i.childNodes)));var r,i,o},E.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=E.css(e,"position"),c=E(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=E.css(e,"top"),u=E.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),x(t)&&(t=t.call(e,n,E.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},E.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){E.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===E.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===E.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=E(e).offset()).top+=E.css(e,"borderTopWidth",!0),i.left+=E.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-E.css(r,"marginTop",!0),left:t.left-i.left-E.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===E.css(e,"position"))e=e.offsetParent;return e||ie})}}),E.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;E.fn[t]=function(e){return z(this,function(e,t,n){var r;if(w(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),E.each(["top","left"],function(e,n){E.cssHooks[n]=ze(b.pixelPosition,function(e,t){if(t)return t=Fe(e,n),Me.test(t)?E(e).position()[n]+"px":t})}),E.each({Height:"height",Width:"width"},function(a,s){E.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){E.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return z(this,function(e,t,n){var r;return w(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?E.css(e,t,i):E.style(e,t,n,i)},s,n?e:void 0,n)}})}),E.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){E.fn[n]=function(e,t){return 0"); 174 | line.addClass("line"); 175 | var xDiff = Math.abs(x1 - x2); 176 | var yDiff = Math.abs(y1 - y2); 177 | var width = Math.sqrt(xDiff * xDiff + yDiff * yDiff); 178 | line.css("left", Math.round((x1 + x2) / 2 - width / 2)); 179 | line.css("top", Math.round((y1 + y2) / 2 - LINE_HEIGHT / 2)); 180 | line.css("width", width); 181 | var angle = Math.asin(yDiff / width) * 180 / Math.PI; 182 | if(((y2 - y1) / (x2 - x1)) < 0) { 183 | //console.log("slope: " + ((y2 - y1) / (x2 - x1))) 184 | angle *= -1; 185 | } 186 | // console.log(angle); 187 | line.css("transform", "rotate(" + /*Math.round(*/angle/*)*/ + "deg)"); 188 | return line; 189 | } 190 | 191 | function updateLinesFromNodes() { 192 | for(var ind = 0; ind < edges.length; ind++) { 193 | var edge = edges[ind]; 194 | var a = edge.a; 195 | var b = edge.b; 196 | var line = createLine(parseInt(a.css("left")) + CIRCLE_WIDTH / 2, 197 | parseInt(a.css("top")) + CIRCLE_WIDTH / 2, 198 | parseInt(b.css("left")) + CIRCLE_WIDTH / 2, 199 | parseInt(b.css("top")) + CIRCLE_WIDTH / 2); 200 | edge.nodeline.remove(); 201 | edge.nodeline = line; 202 | $("#stage").append(line); 203 | } 204 | } 205 | 206 | function endresize() { 207 | //console.log("resize over"); 208 | var prev = stage_width; 209 | stage_width = $("#stage").width(); 210 | for(var ind = 0; ind < nodes.length; ind++) { 211 | var node = nodes[ind]; 212 | var left = Math.round(node.x * stage_width); 213 | var max = Math.round(stage_width - CIRCLE_WIDTH); 214 | node.elem.css("left", Math.min(left, max)); 215 | } 216 | updateLinesFromNodes(); 217 | } 218 | 219 | //convert mouse pointer coords to left and top css properties of node 220 | function pointerToLT(xCoord, yCoord) { 221 | xCoord = Math.max(CIRCLE_WIDTH / 2, xCoord); 222 | xCoord = Math.min(xCoord, $("#stage").width() - CIRCLE_WIDTH / 2); 223 | yCoord = Math.max(yCoord, CIRCLE_WIDTH / 2); 224 | yCoord = Math.min(yCoord, $("#stage").height() - CIRCLE_WIDTH / 2); 225 | xCoord -= CIRCLE_WIDTH / 2; 226 | yCoord -= CIRCLE_WIDTH / 2; 227 | xCoord = Math.round(xCoord); 228 | yCoord = Math.round(yCoord); 229 | return {left: xCoord, top:yCoord}; 230 | } 231 | 232 | function updateNodeX(nodeElem) { 233 | for(var i = 0; i < nodes.length; i++) { 234 | var node = nodes[i]; 235 | if(node.elem.is(nodeElem)) { 236 | // console.log("changing internals"); 237 | node.x = parseInt(nodeElem.css("left")) / $("#stage").width(); 238 | return; 239 | } 240 | } 241 | } 242 | 243 | function nodeNumToLabel(nodeNum) { 244 | return $(".node").eq(nodeNum).text(); 245 | } 246 | 247 | function labelToNodeNum(label) { 248 | var returnVal; 249 | $(".node").each(function(ind) { 250 | if($(this).text() == label) { 251 | console.log(ind); 252 | returnVal = ind; 253 | } 254 | }); 255 | return returnVal; 256 | } 257 | 258 | function genDisplay(processArray) { 259 | console.log(processArray); 260 | var ind = 0; 261 | var ind2 = 0; 262 | var interval = setInterval(function() { 263 | if(ind2 >= processArray[ind][1].length) { 264 | $(".node").removeClass("visiting"); 265 | $(".node").eq(processArray[ind][0]).addClass("visited"); 266 | ind++; 267 | ind2 = 0; 268 | } 269 | if(ind >= processArray.length) { 270 | clearInterval(interval); 271 | } 272 | console.log(ind, ind2); 273 | $(".node").removeClass("on"); 274 | var node = $(".node").eq(processArray[ind][0]); 275 | var nodeVisiting = $(".node").eq(processArray[ind][1][ind2]); 276 | nodeVisiting.addClass("visiting"); 277 | node.addClass("on"); 278 | ind2++; 279 | }, 1000); 280 | } 281 | 282 | function printToSidebar(txt) { 283 | $("#log").append("

" + txt + "

"); 284 | } 285 | 286 | function callShortestPath(nodeNum1, nodeNum2) { 287 | var nodeNum1 = labelToNodeNum(nodeNum1); 288 | var nodeNum2 = labelToNodeNum(nodeNum2); 289 | console.log(nodeNum1, nodeNum2); 290 | var result = shortestPath(nodeNum1, nodeNum2); 291 | genDisplay(result.process); 292 | 293 | printToSidebar("Length: " + result.length); 294 | 295 | //Print out path 296 | var vertlist = []; 297 | var vert = result[result.length - 1][0]; 298 | while(vert.prevVertex != null) { 299 | vertlist.push(vert); 300 | vert = vert.prevVertex; 301 | } 302 | console.log(vertlist); 303 | } 304 | 305 | function handleAddNode(xCoord, yCoord) { 306 | //place node inside stage boundaries 307 | xCoord = Math.max(CIRCLE_WIDTH / 2, xCoord); 308 | xCoord = Math.min(xCoord, $("#stage").width() - CIRCLE_WIDTH / 2); 309 | yCoord = Math.max(yCoord, CIRCLE_WIDTH / 2); 310 | yCoord = Math.min(yCoord, $("#stage").height() - CIRCLE_WIDTH / 2); 311 | 312 | //create node DOM element and associated node object in list 313 | var circle = $("
").addClass("node"); 314 | var node = {elem:circle, x:(xCoord / $("#stage").width())}; 315 | nodes.push(node); 316 | xCoord -= CIRCLE_WIDTH / 2; 317 | yCoord -= CIRCLE_WIDTH / 2; 318 | circle.css("left", Math.round(xCoord)); 319 | circle.css("top", Math.round(yCoord)); 320 | if(deleted.length != 0) { 321 | circle.html(deleted.shift()); 322 | } 323 | else { 324 | circle.html(nodes.length - 1); 325 | } 326 | $("#stage").append(circle); 327 | updateSelectBox(); 328 | } 329 | 330 | function handleDeleteNode(node) { 331 | //delete associated edges 332 | for(var ind = 0; ind < edges.length; ind++) { 333 | var edge = edges[ind]; 334 | if(edge.a.is(node) || edge.b.is(node)) { 335 | console.log(edge); 336 | 337 | edge.nodeline.hide(); 338 | edges.splice(ind, 1); 339 | ind--; 340 | } 341 | } 342 | deleted.push(node.text()); 343 | deleted.sort(); 344 | var index = $(".node").index(node); 345 | console.log(index); 346 | nodes.splice(index, 1); 347 | node.remove(); 348 | updateSelectBox(); 349 | } 350 | 351 | function handleAddLine(node) { 352 | 353 | if(nodeHeld == null) { 354 | nodeHeld = node; 355 | $("#tempLine").show(); 356 | return; 357 | } 358 | var line = createLine(parseInt(nodeHeld.css("left")) + CIRCLE_WIDTH / 2, 359 | parseInt(nodeHeld.css("top")) + CIRCLE_WIDTH / 2, 360 | parseInt(node.css("left")) + CIRCLE_WIDTH / 2, 361 | parseInt(node.css("top")) + CIRCLE_WIDTH / 2); 362 | $("#stage").append(line); 363 | var edge = {a: nodeHeld, b: (node), nodeline:line}; 364 | edges.push(edge); 365 | 366 | //reset tempLine 367 | $("#tempLine").css("top", 0) 368 | $("#tempLine").css("left", 0); 369 | $("#tempLine").css("width", 0); 370 | nodeHeld = null; 371 | } 372 | 373 | function handleDeleteLine(line) { 374 | for(var ind = 0; ind < edges.length; ind++) { 375 | if(edges[ind].nodeline.is(line)) { 376 | edges.splice(ind, 1); 377 | line.remove(); 378 | return; 379 | } 380 | } 381 | } 382 | 383 | //place node at final position and update node list with position 384 | function handleMoveNodeMouseUp(e) { 385 | // console.log("mouse up"); 386 | var pos = getXandY(e); 387 | var processedCoords = pointerToLT(pos.x, pos.y); 388 | nodeMoving.css("left", processedCoords.left); 389 | nodeMoving.css("top", processedCoords.top); 390 | updateNodeX(nodeMoving); 391 | updateLinesFromNodes(); 392 | nodeMoving = null; 393 | } 394 | 395 | function updateSelectBox() { 396 | $(".shortest-path .form-control").empty(); 397 | var options = []; 398 | for(var ind = 0; ind < nodes.length; ind++) { 399 | options.push($(".node").eq(ind).text()); 400 | } 401 | options.sort(); 402 | for(var ind = 0; ind < options.length; ind++) { 403 | $(".shortest-path .form-control").append(""); 404 | } 405 | } 406 | 407 | function handleShortestPathBtnClicked() { 408 | var nodeNum1 = parseInt($("#node1 option:selected").text()); 409 | var nodeNum2 = parseInt($("#node2 option:selected").text()); 410 | if(nodeNum1 != nodeNum2) { 411 | callShortestPath(nodeNum1, nodeNum2); 412 | } 413 | $(".node").removeClass("on"); 414 | $(".node").removeClass("visited"); 415 | $(".node").removeClass("visiting"); 416 | } 417 | }); -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | body{ 2 | overflow: hidden; 3 | background: url(img/bg.png); 4 | } 5 | .control { 6 | border:3px solid rgb(128, 0, 6); 7 | padding:5px; 8 | margin-bottom:10px; 9 | cursor: default; 10 | user-select:none; 11 | border-radius: 10px; 12 | text-align: center; 13 | background-color: #ffffff; 14 | } 15 | .control:hover { 16 | background-color:#f1ee3a; 17 | } 18 | .control span { 19 | margin-left:5px; 20 | } 21 | .control.selected { 22 | background-color:#00fc2a; 23 | } 24 | .control.selected:hover { 25 | background-color:#62ffff; 26 | } 27 | h1{ 28 | padding-top:-50px; 29 | margin-top:-30px; 30 | text-align: center; 31 | color: #fae6ff; 32 | } 33 | h2{ 34 | text-align: center; 35 | color: #fae6ff; 36 | } 37 | h4{ 38 | text-align: center; 39 | margin-top: -10px; 40 | color: #fae6ff; 41 | } 42 | #message,#log 43 | { 44 | color:aliceblue; 45 | } 46 | .node { 47 | position:absolute; 48 | display:table-cell; 49 | background-color:rgb(253, 253, 253); 50 | width:30px; 51 | height:30px; 52 | border-radius:50%; 53 | /* line-height:30px;*/ 54 | text-align:center; 55 | vertical-align: middle; 56 | cursor: default; 57 | user-select:none; 58 | z-index:2; 59 | } 60 | 61 | #stage { 62 | height:600px; 63 | padding-left:0px; 64 | padding-right:0px; 65 | border: 5px solid rgb(111, 136, 248); 66 | position:relative; 67 | border-radius: 10px; 68 | } 69 | 70 | .container-fluid.custom { 71 | margin: 50px 0px; 72 | } 73 | 74 | #sidebar { 75 | padding:0px 15px; 76 | } 77 | #sidebar .inner { 78 | border: 3px solid rgb(3, 255, 150); 79 | height:100%; 80 | padding: 10px; 81 | border-radius: 10px; 82 | } 83 | #message { 84 | font-style: italic; 85 | text-align: center; 86 | 87 | } 88 | 89 | line { 90 | stroke: black; 91 | stroke-width:2; 92 | } 93 | #tempLine { 94 | display:none; 95 | } 96 | .line { 97 | height:2px; 98 | background-color:rgb(82, 181, 238); 99 | position:absolute; 100 | z-index:1; 101 | } 102 | 103 | #controlbar, #stage, #sidebar { 104 | margin-bottom:15px; 105 | } 106 | #shortest-path-button { 107 | margin-left:20px; 108 | font-size: 20px; 109 | background-color: rgb(63, 35, 142); 110 | border-radius: 50px; 111 | padding:10px 50px; 112 | } 113 | #shortest-path-button:hover { 114 | background-color: rgb(0, 255, 255); 115 | color: rgb(2, 2, 37); 116 | font-weight: 600; 117 | } 118 | #shortest-path-heading { 119 | margin-top:50px; 120 | font-weight: bold; 121 | border-radius: 10px; 122 | color: #fae6ff; 123 | } 124 | .on { 125 | /* background-color:purple;*/ 126 | 127 | } 128 | .visiting { 129 | border:2px solid rgb(240, 101, 9); 130 | } 131 | .visited { 132 | background-color: rgb(30, 243, 11); 133 | } 134 | button { 135 | border-radius: 10px; 136 | align-items: center; 137 | } 138 | .form-group 139 | { 140 | color:aliceblue; 141 | } --------------------------------------------------------------------------------