graphdb-workbench 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/11.3957302d7a301df30dd1.bundle.js +1 -1
- package/dist/11.3957302d7a301df30dd1.bundle.js.map +1 -1
- package/dist/120.80843604737b7c260788.bundle.js +1 -1
- package/dist/120.80843604737b7c260788.bundle.js.map +1 -1
- package/dist/18.44723ea06155c72f46ae.bundle.js +1 -1
- package/dist/18.44723ea06155c72f46ae.bundle.js.map +1 -1
- package/dist/25.9e0925889b3a3f79c7fe.bundle.js +1 -1
- package/dist/25.9e0925889b3a3f79c7fe.bundle.js.map +1 -1
- package/dist/29.9bdb27c21d6eacac1341.bundle.js +1 -1
- package/dist/29.9bdb27c21d6eacac1341.bundle.js.map +1 -1
- package/dist/30.34b74ada583b1b0af913.bundle.js +1 -1
- package/dist/30.34b74ada583b1b0af913.bundle.js.map +1 -1
- package/dist/68.e25480b7770a679a9654.bundle.js +1 -1
- package/dist/68.e25480b7770a679a9654.bundle.js.map +1 -1
- package/dist/{bundle.a8677c75aad1ad7b3b6a.bundle.js → bundle.deea1d235ad6ebbd617a.bundle.js} +3 -3
- package/dist/bundle.deea1d235ad6ebbd617a.bundle.js.map +1 -0
- package/dist/index.html +3 -3
- package/dist/js/angular/core/directives/rdfresourcesearch/templates/rdfResourceSearchTemplate.html +1 -1
- package/dist/pages/autocomplete.html +1 -1
- package/dist/pages/choose-repository-type.html +1 -1
- package/dist/pages/cluster-management/clusterInfo.html +3 -3
- package/dist/pages/create-index.html +4 -4
- package/dist/pages/dependencies.html +1 -1
- package/dist/pages/domainRangeInfo.html +2 -2
- package/dist/pages/edit.html +1 -1
- package/dist/pages/explore.html +1 -1
- package/dist/pages/export.html +1 -1
- package/dist/pages/find.html +1 -1
- package/dist/pages/graph-config/saveGraphConfig.html +11 -11
- package/dist/pages/graphs-visualizations.html +7 -7
- package/dist/pages/import.html +1 -1
- package/dist/pages/jdbc-create.html +5 -5
- package/dist/pages/monitor/queries.html +1 -1
- package/dist/pages/monitor/resources.html +2 -2
- package/dist/pages/namespaces.html +2 -2
- package/dist/pages/plugins.html +1 -1
- package/dist/pages/rdfClassHierarchyInfo.html +7 -7
- package/dist/pages/rdfrank.html +2 -2
- package/dist/pages/repositories.html +2 -2
- package/dist/pages/repository.html +2 -2
- package/dist/pages/similarity-indexes.html +1 -1
- package/dist/pages/sparql-template-create.html +5 -5
- package/dist/pages/sparql.html +3 -3
- package/dist/pages/webapi.html +2 -2
- package/dist/res/swagger/index.html +27 -27
- package/package.json +1 -1
- package/dist/bundle.a8677c75aad1ad7b3b6a.bundle.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["webpack:///./src/js/lib/d3-tip/d3-tip-patch.js","webpack:///./src/js/lib/common/d3-utils.js","webpack:///./src/js/angular/repositories/repository.constants.js","webpack:///./src/js/angular/graphexplore/controllers/graphs-visualizations.controller.js"],"names":["direction","offset","html","node","initNode","svg","point","target","customPosition","tip","vis","el","tagName","toLowerCase","ownerSVGElement","createSVGPoint","document","body","appendChild","show","args","Array","prototype","slice","call","arguments","length","SVGElement","pop","coords","content","apply","this","poffset","dir","nodel","getNodeEl","i","directions","scrollTop","documentElement","scrollLeft","customPos","style","opacity","classed","direction_callbacks","get","top","left","hide","attr","n","v","d3","selection","functor","destroy","remove","map","bbox","getScreenBBox","y","offsetHeight","x","offsetWidth","s","e","w","nw","ne","sw","se","keys","select","createElement","position","targetel","event","getScreenCTM","parentNode","matrix","tbbox","getBBox","width","height","matrixTransform","D3","Text","calcFontSizeRaw","text","radius","minimumSize","isMultiline","textSize","substring","match","Math","round","calcFontSize","getTextWithElipsisIfNeeded","str","threshold","Transition","fadeIn","sel","duration","transition","fadeOut","Click","delayDblClick","dispatch","rebind","down","wait","on","mouse","Date","d","a","b","sqrt","pow","window","clearTimeout","dblclick","setTimeout","click","STATIC_RULESETS","id","name","REPOSITORY_TYPES","graphdbRepo","free","eeWorker","eeMaster","ontop","fedx","FILENAME_PATTERN","RegExp","NUMBER_PATTERN","GraphsVisualizationsCtrl","$scope","$rootScope","$repositories","$licenseService","toastr","$timeout","$http","ClassInstanceDetailsService","AutocompleteRestService","$q","$location","$jwtAuth","UiScrollService","ModalService","$modal","$window","LocalStorageAdapter","LSKeys","SavedGraphsRestService","GraphConfigRestService","RDF4JRepositoriesRestService","$translate","languageChanged","propertiesObj","propertiesQueryObj","items","propertiesNotFiltered","searchVisible","nodeSelected","queryResultsMode","embedded","search","openedNodeInfoPanel","undefined","invalidLimit","INVALID_LINKS_MSG","instant","INVALID_LINKS_TOOLTIP","$on","propertiesSearchPlaceholder","onopen","onclose","angular","noop","query","uri","config","saved","noGoHome","datasource","current","type2color","colorIndex","nodeLabelMinFontSize","panAndZoom","behavior","zoom","scaleExtent","transformValues","tipElement","openedLink","copyToClipboard","openCopyToClipboardModal","renderSettings","settings","languagesMap","_","languages","preferredTypesMap","preferredTypes","rejectedTypesMap","rejectedTypes","preferredPredicatesMap","preferredPredicates","rejectedPredicatesMap","rejectedPredicates","key","index","count","success","initLazyList","$watch","each","item","revision","adapterContainer","adapter","remain","propertiesFilterFunc","indexOf","resetState","configLoaded","lastSavedGraphName","lastSavedGraphId","shared","numberOfPinnedNodes","pushHistory","searchParams","state","goToHome","url","shouldShowSettings","defaultGraphConfig","shouldDisableSameAs","sameAsCheckbox","$","prop","isDefined","reload","toggleMoreInfo","ev","element","currentTarget","parent","next","toggle","children","toggleClass","defaultSettings","linksLimit","includeInferred","sameAsState","showLinksText","preferredTypesOnly","preferredPredicatesOnly","includeSchema","saveSettings","copy","when","getPrincipal","then","principal","settingsFromPrincipal","appSettings","localStorageSettings","GRAPHS_VIZ","unique","set","initSettings","resetSettings","validateLinksLimit","changeLimit","delta","test","showSettings","showInfoPanel","showFilter","showNodeInfo","showPredicates","reExpandNode","rootNodeIri","$broadcast","loadGraphForQuery","queryString","sameAsParam","inferredParam","sendSameAs","sendInferred","loading","method","headers","data","response","initGraphFromResponse","error","getError","removeSpecialChars","string","replace","convertTripleToLinkId","triple","tripleLike","tripleParts","split","join","convertLinkDataToLinkId","link","source","iri","getNodeX","isTriple","getElementById","__data__","getNodeY","createTriple","value","trim","createArrowMarkerUniqueID","Graph","nodes","links","tripleNodes","Map","tripleLinksCopy","addNode","push","computeConnectedness","counts","seenLinks","i1","i2","seenKey","min","max","connectedness","addAndMatchLinks","newLinks","isTripleSource","getTripleNode","find","o","isTripleTarget","matchedLink","predicates","linkId","graph","has","matchLinksToNodes","delete","filter","countLinks","findLinksForNode","l","linksTypes","linksForNode","types","uniq","flatten","linksPredicates","removeTriples","triplesToRemove","targetTriples","size","forEach","reject","sourceSplit","lSource","lTarget","targetSplit","isRejected","removeNode","removeNodeLeafLinks","targetLinks","addTriple","weight","copyState","nodesCopy","labels","rdfRank","fixed","triplesCopy","JSON","stringify","from","entries","scale","translate","restoreState","parse","draw","updateSettings","t","sameAs","inference","startMode","loadGraphConfig","selectAll","getGraphConfigs","graphCallback","graphConfigs","loadConfigForId","configId","successCallback","getConfig","findConfigById","grep","easyGraphSearch","openUri","startIRI","startGraphQuery","loadGraphForConfig","startQueryIncludeInferred","startQuerySameAs","deleteConfig","openSimpleModal","title","message","configName","warning","result","deleteGraphConfig","refreshSavedGraphs","goToGraphConfig","onpopstate","savedGraph","loadSavedGraph","initGraphFromQueryParam","inputValue","params","rootNode","expandNode","catch","err","getSavedGraph","msg","loadGraphFromQueryParam","initForRepository","newRepo","getActiveRepository","hasInitedRepository","getNamespacesPromise","getNamespaces","nss","results","bindings","namespace","prefix","namespaces","sortBy","checkAutocompleteStatus","isLicenseValid","getAutocompletePromise","replaceIRIWithPrefix","namespacePrefix","findLast","addedTag","tag","uriParts","uriPart","localName","isUndefined","expandedUri","getNamespaceUriForPrefix","expandPrefix","pageslideExpanded","validateTag","category","wildcardOK","wildcardPos","getTagClass","tagText","endsWith","empty","multiClickDelay","nodeLabelRectScaleX","color1","linear","domain","range","interpolate","interpolateHslLong","color2","getColor","type","force","layout","gravity","append","showNodeTipAndIconsTimer","removeIconsTimer","loader","setLoadingState","getLoadingState","init","resetRootNode","container","stopPropagation","removeMenuIfVisible","stop","getBoundingClientRect","bottom","createTipText","p","getShortPredicate","numOfPredLeft","numberOfPredLeft","textToShow","tipPredicateElement","tipPredicates","textWidth","ctx","getContext","font","measureText","calculateWidth","hideTipForNode","cancel","tipTimer","charge","linkDistance","span","splitedLink","predicateText","addClass","textLength","getPredicateTextLength","enter","predicate","getPredicate","tipPredicateTimer","thisPredicateTipElement","showPredicateToolTip","revertElementsStyleToDefault","tripleNode","clickedNode","button","nodeCopy","pred","applyElementsStyleChanges","foundNodeIndex","findIndex","getTripleNodeIndex","isPartOfTriple","partOfTriple","nodeIndex","openPredicates","linkActions","mouseEventTimer","upEventLast","virtualClickEventTimer","moveEventCount","downEventHandler","timeStamp","preventDefault","upEventHandler","info","closeInfoPanel","showPinAnimation","startSize","endSize","startOpacity","endOpacity","animate","pin","innerD","drag","origin","sourceEvent","fixedBeforeDrag","isBeingDragged","beginDragging","px","py","pinWasFixed","resume","menuEvents","closeIcon","expandIcon","focusIcon","copyURIIcon","removeIcons","alpha","initIcons","expandNodeIcons","thisTipElement","showTipForNode","hideNode","shiftKey","updateTipForNode","nodeLabels","insert","fontSize","label","textContent","endlessLoopGuard","scrollHeight","clientHeight","scrollWidth","clientWidth","updateNodeLabels","geom","quadtree","sourceX","targetX","sourceY","targetY","linkedNodes","p1","p2","atan2","PI","angleDeg","abs","findAngleBetweenNodes","sourceId","targetId","twoWayLinkID","textNode","createTextNode","lastChild","start","getPositionAndAngle","angle","cos","sin","collapseIcon","actionsTip","expandedState","right","isExpanded","getAttribute","animateMenu","delay","ease","ctrlKey","metaKey","initGraph","renderGraphFromResponse","isStartNode","linksFound","newLink","existingLink","linksCopy","tripleLinksIt","values","nodesFromLinks","array","distinctBy","union","existingNodes","Boolean","tripleNodesIt","newNodes","some","promises","newNodesData","newNode","res","all","newNodeData","theta","expandIri","nodeTypes","nodeIri","resourceType","encodedIri","encodeURI","rdfsLabel","rdfsComment","comment","expanded","dataNodeKeysQuery","mapKeys","nodeImage","imageVal","updatePredicatesColor","getElementsByClassName","linkLink","stroke","strokeWidth","markers","marker","markerLink","setAttribute","className","color","preds","predLink","fill","oppLinkIRI","oppTriplePred","currEl","fontWeight","shortIRI","toggleSidePanel","clickLink","predData","clickedEl","every","linkPred","splitPredicate","isLoadingLocation","hasActiveLocation","rotate","isLeft","pivotX","pivotY","noHistory","saveOrUpdateGraph","graphToSave","saveGraphModal","renameSavedGraph","graphToRename","editSavedGraphHttp","editSavedGraph","mode","graphExists","open","templateUrl","controller","resolve","restart","addNewSavedGraph","status","saveGraphHttp","getSavedGraphs","savedGraphs","graphToLoad","owner","copyToClipboardSavedGraph","location","protocol","host","pathname","deleteSavedGraph","graphName","deleteSavedGraphHttp","openIRI","togglePinAllNodes","nodeName","keyCode","getLiteralFromPropValue","SaveGraphModalCtrl","$modalInstance","okButtonText","ok","form","$valid","close","saveNew","dismiss","module","$tooltipProvider","options","appendToBody","$inject"],"mappings":"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","file":"25.9e0925889b3a3f79c7fe.bundle.js","sourcesContent":["// d3.tip\n// Copyright (c) 2013 Justin Palmer\n//\n// Tooltips for d3.js SVG visualizations\n\n(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module with d3 as a dependency.\n define([], factory)\n } else if (typeof module === 'object' && module.exports) {\n // CommonJS\n module.exports = function(d3) {\n d3.tip = factory(d3)\n return d3.tip\n }\n } else {\n // Browser global.\n root.d3.tip = factory(root.d3)\n }\n}(this, function () {\n // Public - contructs a new tooltip\n //\n // Returns a tip\n return function() {\n var direction = d3_tip_direction,\n offset = d3_tip_offset,\n html = d3_tip_html,\n node = initNode(),\n svg = null,\n point = null,\n target = null,\n customPosition = null\n\n function tip(vis) {\n svg = getSVGNode(vis)\n point = svg.createSVGPoint()\n document.body.appendChild(node)\n }\n\n // Public - show the tooltip on the screen\n //\n // Returns a tip\n tip.show = function() {\n var args = Array.prototype.slice.call(arguments)\n if(args[args.length - 1] instanceof SVGElement) target = args.pop()\n\n var content = html.apply(this, args),\n poffset = offset.apply(this, args),\n dir = direction.apply(this, args),\n nodel = getNodeEl(),\n i = directions.length,\n coords,\n scrollTop = document.documentElement.scrollTop || document.body.scrollTop,\n scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft,\n customPos = customPosition.apply(this, args)\n\n nodel.html(content)\n .style({ opacity: 1, 'pointer-events': 'all' })\n\n while(i--) nodel.classed(directions[i], false)\n coords = direction_callbacks.get(dir).apply(this)\n\n if (customPos) {\n nodel.style(customPos)\n } else {\n nodel.classed(dir, true).style({\n top: (coords.top + poffset[0]) + scrollTop + 'px',\n left: (coords.left + poffset[1]) + scrollLeft + 'px'\n })\n }\n\n return tip\n }\n\n // Public - hide the tooltip\n //\n // Returns a tip\n tip.hide = function() {\n var nodel = getNodeEl()\n nodel.style({ opacity: 0, 'pointer-events': 'none' })\n return tip\n }\n\n // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.\n //\n // n - name of the attribute\n // v - value of the attribute\n //\n // Returns tip or attribute value\n tip.attr = function(n, v) {\n if (arguments.length < 2 && typeof n === 'string') {\n return getNodeEl().attr(n)\n } else {\n var args = Array.prototype.slice.call(arguments)\n d3.selection.prototype.attr.apply(getNodeEl(), args)\n }\n\n return tip\n }\n\n // Public: Proxy style calls to the d3 tip container. Sets or gets a style value.\n //\n // n - name of the property\n // v - value of the property\n //\n // Returns tip or style property value\n tip.style = function(n, v) {\n if (arguments.length < 2 && typeof n === 'string') {\n return getNodeEl().style(n)\n } else {\n var args = Array.prototype.slice.call(arguments)\n d3.selection.prototype.style.apply(getNodeEl(), args)\n }\n\n return tip\n }\n\n // Public: Set or get the direction of the tooltip\n //\n // v - One of n(north), s(south), e(east), or w(west), nw(northwest),\n // sw(southwest), ne(northeast) or se(southeast)\n //\n // Returns tip or direction\n tip.direction = function(v) {\n if (!arguments.length) return direction\n direction = v == null ? v : d3.functor(v)\n\n return tip\n }\n\n // Public: Sets or gets the offset of the tip\n //\n // v - Array of [x, y] offset\n //\n // Returns offset or\n tip.offset = function(v) {\n if (!arguments.length) return offset\n offset = v == null ? v : d3.functor(v)\n\n return tip\n }\n\n // Public: sets or gets the html value of the tooltip\n //\n // v - String value of the tip\n //\n // Returns html value or tip\n tip.html = function(v) {\n if (!arguments.length) return html\n html = v == null ? v : d3.functor(v)\n\n return tip\n }\n\n tip.customPosition = function(v) {\n if (!arguments.length) return customPosition\n customPosition = v == null ? v : d3.functor(v)\n\n return tip\n }\n\n // Public: destroys the tooltip and removes it from the DOM\n //\n // Returns a tip\n tip.destroy = function() {\n if(node) {\n getNodeEl().remove();\n node = null;\n }\n return tip;\n }\n\n function d3_tip_direction() { return 'n' }\n function d3_tip_offset() { return [0, 0] }\n function d3_tip_html() { return ' ' }\n\n var direction_callbacks = d3.map({\n n: direction_n,\n s: direction_s,\n e: direction_e,\n w: direction_w,\n nw: direction_nw,\n ne: direction_ne,\n sw: direction_sw,\n se: direction_se\n }),\n\n directions = direction_callbacks.keys()\n\n function direction_n() {\n var bbox = getScreenBBox()\n return {\n top: bbox.n.y - node.offsetHeight,\n left: bbox.n.x - node.offsetWidth / 2\n }\n }\n\n function direction_s() {\n var bbox = getScreenBBox()\n return {\n top: bbox.s.y,\n left: bbox.s.x - node.offsetWidth / 2\n }\n }\n\n function direction_e() {\n var bbox = getScreenBBox()\n return {\n top: bbox.e.y - node.offsetHeight / 2,\n left: bbox.e.x\n }\n }\n\n function direction_w() {\n var bbox = getScreenBBox()\n return {\n top: bbox.w.y - node.offsetHeight / 2,\n left: bbox.w.x - node.offsetWidth\n }\n }\n\n function direction_nw() {\n var bbox = getScreenBBox()\n return {\n top: bbox.nw.y - node.offsetHeight,\n left: bbox.nw.x - node.offsetWidth\n }\n }\n\n function direction_ne() {\n var bbox = getScreenBBox()\n return {\n top: bbox.ne.y - node.offsetHeight,\n left: bbox.ne.x\n }\n }\n\n function direction_sw() {\n var bbox = getScreenBBox()\n return {\n top: bbox.sw.y,\n left: bbox.sw.x - node.offsetWidth\n }\n }\n\n function direction_se() {\n var bbox = getScreenBBox()\n return {\n top: bbox.se.y,\n left: bbox.e.x\n }\n }\n\n function initNode() {\n var node = d3.select(document.createElement('div'))\n node.style({\n position: 'absolute',\n top: 0,\n opacity: 0,\n 'pointer-events': 'none',\n 'box-sizing': 'border-box'\n })\n\n return node.node()\n }\n\n function getSVGNode(el) {\n el = el.node()\n if(el.tagName.toLowerCase() === 'svg')\n return el\n\n return el.ownerSVGElement\n }\n\n function getNodeEl() {\n if(node === null) {\n node = initNode();\n // re-add node to DOM\n document.body.appendChild(node);\n };\n return d3.select(node);\n }\n\n // Private - gets the screen coordinates of a shape\n //\n // Given a shape on the screen, will return an SVGPoint for the directions\n // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),\n // sw(southwest).\n //\n // +-+-+\n // | |\n // + +\n // | |\n // +-+-+\n //\n // Returns an Object {n, s, e, w, nw, sw, ne, se}\n function getScreenBBox() {\n var targetel = target || d3.event.target;\n\n while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) {\n targetel = targetel.parentNode;\n }\n\n var bbox = {},\n matrix = targetel.getScreenCTM(),\n tbbox = targetel.getBBox(),\n width = tbbox.width,\n height = tbbox.height,\n x = tbbox.x,\n y = tbbox.y\n\n point.x = x\n point.y = y\n bbox.nw = point.matrixTransform(matrix)\n point.x += width\n bbox.ne = point.matrixTransform(matrix)\n point.y += height\n bbox.se = point.matrixTransform(matrix)\n point.x -= width\n bbox.sw = point.matrixTransform(matrix)\n point.y -= height / 2\n bbox.w = point.matrixTransform(matrix)\n point.x += width\n bbox.e = point.matrixTransform(matrix)\n point.x -= width / 2\n point.y -= height / 2\n bbox.n = point.matrixTransform(matrix)\n point.y += height\n bbox.s = point.matrixTransform(matrix)\n\n return bbox\n }\n\n return tip\n };\n\n}));","var D3 = D3 || {};\n\nD3.Text = function () {\n function calcFontSizeRaw(text, radius, minimumSize, isMultiline) {\n minimumSize = minimumSize || 10;\n\n var textSize = radius / 3;\n if (typeof text === \"string\") {\n var len = text.substring(0, radius / 3).length + 1.5;\n textSize *= 10 / len;\n textSize += 1;\n // experimental alternative method:\n // var textSize = 3.3 * radius / text.length;\n\n // Tweak for Indian scripts and CJK ones\n if (text.match(/[\\u0900-\\u0DFF\\u1100-\\u11FF\\u2E80-\\u2EFF\\u3000-\\u9FFF]/)) {\n textSize *= 0.6;\n }\n\n if (textSize < minimumSize) {\n textSize = minimumSize;\n }\n\n /* Disabled for the time being, better without this\n if (isMultiline) {\n var numWords = text.split(/\\s+/).length;\n if (numWords > 1) {\n if (numWords > 4) {\n numWords = 4;\n }\n textSize += textSize * (4 - numWords) * 0.1;\n }\n }\n */\n\n return Math.round(textSize);\n }\n\n if (textSize < minimumSize) {\n textSize = minimumSize;\n }\n\n return Math.round(textSize);\n }\n\n function calcFontSize(text, radius, minimumSize, isMultiline) {\n return calcFontSizeRaw(text, radius, minimumSize, isMultiline) + 'px';\n }\n\n function getTextWithElipsisIfNeeded(str, threshold) {\n if (typeof str === \"string\") {\n if (str.length > threshold) {\n return str.substring(0, threshold - 3) + \"...\";\n }\n }\n return str;\n }\n\n return {\n calcFontSizeRaw: calcFontSizeRaw,\n calcFontSize: calcFontSize,\n getTextWithElipsisIfNeeded: getTextWithElipsisIfNeeded\n };\n}();\n\nD3.Transition = function () {\n function fadeIn(sel, duration) {\n sel.style(\"opacity\", 0.0)\n .transition()\n .duration(duration)\n .style(\"opacity\", 1.0);\n }\n\n function fadeOut(sel, duration) {\n sel.style(\"opacity\", 1.0)\n .transition()\n .duration(duration)\n .style(\"opacity\", 0.0);\n }\n\n return {\n fadeIn: fadeIn,\n fadeOut: fadeOut\n };\n}();\n\nD3.Click = function () {\n function delayDblClick() {\n var event = d3.dispatch('click', 'dblclick');\n\n function cc(selection) {\n var down,\n tolerance = 5,\n last,\n wait = null;\n\n // euclidean distance\n function dist(a, b) {\n return Math.sqrt(Math.pow(a[0] - b[0], 2), Math.pow(a[1] - b[1], 2));\n }\n\n selection.on('mousedown', function () {\n down = d3.mouse(document.body);\n last = +new Date();\n });\n selection.on('mouseup', function (d) {\n if (dist(down, d3.mouse(document.body)) > tolerance) {\n return;\n } else {\n if (wait) {\n window.clearTimeout(wait);\n wait = null;\n event.dblclick(d);\n } else {\n wait = window.setTimeout((function (e) {\n return function () {\n event.click(d);\n wait = null;\n };\n })(d3.event), 250);\n }\n }\n });\n }\n\n return d3.rebind(cc, event, 'on');\n }\n\n return {\n delayDblClick: delayDblClick\n };\n}();\n\nexport default D3;\n","export const STATIC_RULESETS = [\n {id: 'empty', name: 'No inference'},\n {id: 'rdfs-optimized', name: 'RDFS (Optimized)'},\n {id: 'rdfs', name: 'RDFS'},\n {id: 'rdfsplus-optimized', name: 'RDFS-Plus (Optimized)'},\n {id: 'owl-horst-optimized', name: 'OWL-Horst (Optimized)'},\n {id: 'owl-horst', name: 'OWL-Horst'},\n {id: 'owl2-ql-optimized', name: 'OWL2-QL (Optimized)'},\n {id: 'owl2-ql', name: 'OWL2-QL'},\n {id: 'owl-max-optimized', name: 'OWL-Max (Optimized)'},\n {id: 'owl-max', name: 'OWL-Max'},\n {id: 'owl2-rl-optimized', name: 'OWL2-RL (Optimized)'},\n {id: 'owl2-rl', name: 'OWL2-RL'},\n\n];\n\nexport const REPOSITORY_TYPES = {graphdbRepo: 'graphdb', free: 'free', eeWorker: 'worker', eeMaster: 'master', ontop: 'ontop', se: 'se', fedx: 'fedx'};\nexport const FILENAME_PATTERN = new RegExp('^[a-zA-Z0-9-_]+$');\nexport const NUMBER_PATTERN = new RegExp('^[0-9]+$');\n","import 'angular/core/services';\nimport D3 from 'lib/common/d3-utils.js';\nimport d3tip from 'lib/d3-tip/d3-tip-patch';\nimport 'angular/utils/local-storage-adapter';\nimport {NUMBER_PATTERN} from \"../../repositories/repository.constants\";\n\nconst modules = [\n 'ui.scroll.jqlite',\n 'ui.scroll',\n 'toastr',\n 'ui.bootstrap',\n 'ngTagsInput',\n 'graphdb.framework.utils.localstorageadapter'\n];\n\nangular\n .module('graphdb.framework.graphexplore.controllers.graphviz', modules)\n .controller('GraphsVisualizationsCtrl', GraphsVisualizationsCtrl)\n .controller('SaveGraphModalCtrl', SaveGraphModalCtrl)\n .config(['$tooltipProvider', function ($tooltipProvider) {\n $tooltipProvider.options({appendToBody: true});\n }]);\n\nGraphsVisualizationsCtrl.$inject = [\"$scope\", \"$rootScope\", \"$repositories\", \"$licenseService\", \"toastr\", \"$timeout\", \"$http\", \"ClassInstanceDetailsService\", \"AutocompleteRestService\", \"$q\", \"$location\", \"$jwtAuth\", \"UiScrollService\", \"ModalService\", \"$modal\", \"$window\", \"LocalStorageAdapter\", \"LSKeys\", \"SavedGraphsRestService\", \"GraphConfigRestService\", \"RDF4JRepositoriesRestService\", \"$translate\"];\n\nfunction GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseService, toastr, $timeout, $http, ClassInstanceDetailsService, AutocompleteRestService, $q, $location, $jwtAuth, UiScrollService, ModalService, $modal, $window, LocalStorageAdapter, LSKeys, SavedGraphsRestService, GraphConfigRestService, RDF4JRepositoriesRestService, $translate) {\n\n $scope.languageChanged = false;\n $scope.propertiesObj = {};\n $scope.propertiesQueryObj = {};\n\n $scope.propertiesObj.items = [];\n $scope.propertiesNotFiltered = [];\n $scope.searchVisible = false;\n $scope.nodeSelected = false;\n $scope.queryResultsMode = false;\n $scope.embedded = $location.search().embedded;\n $scope.openedNodeInfoPanel = undefined;\n\n $scope.invalidLimit = false;\n $scope.INVALID_LINKS_MSG = $translate.instant('sidepanel.invalid.limit.links.msg');\n $scope.INVALID_LINKS_TOOLTIP = $translate.instant('sidepanel.invalid.limit.links.tooltip');\n\n $rootScope.$on('$translateChangeSuccess', function () {\n $scope.INVALID_LINKS_MSG = $translate.instant('sidepanel.invalid.limit.links.msg');\n $scope.INVALID_LINKS_TOOLTIP = $translate.instant('sidepanel.invalid.limit.links.tooltip');\n $scope.propertiesSearchPlaceholder = $translate.instant(\"visual.search.instance.placeholder\");\n });\n\n // Handle pageslide directive callbacks which incidentally appeared to be present in the angular's\n // scope, so we need to define our's and pass them to pageslide, otherwise it throws an error.\n $scope.onopen = $scope.onclose = () => angular.noop();\n\n // embedded and other params when the controller is initialized\n if ($scope.embedded && ($location.search().query ||\n $location.search().uri ||\n $location.search().config ||\n $location.search().saved)) {\n\n $scope.noGoHome = true;\n }\n\n // creating datasource for class properties data\n const datasource = {};\n let position = 0;\n let current = 0;\n let type2color = {};\n let colorIndex = 0;\n const nodeLabelMinFontSize = 16; // pixels\n // define zoom and drag behavior; keep this out of draw() to preserve state when nodes are added/removed\n const panAndZoom = d3.behavior.zoom()\n .scaleExtent([0.5, 10]);\n let transformValues;\n // build svg element\n const width = 1000;\n const height = 1000;\n let tipElement;\n let openedLink;\n\n $rootScope.key = \"\";\n\n datasource.get = function (index, count, success) {\n return UiScrollService.initLazyList(index, count, success, position, $scope.propertiesObj.items);\n };\n\n $rootScope.$watch(function () {\n return $rootScope.key;\n }, function () {\n position = 0;\n _.each($scope.propertiesObj.items, function (item) {\n if ($rootScope.key > item) {\n position++;\n }\n });\n current++;\n });\n\n datasource.revision = function () {\n return current;\n };\n\n $scope.datasource = datasource;\n\n // adapter implementation for ui-scroll directive\n $scope.adapterContainer = {adapter: {remain: true}};\n\n $scope.propertiesQueryObj.query = '';\n $scope.propertiesSearchPlaceholder = $translate.instant(\"visual.search.instance.placeholder\");\n $scope.propertiesFilterFunc = propertiesFilterFunc;\n\n $scope.resetState = function () {\n $scope.searchVisible = false;\n $scope.nodeSelected = false;\n $scope.configLoaded = null;\n $scope.queryResultsMode = false;\n $scope.lastSavedGraphName = null;\n $scope.lastSavedGraphId = null;\n $scope.shared = false;\n $scope.numberOfPinnedNodes = 0;\n\n // Reset type colours\n type2color = {};\n colorIndex = 0;\n };\n\n $scope.pushHistory = function (searchParams, state) {\n if ($scope.embedded) {\n searchParams.embedded = true;\n }\n $location.search(searchParams);\n $location.state(state);\n };\n\n $scope.goToHome = function () {\n $scope.resetState();\n $location.url(\"graphs-visualizations\");\n };\n\n $scope.shouldShowSettings = function () {\n return $scope.configLoaded && $scope.configLoaded.id === $scope.defaultGraphConfig.id;\n };\n\n $scope.shouldDisableSameAs = function () {\n const sameAsCheckbox = $('#sameAsCheck');\n if ($scope.settings && !$scope.settings['includeInferred'] && sameAsCheckbox.prop('checked')) {\n sameAsCheckbox.prop(\"checked\", false);\n $scope.settings['sameAsState'] = false;\n }\n\n return $scope.settings && !$scope.settings['includeInferred'];\n };\n\n function propertiesFilterFunc(item) {\n return item.key\n .toLowerCase()\n .indexOf($scope.propertiesQueryObj.query.toLowerCase()) >= 0;\n }\n\n $scope.$watch('propertiesObj.items', function () {\n if (angular.isDefined($scope.propertiesObj.items) && $scope.propertiesObj.items.length > 0) {\n $timeout(function () {\n $scope.adapterContainer.adapter.reload();\n }, 500);\n }\n });\n\n $scope.toggleMoreInfo = function (ev) {\n angular.element(ev.currentTarget).parent().next().toggle(200);\n angular.element(ev.currentTarget).children('span').toggleClass(\"icon-caret-down\").toggleClass(\"icon-caret-up\");\n };\n\n function updatePredicateLabels() {\n if (!$scope.saveSettings['showLinksText']) {\n d3.selectAll(\"svg .link-wrapper text\")\n .style(\"display\", \"none\");\n } else {\n d3.selectAll(\"svg .link-wrapper text\")\n .style(\"display\", \"block\");\n }\n }\n\n function updateNodeLabels(nodeLabels) {\n nodeLabels.each(function (d) {\n d.fontSize = D3.Text.calcFontSizeRaw(d.labels[0].label, d.size, nodeLabelMinFontSize, true);\n // TODO: get language and set it on the label html tag\n })\n .attr(\"height\", function (d) {\n return d.fontSize * 3;\n })\n // if this was kosher we would use xhtml:body here but if we do that angular (or the browser)\n // goes crazy and resizes/messes up other unrelated elements. div seems to work too.\n .append(\"xhtml:div\")\n .attr(\"class\", \"node-label-body\")\n .style(\"font-size\", function (d) {\n return d.fontSize + 'px';\n })\n .append('xhtml:div')\n .text(function (d) {\n return d.labels[0].label;\n });\n\n // Our own implementation of what browsers should really do but they either can't or don't do properly.\n // This code will look at each node's label element and check if the text fits. This is achieved by\n // checking the DOM properties scrollHeight/-Width and clientHeight/-Width. Generally if the scroll ones\n // are bigger than the client ones the content doesn't fit.\n $timeout(function () {\n $('.node-label-body div').each(function (i, e) {\n // Initial text is minus one character as we'll be adding a one-character suffix if we need to truncate\n let text = e.textContent.substring(0, e.textContent.length - 1);\n const suffixToInsert = '…';\n let endlessLoopGuard = 0;\n\n // Loop until the text fits\n while (endlessLoopGuard < 200 && (e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth)) {\n // Take previous text minus one character\n text = text.substring(0, text.length - 1);\n\n // Set the new text + suffix as textContent\n e.textContent = text + suffixToInsert;\n\n endlessLoopGuard++;\n }\n });\n }, 50);\n }\n\n $scope.copyToClipboard = copyToClipboard;\n\n function copyToClipboard(uri) {\n ModalService.openCopyToClipboardModal(uri);\n }\n\n $scope.defaultSettings = {\n linksLimit: 20,\n includeInferred: true,\n sameAsState: true,\n languages: ['en'],\n showLinksText: true,\n preferredTypes: [],\n rejectedTypes: [],\n preferredPredicates: [],\n rejectedPredicates: [\"http://dbpedia.org/property/logo\",\n \"http://dbpedia.org/property/hasPhotoCollection\",\n \"http://dbpedia.org/property/website\",\n \"http://dbpedia.org/property/homepage\",\n \"http://dbpedia.org/ontology/thumbnail\",\n \"http://xmlns.com/foaf/0.1/depiction\",\n \"http://xmlns.com/foaf/0.1/homepage\",\n \"http://xmlns.com/foaf/0.1/mbox\",\n \"http://dbpedia.org/ontology/wikiPage*\",\n \"http://dbpedia.org/property/wikiPage*\",\n \"http://factforge.net/*\"],\n preferredTypesOnly: false,\n preferredPredicatesOnly: false,\n includeSchema: true\n };\n // Static defaults before we do the actual dynamic default settings in initSettings\n $scope.saveSettings = angular.copy($scope.defaultSettings);\n\n function initSettings(principal) {\n const settingsFromPrincipal = principal.appSettings;\n\n // New style settings from principal\n $scope.defaultSettings.includeInferred = settingsFromPrincipal['DEFAULT_INFERENCE'];\n $scope.defaultSettings.sameAsState = settingsFromPrincipal['DEFAULT_INFERENCE'] && settingsFromPrincipal['DEFAULT_SAMEAS'];\n $scope.defaultSettings.includeSchema = settingsFromPrincipal['DEFAULT_VIS_GRAPH_SCHEMA'];\n\n const localStorageSettings = LocalStorageAdapter.get(LSKeys.GRAPHS_VIZ);\n if (localStorageSettings && typeof localStorageSettings === 'object') {\n // Patch existing settings\n try {\n $scope.saveSettings = localStorageSettings;\n if ($scope.saveSettings['includeSchema'] === undefined) {\n // Add the new defaults when migrating from an old GDB\n $scope.saveSettings['includeSchema'] = $scope.defaultSettings['includeSchema'];\n $scope.saveSettings['rejectedPredicates'] = [...$scope.saveSettings['rejectedPredicates'], ...$scope.defaultSettings['rejectedPredicates']].unique();\n }\n } catch (e) {\n $scope.saveSettings = angular.copy($scope.defaultSettings);\n LocalStorageAdapter.set(LSKeys.GRAPHS_VIZ, $scope.saveSettings);\n }\n } else {\n $scope.saveSettings = angular.copy($scope.defaultSettings);\n }\n }\n\n // Using $q.when to proper set values in view\n $q.when($jwtAuth.getPrincipal())\n .then((principal) => initSettings(principal));\n\n function renderSettings() {\n $scope.settings.languagesMap = _.map($scope.settings.languages, function (v) {\n return {'text': v};\n });\n\n $scope.settings.preferredTypesMap = _.map($scope.settings.preferredTypes, function (v) {\n return {'text': v};\n });\n\n $scope.settings.rejectedTypesMap = _.map($scope.settings.rejectedTypes, function (v) {\n return {'text': v};\n });\n\n $scope.settings.preferredPredicatesMap = _.map($scope.settings.preferredPredicates, function (v) {\n return {'text': v};\n });\n\n $scope.settings.rejectedPredicatesMap = _.map($scope.settings.rejectedPredicates, function (v) {\n return {'text': v};\n });\n }\n\n $scope.resetSettings = function () {\n $scope.settings = angular.copy($scope.defaultSettings);\n $scope.validateLinksLimit();\n renderSettings();\n };\n\n $scope.changeLimit = function (delta) {\n let linksLimit = $scope.settings.linksLimit + delta;\n if (linksLimit < 1) {\n linksLimit = 1;\n }\n if (linksLimit > 1000) {\n linksLimit = 1000;\n }\n $scope.settings.linksLimit = linksLimit;\n };\n\n $scope.validateLinksLimit = function () {\n $scope.invalidLimit = !NUMBER_PATTERN.test($scope.settings.linksLimit);\n }\n\n $scope.showSettings = function () {\n $scope.showInfoPanel = true;\n $scope.showFilter = true;\n $scope.showNodeInfo = false;\n $scope.showPredicates = false;\n if (!$scope.saveSettings) {\n $scope.settings = angular.copy($scope.defaultSettings);\n } else {\n $scope.settings = angular.copy($scope.saveSettings);\n }\n renderSettings();\n };\n\n $scope.reExpandNode = function () {\n if ($scope.rootNodeIri) {\n $scope.$broadcast(\"onRootNodeChange\", $scope.rootNodeIri);\n }\n };\n\n const loadGraphForQuery = function (queryString, sameAsParam, inferredParam) {\n const sendSameAs = (sameAsParam === undefined) ? ($scope.saveSettings['sameAsState']) : sameAsParam === true;\n const sendInferred = (inferredParam === undefined) ? ($scope.saveSettings['includeInferred']) : inferredParam === true;\n $scope.loading = true;\n $http({\n url: 'rest/explore-graph/graph',\n method: 'POST',\n headers: {\n 'Content-Type' : 'application/json'\n },\n data: {\n query: queryString,\n linksLimit: $scope.saveSettings['linksLimit'],\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n includeInferred: sendInferred,\n sameAsState: sendSameAs\n }\n }).then(function (response) {\n // Node draw will turn off loader\n initGraphFromResponse(response);\n }, function (response) {\n $scope.loading = false;\n toastr.error(getError(response.data), $translate.instant('graphexplore.error.cannot.load.graph'));\n });\n };\n\n $scope.updateSettings = function () {\n if ($scope.invalidLimit) {\n toastr.error($scope.INVALID_LINKS_TOOLTIP, $scope.INVALID_LINKS_MSG);\n return;\n }\n $scope.saveSettings = $scope.settings;\n $scope.saveSettings.languages = _.map($scope.saveSettings['languagesMap'], function (s) {\n return s['text'];\n });\n\n $scope.saveSettings.preferredTypes = _.map($scope.saveSettings['preferredTypesMap'], function (t) {\n return t['text'];\n });\n $scope.saveSettings.rejectedTypes = _.map($scope.saveSettings['rejectedTypesMap'], function (t) {\n return t['text'];\n });\n\n $scope.saveSettings.preferredPredicates = _.map($scope.saveSettings['preferredPredicatesMap'], function (t) {\n return t['text'];\n });\n $scope.saveSettings.rejectedPredicates = _.map($scope.saveSettings['rejectedPredicatesMap'], function (t) {\n return t['text'];\n });\n\n // TODO\n // reexpand root node\n if ($scope.rootNodeIri) {\n $scope.reExpandNode($scope.rootNodeIri);\n } else if ($scope.queryResultsMode && $location.search().query) {\n loadGraphForQuery($location.search().query,\n $location.search().sameAs,\n $location.search().inference);\n } else if ($scope.configLoaded.startMode === 'query') {\n $scope.loadGraphConfig($scope.configLoaded);\n }\n\n updatePredicateLabels();\n\n $scope.showInfoPanel = false;\n $scope.showFilter = false;\n\n LocalStorageAdapter.set(LSKeys.GRAPHS_VIZ, $scope.saveSettings);\n };\n\n $scope.showInfoPanel = false;\n\n /**\n * Removes brackets and serial commas from IRIs\n * when used to create ids for links and markers,\n * because elements with ids that contain such\n * are not valid XHTML and cause a host problems\n * when trying to style individual elements\n * @param string\n * @returns {*}\n */\n function removeSpecialChars(string) {\n return string.replace(/[()']/g, \"\");\n }\n\n /**\n * Converts triple to link id or generates unique id (needed for arrows)\n * @param triple\n * @param tripleLike\n * @returns {string}\n */\n function convertTripleToLinkId(triple, tripleLike) {\n let tripleParts = triple.split(' ');\n if (tripleLike) {\n return [tripleParts[0], tripleParts[1], tripleParts[2]].join('>');\n }\n return [tripleParts[0], tripleParts[2]].join('>');\n }\n\n function convertLinkDataToLinkId(link) {\n return [link.source.iri, link.target.iri].join('>');\n }\n\n /**\n * If source or target of a link is a triple returns a x\n * for the link, otherwise returns this of the node.\n * Because tick is called before links are created we return node's x,\n * which afterwards will be overridden\n * @param node\n * @returns {number|number|*}\n */\n function getNodeX(node) {\n if (node.isTriple) {\n let el = document.getElementById(removeSpecialChars(convertTripleToLinkId(node.iri)));\n if (el && typeof el.__data__.x !== \"undefined\") {\n return el.__data__.x;\n }\n }\n return node.x;\n }\n\n /**\n * If source or target of a link is a triple returns a y\n * for the link, otherwise returns this of the node.\n * Because tick is called before links are created we return node's y,\n * which afterwards will be overridden\n * @param node\n * @returns {number|number|*}\n */\n function getNodeY(node) {\n if (node.isTriple) {\n let el = document.getElementById(removeSpecialChars(convertTripleToLinkId(node.iri)));\n if (el && typeof el.__data__.y !== \"undefined\") {\n return el.__data__.y;\n }\n }\n return node.y;\n }\n\n function createTriple(value) {\n let tripleParts = value.trim().split(' ');\n return `<<<${tripleParts[0]}> <${tripleParts[1]}> <${tripleParts[2]}>>>`;\n }\n\n /**\n * Creates unique arrow-marker id will allow change color and refX for particular one\n * @param d\n * @returns {string}\n */\n function createArrowMarkerUniqueID(d) {\n let source = d.source.isTriple ? convertTripleToLinkId(d.source.iri, true) : d.source.iri;\n let target = d.target.isTriple ? convertTripleToLinkId(d.target.iri, true) : d.target.iri;\n return removeSpecialChars(`${source}>${target}>marker`);\n }\n\n /**\n * Filters nodes array on a given field\n * @param iri\n * @param array\n * @returns {*}\n */\n function distinctBy(iri, array) {\n let keys = array.map(function (value) { return value[iri]; });\n return array.filter(function (value, index) { return keys.indexOf(value[iri]) === index; });\n }\n\n function Graph() {\n this.nodes = [];\n this.links = [];\n this.tripleNodes = new Map();\n this.tripleLinksCopy = new Map();\n\n this.addNode = function (node, x, y) {\n node.x = x;\n node.y = y;\n this.nodes.push(node);\n return node;\n };\n\n // computes a \"connectedness\" metric on each link, which is then used to hint for longer links.\n // this results in improved clustering and appearance.\n this.computeConnectedness = function () {\n // count the the number of times a given node is connected to other nodes\n // (only for nodes connected to more than one node)\n const counts = {};\n const seenLinks = {};\n _.each(this.links, function (link) {\n const i1 = link.source.iri;\n const i2 = link.target.iri;\n const seenKey = _.min([i1, i2]) + \"|\" + _.max([i1, i2]);\n if (!seenLinks[seenKey]) {\n seenLinks[seenKey] = 1;\n counts[i1] = (counts[i1] || 0) + 1;\n counts[i2] = (counts[i2] || 0) + 1;\n }\n });\n\n // computes the connectedness of each link based on the number of times its nodes were connected\n // (only for links to/from nodes connected to more than one node)\n _.each(this.links, function (link) {\n if (counts[link.source.iri] > 1 && counts[link.target.iri] > 1) {\n link.connectedness = Math.min(5, Math.max(counts[link.source.iri], counts[link.target.iri]) - 1);\n } else {\n link.connectedness = 0;\n }\n });\n };\n\n this.addAndMatchLinks = function (newLinks) {\n const nodes = this.nodes;\n Array.prototype.push.apply(this.links, matchLinksToNodes(newLinks, nodes));\n for (let key of graph.tripleLinksCopy.keys()) {\n if (graph.tripleLinksCopy.get(key).length === 1) {\n graph.tripleLinksCopy.delete(key);\n }\n }\n this.links = this.links.filter(link => link !== null);\n this.computeConnectedness();\n };\n\n const countLinks = function (d, links) {\n return findLinksForNode(d, links).length;\n };\n\n this.countLinks = countLinks;\n\n function findLinksForNode(d, links) {\n return _.filter(links, function (l) {\n return l.source.iri === d.iri || l.target.iri === d.iri;\n });\n }\n\n function linksTypes(d, links) {\n const linksForNode = findLinksForNode(d, links);\n const types = _.map(linksForNode, function (l) {\n return (l.source.iri === d.iri ) ? l.target.types : l.source.types;\n });\n return _.uniq(_.flatten(types));\n }\n\n function linksPredicates(d, links) {\n const linksForNode = findLinksForNode(d, links);\n const predicates = _.map(linksForNode, function (l) {\n return l.predicates;\n });\n return _.uniq(_.flatten(predicates));\n }\n\n this.linksTypes = linksTypes;\n\n this.linksPredicates = linksPredicates;\n\n /**\n * Removes generated triple links and related nodes\n * @param triplesToRemove\n */\n this.removeTriples = function (triplesToRemove) {\n let targetTriples = [];\n if (this.tripleNodes.size > 0) {\n triplesToRemove.forEach((source) => {\n if (this.tripleNodes.has(source)) {\n this.tripleNodes.delete(source);\n this.links = _.reject(this.links, function (l) {\n let sourceSplit = source.split('>');\n let lSource = convertTripleToLinkId(l.source.iri);\n let lTarget = convertTripleToLinkId(l.target.iri);\n // Handle triple targets\n if (lSource === source && graph.tripleNodes.delete(lTarget)) {\n let targetSplit = lTarget.split('>');\n targetTriples.push({\n source: targetSplit[0],\n target: targetSplit[1]\n });\n }\n let isRejected = lSource === source || lTarget === source || (l.source.iri === sourceSplit[0] && l.target.iri === sourceSplit[1]);\n if (isRejected) {\n graph.tripleLinksCopy.delete(`${lSource}>${lTarget}`);\n graph.tripleLinksCopy.delete(`${lTarget}>${lSource}`);\n }\n return isRejected;\n });\n }\n });\n }\n\n // This step is needed for removing artificially created links representing triples\n targetTriples.forEach((target) => {\n this.links = _.reject(this.links, function (l) {\n return l.source.iri === target.source && l.target.iri === target.target;\n });\n });\n }\n\n this.removeNode = function (d) {\n let triplesToRemove = [];\n this.links = _.reject(this.links, function (l) {\n let isRejected = l.source.iri === d.iri || l.target.iri === d.iri;\n if (isRejected) {\n if (l.target.isTriple) {\n triplesToRemove.push(convertTripleToLinkId(l.target.iri));\n }\n if (!l.source.isTriple && !l.target.isTriple) {\n triplesToRemove.push([l.source.iri, l.target.iri].join('>'))\n }\n }\n return isRejected;\n });\n\n this.removeTriples(triplesToRemove);\n\n const links = this.links;\n this.nodes = _.reject(this.nodes, function (n) {\n return countLinks(n, links) === 0;\n });\n if (this.nodes.length === 0) {\n $scope.nodeSelected = false;\n }\n\n this.computeConnectedness();\n };\n\n this.removeNodeLeafLinks = function (d) {\n let triplesToRemove = [];\n let links = this.links;\n this.links = _.reject(this.links, function (l) {\n let isRejected = (l.source.iri === d.iri && countLinks(l.target, links) === 1 && !l.target.isTriple) ||\n (l.target.iri === d.iri && countLinks(l.source, links) === 1 && !l.source.isTriple);\n if (!isRejected) {\n let targetLinks;\n if (l.source.iri === d.iri && countLinks(l.target, links) === 2 && !l.target.isTriple) {\n targetLinks = findLinksForNode(l.target, links);\n } else if (l.target.iri === d.iri && countLinks(l.source, links) === 2 && !l.source.isTriple) {\n targetLinks = findLinksForNode(l.source, links);\n }\n if (!targetLinks) {\n return false;\n }\n // the node to which (or from which) d has link to has only two links, check if the second one is to d also\n isRejected = (targetLinks[0].source.iri === d.iri || targetLinks[0].target.iri) &&\n (targetLinks[1].source.iri === d.iri || targetLinks[1].target.iri);\n }\n if (isRejected) {\n if (l.target.isTriple) {\n triplesToRemove.push(convertTripleToLinkId(l.target.iri));\n }\n if (!l.source.isTriple && !l.target.isTriple) {\n triplesToRemove.push([l.source.iri, l.target.iri].join('>'))\n }\n }\n return isRejected;\n });\n\n this.removeTriples(triplesToRemove);\n\n links = this.links;\n this.nodes = _.reject(this.nodes, function (n) {\n return countLinks(n, links) === 0 && n.iri !== d.iri;\n });\n\n this.computeConnectedness();\n };\n\n this.addTriple = function (triple, x, y) {\n triple.x = x;\n triple.y = y;\n triple.weight = 0;\n let key = convertTripleToLinkId(triple.iri);\n if (!this.tripleNodes.has(key)) {\n triple.weight = 10;\n this.tripleNodes.set(key, [triple]);\n } else {\n let value = this.tripleNodes.get(key);\n value.push(triple);\n this.tripleNodes.set(key, value);\n }\n }\n\n function matchLinksToNodes(newLinks, nodes) {\n return _.map(newLinks, function (link) {\n let source;\n let target;\n if (link.isTripleSource) {\n source = getTripleNode(link.source);\n } else {\n source = _.find(nodes, function (o) {\n return o.iri === link.source;\n })\n }\n if (link.isTripleTarget) {\n target = getTripleNode(link.target);\n } else {\n target = _.find(nodes, function (o) {\n return o.iri === link.target;\n })\n }\n let matchedLink = {\n \"source\": source,\n \"target\": target,\n \"predicates\": link.predicates\n };\n // make copy of links with triples in them\n if (link.isTripleSource || link.isTripleTarget) {\n let sourceId = matchedLink.source.isTriple ? convertTripleToLinkId(matchedLink.source.iri) : matchedLink.source.iri;\n let targetId = matchedLink.target.isTriple ? convertTripleToLinkId(matchedLink.target.iri) : matchedLink.target.iri;\n let linkId = `${sourceId}>${targetId}`;\n if (graph.tripleLinksCopy.has(linkId)) {\n let value = graph.tripleLinksCopy.get(linkId);\n value[0].predicates.push(...matchedLink.predicates);\n value.push(matchedLink);\n graph.tripleLinksCopy.set(linkId, value);\n return null;\n } else {\n graph.tripleLinksCopy.set(linkId, [matchedLink]);\n }\n }\n return matchedLink;\n });\n }\n\n this.copyState = function () {\n const nodesCopy = _.map(this.nodes, function (node) {\n return {\n iri: node.iri,\n isTriple: node.isTriple,\n size: node.size,\n labels: angular.copy(node.labels),\n types: angular.copy(node.types),\n rdfRank: node.rdfRank,\n x: node.x,\n y: node.y,\n fixed: node.fixed\n };\n });\n\n const triplesCopy = JSON.stringify(Array.from(this.tripleNodes.entries()));\n const tripleLinksCopy = JSON.stringify(Array.from(this.tripleLinksCopy.entries()));\n\n const linksCopy = _.map(this.links, function (link) {\n return {\n source: link.source.iri,\n isTripleSource: link.source.isTriple,\n target: link.target.iri,\n isTripleTarget: link.target.isTriple,\n predicates: link.predicates\n };\n });\n\n return {\n nodes: nodesCopy,\n links: linksCopy,\n tripleNodes: triplesCopy,\n tripleLinksCopy: tripleLinksCopy,\n colorIndex: colorIndex,\n type2color: type2color,\n scale: panAndZoom.scale(),\n translate: panAndZoom.translate()\n };\n };\n\n this.restoreState = function (state) {\n $scope.nodeSelected = true;\n $scope.searchVisible = false;\n\n this.nodes = angular.copy(state.nodes);\n // check if triples exists is needed for old configs\n this.tripleNodes = state.tripleNodes ? new Map(JSON.parse(state.tripleNodes)) : new Map();\n this.links = [];\n this.addAndMatchLinks(state.links);\n this.tripleLinksCopy = state.tripleLinksCopy ? new Map(JSON.parse(state.tripleLinksCopy)) : new Map();\n\n _.each(this.nodes, function (d) {\n if (d.fixed) {\n $scope.numberOfPinnedNodes++;\n }\n });\n\n if (angular.isDefined(state.colorIndex) && angular.isDefined(state.type2color)) {\n colorIndex = state.colorIndex;\n type2color = angular.copy(state.type2color);\n }\n\n if (angular.isDefined(state.translate) && angular.isDefined(state.scale)) {\n transformValues = \"translate(\" + state.translate[0] + \", \" + state.translate[1] + \") scale(\" + state.scale + \")\";\n panAndZoom.translate(state.translate);\n panAndZoom.scale(state.scale);\n }\n\n draw();\n };\n }\n\n let graph = new Graph();\n\n $scope.defaultGraphConfig = {\n id: 'default',\n name: 'Easy graph',\n startMode: 'search'\n };\n\n // Graph Config\n $scope.getGraphConfigs = function (graphCallback) {\n GraphConfigRestService.getGraphConfigs()\n .success(function (data) {\n $scope.graphConfigs = data;\n if (graphCallback) {\n graphCallback();\n }\n }).error(function (data) {\n toastr.error(getError(data), $translate.instant('graphexplore.error.graph.configs.short.msg'));\n });\n };\n\n $scope.loadConfigForId = function (configId, successCallback) {\n if (configId === $scope.defaultGraphConfig.id) {\n $scope.loadGraphConfig($scope.defaultGraphConfig);\n } else {\n GraphConfigRestService.getConfig(configId)\n .success(function (data) {\n $scope.loadGraphConfig(data);\n successCallback();\n })\n .error(function (data) {\n toastr.error(getError(data), $translate.instant('graphexplore.error.could.not.load.config', {configId: configId}));\n });\n }\n };\n\n $scope.findConfigById = function (configId) {\n if (configId === $scope.defaultGraphConfig.id) {\n return $scope.defaultGraphConfig;\n }\n return $.grep($scope.graphConfigs, function (e) {\n return e.id === configId;\n })[0];\n };\n\n $scope.easyGraphSearch = function (iri) {\n $scope.configLoaded = $scope.defaultGraphConfig;\n $scope.openUri(iri);\n };\n\n $scope.loadGraphConfig = function (config) {\n $scope.configLoaded = config;\n if (config.startMode === 'search') {\n $scope.searchVisible = true;\n } else if (config.startMode === 'node' && config.startIRI) {\n $timeout(function () {\n $scope.openUri(config.startIRI, true);\n }, 0);\n } else if (config.startMode === 'query' && config.startGraphQuery) {\n $scope.loading = true;\n GraphConfigRestService.loadGraphForConfig(config, config.startQueryIncludeInferred, $scope.saveSettings['linksLimit'], config.startQuerySameAs)\n .then(function (response) {\n // Node drawing will turn off loader\n initGraphFromResponse(response);\n }, function (data) {\n $scope.loading = false;\n toastr.error(getError(data), $translate.instant('graphexplore.error.graph.load'));\n });\n }\n };\n\n $scope.deleteConfig = function (config) {\n ModalService.openSimpleModal({\n title: $translate.instant('common.confirm'),\n message: $translate.instant('graphexplore.delete.graph', {configName: config.name}),\n warning: true\n }).result\n .then(function () {\n GraphConfigRestService.deleteGraphConfig(config)\n .success(function () {\n $scope.getGraphConfigs();\n $scope.refreshSavedGraphs();\n }).error(function (data) {\n toastr.error(getError(data), $translate.instant('graphexplore.error.cannot.delete.config'));\n });\n });\n };\n\n $scope.goToGraphConfig = function (config) {\n $scope.pushHistory({config: config.id}, {config: config});\n $scope.resetState();\n $scope.loadGraphConfig(config);\n };\n\n $window.onpopstate = function (event) {\n $scope.resetState();\n\n if (event.state) {\n if (event.state.config) {\n $scope.loadGraphConfig(event.state.config);\n if (event.state.uri) {\n $scope.openUri(event.state.uri, true);\n }\n } else if (event.state.savedGraph) {\n $scope.loadSavedGraph(event.state.savedGraph, true);\n }\n }\n };\n\n const initGraphFromQueryParam = function () {\n // view sparql\n if ($location.search().query) {\n $scope.searchVisible = false;\n $scope.queryResultsMode = true;\n loadGraphForQuery($location.search().query,\n $location.search().sameAs,\n $location.search().inference);\n } else {\n // broadcasted event from view resource directive to take input value\n $scope.$on('onRootNodeChange', function (e, inputValue) {\n $scope.loading = true;\n if (angular.isDefined(inputValue)) {\n $scope.rootNodeIri = inputValue;\n $http({\n url: 'rest/explore-graph/node',\n method: 'GET',\n params: {\n iri: inputValue,\n config: $scope.configLoaded ? $scope.configLoaded.id : $scope.defaultGraphConfig.id,\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n includeInferred: $scope.saveSettings['includeInferred'],\n sameAsState: $scope.saveSettings['sameAsState']\n }\n }).then(function (response) {\n $scope.nodeSelected = true;\n $scope.searchVisible = false;\n if (response.data.types === null) {\n response.data.types = \"greyColor\";\n }\n graph = new Graph();\n const rootNode = graph.addNode(response.data, width / 2, height / 2);\n\n transformValues = \"translate(0, -70) scale(1)\";\n panAndZoom.translate([0, -70]);\n panAndZoom.scale(1);\n\n expandNode(rootNode, true);\n }).catch(function (err) {\n $scope.loading = false;\n toastr.error(getError(err), $translate.instant('graphexplore.error.could.not.load.graph'));\n });\n }\n });\n }\n\n if ($location.search().uri) {\n $scope.openUri($location.search().uri);\n }\n\n if ($location.search().saved) {\n SavedGraphsRestService.getSavedGraph($location.search().saved)\n .success(function (data) {\n $scope.loadSavedGraph(data);\n })\n .error(function (data) {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.could.not.open'));\n });\n }\n };\n\n const loadGraphFromQueryParam = function () {\n // view graph config\n if ($location.search().config) {\n $scope.loadConfigForId($location.search().config, initGraphFromQueryParam);\n } else if ($location.search().query || $location.search().uri) {\n $scope.loadGraphConfig($scope.defaultGraphConfig);\n initGraphFromQueryParam();\n } else {\n initGraphFromQueryParam();\n }\n };\n\n $scope.replaceIRIWithPrefix = function (iri) {\n const namespaces = $scope.namespaces;\n const namespacePrefix = _.findLast(namespaces, function (o) {\n return iri.indexOf(o.uri) === 0;\n });\n return namespacePrefix ? (namespacePrefix.prefix + \":\" + iri.substring(namespacePrefix.uri.length)) : iri;\n };\n\n function expandPrefix(str, namespaces) {\n const ABS_URI_REGEX = /^<?(http|urn).*>?/;\n if (!ABS_URI_REGEX.test(str)) {\n const uriParts = str.split(':');\n const uriPart = uriParts[0];\n const localName = uriParts[1];\n if (!angular.isUndefined(localName)) {\n const expandedUri = ClassInstanceDetailsService.getNamespaceUriForPrefix(namespaces, uriPart);\n if (expandedUri) {\n return expandedUri + localName;\n }\n }\n }\n return str;\n }\n\n $scope.addedTag = function (tag) {\n if (tag.text.indexOf(':') < 0) {\n toastr.warning($translate.instant('graphexplore.absolute.prefixed.iri'));\n return null;\n }\n tag.text = expandPrefix(tag.text, $scope.namespaces);\n $scope.pageslideExpanded = true;\n return tag;\n };\n\n $scope.validateTag = function (tag, category, wildcardOK) {\n if (tag.text.indexOf(':') < 0) {\n if (wildcardOK) {\n toastr.warning($translate.instant('graphexplore.absolute.prefixed.iri.option'), category);\n } else {\n toastr.warning($translate.instant('graphexplore.absolute.prefixed.iri'), category);\n }\n return false;\n }\n const wildcardPos = tag.text.indexOf('*');\n if (wildcardPos >= 0) {\n if (!wildcardOK) {\n toastr.warning($translate.instant('graphexplore.wildcards.not.allowed'), category);\n return false;\n } else if (wildcardPos < tag.text.length - 1) {\n toastr.warning($translate.instant('graphexplore.wildcards.last.char'), category);\n return false;\n }\n }\n return true;\n };\n\n $scope.getTagClass = function (tagText) {\n if (tagText.endsWith('*')) {\n return 'tag-item-wildcard';\n }\n return null;\n };\n\n $scope.getActiveRepository = function () {\n return $repositories.getActiveRepository();\n };\n\n $scope.isLicenseValid = function() {\n return $licenseService.isLicenseValid();\n }\n\n // Flag to avoid calling repo init logic twice\n $scope.hasInitedRepository = false;\n\n // This method may be called twice - once by us explicitly and once by the repositoryInit event.\n // In some race conditions getActiveRepository() will be already set when we enter it the first\n // time but then we'll be called again by the event, so we need the above flag to avoid double\n // initialization and weirdness.\n function initForRepository(newRepo) {\n if (!$repositories.getActiveRepository() || $scope.hasInitedRepository && !newRepo) {\n return;\n }\n\n $scope.hasInitedRepository = true;\n\n if (!newRepo) {\n // Process params only if this isn't a repo that was just selected from the dropdown menu\n $scope.getGraphConfigs(loadGraphFromQueryParam);\n }\n\n // Inits namespaces for repo\n $scope.getNamespacesPromise = RDF4JRepositoriesRestService.getNamespaces($scope.getActiveRepository())\n .success(function (data) {\n const nss = _.map(data.results.bindings, function (o) {\n return {\"uri\": o.namespace.value, \"prefix\": o.prefix.value};\n });\n $scope.namespaces = _.sortBy(nss, function (n) {\n return n.uri.length;\n });\n\n checkAutocompleteStatus();\n }).error(function (data) {\n toastr.error(getError(data), $translate.instant('graphexplore.error.view.will.not.work'));\n });\n }\n\n function checkAutocompleteStatus() {\n if ($licenseService.isLicenseValid()) {\n $scope.getAutocompletePromise = AutocompleteRestService.checkAutocompleteStatus();\n }\n }\n\n $scope.$on('autocompleteStatus', function() {\n checkAutocompleteStatus();\n });\n\n $scope.$on('repositoryIsSet', function (event, args) {\n // New repo set from dropdown, clear init state\n if (args.newRepo) {\n $scope.hasInitedRepository = false;\n }\n\n initForRepository(args.newRepo);\n\n // New repo set from dropdown, clear state and go to home page\n if (args.newRepo) {\n $scope.resetState();\n // Quick-n-dirty way to get rid of the existing vis\n $('.graph-visualization svg').empty();\n\n // When we come from the sparql view and then change the repo though the dropdown,\n // should goToHome and reinit the view, for the search to view on the home page\n if ($location.search().query) {\n $scope.goToHome();\n initGraphFromQueryParam();\n }\n\n }\n });\n\n initForRepository();\n\n const multiClickDelay = 500; // max delay between clicks for multiple click events\n\n const nodeLabelRectScaleX = 1.75;\n\n const color1 = d3.scale.linear()\n .domain([0, 9])\n .range([\"hsl(0, 100%, 75%)\", \"hsl(360, 90%, 82%)\"])\n .interpolate(d3.interpolateHslLong);\n\n const color2 = d3.scale.linear()\n .domain([0, 9])\n .range([\"hsl(180, 50%, 75%)\", \"hsl(540, 40%, 82%)\"])\n .interpolate(d3.interpolateHslLong);\n\n $scope.getColor = function (type) {\n if (angular.isUndefined(type2color[type])) {\n type2color[type] = colorIndex;\n colorIndex++;\n }\n\n const index = type2color[type];\n if (index > 39) {\n return \"#c2c2c2\";\n } else if (index % 2 === 0) {\n return color1(index / 2);\n } else {\n return color2(index / 2);\n }\n };\n\n const force = d3.layout.force()\n .gravity(0.07)\n .size([width, height]);\n\n const svg = d3.select(\".main-container .graph-visualization\").append(\"svg\")\n .attr(\"viewBox\", \"0 0 \" + width + \" \" + height)\n .attr(\"preserveAspectRatio\", \"xMidYMid meet\");\n\n let showNodeTipAndIconsTimer = 0;\n let removeIconsTimer = 0;\n\n const loader = new Loader();\n\n function draw(resetRootNode) {\n // remove all group elements and rec to rebuild the graph when the user clicks on it\n d3.selectAll(\"svg g\").remove();\n d3.selectAll(\"svg rect\").remove();\n d3.selectAll('.d3-tip').remove();\n d3.selectAll('.menu-events').remove();\n\n // zoom and drag event\n panAndZoom.on(\"zoom\", panAndZoomed);\n\n // building rectangular so we can bind zoom and drag effects\n svg.append(\"rect\")\n .attr(\"width\", width * 10)\n .attr(\"height\", height * 10)\n .attr(\"x\", -(width * 10 - width) / 2)\n .attr(\"y\", -(height * 10 - height) / 2)\n .style(\"fill\", \"none\")\n .style(\"pointer-events\", \"all\")\n .call(panAndZoom)\n .on(\"click\", function () {\n d3.event.stopPropagation();\n removeMenuIfVisible();\n // Clicking outside the graph stops the layout\n force.stop();\n });\n\n\n const container = svg.append(\"g\").attr(\"class\", \"nodes-container\")\n .attr(\"transform\", function () {\n if (angular.isDefined(transformValues) && !resetRootNode) {\n return transformValues;\n }\n return '';\n });\n\n const tip = d3tip()\n .attr('class', 'd3-tip')\n .customPosition(function () {\n const bbox = tipElement.getBoundingClientRect();\n return {\n top: (bbox.bottom + 10) + 'px',\n left: (bbox.left - 30) + 'px'\n };\n })\n .html(function (d) {\n let html = '';\n\n if (d.fixed) {\n // add pin icon if pinned down\n html += '<i class=\"icon-pin\"></i> ';\n }\n\n if (d.types.length > 0) {\n // mid-dot delimited types\n html += _.join(_.map(d.types, function (t) {\n return $scope.replaceIRIWithPrefix(t);\n }), ' \\u00B7 ');\n } else {\n html += '<i>No types</i>';\n }\n\n return html;\n });\n\n const numberOfPredLeft = function (d) {\n return d.predicates.length - 10;\n };\n\n // This will create text that will appear in d3tip\n const createTipText = function (d) {\n let html = '';\n html += _.join(_.map(d.predicates, function (p, index) {\n if (index === 0) {\n return getShortPredicate(p);\n // If we have less than or ten predicates should show them with middle dot separated\n } else if (index < 10) {\n return ' \\u00B7 ' + getShortPredicate(p);\n // On eleventh predicate just append how many more predicates left to show to the user\n } else if (index === 10) {\n const numOfPredLeft = numberOfPredLeft(d);\n // Show how many predicates left\n const textToShow = numOfPredLeft > 1 ? numOfPredLeft + ' predicates'\n : numOfPredLeft + ' predicate';\n return ' \\u00B7 ' + $translate.instant('graphexplore.tip.text', {textToShow: textToShow});\n }\n }), '');\n\n return html;\n };\n\n const calculateWidth = function (d) {\n const text = createTipText(d);\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext(\"2d\");\n ctx.font = \"13px Arial\";\n\n if (d.predicates.length < 10) {\n return ctx.measureText(text).width;\n } else {\n return ctx.measureText(text).width / 2;\n }\n };\n\n let tipPredicateElement;\n let tipPredicateTimer;\n\n const tipPredicates = d3tip()\n .attr('class', 'd3-tip')\n .customPosition(function (d) {\n const bbox = tipPredicateElement.getBoundingClientRect();\n const textWidth = calculateWidth(d);\n return {\n top: (bbox.top - 30) + 'px',\n left: (bbox.left - 30) + 'px',\n width: textWidth + 'px'\n };\n })\n .html(function (d) {\n return createTipText(d);\n });\n\n let tipTimer;\n // Shows the tooltip for a node but with a slight delay\n const showTipForNode = function (d, event) {\n $timeout.cancel(tipTimer);\n const thisTipElement = tipElement = event.target;\n $timeout(function () {\n if (tipElement === thisTipElement) {\n tip.show(d, tipElement);\n }\n }, 300);\n };\n\n // Hides the tooltip for the node and resets some variables\n const hideTipForNode = function () {\n $timeout.cancel(tipTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n tipElement = null;\n tip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n };\n\n // Updates the text in the tooltip if already visible\n const updateTipForNode = function (d) {\n if (tipElement) {\n tip.show(d, tipElement);\n }\n };\n\n svg.call(tip);\n\n // Shows like tooltip list of predicates but with a slight delay\n const showPredicateToolTip = function (d) {\n $timeout.cancel(tipPredicateTimer);\n const thisPredicateTipElement = tipPredicateElement = d3.event.target;\n $timeout(function () {\n if (tipPredicateElement === thisPredicateTipElement && d.predicates.length > 1) {\n tipPredicates.show(d, tipPredicateElement);\n }\n }, 300);\n };\n\n // Hides the tooltip with predicates and resets some variables\n const hidePredicateToolTip = function () {\n $timeout.cancel(tipPredicateTimer);\n tipPredicateElement = null;\n tipPredicates.hide();\n };\n\n svg.call(tipPredicates);\n\n let link = svg.selectAll(\".link\");\n let node = svg.selectAll(\".node\");\n\n force.nodes(graph.nodes).charge(-3000);\n\n force.links(graph.links).linkDistance(function (l) {\n if (l.source.isTriple || l.target.isTriple) {\n return 0;\n }\n // link distance depends on length of text with an added bonus for strongly connected nodes,\n // i.e. they will be pushed further from each other so that their common nodes can cluster up\n return getPredicateTextLength(l) + 30 * l.connectedness;\n });\n\n // arrow markers\n container.append(\"defs\").selectAll(\"marker\")\n .data(force.links())\n .enter().append(\"marker\")\n .attr(\"class\", \"arrow-marker\")\n .attr(\"id\", function (d) {\n return createArrowMarkerUniqueID(d);\n })\n .attr(\"viewBox\", \"0 -5 10 10\")\n .attr(\"refX\", function (d) {\n // The positioning of the arrow for triple target nodes differ from normal ones\n return d.target.isTriple ? 11 : d.target.size + 11;\n })\n .attr(\"refY\", 0)\n .attr(\"markerWidth\", 10)\n .attr(\"markerHeight\", 10)\n .attr(\"orient\", \"auto\")\n .append(\"path\")\n .attr(\"d\", \"M0,-5L10,0L0,5 L10,0 L0, -5\");\n\n // add the links, nodes, predicates and node labels\n link = container.selectAll(\".link\")\n .data(graph.links)\n .enter().append(\"g\")\n .attr(\"class\", \"link-wrapper\")\n .attr(\"id\", function (d) {\n return removeSpecialChars(convertLinkDataToLinkId(d));\n })\n .append(\"line\")\n .attr(\"class\", \"link\")\n .style(\"stroke-width\", 1)\n .style(\"fill\", \"transparent\")\n .style(\"marker-end\", function (d) {\n let targetArrowId = createArrowMarkerUniqueID(d);\n return `url(#${targetArrowId})`;\n });\n\n const predicate = container.selectAll(\".link-wrapper\")\n .append(\"text\")\n .text(function (d) {\n return getPredicate(d);\n })\n .attr(\"class\", function (d) {\n if (d.predicates.length > 1 || graph.tripleNodes.has(convertLinkDataToLinkId(d))) {\n return \"predicates\";\n }\n return \"predicate\";\n })\n .attr(\"dy\", \"-0.5em\")\n .style(\"text-anchor\", \"middle\")\n .style(\"display\", $scope.saveSettings.showLinksText ? \"\" : \"none\")\n .on(\"mouseover\", function (d) {\n d3.event.stopPropagation();\n showPredicateToolTip(d);\n })\n .on('mouseout', hidePredicateToolTip)\n .on(\"click\", function (d) {\n d3.event.stopPropagation();\n linkActions(d);\n });\n\n // node events and variables\n let mouseEventTimer;\n let upEventLast = 0;\n let virtualClickEventTimer = 0;\n let moveEventCount = 0;\n\n // tracks mousedown and touchstart events in order to count single or double click\n // (checked in upEventHandler)\n const downEventHandler = function () {\n if (d3.event.button && d3.event.button !== 0) {\n return;\n }\n\n hideTipForNode();\n $timeout.cancel(mouseEventTimer);\n $scope.showPredicates = false;\n if (d3.event.timeStamp - upEventLast < multiClickDelay) {\n virtualClickEventTimer++;\n } else {\n virtualClickEventTimer = 1;\n }\n\n upEventLast = d3.event.timeStamp;\n\n d3.event.preventDefault();\n };\n\n // builds upon downEventHandler and adds additional functionality for touch devices\n const touchStartEventHandler = function (d) {\n downEventHandler();\n\n // for touch devices we track touch and hold for 1s in order to remove a node\n moveEventCount = 0;\n mouseEventTimer = $timeout(function () {\n if (moveEventCount < 5) {\n // remove the node only if not many move events were fired,\n // this avoids conflict with dragging nodes\n hideNode(d);\n }\n mouseEventTimer = null;\n virtualClickEventTimer = 0;\n }, 1000);\n };\n\n // tracks the number of move events (checked in the touchend event handler)\n const moveEventHandler = function () {\n moveEventCount++;\n };\n\n const showNodeTipAndIcons = function (d) {\n if (!d.isBeingDragged) {\n const event = d3.event;\n $timeout.cancel(removeIconsTimer);\n showNodeTipAndIconsTimer = $timeout(() => {\n if (expandNodeIcons(d, this)) {\n showTipForNode(d, event);\n }\n }, 400);\n }\n };\n\n const upEventHandler = function (d) {\n if (d3.event.button && d3.event.button !== 0) {\n return;\n }\n\n $timeout.cancel(mouseEventTimer);\n\n const event = d3.event;\n const element = this;\n if (d3.event.timeStamp - upEventLast < multiClickDelay) {\n if (virtualClickEventTimer === 1) {\n mouseEventTimer = $timeout(function () {\n clickedNode(d, element, event);\n }, 40 + multiClickDelay - (d3.event.timeStamp - upEventLast));\n } else if (virtualClickEventTimer === 2) {\n // expand node\n const shownLinks = graph.countLinks(d, graph.links);\n if (shownLinks <= $scope.saveSettings['linksLimit']) {\n expandNode(d, false, element.parentNode);\n } else {\n toastr.info($translate.instant('graphexplore.increase.limit'), $translate.instant('graphexplore.node.at.max'));\n }\n $scope.closeInfoPanel();\n }\n }\n\n d3.event.preventDefault();\n };\n\n // Shows growing or shrinking pin animation\n function showPinAnimation(d, type) {\n let startSize;\n let endSize;\n let startOpacity;\n let endOpacity;\n let animate = true;\n\n if (type === 'down') {\n startSize = d.size * 2;\n endSize = d.size / 3;\n startOpacity = 0.8;\n endOpacity = 0.3;\n } else if (type === 'down-fixed') {\n startSize = d.size * 2;\n endSize = d.size;\n startOpacity = 0.8;\n endOpacity = 0.66;\n } else if (type === 'up') {\n startSize = d.size / 3;\n endSize = d.size * 2;\n startOpacity = 0.3;\n endOpacity = 0.8;\n } else if (type === 'fixed') {\n startSize = d.size;\n startOpacity = 0.66;\n animate = false;\n } else {\n return; // unknown\n }\n\n let pin = container.selectAll('.node-wrapper')\n .filter(function (innerD) {\n return innerD === d;\n })\n .append('text')\n .text('\\ue90f') // pin icon\n .classed('icon-any pinned', true)\n .style('font-size', startSize + 'px')\n .attr('x', function (d) {\n return d.x;\n })\n .attr('y', function (d) {\n return d.y;\n })\n .attr('opacity', startOpacity);\n\n if (type === 'fixed' || type === 'down-fixed') {\n d.pin = pin;\n }\n\n if (animate) {\n pin = pin.transition()\n .duration(1000)\n .style('font-size', function () {\n return endSize + 'px';\n })\n .attr('opacity', endOpacity);\n\n if (type !== 'down-fixed') {\n pin.remove();\n }\n }\n }\n\n function removePin() {\n d3.select('.pinned').remove();\n }\n\n // Unfixes nodes that were dragged previously\n const rightClickHandler = function (d) {\n if (d3.event.shiftKey) {\n // Do nothing with shift key, use to access context menu\n return;\n }\n\n d3.event.preventDefault();\n\n removeMenuIfVisible();\n $scope.closeInfoPanel();\n\n if (d.fixed) {\n // unpin\n $scope.numberOfPinnedNodes--;\n d.fixed = false;\n showPinAnimation(d, 'up');\n force.resume();\n } else {\n // pin down\n $scope.numberOfPinnedNodes++;\n d.fixed = true;\n showPinAnimation(d, 'down');\n }\n // update pin in tooltip\n updateTipForNode(d);\n };\n\n const drag = d3.behavior.drag()\n .origin(function (d) {\n return d;\n })\n .on(\"dragstart\", dragstarted)\n .on(\"drag\", dragged)\n .on(\"dragend\", dragended);\n\n\n function dragstarted(d) {\n if (d3.event.sourceEvent.button === 0) {\n d.fixedBeforeDrag = d.fixed;\n d.isBeingDragged = true;\n d.beginDragging = true;\n removeMenuIfVisible();\n d3.event.sourceEvent.stopPropagation();\n d3.select(this).classed(\"dragging\", true);\n }\n }\n\n function dragged(d) {\n if (d.isBeingDragged) {\n // reset click counter to avoid conflicts between clicks and drags\n virtualClickEventTimer = 0;\n\n d.px = d3.event.x;\n d.py = d3.event.y;\n if (!d.fixed) {\n $scope.numberOfPinnedNodes++;\n d.fixed = true;\n showPinAnimation(d, 'down-fixed');\n } else if (d.beginDragging) {\n showPinAnimation(d, 'fixed');\n }\n d.pinWasFixed = true;\n d.beginDragging = null;\n\n force.resume();\n }\n }\n\n function dragended(d) {\n if (d.isBeingDragged) {\n if (d.pinWasFixed) {\n d.pinWasFixed = null;\n removePin();\n }\n d.isBeingDragged = false;\n d3.select(this).classed(\"dragging\", false);\n }\n }\n\n node = container.selectAll(\".node\")\n .data(graph.nodes)\n .enter().append(\"g\")\n .attr(\"class\", \"node-wrapper\")\n .attr(\"id\", function (d) {\n return d.iri;\n })\n .append(\"circle\")\n .attr(\"class\", \"node\")\n .attr(\"r\", function (d) {\n return d.size;\n })\n .style(\"fill\", function (d) {\n if (d.types === \"greyColor\") {\n return \"c2c2c2\";\n }\n return $scope.getColor(d.types[0]);\n })\n .call(drag)\n .on('mouseover', showNodeTipAndIcons)\n .on('mouseout', hideTipForNode)\n .on(\"mousedown\", downEventHandler)\n .on(\"touchstart\", touchStartEventHandler)\n // no need to track move for mouse\n .on(\"touchmove\", moveEventHandler)\n .on(\"mouseup\", upEventHandler)\n .on(\"touchend\", upEventHandler)\n .on(\"contextmenu\", rightClickHandler);\n\n const nodeLabels = container.selectAll(\".node-wrapper\").append(\"foreignObject\")\n .style(\"pointer-events\", \"none\")\n .attr(\"width\", function (d) {\n return d.size * 2 * nodeLabelRectScaleX;\n });\n // height will be computed by updateNodeLabels\n\n container.insert(\"g\").attr(\"class\", \"menu-events\");\n\n updateNodeLabels(nodeLabels);\n\n force.on(\"tick\", function () {\n // recalculate nodes positions and repel them if they collide\n let q = d3.geom.quadtree(graph.nodes);\n let i = 0;\n const n = graph.nodes.length;\n // FIXME while (++i < n) q.visit(collide(graph.nodes[i]));\n\n // recalculate links attributes\n link.attr(\"x1\", function (d) {\n return getNodeX(d.source);\n }).attr(\"y1\", function (d) {\n return getNodeY(d.source);\n }).attr(\"x2\", function (d) {\n return getNodeX(d.target);\n }).attr(\"y2\", function (d) {\n return getNodeY(d.target);\n });\n\n // recalculate predicates attributes\n predicate.attr(\"x\", function (d) {\n let sourceX = getNodeX(d.source);\n let targetX = getNodeX(d.target);\n return d.x = (sourceX + targetX) * 0.5;\n }).attr(\"y\", function (d) {\n let sourceY = getNodeY(d.source);\n let targetY = getNodeY(d.target);\n return d.y = (sourceY + targetY) * 0.5;\n }).attr(\"transform\", function (d) {\n const angle = findAngleBetweenNodes(d, d.direction);\n return \"rotate(\" + angle + \", \" + d.x + \", \" + d.y + \")\";\n });\n\n // recalculate nodes attributes\n node.attr(\"cx\", function (d) {\n return d.x;\n }).attr(\"cy\", function (d) {\n return d.y;\n });\n\n // update node loader position\n container.select(\".node-loader\").attr(\"x\", function (d) {\n return d.x - d.size + 3; //square svg is not perfectly centered and need +3 units on x ordinate to fit in circle\n }).attr(\"y\", function (d) {\n return d.y - d.size;\n });\n\n container.select(\".loader-container\").attr(\"cx\", function (d) {\n return d.x;\n }).attr(\"cy\", function (d) {\n return d.y;\n });\n\n nodeLabels.attr(\"x\", function (d) {\n return d.x - (d.size * nodeLabelRectScaleX);\n }).attr(\"y\", function (d) {\n // the height of the nodeLabel box is 3 times the fontSize computed by updateNodeLabels\n // and we want to offset it so that its middle matches the centre of the circle, hence divided by 2\n return d.y - 3 * d.fontSize / 2;\n });\n\n // Update position of shrinking pin animation (if any)\n d3.select('.pinned').attr(\"x\", function (d) {\n return d.x;\n }).attr(\"y\", function (d) {\n return d.y;\n });\n });\n\n function panAndZoomed() {\n transformValues = \"translate(\" + d3.event.translate + \") scale(\" + d3.event.scale + \")\";\n container.attr(\"transform\", transformValues);\n }\n\n if (angular.isDefined(loader)) {\n loader.setLoadingState(false);\n }\n\n if ($scope.loading) {\n $scope.loading = false;\n }\n\n d3.selectAll('.link-wrapper').each(function () {\n const source = $(this).attr(\"id\").split(\">\")[0];\n const target = $(this).attr(\"id\").split(\">\")[1];\n d3.selectAll('.link').each(function (link) {\n let sourceId = removeSpecialChars(link.source.iri);\n let targetId = removeSpecialChars(link.target.iri);\n if (sourceId === target && targetId === source) {\n let twoWayLinkID = sourceId;\n twoWayLinkID += \">\";\n twoWayLinkID += targetId;\n const textNode = document.createTextNode(' \\u27F6');\n document.getElementById(twoWayLinkID).lastChild.appendChild(textNode);\n link.direction = \"double\";\n }\n });\n });\n\n d3.selectAll('.d3-actions-tip').remove();\n\n force.start();\n }\n\n /* FIXME\n // check for collision of the nodes\n function collide(node, bigger) {\n return function (quad, x1, y1, x2, y2) {\n if (quad.point && (quad.point !== node)) {\n var x = node.x - quad.point.x,\n y = node.y - quad.point.y,\n l = Math.sqrt(x * x + y * y),\n r = node.size + quad.point.size;\n if (l < r) {\n l = (l - r) / l * .5;\n node.x -= x *= l;\n node.y -= y *= l;\n quad.point.x += x;\n quad.point.y += y;\n }\n }\n return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;\n };\n }\n */\n\n draw();\n\n // find angle between pair of nodes so we can position predicates\n function findAngleBetweenNodes(linkedNodes, direction) {\n const p1 = {\n x: getNodeX(linkedNodes.source),\n y: getNodeY(linkedNodes.source)\n };\n\n const p2 = {\n x: getNodeX(linkedNodes.target),\n y: getNodeY(linkedNodes.target)\n };\n if (direction) {\n return Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;\n } else {\n const angleDeg = Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;\n if (angleDeg <= 90 && angleDeg >= -90) {\n return angleDeg;\n }\n return (angleDeg > 0 ? -1 : 1) * (180 - Math.abs(angleDeg));\n }\n }\n\n const menuEvents = new MenuEvents();\n\n // expanding and collapsing of the nodes\n function clickedNode(d, element, event) {\n $scope.showInfoPanel = false;\n $scope.showPredicates = false;\n $scope.showNodeInfo = false;\n\n // shift + ctrl/cmd + click focuses node\n if (event.shiftKey && (event.ctrlKey || event.metaKey)) {\n $rootScope.$broadcast(\"onRootNodeChange\", d.iri);\n return false;\n }\n\n // ctrl/cmd + click hides the node\n if (event.ctrlKey || event.metaKey) {\n hideNode(d);\n return false;\n }\n\n // If value of openedNodeInfoPanel is different than \"undefined\"\n // we evaluate if clicked node value is the same and close it\n if (typeof $scope.openedNodeInfoPanel !== \"undefined\" && $scope.openedNodeInfoPanel === d) {\n $scope.pageslideExpanded = false;\n $scope.openedNodeInfoPanel = undefined;\n return false;\n }\n\n showNodeInfo(d);\n return true;\n }\n\n function expandNodeIcons(d, element) {\n if ($scope.showInfoPanel) {\n return false;\n }\n\n if (menuEvents.closeIcon || menuEvents.expandIcon || menuEvents.focusIcon || menuEvents.copyURIIcon) {\n menuEvents.removeIcons();\n }\n\n // If nodes are still rearranging result of force.alpha() is more than 0.05\n // and we don't want to show node's icons on mouse over and stop rearrangement\n if (force.alpha() < 0.05) {\n menuEvents.initIcons(d, element.parentNode);\n force.stop();\n\n return true;\n }\n\n return false;\n }\n\n function hideNode(d) {\n graph.removeNode(d);\n draw();\n }\n\n function collapseNode(d) {\n d.isExpanded = false;\n graph.removeNodeLeafLinks(d);\n draw();\n }\n\n function initGraph(response) {\n $scope.nodeSelected = true;\n if (response.data.types === null) {\n response.data.types = \"greyColor\";\n }\n graph = new Graph();\n transformValues = \"translate(0, -70) scale(1)\";\n panAndZoom.translate([0, -70]);\n panAndZoom.scale(1);\n }\n\n function initGraphFromResponse(response) {\n initGraph(response);\n renderGraphFromResponse(response);\n }\n\n function renderGraphFromResponse(response, d, isStartNode) {\n let linksFound = response.data;\n // filter existing links\n linksFound = _.filter(linksFound, function (newLink) {\n return _.findIndex(graph.links,\n function (existingLink) {\n return newLink.source === existingLink.source.iri && newLink.target === existingLink.target.iri;\n }) === -1;\n });\n let linksCopy = [];\n const tripleLinksIt = graph.tripleLinksCopy.values();\n for (let i = 0; i < graph.tripleLinksCopy.size; i++) {\n let linkCopy = tripleLinksIt.next().value;\n linkCopy.forEach(link => {\n linksCopy.push(link);\n });\n }\n // filter existing shadow links\n linksFound = _.filter(linksFound, function (newLink) {\n return _.findIndex(linksCopy,\n function (existingLink) {\n return newLink.source === existingLink.source.iri && newLink.target === existingLink.target.iri;\n }) === -1;\n });\n // filter reflexive links until we find a way to render them GDB-1853\n linksFound = _.filter(linksFound, function (newLink) {\n return newLink.source !== newLink.target;\n });\n const nodesFromLinks = distinctBy('iri',_.union(_.flatten(_.map(response.data, function (link) {\n return [\n { iri: link.source,\n isTriple: link.isTripleSource },\n {\n iri: link.target,\n isTriple: link.isTripleTarget }];\n }))));\n const existingNodes = _.map(graph.nodes, function (n) {\n return {\n iri: n.iri,\n isTriple: Boolean(n.isTriple)\n };\n });\n const tripleNodesIt = graph.tripleNodes.values();\n for (let i = 0; i < graph.tripleNodes.size; i++) {\n let nodes = tripleNodesIt.next().value;\n nodes.forEach(node => {\n existingNodes.push({\n iri: node.iri,\n isTriple: node.isTriple\n });\n });\n }\n const newNodes = _.reject(nodesFromLinks, function (n) {\n return _.some(existingNodes, n);\n });\n\n if (newNodes.length === 0) {\n if (isStartNode) {\n toastr.info($translate.instant('graphexplore.error.node.connections'));\n } else if (linksFound.length === 0) {\n toastr.info($translate.instant('graphexplore.error.node.connections'));\n }\n\n graph.addAndMatchLinks(linksFound);\n draw();\n } else {\n const promises = [];\n const newNodesData = [];\n\n _.forEach(newNodes, function (newNode, index) {\n promises.push($http({\n url: 'rest/explore-graph/node',\n method: 'GET',\n params: {\n iri: newNode.isTriple ? createTriple(newNode.iri) : newNode.iri,\n config: $scope.configLoaded.id,\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n includeInferred: $scope.saveSettings['includeInferred'],\n sameAsState: $scope.saveSettings['sameAsState']\n }\n }).then(function (res) {\n // Save the data for later\n newNodesData[index] = res.data;\n }));\n });\n\n // Waits for all of the collected promises and then:\n // - adds each new node\n // - redraws the graph\n $q.all(promises).then(function () {\n _.forEach(newNodesData, function (newNodeData, index) {\n // Calculate initial positions for the new nodes based on spreading them evenly\n // on a circle around the node we came from.\n const theta = 2 * Math.PI * index / newNodesData.length;\n const x = (d ? d.x : 0) + Math.cos(theta) * height / 3;\n const y = (d ? d.y : 0) + Math.sin(theta) * height / 3;\n if (newNodeData.isTriple) {\n graph.addTriple(newNodeData, x, y);\n } else {\n graph.addNode(newNodeData, x, y);\n }\n });\n\n graph.addAndMatchLinks(linksFound);\n if (d) {\n d.isExpanded = true;\n }\n draw();\n });\n }\n }\n\n function expandNode(d, isStartNode, parentNode) {\n if (loader.getLoadingState()) {\n return;\n }\n loader.init(d, parentNode);\n\n const expandIri = d.iri;\n $http({\n url: 'rest/explore-graph/links',\n method: 'GET',\n params: {\n iri: expandIri, linksLimit: $scope.saveSettings['linksLimit'],\n includeInferred: $scope.saveSettings['includeInferred'],\n config: $scope.configLoaded.id,\n preferredTypes: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['preferredTypes'],\n rejectedTypes: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['rejectedTypes'],\n preferredPredicates: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['preferredPredicates'],\n rejectedPredicates: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['rejectedPredicates'],\n preferredTypesOnly: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['preferredTypesOnly'],\n preferredPredicatesOnly: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['preferredPredicatesOnly'],\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n sameAsState: $scope.saveSettings['sameAsState'],\n includeSchema: $scope.saveSettings['includeSchema']\n }\n }).then(function (response) {\n renderGraphFromResponse(response, d, isStartNode);\n }, function (response) {\n const msg = getError(response.data);\n toastr.error(msg, $translate.instant('graphexplore.error.exploring.node'));\n $scope.loading = false;\n loader.setLoadingState(false);\n });\n }\n\n function removeMenuIfVisible() {\n if (angular.isDefined(menuEvents) && menuEvents.expandedState) {\n menuEvents.removeIcons();\n }\n }\n\n function MenuEvents() {\n this.closeIcon = undefined;\n this.expandIcon = undefined;\n this.collapseIcon = undefined;\n this.focusIcon = undefined;\n this.copyURIIcon = undefined;\n this.actionsTip = undefined;\n\n this.removeIcons = function () {\n this.closeIcon.remove(\"g\");\n if (this.expandIcon) {\n this.expandIcon.remove(\"g\");\n }\n\n if (this.collapseIcon) {\n this.collapseIcon.remove(\"g\");\n }\n\n this.focusIcon.remove(\"g\");\n this.copyURIIcon.remove(\"g\");\n this.closeIcon = undefined;\n this.expandIcon = undefined;\n this.collapseIcon = undefined;\n this.focusIcon = undefined;\n this.copyURIIcon = undefined;\n\n this.expandedState = false;\n };\n\n this.expandedState = false;\n\n function getPositionAndAngle(angle, d) {\n const x = d.x - 14 + (d.size + 15) * Math.cos(angle * Math.PI / 180 - Math.PI / 2);\n const y = d.y - 14 + (d.size + 15) * Math.sin(angle * Math.PI / 180 - Math.PI / 2);\n return \"translate(\" + x + \",\" + y + \")\";\n }\n\n this.initIcons = function (node, parentNode) {\n // init action tips on hover of the icons\n const actionsTip = d3tip()\n .attr('class', 'd3-tip d3-actions-tip')\n .customPosition(function () {\n const bbox = d3.event.target.getBoundingClientRect();\n return {\n top: (bbox.top - 20) + 'px',\n left: (bbox.right + 10) + 'px'\n };\n })\n .html(function (name) {\n return name;\n });\n svg.call(actionsTip);\n const angle = 20;\n if (node.isExpanded) {\n this.collapseIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"collapse-icon\")\n .attr(\"name\", \"collapse\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.collapseIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.collapseIcon.append(\"path\")\n .attr(\"d\", \"M22.67,12a.59.59,0,0,1-.53.65l-6.88.72H15.2a.59.59,0,0,1-.59-.65l.72-6.88A.58.58,0,0,1,16,5.33a.59.59,0,0,1,.53.65L16,11.11,21.3,5.79a.64.64,0,0,1,.91.91L16.89,12,22,11.49A.59.59,0,0,1,22.67,12ZM12.59,14.75l-6.75.85a.59.59,0,0,0-.51.66.58.58,0,0,0,.66.51l4.95-.62-5.2,5.2a.64.64,0,1,0,.91.91l5.2-5.2L11.23,22a.59.59,0,0,0,.51.66h.07a.59.59,0,0,0,.59-.52l.85-6.75a.59.59,0,0,0-.17-.49A.58.58,0,0,0,12.59,14.75Z\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.collapseIcon.on(\"click\", function () {\n collapseNode(node);\n }).on('mouseover', function () {\n actionsTip.show(this.getAttribute(\"name\"));\n $timeout.cancel(showNodeTipAndIconsTimer);\n $timeout.cancel(removeIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n } else {\n this.expandIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"expand-icon\")\n .attr(\"name\", \"expand\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.expandIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.expandIcon.append(\"path\")\n .attr(\"d\", \"M22.37,6.28l-.72,6.88a.59.59,0,0,1-.59.53H21a.59.59,0,0,1-.53-.65L21,7.9l-5.32,5.32a.64.64,0,0,1-.91-.91L20.1,7,15,7.53a.59.59,0,0,1-.12-1.18l6.88-.72a.59.59,0,0,1,.65.65ZM12.89,20.34,7.95,21l5.2-5.2a.64.64,0,0,0-.91-.91L7,20.05l.62-4.95A.59.59,0,0,0,6.48,15l-.85,6.75a.59.59,0,0,0,.59.67h.07L13,21.52a.59.59,0,1,0-.15-1.18Z\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.expandIcon.on(\"click\", function () {\n expandNode(node, false, parentNode);\n }).on('mouseover', function () {\n actionsTip.show(this.getAttribute(\"name\"));\n $timeout.cancel(removeIconsTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n }\n\n\n this.focusIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"focus-icon\")\n .attr(\"name\", \"focus\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.focusIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.focusIcon.append(\"path\")\n .attr(\"d\", \"M14.2,23.81a9.8,9.8,0,1,1,6.93-2.87h0A9.74,9.74,0,0,1,14.2,23.81Zm0-18.17a8.37,8.37,0,1,0,5.92,14.29h0A8.37,8.37,0,0,0,14.2,5.64Zm1.42,6.95a2,2,0,1,0,0,2.85A2,2,0,0,0,15.62,12.59Z\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.focusIcon.on(\"click\", function () {\n $rootScope.$broadcast(\"onRootNodeChange\", node.iri);\n }).on('mouseover', function () {\n actionsTip.show(this.getAttribute(\"name\"));\n $timeout.cancel(removeIconsTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n\n this.copyURIIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"icon-link\")\n .attr(\"name\", \"link\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.copyURIIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.copyURIIcon.append(\"path\")\n .attr(\"d\", \"M 13.457031 10.164062 C 13.648438 10.164062 13.820312 10.242188 13.941406 10.363281 L 15.492188 11.859375 C 15.984375 12.332031 16.292969 12.992188 16.292969 13.714844 C 16.292969 14.441406 15.984375 15.097656 15.492188 15.574219 L 10.394531 20.496094 C 9.902344 20.972656 9.222656 21.265625 8.472656 21.265625 C 7.71875 21.265625 7.039062 20.972656 6.546875 20.496094 L 4.996094 19 C 4.507812 18.523438 4.203125 17.867188 4.203125 17.144531 C 4.203125 16.421875 4.507812 15.765625 4.996094 15.289062 L 7.542969 12.824219 C 7.667969 12.707031 7.84375 12.628906 8.035156 12.628906 C 8.417969 12.628906 8.726562 12.929688 8.726562 13.300781 C 8.726562 13.484375 8.648438 13.652344 8.523438 13.773438 L 5.976562 16.234375 C 5.738281 16.46875 5.589844 16.792969 5.589844 17.148438 C 5.589844 17.503906 5.738281 17.824219 5.976562 18.058594 L 7.527344 19.566406 C 7.773438 19.792969 8.105469 19.929688 8.472656 19.929688 C 8.835938 19.929688 9.167969 19.792969 9.414062 19.566406 L 14.511719 14.644531 C 14.753906 14.410156 14.90625 14.089844 14.90625 13.730469 C 14.90625 13.375 14.753906 13.054688 14.511719 12.820312 L 12.964844 11.324219 C 12.839844 11.203125 12.761719 11.039062 12.761719 10.855469 C 12.761719 10.488281 13.070312 10.1875 13.449219 10.1875 Z M 17.082031 3.976562 C 17.082031 3.976562 17.085938 3.976562 17.085938 3.976562 C 17.824219 3.976562 18.492188 4.261719 18.980469 4.722656 L 20.535156 6.203125 C 21.042969 6.679688 21.355469 7.34375 21.355469 8.082031 C 21.355469 8.792969 21.058594 9.441406 20.582031 9.914062 L 18.0625 12.402344 C 17.9375 12.527344 17.761719 12.605469 17.566406 12.605469 C 17.183594 12.605469 16.875 12.304688 16.875 11.9375 C 16.875 11.753906 16.949219 11.589844 17.070312 11.46875 L 19.605469 8.984375 C 19.847656 8.75 19.996094 8.429688 19.996094 8.070312 C 19.996094 7.714844 19.847656 7.394531 19.605469 7.160156 L 18.019531 5.667969 C 17.773438 5.445312 17.4375 5.304688 17.070312 5.300781 C 16.703125 5.304688 16.367188 5.453125 16.128906 5.691406 L 11.085938 10.667969 C 10.84375 10.898438 10.695312 11.222656 10.695312 11.578125 C 10.695312 11.933594 10.84375 12.257812 11.085938 12.488281 L 12.675781 13.980469 C 12.804688 14.101562 12.882812 14.273438 12.882812 14.457031 C 12.882812 14.828125 12.574219 15.128906 12.191406 15.128906 C 12.003906 15.128906 11.832031 15.054688 11.707031 14.9375 L 10.140625 13.457031 C 9.636719 12.980469 9.324219 12.316406 9.324219 11.582031 C 9.324219 10.863281 9.621094 10.214844 10.101562 9.742188 L 15.140625 4.765625 C 15.625 4.285156 16.304688 3.980469 17.054688 3.976562 Z M 17.082031 3.976562\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.copyURIIcon.on(\"click\", function () {\n copyToClipboard(node.iri);\n removeMenuIfVisible();\n actionsTip.hide();\n }).on('mouseover', function () {\n actionsTip.show(\"<div style='text-align: center;'><b>Copy to ClipBoard</b><br>\" + node.iri + \"</div>\");\n $timeout.cancel(removeIconsTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n\n this.closeIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"close-icon\")\n .attr(\"name\", \"remove\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.closeIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.closeIcon.append(\"path\")\n .attr(\"d\", \"M14.94,14l5.87-5.87a.66.66,0,1,0-.94-.94L14,13.06,8.13,7.19a.66.66,0,0,0-.94.94L13.06,14,7.19,19.87a.66.66,0,1,0,.94.94L14,14.94l5.87,5.87a.66.66,0,1,0,.94-.94Z\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.closeIcon.on(\"click\", function () {\n hideNode(node);\n }).on('mouseover', function () {\n actionsTip.show(this.getAttribute(\"name\"));\n $timeout.cancel(removeIconsTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n\n this.animateMenu(node);\n };\n\n this.animateMenu = function (node) {\n const animationDuration = 100;\n const easeEffects = [\"linear\", \"quad\", \"cubic\", \"sin\", \"exp\", \"circle\", \"elastic\", \"back\", \"bounce\"]; // https://github.com/d3/d3-3.x-api-reference/blob/master/Transitions.md#easing\n const easeEffect = easeEffects[3];\n let delay = 0;\n const dellayAddition = 35;\n let angle = 20; // angle of the first icon 0 is at 12 o'clock\n\n if (this.expandIcon) {\n this.expandIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n }\n\n if (this.collapseIcon) {\n this.collapseIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n }\n\n this.copyURIIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n angle += 30;\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n\n this.focusIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n angle += 30;\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n\n\n this.closeIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n angle += 30;\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n\n this.expandedState = true;\n };\n }\n\n function Loader() {\n this.state = false;\n\n this.setLoadingState = function (state) {\n this.state = state;\n };\n\n this.getLoadingState = function () {\n return this.state;\n };\n\n this.init = function (node, parentNode) {\n d3.select(parentNode).append(\"circle\")\n .attr(\"cx\", function () {\n return node.x;\n })\n .attr(\"cy\", function () {\n return node.y;\n })\n .attr(\"class\", \"loader-container\")\n .attr(\"r\", function () {\n return node.size;\n })\n .style(\"fill\", \"fff\")\n .style(\"opacity\", \"0.7\");\n\n d3.select(parentNode).append(\"image\")\n .attr(\"xlink:href\", \"js/angular/templates/loader/ot-loader.svg?v=2.0.0\")\n .attr(\"x\", function () {\n return node.x - node.size + 5;\n })\n .attr(\"y\", function () {\n return node.y - node.size;\n })\n .attr(\"width\", function () {\n return node.size * 2;\n })\n .attr(\"height\", function () {\n return node.size * 2;\n })\n .attr(\"class\", \"node-loader\");\n };\n }\n\n function showNodeInfo(d) {\n force.stop();\n // Assign value of node, which info panel has been opened\n $scope.openedNodeInfoPanel = d;\n $scope.showNodeInfo = true;\n $scope.showFilter = false;\n $scope.showPredicates = false;\n $scope.nodeLabels = d.labels;\n $scope.nodeTypes = d.types;\n $scope.rdfRank = d.rdfRank;\n $scope.nodeIri = d.iri;\n $scope.resourceType = d.isTriple ? 'triple' : 'uri';\n $scope.encodedIri = d.isTriple ? encodeURI(createTriple(d.iri)) : encodeURI(d.iri);\n $scope.showInfoPanel = true;\n\n $scope.rdfsLabel = d.labels[0].label;\n $scope.rdfsComment = d.comment;\n $scope.expanded = false;\n\n $scope.propertiesQueryObj.query = '';\n $scope.dataNodeKeysQuery = '';\n $http.get('rest/explore-graph/properties', {\n params: {\n iri: d.isTriple ? createTriple(d.iri) : d.iri,\n config: $scope.configLoaded.id,\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n includeInferred: $scope.saveSettings['includeInferred'],\n sameAsState: $scope.saveSettings['sameAsState'],\n rejectedPredicates: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['rejectedPredicates']\n }\n }).then(function (response) {\n $scope.data = _.mapKeys(response.data, function (value, key) {\n return $scope.replaceIRIWithPrefix(key);\n });\n $scope.propertiesObj.items = [];\n\n _.forEach($scope.data, function (value, key) {\n $scope.propertiesObj.items.push({key: key, value: value});\n });\n $scope.nodeImage = undefined;\n\n $scope.propertiesNotFiltered = $scope.propertiesObj.items;\n\n const imageVal = _.find($scope.propertiesObj.items, function (o) {\n return o.key === 'image';\n });\n if (imageVal) {\n $scope.nodeImage = imageVal['value'][0].v;\n }\n $scope.propertiesObj.items = _.reject($scope.propertiesObj.items, function (o) {\n return o.key === 'image';\n });\n $scope.propertiesNotFiltered = $scope.propertiesObj.items;\n }, function (response) {\n toastr.warning(getError(response.data), \"Error\");\n });\n }\n\n $scope.toggleSidePanel = function () {\n $scope.pageslideExpanded = !$scope.pageslideExpanded;\n };\n\n $scope.closeInfoPanel = function () {\n $scope.pageslideExpanded = false;\n $scope.openedNodeInfoPanel = undefined;\n $scope.predicates = [];\n openedLink = null;\n // o, angular, o, miracle\n $timeout(function () {\n $scope.showInfoPanel = false;\n });\n };\n\n function applyElementsStyleChanges(tripleNode) {\n updatePredicatesColor('predicate', 'var(--onto-orange-dark)', tripleNode);\n updatePredicatesColor('predicates', 'var(--onto-orange-dark)', tripleNode);\n\n let links = document.getElementsByClassName('link');\n if (links) {\n _.each(links, function (link) {\n let linkLink = link.__data__;\n if (linkLink.source.iri.indexOf(tripleNode.iri) >= 0 || linkLink.target.iri.indexOf(tripleNode.iri) >= 0) {\n link.style.stroke = 'var(--onto-orange-dark)';\n link.style.strokeWidth = 4;\n }\n })\n }\n\n let markers = document.getElementsByClassName('arrow-marker');\n if (markers) {\n _.each(markers, function (marker) {\n let markerLink = marker.__data__;\n if (markerLink.source.iri.indexOf(tripleNode.iri) >= 0 || markerLink.target.iri.indexOf(tripleNode.iri) >= 0) {\n marker.style.stroke = 'var(--onto-orange-dark)';\n if (!marker.__data__.target.isTriple) {\n marker.setAttribute(\"refX\", \"23\");\n }\n }\n });\n }\n }\n\n $scope.clickLink = function (predData) {\n if (graph.tripleNodes.has(predData.linkId)) {\n revertElementsStyleToDefault();\n let tripleNode = graph.tripleNodes.get(predData.linkId)[predData.nodeIndex];\n // Shows selected triple and its properties\n showNodeInfo(tripleNode);\n $scope.showPredicates = true;\n\n let clickedEl = document.getElementById(predData.linkId + predData.nodeIndex);\n if (clickedEl) {\n clickedEl.style.fontWeight = \"bold\";\n }\n\n let nodeCopy = {};\n const tripleLinksIt = graph.tripleLinksCopy.values();\n for (let i = 0; i < graph.tripleLinksCopy.size; i++) {\n let links = tripleLinksIt.next().value;\n if (links.length > 1) {\n links.every(link => {\n if (link.source.iri === tripleNode.iri) {\n nodeCopy.iri = links[0].source.iri;\n if (link.target.isTriple) {\n nodeCopy.oppLinkIRI = convertTripleToLinkId(link.target.iri);\n nodeCopy.oppTriplePred = getShortPredicate(link.target.iri.split(' ')[1]);\n }\n nodeCopy.pred = getShortPredicate(tripleNode.iri.split(' ')[1]);\n if (link.predicates.length === 1) {\n nodeCopy.linkPred = link.predicates[0];\n }\n return false;\n }\n if (link.target.iri === tripleNode.iri) {\n nodeCopy.iri = links[0].target.iri;\n if (link.source.isTriple) {\n nodeCopy.oppLinkIRI = convertTripleToLinkId(link.source.iri);\n nodeCopy.oppTriplePred = getShortPredicate(link.source.iri.split(' ')[1]);\n }\n nodeCopy.pred = getShortPredicate(tripleNode.iri.split(' ')[1]);\n if (link.predicates.length === 1) {\n nodeCopy.linkPred = link.predicates[0];\n }\n return false;\n }\n return true;\n });\n }\n }\n\n if (!nodeCopy.iri) {\n nodeCopy.iri = tripleNode.iri;\n nodeCopy.pred = getShortPredicate(tripleNode.iri.split(' ')[1]);\n }\n\n applyElementsStyleChanges(nodeCopy);\n }\n }\n\n function updatePredicatesColor(className, color, tripleNode) {\n let preds = document.getElementsByClassName(className);\n\n if (preds) {\n _.each(preds, function (pred) {\n let predLink = pred.__data__;\n if (tripleNode) {\n if (predLink.source.iri.indexOf(tripleNode.iri) >= 0 || predLink.target.iri.indexOf(tripleNode.iri) >= 0) {\n pred.style.fill = color;\n }\n if (convertTripleToLinkId(tripleNode.iri) === convertLinkDataToLinkId(predLink)) {\n pred.textContent = tripleNode.pred;\n pred.style.fill = color;\n }\n if (tripleNode.oppLinkIRI && tripleNode.oppLinkIRI === convertLinkDataToLinkId(predLink)) {\n pred.textContent = tripleNode.oppTriplePred;\n pred.style.fill = color;\n }\n } else {\n pred.style.fill = color;\n pred.textContent = getPredicate(predLink);\n }\n })\n }\n }\n\n function revertElementsStyleToDefault() {\n _.each($scope.predicates, function (pred) {\n let currEl = document.getElementById(pred.linkId + pred.nodeIndex);\n if (currEl) {\n currEl.style.fontWeight = \"normal\";\n }\n });\n let links = document.getElementsByClassName('link');\n if (links) {\n _.each(links, function (link) {\n link.style.stroke = '#999';\n link.style.strokeWidth = 1;\n })\n }\n updatePredicatesColor('predicate', '');\n updatePredicatesColor('predicates', '');\n\n let markers = document.getElementsByClassName('arrow-marker');\n\n if (markers) {\n _.each(markers, function (marker) {\n marker.style.stroke = '#999';\n // RefX for triple targets isn't changed, because they are not affected by increasing of stroke-width\n if (!marker.__data__.target.isTriple) {\n marker.setAttribute(\"refX\", \"59\");\n }\n });\n }\n }\n\n function linkActions(d) {\n revertElementsStyleToDefault();\n let linkId = convertLinkDataToLinkId(d);\n if (d.predicates.length === 1 && graph.tripleNodes.has(linkId)) {\n openedLink = null;\n let tripleNode = graph.tripleNodes.get(linkId)[0];\n // If there is a triple in this link, show its properties\n if (clickedNode(tripleNode, this, d3.event.button)) {\n let nodeCopy = {};\n nodeCopy.iri = tripleNode.iri;\n nodeCopy.pred = getShortPredicate(tripleNode.iri.split(' ')[1]);\n applyElementsStyleChanges(nodeCopy);\n }\n return;\n }\n openPredicates(d);\n }\n\n function openPredicates(d) {\n $scope.showNodeInfo = false;\n // open predicates sidebar if they are more than one\n $scope.showPredicates = d.predicates.length > 1;\n $scope.showFilter = false;\n $scope.showInfoPanel = false;\n\n if (openedLink === d) {\n $scope.showNodeInfo = false;\n $scope.showInfoPanel = false;\n openedLink = null;\n return;\n }\n\n openedLink = d;\n\n if ($scope.showPredicates) {\n $scope.predicates = _.map(d.predicates, function (p) {\n let foundNodeIndex = getTripleNodeIndex(p, d);\n let isPartOfTriple = foundNodeIndex > -1;\n return {\n value: getShortPredicate(p),\n partOfTriple: isPartOfTriple,\n linkId: isPartOfTriple ? convertLinkDataToLinkId(d) : '',\n nodeIndex: foundNodeIndex\n };\n });\n $scope.showInfoPanel = true;\n }\n }\n\n function getTripleNode(triple) {\n let linkId = convertTripleToLinkId(triple);\n if (graph.tripleNodes.has(linkId)) {\n return graph.tripleNodes.get(linkId).find(el => el.iri === triple);\n }\n }\n\n function getTripleNodeIndex(pred, d) {\n let linkId = convertLinkDataToLinkId(d);\n if (graph.tripleNodes.has(linkId)) {\n return graph.tripleNodes.get(linkId).findIndex(el => el.iri.indexOf(pred) >= 0);\n } else {\n return -1;\n }\n }\n\n // get each predicate and check if there are more than one for same source and target\n function getPredicate(d) {\n if (d.predicates.length > 1) {\n return d.predicates.length + \" predicates\";\n }\n return getShortPredicate(d.predicates[0]);\n }\n\n function getShortPredicate(p) {\n const shortIRI = $scope.replaceIRIWithPrefix(p);\n if (shortIRI.length === p.length) {\n return p.split('/')[p.split('/').length - 1];\n } else {\n return shortIRI;\n }\n }\n\n // calculate predicate text length so we can have dynamic link lengths\n function getPredicateTextLength(link) {\n const span = $('<span></span>');\n const splitedLink = link.predicates[0].split('/');\n const predicateText = splitedLink[splitedLink.length - 1];\n span.addClass('predicate-text').text(predicateText);\n $('body').append(span);\n const textLength = span.width() + link.source.size * 2 + link.target.size * 2 + 50;\n span.remove();\n return textLength * 0.75;\n }\n\n $scope.splitPredicate = function (predicate) {\n return predicate.split('/')[predicate.split('/').length - 1];\n };\n\n $scope.getActiveRepository = function () {\n return $repositories.getActiveRepository();\n };\n\n $scope.isLoadingLocation = function () {\n return $repositories.isLoadingLocation();\n };\n\n $scope.hasActiveLocation = function () {\n return $repositories.hasActiveLocation();\n };\n\n $scope.rotate = function (isLeft) {\n removeMenuIfVisible();\n\n // compute common rotation math such as the angle, its sine and cosine and the pivot point\n const theta = (isLeft ? 1 : -1) * 2 * Math.PI / 180; // + rotates left, - rotates right\n const cos = Math.cos(theta);\n const sin = Math.sin(theta);\n const pivotX = width / 2; // i.e. centre of viewport\n const pivotY = height / 2;\n\n // rotates each node around the pivot\n d3.selectAll(\".node-wrapper\")\n .each(function (d) {\n d.x = pivotX + (cos * (d.x - pivotX) + sin * (d.y - pivotY));\n d.y = pivotY + (-sin * (d.x - pivotX) + cos * (d.y - pivotY));\n if (d.fixed) {\n // Fixed nodes need their px and py updated too\n d.px = d.x;\n d.py = d.y;\n }\n });\n\n force.resume();\n };\n\n $scope.openUri = function (uri, noHistory) {\n if (!noHistory) {\n const searchParams = {};\n if ($scope.configLoaded.id !== $scope.defaultGraphConfig.id) {\n searchParams.config = $scope.configLoaded.id;\n }\n searchParams.uri = uri;\n $scope.pushHistory(searchParams, {uri: uri, config: $scope.configLoaded});\n }\n $scope.$broadcast(\"onRootNodeChange\", uri);\n };\n\n function saveGraphHttp(graph) {\n if ($scope.configLoaded) {\n graph.config = $scope.configLoaded.id;\n }\n SavedGraphsRestService.addNewSavedGraph(graph)\n .success(function (data, status, headers) {\n $scope.lastSavedGraphName = graph.name;\n $scope.lastSavedGraphId = headers()['x-saved-graph-id'];\n $scope.shared = graph.shared;\n $scope.refreshSavedGraphs();\n toastr.success($translate.instant('graphexplore.saved.graph', {name: graph.name}));\n })\n .error(function (data, status) {\n if (status === 422) {\n $scope.saveGraphModal('new', graph, true);\n } else {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.cannot.create.graph'));\n }\n });\n }\n\n $scope.saveOrUpdateGraph = function () {\n const data = JSON.stringify(graph.copyState());\n const graphToSave = {id: $scope.lastSavedGraphId, name: $scope.lastSavedGraphName, data: data, shared: $scope.shared};\n\n if (graphToSave.id) {\n $scope.saveGraphModal('update', graphToSave);\n } else {\n $scope.saveGraphModal('new', graphToSave);\n }\n };\n\n $scope.renameSavedGraph = function (graphToRename) {\n // By not sending the 'data' part of a graph we only change the name\n $scope.saveGraphModal('rename', {id: graphToRename.id, name: graphToRename.name, config: graphToRename.config, shared: graphToRename.shared});\n };\n\n const editSavedGraphHttp = function (savedGraph) {\n SavedGraphsRestService.editSavedGraph(savedGraph)\n .success(function () {\n $scope.lastSavedGraphName = savedGraph.name;\n $scope.shared = savedGraph.shared;\n $scope.refreshSavedGraphs();\n toastr.success($translate.instant('graphexplore.saved.graph.was.edited', {name: savedGraph.name}));\n })\n .error(function (data) {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.cannot.edit'));\n });\n };\n\n $scope.saveGraphModal = function (mode, graphToSave, graphExists) {\n const modalInstance = $modal.open({\n templateUrl: 'js/angular/graphexplore/templates/modal/save-graph.html',\n controller: 'SaveGraphModalCtrl',\n resolve: {\n data: function () {\n return {\n mode: mode,\n graph: graphToSave,\n graphExists: graphExists,\n shared: graphToSave.shared\n };\n }\n }\n });\n\n modalInstance.result.then(function (data) {\n if (data.restart) {\n $scope.saveGraphModal(data.mode, data.graph, false);\n return;\n }\n switch (data.mode) {\n case 'new':\n saveGraphHttp(data.graph);\n break;\n case 'update':\n editSavedGraphHttp(data.graph);\n break;\n case 'rename':\n editSavedGraphHttp(data.graph);\n break;\n }\n });\n };\n\n $scope.refreshSavedGraphs = function () {\n SavedGraphsRestService.getSavedGraphs()\n .success(function (data) {\n $scope.savedGraphs = data;\n })\n .error(function (data) {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.getting.saved.graphs'));\n });\n };\n\n\n $scope.loadSavedGraph = function (graphToLoad, noHistory) {\n if (graphToLoad.owner) {\n // Own saved graph\n $scope.lastSavedGraphName = graphToLoad.name;\n $scope.lastSavedGraphId = graphToLoad.id;\n $scope.shared = graphToLoad.shared;\n $scope.configLoaded = $scope.findConfigById(graphToLoad.config);\n } else {\n // Someone else's saved graph\n $scope.lastSavedGraphName = null;\n $scope.lastSavedGraphId = null;\n $scope.shared = graphToLoad.shared;\n }\n\n if (!$scope.configLoaded) {\n // Fallback to default config, either because config is gone or because graph isn't owned\n $scope.configLoaded = $scope.defaultGraphConfig;\n }\n\n $location.url(\"?saved=\" + graphToLoad.id);\n graph.restoreState(JSON.parse(graphToLoad.data));\n if (!noHistory) {\n $scope.pushHistory({saved: graphToLoad.id}, {savedGraph: graphToLoad});\n }\n };\n\n $scope.copyToClipboardSavedGraph = function (savedGraph) {\n const url = [location.protocol, '//', location.host, location.pathname, '?saved=', savedGraph.id].join('');\n copyToClipboard(url);\n };\n\n function deleteSavedGraphHttp(savedGraph) {\n SavedGraphsRestService.deleteSavedGraph(savedGraph)\n .success(function () {\n $scope.refreshSavedGraphs();\n toastr.success($translate.instant('graphexplore.saved.graph.was.deleted', {name: savedGraph.name}));\n })\n .error(function (data) {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.cannot.delete'));\n });\n }\n\n $scope.deleteSavedGraph = function (savedGraph) {\n ModalService.openSimpleModal({\n title: $translate.instant('common.confirm'),\n message: $translate.instant('graphexplore.confirm.delete.graph', {graphName: savedGraph.name}),\n warning: true\n }).result\n .then(function () {\n deleteSavedGraphHttp(savedGraph);\n });\n };\n\n $scope.openIRI = function (link, event) {\n if (event.shiftKey) {\n $scope.$broadcast(\"onRootNodeChange\", link);\n } else {\n window.open(link, '_blank');\n }\n return false;\n };\n\n $scope.togglePinAllNodes = function () {\n removeMenuIfVisible();\n\n const value = $scope.numberOfPinnedNodes <= 0;\n\n $scope.numberOfPinnedNodes = 0;\n d3.selectAll('.node').each(function (d) {\n d.fixed = value;\n if (value) {\n $scope.numberOfPinnedNodes++;\n }\n });\n\n force.resume();\n };\n\n // event for capturing left and right arrows used for rotation\n $('body').on(\"keydown\", function (event) {\n if (event.target.nodeName === 'input' || !$scope.nodeSelected) {\n // don't do anything when the target is an input field or no node is selected\n } else if (event.keyCode === 37) {\n // left arrow rotates left\n $scope.rotate(true);\n } else if (event.keyCode === 39) {\n // right arrow rotates right\n $scope.rotate(false);\n }\n });\n\n $scope.getLiteralFromPropValue = function (value) {\n return value.substring(value.indexOf(':') + 1);\n }\n}\n\nSaveGraphModalCtrl.$inject = ['$scope', '$modalInstance', 'data', '$translate'];\n\nfunction SaveGraphModalCtrl($scope, $modalInstance, data, $translate) {\n $scope.mode = data.mode;\n $scope.graph = angular.copy(data.graph);\n $scope.graphExists = data.graphExists;\n\n switch ($scope.mode) {\n case 'new':\n $scope.title = $translate.instant('graphexplore.create.new.graph');\n $scope.okButtonText = $translate.instant('common.create.btn');\n break;\n case 'update':\n $scope.title = $translate.instant('graphexplore.update');\n $scope.okButtonText = $translate.instant('common.save.btn');\n break;\n case 'rename':\n $scope.title = $translate.instant('graphexplore.rename');\n $scope.okButtonText = $translate.instant('common.save.btn');\n }\n\n $scope.ok = function () {\n if ($scope.form.$valid) {\n $modalInstance.close({graph: $scope.graph, mode: $scope.mode});\n }\n };\n\n $scope.saveNew = function () {\n $scope.graph.name = $scope.graph.name + ' (new)';\n $modalInstance.close({graph: $scope.graph, mode: 'new', restart: true});\n };\n\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n}\n"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"sources":["webpack:///./src/js/lib/d3-tip/d3-tip-patch.js","webpack:///./src/js/lib/common/d3-utils.js","webpack:///./src/js/angular/repositories/repository.constants.js","webpack:///./src/js/angular/graphexplore/controllers/graphs-visualizations.controller.js"],"names":["direction","offset","html","node","initNode","svg","point","target","customPosition","tip","vis","el","tagName","toLowerCase","ownerSVGElement","createSVGPoint","document","body","appendChild","show","args","Array","prototype","slice","call","arguments","length","SVGElement","pop","coords","content","apply","this","poffset","dir","nodel","getNodeEl","i","directions","scrollTop","documentElement","scrollLeft","customPos","style","opacity","classed","direction_callbacks","get","top","left","hide","attr","n","v","d3","selection","functor","destroy","remove","map","bbox","getScreenBBox","y","offsetHeight","x","offsetWidth","s","e","w","nw","ne","sw","se","keys","select","createElement","position","targetel","event","getScreenCTM","parentNode","matrix","tbbox","getBBox","width","height","matrixTransform","D3","Text","calcFontSizeRaw","text","radius","minimumSize","isMultiline","textSize","substring","match","Math","round","calcFontSize","getTextWithElipsisIfNeeded","str","threshold","Transition","fadeIn","sel","duration","transition","fadeOut","Click","delayDblClick","dispatch","rebind","down","wait","on","mouse","Date","d","a","b","sqrt","pow","window","clearTimeout","dblclick","setTimeout","click","STATIC_RULESETS","id","name","REPOSITORY_TYPES","graphdbRepo","free","eeWorker","eeMaster","ontop","fedx","FILENAME_PATTERN","RegExp","NUMBER_PATTERN","GraphsVisualizationsCtrl","$scope","$rootScope","$repositories","$licenseService","toastr","$timeout","$http","ClassInstanceDetailsService","AutocompleteRestService","$q","$location","$jwtAuth","UiScrollService","ModalService","$modal","$window","LocalStorageAdapter","LSKeys","SavedGraphsRestService","GraphConfigRestService","RDF4JRepositoriesRestService","$translate","languageChanged","propertiesObj","propertiesQueryObj","items","propertiesNotFiltered","searchVisible","nodeSelected","queryResultsMode","embedded","search","openedNodeInfoPanel","undefined","invalidLimit","INVALID_LINKS_MSG","instant","INVALID_LINKS_TOOLTIP","$on","propertiesSearchPlaceholder","onopen","onclose","angular","noop","query","uri","config","saved","noGoHome","datasource","current","type2color","colorIndex","nodeLabelMinFontSize","panAndZoom","behavior","zoom","scaleExtent","transformValues","tipElement","openedLink","copyToClipboard","openCopyToClipboardModal","renderSettings","settings","languagesMap","_","languages","preferredTypesMap","preferredTypes","rejectedTypesMap","rejectedTypes","preferredPredicatesMap","preferredPredicates","rejectedPredicatesMap","rejectedPredicates","key","index","count","success","initLazyList","$watch","each","item","revision","adapterContainer","adapter","remain","propertiesFilterFunc","indexOf","resetState","configLoaded","lastSavedGraphName","lastSavedGraphId","shared","numberOfPinnedNodes","pushHistory","searchParams","state","goToHome","url","shouldShowSettings","defaultGraphConfig","shouldDisableSameAs","sameAsCheckbox","$","prop","isDefined","reload","toggleMoreInfo","ev","element","currentTarget","parent","next","toggle","children","toggleClass","defaultSettings","linksLimit","includeInferred","sameAsState","showLinksText","preferredTypesOnly","preferredPredicatesOnly","includeSchema","saveSettings","copy","when","getPrincipal","then","principal","settingsFromPrincipal","appSettings","localStorageSettings","GRAPHS_VIZ","unique","set","initSettings","resetSettings","validateLinksLimit","changeLimit","delta","test","showSettings","showInfoPanel","showFilter","showNodeInfo","showPredicates","reExpandNode","rootNodeIri","$broadcast","loadGraphForQuery","queryString","sameAsParam","inferredParam","sendSameAs","sendInferred","loading","method","headers","data","response","initGraphFromResponse","error","getError","removeSpecialChars","string","replace","convertTripleToLinkId","triple","tripleLike","tripleParts","split","join","convertLinkDataToLinkId","link","source","iri","getNodeX","isTriple","getElementById","__data__","getNodeY","createTriple","value","trim","createArrowMarkerUniqueID","Graph","nodes","links","tripleNodes","Map","tripleLinksCopy","addNode","push","computeConnectedness","counts","seenLinks","i1","i2","seenKey","min","max","connectedness","addAndMatchLinks","newLinks","isTripleSource","getTripleNode","find","o","isTripleTarget","matchedLink","predicates","linkId","graph","has","matchLinksToNodes","delete","filter","countLinks","findLinksForNode","l","linksTypes","linksForNode","types","uniq","flatten","linksPredicates","removeTriples","triplesToRemove","targetTriples","size","forEach","reject","sourceSplit","lSource","lTarget","targetSplit","isRejected","removeNode","removeNodeLeafLinks","targetLinks","addTriple","weight","copyState","nodesCopy","labels","rdfRank","fixed","triplesCopy","JSON","stringify","from","entries","scale","translate","restoreState","parse","draw","updateSettings","t","sameAs","inference","startMode","loadGraphConfig","selectAll","getGraphConfigs","graphCallback","graphConfigs","loadConfigForId","configId","successCallback","getConfig","findConfigById","grep","easyGraphSearch","openUri","startIRI","startGraphQuery","loadGraphForConfig","startQueryIncludeInferred","startQuerySameAs","deleteConfig","openSimpleModal","title","message","configName","warning","result","deleteGraphConfig","refreshSavedGraphs","goToGraphConfig","onpopstate","savedGraph","loadSavedGraph","initGraphFromQueryParam","inputValue","params","rootNode","expandNode","catch","err","getSavedGraph","msg","loadGraphFromQueryParam","initForRepository","newRepo","getActiveRepository","hasInitedRepository","getNamespacesPromise","getNamespaces","nss","results","bindings","namespace","prefix","namespaces","sortBy","checkAutocompleteStatus","isLicenseValid","getAutocompletePromise","replaceIRIWithPrefix","namespacePrefix","findLast","addedTag","tag","uriParts","uriPart","localName","isUndefined","expandedUri","getNamespaceUriForPrefix","expandPrefix","pageslideExpanded","validateTag","category","wildcardOK","wildcardPos","getTagClass","tagText","endsWith","empty","multiClickDelay","nodeLabelRectScaleX","color1","linear","domain","range","interpolate","interpolateHslLong","color2","getColor","type","force","layout","gravity","append","showNodeTipAndIconsTimer","removeIconsTimer","loader","setLoadingState","getLoadingState","init","resetRootNode","container","stopPropagation","removeMenuIfVisible","stop","getBoundingClientRect","bottom","createTipText","p","getShortPredicate","numOfPredLeft","numberOfPredLeft","textToShow","tipPredicateElement","tipPredicates","textWidth","ctx","getContext","font","measureText","calculateWidth","hideTipForNode","cancel","tipTimer","charge","linkDistance","span","splitedLink","predicateText","addClass","textLength","getPredicateTextLength","enter","predicate","getPredicate","tipPredicateTimer","thisPredicateTipElement","showPredicateToolTip","revertElementsStyleToDefault","tripleNode","clickedNode","button","nodeCopy","pred","applyElementsStyleChanges","foundNodeIndex","findIndex","getTripleNodeIndex","isPartOfTriple","partOfTriple","nodeIndex","openPredicates","linkActions","mouseEventTimer","upEventLast","virtualClickEventTimer","moveEventCount","downEventHandler","timeStamp","preventDefault","upEventHandler","info","closeInfoPanel","showPinAnimation","startSize","endSize","startOpacity","endOpacity","animate","pin","innerD","drag","origin","sourceEvent","fixedBeforeDrag","isBeingDragged","beginDragging","px","py","pinWasFixed","resume","menuEvents","closeIcon","expandIcon","focusIcon","copyURIIcon","removeIcons","alpha","initIcons","expandNodeIcons","thisTipElement","showTipForNode","hideNode","shiftKey","updateTipForNode","nodeLabels","insert","fontSize","label","textContent","endlessLoopGuard","scrollHeight","clientHeight","scrollWidth","clientWidth","updateNodeLabels","geom","quadtree","sourceX","targetX","sourceY","targetY","linkedNodes","p1","p2","atan2","PI","angleDeg","abs","findAngleBetweenNodes","sourceId","targetId","twoWayLinkID","textNode","createTextNode","lastChild","start","getPositionAndAngle","angle","cos","sin","collapseIcon","actionsTip","expandedState","right","isExpanded","getAttribute","animateMenu","delay","ease","ctrlKey","metaKey","initGraph","renderGraphFromResponse","isStartNode","linksFound","newLink","existingLink","linksCopy","tripleLinksIt","values","nodesFromLinks","array","distinctBy","union","existingNodes","Boolean","tripleNodesIt","newNodes","some","promises","newNodesData","newNode","res","all","newNodeData","theta","expandIri","nodeTypes","nodeIri","resourceType","encodedIri","encodeURI","rdfsLabel","rdfsComment","comment","expanded","dataNodeKeysQuery","mapKeys","nodeImage","imageVal","updatePredicatesColor","getElementsByClassName","linkLink","stroke","strokeWidth","markers","marker","markerLink","setAttribute","className","color","preds","predLink","fill","oppLinkIRI","oppTriplePred","currEl","fontWeight","shortIRI","toggleSidePanel","clickLink","predData","clickedEl","every","linkPred","splitPredicate","isLoadingLocation","hasActiveLocation","rotate","isLeft","pivotX","pivotY","noHistory","saveOrUpdateGraph","graphToSave","saveGraphModal","renameSavedGraph","graphToRename","editSavedGraphHttp","editSavedGraph","mode","graphExists","open","templateUrl","controller","resolve","restart","addNewSavedGraph","status","saveGraphHttp","getSavedGraphs","savedGraphs","graphToLoad","owner","copyToClipboardSavedGraph","location","protocol","host","pathname","deleteSavedGraph","graphName","deleteSavedGraphHttp","openIRI","togglePinAllNodes","nodeName","keyCode","getLiteralFromPropValue","SaveGraphModalCtrl","$modalInstance","okButtonText","ok","form","$valid","close","saveNew","dismiss","module","$tooltipProvider","options","appendToBody","$inject"],"mappings":"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","file":"25.9e0925889b3a3f79c7fe.bundle.js","sourcesContent":["// d3.tip\n// Copyright (c) 2013 Justin Palmer\n//\n// Tooltips for d3.js SVG visualizations\n\n(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module with d3 as a dependency.\n define([], factory)\n } else if (typeof module === 'object' && module.exports) {\n // CommonJS\n module.exports = function(d3) {\n d3.tip = factory(d3)\n return d3.tip\n }\n } else {\n // Browser global.\n root.d3.tip = factory(root.d3)\n }\n}(this, function () {\n // Public - contructs a new tooltip\n //\n // Returns a tip\n return function() {\n var direction = d3_tip_direction,\n offset = d3_tip_offset,\n html = d3_tip_html,\n node = initNode(),\n svg = null,\n point = null,\n target = null,\n customPosition = null\n\n function tip(vis) {\n svg = getSVGNode(vis)\n point = svg.createSVGPoint()\n document.body.appendChild(node)\n }\n\n // Public - show the tooltip on the screen\n //\n // Returns a tip\n tip.show = function() {\n var args = Array.prototype.slice.call(arguments)\n if(args[args.length - 1] instanceof SVGElement) target = args.pop()\n\n var content = html.apply(this, args),\n poffset = offset.apply(this, args),\n dir = direction.apply(this, args),\n nodel = getNodeEl(),\n i = directions.length,\n coords,\n scrollTop = document.documentElement.scrollTop || document.body.scrollTop,\n scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft,\n customPos = customPosition.apply(this, args)\n\n nodel.html(content)\n .style({ opacity: 1, 'pointer-events': 'all' })\n\n while(i--) nodel.classed(directions[i], false)\n coords = direction_callbacks.get(dir).apply(this)\n\n if (customPos) {\n nodel.style(customPos)\n } else {\n nodel.classed(dir, true).style({\n top: (coords.top + poffset[0]) + scrollTop + 'px',\n left: (coords.left + poffset[1]) + scrollLeft + 'px'\n })\n }\n\n return tip\n }\n\n // Public - hide the tooltip\n //\n // Returns a tip\n tip.hide = function() {\n var nodel = getNodeEl()\n nodel.style({ opacity: 0, 'pointer-events': 'none' })\n return tip\n }\n\n // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.\n //\n // n - name of the attribute\n // v - value of the attribute\n //\n // Returns tip or attribute value\n tip.attr = function(n, v) {\n if (arguments.length < 2 && typeof n === 'string') {\n return getNodeEl().attr(n)\n } else {\n var args = Array.prototype.slice.call(arguments)\n d3.selection.prototype.attr.apply(getNodeEl(), args)\n }\n\n return tip\n }\n\n // Public: Proxy style calls to the d3 tip container. Sets or gets a style value.\n //\n // n - name of the property\n // v - value of the property\n //\n // Returns tip or style property value\n tip.style = function(n, v) {\n if (arguments.length < 2 && typeof n === 'string') {\n return getNodeEl().style(n)\n } else {\n var args = Array.prototype.slice.call(arguments)\n d3.selection.prototype.style.apply(getNodeEl(), args)\n }\n\n return tip\n }\n\n // Public: Set or get the direction of the tooltip\n //\n // v - One of n(north), s(south), e(east), or w(west), nw(northwest),\n // sw(southwest), ne(northeast) or se(southeast)\n //\n // Returns tip or direction\n tip.direction = function(v) {\n if (!arguments.length) return direction\n direction = v == null ? v : d3.functor(v)\n\n return tip\n }\n\n // Public: Sets or gets the offset of the tip\n //\n // v - Array of [x, y] offset\n //\n // Returns offset or\n tip.offset = function(v) {\n if (!arguments.length) return offset\n offset = v == null ? v : d3.functor(v)\n\n return tip\n }\n\n // Public: sets or gets the html value of the tooltip\n //\n // v - String value of the tip\n //\n // Returns html value or tip\n tip.html = function(v) {\n if (!arguments.length) return html\n html = v == null ? v : d3.functor(v)\n\n return tip\n }\n\n tip.customPosition = function(v) {\n if (!arguments.length) return customPosition\n customPosition = v == null ? v : d3.functor(v)\n\n return tip\n }\n\n // Public: destroys the tooltip and removes it from the DOM\n //\n // Returns a tip\n tip.destroy = function() {\n if(node) {\n getNodeEl().remove();\n node = null;\n }\n return tip;\n }\n\n function d3_tip_direction() { return 'n' }\n function d3_tip_offset() { return [0, 0] }\n function d3_tip_html() { return ' ' }\n\n var direction_callbacks = d3.map({\n n: direction_n,\n s: direction_s,\n e: direction_e,\n w: direction_w,\n nw: direction_nw,\n ne: direction_ne,\n sw: direction_sw,\n se: direction_se\n }),\n\n directions = direction_callbacks.keys()\n\n function direction_n() {\n var bbox = getScreenBBox()\n return {\n top: bbox.n.y - node.offsetHeight,\n left: bbox.n.x - node.offsetWidth / 2\n }\n }\n\n function direction_s() {\n var bbox = getScreenBBox()\n return {\n top: bbox.s.y,\n left: bbox.s.x - node.offsetWidth / 2\n }\n }\n\n function direction_e() {\n var bbox = getScreenBBox()\n return {\n top: bbox.e.y - node.offsetHeight / 2,\n left: bbox.e.x\n }\n }\n\n function direction_w() {\n var bbox = getScreenBBox()\n return {\n top: bbox.w.y - node.offsetHeight / 2,\n left: bbox.w.x - node.offsetWidth\n }\n }\n\n function direction_nw() {\n var bbox = getScreenBBox()\n return {\n top: bbox.nw.y - node.offsetHeight,\n left: bbox.nw.x - node.offsetWidth\n }\n }\n\n function direction_ne() {\n var bbox = getScreenBBox()\n return {\n top: bbox.ne.y - node.offsetHeight,\n left: bbox.ne.x\n }\n }\n\n function direction_sw() {\n var bbox = getScreenBBox()\n return {\n top: bbox.sw.y,\n left: bbox.sw.x - node.offsetWidth\n }\n }\n\n function direction_se() {\n var bbox = getScreenBBox()\n return {\n top: bbox.se.y,\n left: bbox.e.x\n }\n }\n\n function initNode() {\n var node = d3.select(document.createElement('div'))\n node.style({\n position: 'absolute',\n top: 0,\n opacity: 0,\n 'pointer-events': 'none',\n 'box-sizing': 'border-box'\n })\n\n return node.node()\n }\n\n function getSVGNode(el) {\n el = el.node()\n if(el.tagName.toLowerCase() === 'svg')\n return el\n\n return el.ownerSVGElement\n }\n\n function getNodeEl() {\n if(node === null) {\n node = initNode();\n // re-add node to DOM\n document.body.appendChild(node);\n };\n return d3.select(node);\n }\n\n // Private - gets the screen coordinates of a shape\n //\n // Given a shape on the screen, will return an SVGPoint for the directions\n // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),\n // sw(southwest).\n //\n // +-+-+\n // | |\n // + +\n // | |\n // +-+-+\n //\n // Returns an Object {n, s, e, w, nw, sw, ne, se}\n function getScreenBBox() {\n var targetel = target || d3.event.target;\n\n while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) {\n targetel = targetel.parentNode;\n }\n\n var bbox = {},\n matrix = targetel.getScreenCTM(),\n tbbox = targetel.getBBox(),\n width = tbbox.width,\n height = tbbox.height,\n x = tbbox.x,\n y = tbbox.y\n\n point.x = x\n point.y = y\n bbox.nw = point.matrixTransform(matrix)\n point.x += width\n bbox.ne = point.matrixTransform(matrix)\n point.y += height\n bbox.se = point.matrixTransform(matrix)\n point.x -= width\n bbox.sw = point.matrixTransform(matrix)\n point.y -= height / 2\n bbox.w = point.matrixTransform(matrix)\n point.x += width\n bbox.e = point.matrixTransform(matrix)\n point.x -= width / 2\n point.y -= height / 2\n bbox.n = point.matrixTransform(matrix)\n point.y += height\n bbox.s = point.matrixTransform(matrix)\n\n return bbox\n }\n\n return tip\n };\n\n}));","var D3 = D3 || {};\n\nD3.Text = function () {\n function calcFontSizeRaw(text, radius, minimumSize, isMultiline) {\n minimumSize = minimumSize || 10;\n\n var textSize = radius / 3;\n if (typeof text === \"string\") {\n var len = text.substring(0, radius / 3).length + 1.5;\n textSize *= 10 / len;\n textSize += 1;\n // experimental alternative method:\n // var textSize = 3.3 * radius / text.length;\n\n // Tweak for Indian scripts and CJK ones\n if (text.match(/[\\u0900-\\u0DFF\\u1100-\\u11FF\\u2E80-\\u2EFF\\u3000-\\u9FFF]/)) {\n textSize *= 0.6;\n }\n\n if (textSize < minimumSize) {\n textSize = minimumSize;\n }\n\n /* Disabled for the time being, better without this\n if (isMultiline) {\n var numWords = text.split(/\\s+/).length;\n if (numWords > 1) {\n if (numWords > 4) {\n numWords = 4;\n }\n textSize += textSize * (4 - numWords) * 0.1;\n }\n }\n */\n\n return Math.round(textSize);\n }\n\n if (textSize < minimumSize) {\n textSize = minimumSize;\n }\n\n return Math.round(textSize);\n }\n\n function calcFontSize(text, radius, minimumSize, isMultiline) {\n return calcFontSizeRaw(text, radius, minimumSize, isMultiline) + 'px';\n }\n\n function getTextWithElipsisIfNeeded(str, threshold) {\n if (typeof str === \"string\") {\n if (str.length > threshold) {\n return str.substring(0, threshold - 3) + \"...\";\n }\n }\n return str;\n }\n\n return {\n calcFontSizeRaw: calcFontSizeRaw,\n calcFontSize: calcFontSize,\n getTextWithElipsisIfNeeded: getTextWithElipsisIfNeeded\n };\n}();\n\nD3.Transition = function () {\n function fadeIn(sel, duration) {\n sel.style(\"opacity\", 0.0)\n .transition()\n .duration(duration)\n .style(\"opacity\", 1.0);\n }\n\n function fadeOut(sel, duration) {\n sel.style(\"opacity\", 1.0)\n .transition()\n .duration(duration)\n .style(\"opacity\", 0.0);\n }\n\n return {\n fadeIn: fadeIn,\n fadeOut: fadeOut\n };\n}();\n\nD3.Click = function () {\n function delayDblClick() {\n var event = d3.dispatch('click', 'dblclick');\n\n function cc(selection) {\n var down,\n tolerance = 5,\n last,\n wait = null;\n\n // euclidean distance\n function dist(a, b) {\n return Math.sqrt(Math.pow(a[0] - b[0], 2), Math.pow(a[1] - b[1], 2));\n }\n\n selection.on('mousedown', function () {\n down = d3.mouse(document.body);\n last = +new Date();\n });\n selection.on('mouseup', function (d) {\n if (dist(down, d3.mouse(document.body)) > tolerance) {\n return;\n } else {\n if (wait) {\n window.clearTimeout(wait);\n wait = null;\n event.dblclick(d);\n } else {\n wait = window.setTimeout((function (e) {\n return function () {\n event.click(d);\n wait = null;\n };\n })(d3.event), 250);\n }\n }\n });\n }\n\n return d3.rebind(cc, event, 'on');\n }\n\n return {\n delayDblClick: delayDblClick\n };\n}();\n\nexport default D3;\n","export const STATIC_RULESETS = [\n {id: 'empty', name: 'No inference'},\n {id: 'rdfs-optimized', name: 'RDFS (Optimized)'},\n {id: 'rdfs', name: 'RDFS'},\n {id: 'rdfsplus-optimized', name: 'RDFS-Plus (Optimized)'},\n {id: 'owl-horst-optimized', name: 'OWL-Horst (Optimized)'},\n {id: 'owl-horst', name: 'OWL-Horst'},\n {id: 'owl2-ql-optimized', name: 'OWL2-QL (Optimized)'},\n {id: 'owl2-ql', name: 'OWL2-QL'},\n {id: 'owl-max-optimized', name: 'OWL-Max (Optimized)'},\n {id: 'owl-max', name: 'OWL-Max'},\n {id: 'owl2-rl-optimized', name: 'OWL2-RL (Optimized)'},\n {id: 'owl2-rl', name: 'OWL2-RL'},\n\n];\n\nexport const REPOSITORY_TYPES = {graphdbRepo: 'graphdb', free: 'free', eeWorker: 'worker', eeMaster: 'master', ontop: 'ontop', se: 'se', fedx: 'fedx'};\nexport const FILENAME_PATTERN = new RegExp('^[a-zA-Z0-9-_]+$');\nexport const NUMBER_PATTERN = new RegExp('^[0-9]+$');\n","import 'angular/core/services';\nimport D3 from 'lib/common/d3-utils.js';\nimport d3tip from 'lib/d3-tip/d3-tip-patch';\nimport 'angular/utils/local-storage-adapter';\nimport {NUMBER_PATTERN} from \"../../repositories/repository.constants\";\n\nconst modules = [\n 'ui.scroll.jqlite',\n 'ui.scroll',\n 'toastr',\n 'ui.bootstrap',\n 'ngTagsInput',\n 'graphdb.framework.utils.localstorageadapter'\n];\n\nangular\n .module('graphdb.framework.graphexplore.controllers.graphviz', modules)\n .controller('GraphsVisualizationsCtrl', GraphsVisualizationsCtrl)\n .controller('SaveGraphModalCtrl', SaveGraphModalCtrl)\n .config(['$tooltipProvider', function ($tooltipProvider) {\n $tooltipProvider.options({appendToBody: true});\n }]);\n\nGraphsVisualizationsCtrl.$inject = [\"$scope\", \"$rootScope\", \"$repositories\", \"$licenseService\", \"toastr\", \"$timeout\", \"$http\", \"ClassInstanceDetailsService\", \"AutocompleteRestService\", \"$q\", \"$location\", \"$jwtAuth\", \"UiScrollService\", \"ModalService\", \"$modal\", \"$window\", \"LocalStorageAdapter\", \"LSKeys\", \"SavedGraphsRestService\", \"GraphConfigRestService\", \"RDF4JRepositoriesRestService\", \"$translate\"];\n\nfunction GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseService, toastr, $timeout, $http, ClassInstanceDetailsService, AutocompleteRestService, $q, $location, $jwtAuth, UiScrollService, ModalService, $modal, $window, LocalStorageAdapter, LSKeys, SavedGraphsRestService, GraphConfigRestService, RDF4JRepositoriesRestService, $translate) {\n\n $scope.languageChanged = false;\n $scope.propertiesObj = {};\n $scope.propertiesQueryObj = {};\n\n $scope.propertiesObj.items = [];\n $scope.propertiesNotFiltered = [];\n $scope.searchVisible = false;\n $scope.nodeSelected = false;\n $scope.queryResultsMode = false;\n $scope.embedded = $location.search().embedded;\n $scope.openedNodeInfoPanel = undefined;\n\n $scope.invalidLimit = false;\n $scope.INVALID_LINKS_MSG = $translate.instant('sidepanel.invalid.limit.links.msg');\n $scope.INVALID_LINKS_TOOLTIP = $translate.instant('sidepanel.invalid.limit.links.tooltip');\n\n $rootScope.$on('$translateChangeSuccess', function () {\n $scope.INVALID_LINKS_MSG = $translate.instant('sidepanel.invalid.limit.links.msg');\n $scope.INVALID_LINKS_TOOLTIP = $translate.instant('sidepanel.invalid.limit.links.tooltip');\n $scope.propertiesSearchPlaceholder = $translate.instant(\"visual.search.instance.placeholder\");\n });\n\n // Handle pageslide directive callbacks which incidentally appeared to be present in the angular's\n // scope, so we need to define our's and pass them to pageslide, otherwise it throws an error.\n $scope.onopen = $scope.onclose = () => angular.noop();\n\n // embedded and other params when the controller is initialized\n if ($scope.embedded && ($location.search().query ||\n $location.search().uri ||\n $location.search().config ||\n $location.search().saved)) {\n\n $scope.noGoHome = true;\n }\n\n // creating datasource for class properties data\n const datasource = {};\n let position = 0;\n let current = 0;\n let type2color = {};\n let colorIndex = 0;\n const nodeLabelMinFontSize = 16; // pixels\n // define zoom and drag behavior; keep this out of draw() to preserve state when nodes are added/removed\n const panAndZoom = d3.behavior.zoom()\n .scaleExtent([0.5, 10]);\n let transformValues;\n // build svg element\n const width = 1000;\n const height = 1000;\n let tipElement;\n let openedLink;\n\n $rootScope.key = \"\";\n\n datasource.get = function (index, count, success) {\n return UiScrollService.initLazyList(index, count, success, position, $scope.propertiesObj.items);\n };\n\n $rootScope.$watch(function () {\n return $rootScope.key;\n }, function () {\n position = 0;\n _.each($scope.propertiesObj.items, function (item) {\n if ($rootScope.key > item) {\n position++;\n }\n });\n current++;\n });\n\n datasource.revision = function () {\n return current;\n };\n\n $scope.datasource = datasource;\n\n // adapter implementation for ui-scroll directive\n $scope.adapterContainer = {adapter: {remain: true}};\n\n $scope.propertiesQueryObj.query = '';\n $scope.propertiesSearchPlaceholder = $translate.instant(\"visual.search.instance.placeholder\");\n $scope.propertiesFilterFunc = propertiesFilterFunc;\n\n $scope.resetState = function () {\n $scope.searchVisible = false;\n $scope.nodeSelected = false;\n $scope.configLoaded = null;\n $scope.queryResultsMode = false;\n $scope.lastSavedGraphName = null;\n $scope.lastSavedGraphId = null;\n $scope.shared = false;\n $scope.numberOfPinnedNodes = 0;\n\n // Reset type colours\n type2color = {};\n colorIndex = 0;\n };\n\n $scope.pushHistory = function (searchParams, state) {\n if ($scope.embedded) {\n searchParams.embedded = true;\n }\n $location.search(searchParams);\n $location.state(state);\n };\n\n $scope.goToHome = function () {\n $scope.resetState();\n $location.url(\"graphs-visualizations\");\n };\n\n $scope.shouldShowSettings = function () {\n return $scope.configLoaded && $scope.configLoaded.id === $scope.defaultGraphConfig.id;\n };\n\n $scope.shouldDisableSameAs = function () {\n const sameAsCheckbox = $('#sameAsCheck');\n if ($scope.settings && !$scope.settings['includeInferred'] && sameAsCheckbox.prop('checked')) {\n sameAsCheckbox.prop(\"checked\", false);\n $scope.settings['sameAsState'] = false;\n }\n\n return $scope.settings && !$scope.settings['includeInferred'];\n };\n\n function propertiesFilterFunc(item) {\n return item.key\n .toLowerCase()\n .indexOf($scope.propertiesQueryObj.query.toLowerCase()) >= 0;\n }\n\n $scope.$watch('propertiesObj.items', function () {\n if (angular.isDefined($scope.propertiesObj.items) && $scope.propertiesObj.items.length > 0) {\n $timeout(function () {\n $scope.adapterContainer.adapter.reload();\n }, 500);\n }\n });\n\n $scope.toggleMoreInfo = function (ev) {\n angular.element(ev.currentTarget).parent().next().toggle(200);\n angular.element(ev.currentTarget).children('span').toggleClass(\"icon-caret-down\").toggleClass(\"icon-caret-up\");\n };\n\n function updatePredicateLabels() {\n if (!$scope.saveSettings['showLinksText']) {\n d3.selectAll(\"svg .link-wrapper text\")\n .style(\"display\", \"none\");\n } else {\n d3.selectAll(\"svg .link-wrapper text\")\n .style(\"display\", \"block\");\n }\n }\n\n function updateNodeLabels(nodeLabels) {\n nodeLabels.each(function (d) {\n d.fontSize = D3.Text.calcFontSizeRaw(d.labels[0].label, d.size, nodeLabelMinFontSize, true);\n // TODO: get language and set it on the label html tag\n })\n .attr(\"height\", function (d) {\n return d.fontSize * 3;\n })\n // if this was kosher we would use xhtml:body here but if we do that angular (or the browser)\n // goes crazy and resizes/messes up other unrelated elements. div seems to work too.\n .append(\"xhtml:div\")\n .attr(\"class\", \"node-label-body\")\n .style(\"font-size\", function (d) {\n return d.fontSize + 'px';\n })\n .append('xhtml:div')\n .text(function (d) {\n return d.labels[0].label;\n });\n\n // Our own implementation of what browsers should really do but they either can't or don't do properly.\n // This code will look at each node's label element and check if the text fits. This is achieved by\n // checking the DOM properties scrollHeight/-Width and clientHeight/-Width. Generally if the scroll ones\n // are bigger than the client ones the content doesn't fit.\n $timeout(function () {\n $('.node-label-body div').each(function (i, e) {\n // Initial text is minus one character as we'll be adding a one-character suffix if we need to truncate\n let text = e.textContent.substring(0, e.textContent.length - 1);\n const suffixToInsert = '…';\n let endlessLoopGuard = 0;\n\n // Loop until the text fits\n while (endlessLoopGuard < 200 && (e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth)) {\n // Take previous text minus one character\n text = text.substring(0, text.length - 1);\n\n // Set the new text + suffix as textContent\n e.textContent = text + suffixToInsert;\n\n endlessLoopGuard++;\n }\n });\n }, 50);\n }\n\n $scope.copyToClipboard = copyToClipboard;\n\n function copyToClipboard(uri) {\n ModalService.openCopyToClipboardModal(uri);\n }\n\n $scope.defaultSettings = {\n linksLimit: 20,\n includeInferred: true,\n sameAsState: true,\n languages: ['en'],\n showLinksText: true,\n preferredTypes: [],\n rejectedTypes: [],\n preferredPredicates: [],\n rejectedPredicates: [\"http://dbpedia.org/property/logo\",\n \"http://dbpedia.org/property/hasPhotoCollection\",\n \"http://dbpedia.org/property/website\",\n \"http://dbpedia.org/property/homepage\",\n \"http://dbpedia.org/ontology/thumbnail\",\n \"http://xmlns.com/foaf/0.1/depiction\",\n \"http://xmlns.com/foaf/0.1/homepage\",\n \"http://xmlns.com/foaf/0.1/mbox\",\n \"http://dbpedia.org/ontology/wikiPage*\",\n \"http://dbpedia.org/property/wikiPage*\",\n \"http://factforge.net/*\"],\n preferredTypesOnly: false,\n preferredPredicatesOnly: false,\n includeSchema: true\n };\n // Static defaults before we do the actual dynamic default settings in initSettings\n $scope.saveSettings = angular.copy($scope.defaultSettings);\n\n function initSettings(principal) {\n const settingsFromPrincipal = principal.appSettings;\n\n // New style settings from principal\n $scope.defaultSettings.includeInferred = settingsFromPrincipal['DEFAULT_INFERENCE'];\n $scope.defaultSettings.sameAsState = settingsFromPrincipal['DEFAULT_INFERENCE'] && settingsFromPrincipal['DEFAULT_SAMEAS'];\n $scope.defaultSettings.includeSchema = settingsFromPrincipal['DEFAULT_VIS_GRAPH_SCHEMA'];\n\n const localStorageSettings = LocalStorageAdapter.get(LSKeys.GRAPHS_VIZ);\n if (localStorageSettings && typeof localStorageSettings === 'object') {\n // Patch existing settings\n try {\n $scope.saveSettings = localStorageSettings;\n if ($scope.saveSettings['includeSchema'] === undefined) {\n // Add the new defaults when migrating from an old GDB\n $scope.saveSettings['includeSchema'] = $scope.defaultSettings['includeSchema'];\n $scope.saveSettings['rejectedPredicates'] = [...$scope.saveSettings['rejectedPredicates'], ...$scope.defaultSettings['rejectedPredicates']].unique();\n }\n } catch (e) {\n $scope.saveSettings = angular.copy($scope.defaultSettings);\n LocalStorageAdapter.set(LSKeys.GRAPHS_VIZ, $scope.saveSettings);\n }\n } else {\n $scope.saveSettings = angular.copy($scope.defaultSettings);\n }\n }\n\n // Using $q.when to proper set values in view\n $q.when($jwtAuth.getPrincipal())\n .then((principal) => initSettings(principal));\n\n function renderSettings() {\n $scope.settings.languagesMap = _.map($scope.settings.languages, function (v) {\n return {'text': v};\n });\n\n $scope.settings.preferredTypesMap = _.map($scope.settings.preferredTypes, function (v) {\n return {'text': v};\n });\n\n $scope.settings.rejectedTypesMap = _.map($scope.settings.rejectedTypes, function (v) {\n return {'text': v};\n });\n\n $scope.settings.preferredPredicatesMap = _.map($scope.settings.preferredPredicates, function (v) {\n return {'text': v};\n });\n\n $scope.settings.rejectedPredicatesMap = _.map($scope.settings.rejectedPredicates, function (v) {\n return {'text': v};\n });\n }\n\n $scope.resetSettings = function () {\n $scope.settings = angular.copy($scope.defaultSettings);\n $scope.validateLinksLimit();\n renderSettings();\n };\n\n $scope.changeLimit = function (delta) {\n let linksLimit = $scope.settings.linksLimit + delta;\n if (linksLimit < 1) {\n linksLimit = 1;\n }\n if (linksLimit > 1000) {\n linksLimit = 1000;\n }\n $scope.settings.linksLimit = linksLimit;\n };\n\n $scope.validateLinksLimit = function () {\n $scope.invalidLimit = !NUMBER_PATTERN.test($scope.settings.linksLimit);\n }\n\n $scope.showSettings = function () {\n $scope.showInfoPanel = true;\n $scope.showFilter = true;\n $scope.showNodeInfo = false;\n $scope.showPredicates = false;\n if (!$scope.saveSettings) {\n $scope.settings = angular.copy($scope.defaultSettings);\n } else {\n $scope.settings = angular.copy($scope.saveSettings);\n }\n renderSettings();\n };\n\n $scope.reExpandNode = function () {\n if ($scope.rootNodeIri) {\n $scope.$broadcast(\"onRootNodeChange\", $scope.rootNodeIri);\n }\n };\n\n const loadGraphForQuery = function (queryString, sameAsParam, inferredParam) {\n const sendSameAs = (sameAsParam === undefined) ? ($scope.saveSettings['sameAsState']) : sameAsParam === true;\n const sendInferred = (inferredParam === undefined) ? ($scope.saveSettings['includeInferred']) : inferredParam === true;\n $scope.loading = true;\n $http({\n url: 'rest/explore-graph/graph',\n method: 'POST',\n headers: {\n 'Content-Type' : 'application/json'\n },\n data: {\n query: queryString,\n linksLimit: $scope.saveSettings['linksLimit'],\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n includeInferred: sendInferred,\n sameAsState: sendSameAs\n }\n }).then(function (response) {\n // Node draw will turn off loader\n initGraphFromResponse(response);\n }, function (response) {\n $scope.loading = false;\n toastr.error(getError(response.data), $translate.instant('graphexplore.error.cannot.load.graph'));\n });\n };\n\n $scope.updateSettings = function () {\n if ($scope.invalidLimit) {\n toastr.error($scope.INVALID_LINKS_TOOLTIP, $scope.INVALID_LINKS_MSG);\n return;\n }\n $scope.saveSettings = $scope.settings;\n $scope.saveSettings.languages = _.map($scope.saveSettings['languagesMap'], function (s) {\n return s['text'];\n });\n\n $scope.saveSettings.preferredTypes = _.map($scope.saveSettings['preferredTypesMap'], function (t) {\n return t['text'];\n });\n $scope.saveSettings.rejectedTypes = _.map($scope.saveSettings['rejectedTypesMap'], function (t) {\n return t['text'];\n });\n\n $scope.saveSettings.preferredPredicates = _.map($scope.saveSettings['preferredPredicatesMap'], function (t) {\n return t['text'];\n });\n $scope.saveSettings.rejectedPredicates = _.map($scope.saveSettings['rejectedPredicatesMap'], function (t) {\n return t['text'];\n });\n\n // TODO\n // reexpand root node\n if ($scope.rootNodeIri) {\n $scope.reExpandNode($scope.rootNodeIri);\n } else if ($scope.queryResultsMode && $location.search().query) {\n loadGraphForQuery($location.search().query,\n $location.search().sameAs,\n $location.search().inference);\n } else if ($scope.configLoaded.startMode === 'query') {\n $scope.loadGraphConfig($scope.configLoaded);\n }\n\n updatePredicateLabels();\n\n $scope.showInfoPanel = false;\n $scope.showFilter = false;\n\n LocalStorageAdapter.set(LSKeys.GRAPHS_VIZ, $scope.saveSettings);\n };\n\n $scope.showInfoPanel = false;\n\n /**\n * Removes brackets and serial commas from IRIs\n * when used to create ids for links and markers,\n * because elements with ids that contain such\n * are not valid XHTML and cause a host problems\n * when trying to style individual elements\n * @param string\n * @returns {*}\n */\n function removeSpecialChars(string) {\n return string.replace(/[()']/g, \"\");\n }\n\n /**\n * Converts triple to link id or generates unique id (needed for arrows)\n * @param triple\n * @param tripleLike\n * @returns {string}\n */\n function convertTripleToLinkId(triple, tripleLike) {\n let tripleParts = triple.split(' ');\n if (tripleLike) {\n return [tripleParts[0], tripleParts[1], tripleParts[2]].join('>');\n }\n return [tripleParts[0], tripleParts[2]].join('>');\n }\n\n function convertLinkDataToLinkId(link) {\n return [link.source.iri, link.target.iri].join('>');\n }\n\n /**\n * If source or target of a link is a triple returns a x\n * for the link, otherwise returns this of the node.\n * Because tick is called before links are created we return node's x,\n * which afterwards will be overridden\n * @param node\n * @returns {number|number|*}\n */\n function getNodeX(node) {\n if (node.isTriple) {\n let el = document.getElementById(removeSpecialChars(convertTripleToLinkId(node.iri)));\n if (el && typeof el.__data__.x !== \"undefined\") {\n return el.__data__.x;\n }\n }\n return node.x;\n }\n\n /**\n * If source or target of a link is a triple returns a y\n * for the link, otherwise returns this of the node.\n * Because tick is called before links are created we return node's y,\n * which afterwards will be overridden\n * @param node\n * @returns {number|number|*}\n */\n function getNodeY(node) {\n if (node.isTriple) {\n let el = document.getElementById(removeSpecialChars(convertTripleToLinkId(node.iri)));\n if (el && typeof el.__data__.y !== \"undefined\") {\n return el.__data__.y;\n }\n }\n return node.y;\n }\n\n function createTriple(value) {\n let tripleParts = value.trim().split(' ');\n return `<<<${tripleParts[0]}> <${tripleParts[1]}> <${tripleParts[2]}>>>`;\n }\n\n /**\n * Creates unique arrow-marker id will allow change color and refX for particular one\n * @param d\n * @returns {string}\n */\n function createArrowMarkerUniqueID(d) {\n let source = d.source.isTriple ? convertTripleToLinkId(d.source.iri, true) : d.source.iri;\n let target = d.target.isTriple ? convertTripleToLinkId(d.target.iri, true) : d.target.iri;\n return removeSpecialChars(`${source}>${target}>marker`);\n }\n\n /**\n * Filters nodes array on a given field\n * @param iri\n * @param array\n * @returns {*}\n */\n function distinctBy(iri, array) {\n let keys = array.map(function (value) { return value[iri]; });\n return array.filter(function (value, index) { return keys.indexOf(value[iri]) === index; });\n }\n\n function Graph() {\n this.nodes = [];\n this.links = [];\n this.tripleNodes = new Map();\n this.tripleLinksCopy = new Map();\n\n this.addNode = function (node, x, y) {\n node.x = x;\n node.y = y;\n this.nodes.push(node);\n return node;\n };\n\n // computes a \"connectedness\" metric on each link, which is then used to hint for longer links.\n // this results in improved clustering and appearance.\n this.computeConnectedness = function () {\n // count the the number of times a given node is connected to other nodes\n // (only for nodes connected to more than one node)\n const counts = {};\n const seenLinks = {};\n _.each(this.links, function (link) {\n const i1 = link.source.iri;\n const i2 = link.target.iri;\n const seenKey = _.min([i1, i2]) + \"|\" + _.max([i1, i2]);\n if (!seenLinks[seenKey]) {\n seenLinks[seenKey] = 1;\n counts[i1] = (counts[i1] || 0) + 1;\n counts[i2] = (counts[i2] || 0) + 1;\n }\n });\n\n // computes the connectedness of each link based on the number of times its nodes were connected\n // (only for links to/from nodes connected to more than one node)\n _.each(this.links, function (link) {\n if (counts[link.source.iri] > 1 && counts[link.target.iri] > 1) {\n link.connectedness = Math.min(5, Math.max(counts[link.source.iri], counts[link.target.iri]) - 1);\n } else {\n link.connectedness = 0;\n }\n });\n };\n\n this.addAndMatchLinks = function (newLinks) {\n const nodes = this.nodes;\n Array.prototype.push.apply(this.links, matchLinksToNodes(newLinks, nodes));\n for (let key of graph.tripleLinksCopy.keys()) {\n if (graph.tripleLinksCopy.get(key).length === 1) {\n graph.tripleLinksCopy.delete(key);\n }\n }\n this.links = this.links.filter(link => link !== null);\n this.computeConnectedness();\n };\n\n const countLinks = function (d, links) {\n return findLinksForNode(d, links).length;\n };\n\n this.countLinks = countLinks;\n\n function findLinksForNode(d, links) {\n return _.filter(links, function (l) {\n return l.source.iri === d.iri || l.target.iri === d.iri;\n });\n }\n\n function linksTypes(d, links) {\n const linksForNode = findLinksForNode(d, links);\n const types = _.map(linksForNode, function (l) {\n return (l.source.iri === d.iri ) ? l.target.types : l.source.types;\n });\n return _.uniq(_.flatten(types));\n }\n\n function linksPredicates(d, links) {\n const linksForNode = findLinksForNode(d, links);\n const predicates = _.map(linksForNode, function (l) {\n return l.predicates;\n });\n return _.uniq(_.flatten(predicates));\n }\n\n this.linksTypes = linksTypes;\n\n this.linksPredicates = linksPredicates;\n\n /**\n * Removes generated triple links and related nodes\n * @param triplesToRemove\n */\n this.removeTriples = function (triplesToRemove) {\n let targetTriples = [];\n if (this.tripleNodes.size > 0) {\n triplesToRemove.forEach((source) => {\n if (this.tripleNodes.has(source)) {\n this.tripleNodes.delete(source);\n this.links = _.reject(this.links, function (l) {\n let sourceSplit = source.split('>');\n let lSource = convertTripleToLinkId(l.source.iri);\n let lTarget = convertTripleToLinkId(l.target.iri);\n // Handle triple targets\n if (lSource === source && graph.tripleNodes.delete(lTarget)) {\n let targetSplit = lTarget.split('>');\n targetTriples.push({\n source: targetSplit[0],\n target: targetSplit[1]\n });\n }\n let isRejected = lSource === source || lTarget === source || (l.source.iri === sourceSplit[0] && l.target.iri === sourceSplit[1]);\n if (isRejected) {\n graph.tripleLinksCopy.delete(`${lSource}>${lTarget}`);\n graph.tripleLinksCopy.delete(`${lTarget}>${lSource}`);\n }\n return isRejected;\n });\n }\n });\n }\n\n // This step is needed for removing artificially created links representing triples\n targetTriples.forEach((target) => {\n this.links = _.reject(this.links, function (l) {\n return l.source.iri === target.source && l.target.iri === target.target;\n });\n });\n }\n\n this.removeNode = function (d) {\n let triplesToRemove = [];\n this.links = _.reject(this.links, function (l) {\n let isRejected = l.source.iri === d.iri || l.target.iri === d.iri;\n if (isRejected) {\n if (l.target.isTriple) {\n triplesToRemove.push(convertTripleToLinkId(l.target.iri));\n }\n if (!l.source.isTriple && !l.target.isTriple) {\n triplesToRemove.push([l.source.iri, l.target.iri].join('>'))\n }\n }\n return isRejected;\n });\n\n this.removeTriples(triplesToRemove);\n\n const links = this.links;\n this.nodes = _.reject(this.nodes, function (n) {\n return countLinks(n, links) === 0;\n });\n if (this.nodes.length === 0) {\n $scope.nodeSelected = false;\n }\n\n this.computeConnectedness();\n };\n\n this.removeNodeLeafLinks = function (d) {\n let triplesToRemove = [];\n let links = this.links;\n this.links = _.reject(this.links, function (l) {\n let isRejected = (l.source.iri === d.iri && countLinks(l.target, links) === 1 && !l.target.isTriple) ||\n (l.target.iri === d.iri && countLinks(l.source, links) === 1 && !l.source.isTriple);\n if (!isRejected) {\n let targetLinks;\n if (l.source.iri === d.iri && countLinks(l.target, links) === 2 && !l.target.isTriple) {\n targetLinks = findLinksForNode(l.target, links);\n } else if (l.target.iri === d.iri && countLinks(l.source, links) === 2 && !l.source.isTriple) {\n targetLinks = findLinksForNode(l.source, links);\n }\n if (!targetLinks) {\n return false;\n }\n // the node to which (or from which) d has link to has only two links, check if the second one is to d also\n isRejected = (targetLinks[0].source.iri === d.iri || targetLinks[0].target.iri) &&\n (targetLinks[1].source.iri === d.iri || targetLinks[1].target.iri);\n }\n if (isRejected) {\n if (l.target.isTriple) {\n triplesToRemove.push(convertTripleToLinkId(l.target.iri));\n }\n if (!l.source.isTriple && !l.target.isTriple) {\n triplesToRemove.push([l.source.iri, l.target.iri].join('>'))\n }\n }\n return isRejected;\n });\n\n this.removeTriples(triplesToRemove);\n\n links = this.links;\n this.nodes = _.reject(this.nodes, function (n) {\n return countLinks(n, links) === 0 && n.iri !== d.iri;\n });\n\n this.computeConnectedness();\n };\n\n this.addTriple = function (triple, x, y) {\n triple.x = x;\n triple.y = y;\n triple.weight = 0;\n let key = convertTripleToLinkId(triple.iri);\n if (!this.tripleNodes.has(key)) {\n triple.weight = 10;\n this.tripleNodes.set(key, [triple]);\n } else {\n let value = this.tripleNodes.get(key);\n value.push(triple);\n this.tripleNodes.set(key, value);\n }\n }\n\n function matchLinksToNodes(newLinks, nodes) {\n return _.map(newLinks, function (link) {\n let source;\n let target;\n if (link.isTripleSource) {\n source = getTripleNode(link.source);\n } else {\n source = _.find(nodes, function (o) {\n return o.iri === link.source;\n })\n }\n if (link.isTripleTarget) {\n target = getTripleNode(link.target);\n } else {\n target = _.find(nodes, function (o) {\n return o.iri === link.target;\n })\n }\n let matchedLink = {\n \"source\": source,\n \"target\": target,\n \"predicates\": link.predicates\n };\n // make copy of links with triples in them\n if (link.isTripleSource || link.isTripleTarget) {\n let sourceId = matchedLink.source.isTriple ? convertTripleToLinkId(matchedLink.source.iri) : matchedLink.source.iri;\n let targetId = matchedLink.target.isTriple ? convertTripleToLinkId(matchedLink.target.iri) : matchedLink.target.iri;\n let linkId = `${sourceId}>${targetId}`;\n if (graph.tripleLinksCopy.has(linkId)) {\n let value = graph.tripleLinksCopy.get(linkId);\n value[0].predicates.push(...matchedLink.predicates);\n value.push(matchedLink);\n graph.tripleLinksCopy.set(linkId, value);\n return null;\n } else {\n graph.tripleLinksCopy.set(linkId, [matchedLink]);\n }\n }\n return matchedLink;\n });\n }\n\n this.copyState = function () {\n const nodesCopy = _.map(this.nodes, function (node) {\n return {\n iri: node.iri,\n isTriple: node.isTriple,\n size: node.size,\n labels: angular.copy(node.labels),\n types: angular.copy(node.types),\n rdfRank: node.rdfRank,\n x: node.x,\n y: node.y,\n fixed: node.fixed\n };\n });\n\n const triplesCopy = JSON.stringify(Array.from(this.tripleNodes.entries()));\n const tripleLinksCopy = JSON.stringify(Array.from(this.tripleLinksCopy.entries()));\n\n const linksCopy = _.map(this.links, function (link) {\n return {\n source: link.source.iri,\n isTripleSource: link.source.isTriple,\n target: link.target.iri,\n isTripleTarget: link.target.isTriple,\n predicates: link.predicates\n };\n });\n\n return {\n nodes: nodesCopy,\n links: linksCopy,\n tripleNodes: triplesCopy,\n tripleLinksCopy: tripleLinksCopy,\n colorIndex: colorIndex,\n type2color: type2color,\n scale: panAndZoom.scale(),\n translate: panAndZoom.translate()\n };\n };\n\n this.restoreState = function (state) {\n $scope.nodeSelected = true;\n $scope.searchVisible = false;\n\n this.nodes = angular.copy(state.nodes);\n // check if triples exists is needed for old configs\n this.tripleNodes = state.tripleNodes ? new Map(JSON.parse(state.tripleNodes)) : new Map();\n this.links = [];\n this.addAndMatchLinks(state.links);\n this.tripleLinksCopy = state.tripleLinksCopy ? new Map(JSON.parse(state.tripleLinksCopy)) : new Map();\n\n _.each(this.nodes, function (d) {\n if (d.fixed) {\n $scope.numberOfPinnedNodes++;\n }\n });\n\n if (angular.isDefined(state.colorIndex) && angular.isDefined(state.type2color)) {\n colorIndex = state.colorIndex;\n type2color = angular.copy(state.type2color);\n }\n\n if (angular.isDefined(state.translate) && angular.isDefined(state.scale)) {\n transformValues = \"translate(\" + state.translate[0] + \", \" + state.translate[1] + \") scale(\" + state.scale + \")\";\n panAndZoom.translate(state.translate);\n panAndZoom.scale(state.scale);\n }\n\n draw();\n };\n }\n\n let graph = new Graph();\n\n $scope.defaultGraphConfig = {\n id: 'default',\n name: 'Easy graph',\n startMode: 'search'\n };\n\n // Graph Config\n $scope.getGraphConfigs = function (graphCallback) {\n GraphConfigRestService.getGraphConfigs()\n .success(function (data) {\n $scope.graphConfigs = data;\n if (graphCallback) {\n graphCallback();\n }\n }).error(function (data) {\n toastr.error(getError(data), $translate.instant('graphexplore.error.graph.configs.short.msg'));\n });\n };\n\n $scope.loadConfigForId = function (configId, successCallback) {\n if (configId === $scope.defaultGraphConfig.id) {\n $scope.loadGraphConfig($scope.defaultGraphConfig);\n } else {\n GraphConfigRestService.getConfig(configId)\n .success(function (data) {\n $scope.loadGraphConfig(data);\n successCallback();\n })\n .error(function (data) {\n toastr.error(getError(data), $translate.instant('graphexplore.error.could.not.load.config', {configId: configId}));\n });\n }\n };\n\n $scope.findConfigById = function (configId) {\n if (configId === $scope.defaultGraphConfig.id) {\n return $scope.defaultGraphConfig;\n }\n return $.grep($scope.graphConfigs, function (e) {\n return e.id === configId;\n })[0];\n };\n\n $scope.easyGraphSearch = function (iri) {\n $scope.configLoaded = $scope.defaultGraphConfig;\n $scope.openUri(iri);\n };\n\n $scope.loadGraphConfig = function (config) {\n $scope.configLoaded = config;\n if (config.startMode === 'search') {\n $scope.searchVisible = true;\n } else if (config.startMode === 'node' && config.startIRI) {\n $timeout(function () {\n $scope.openUri(config.startIRI, true);\n }, 0);\n } else if (config.startMode === 'query' && config.startGraphQuery) {\n $scope.loading = true;\n GraphConfigRestService.loadGraphForConfig(config, config.startQueryIncludeInferred, $scope.saveSettings['linksLimit'], config.startQuerySameAs)\n .then(function (response) {\n // Node drawing will turn off loader\n initGraphFromResponse(response);\n }, function (data) {\n $scope.loading = false;\n toastr.error(getError(data), $translate.instant('graphexplore.error.graph.load'));\n });\n }\n };\n\n $scope.deleteConfig = function (config) {\n ModalService.openSimpleModal({\n title: $translate.instant('common.confirm'),\n message: $translate.instant('graphexplore.delete.graph', {configName: config.name}),\n warning: true\n }).result\n .then(function () {\n GraphConfigRestService.deleteGraphConfig(config)\n .success(function () {\n $scope.getGraphConfigs();\n $scope.refreshSavedGraphs();\n }).error(function (data) {\n toastr.error(getError(data), $translate.instant('graphexplore.error.cannot.delete.config'));\n });\n });\n };\n\n $scope.goToGraphConfig = function (config) {\n $scope.pushHistory({config: config.id}, {config: config});\n $scope.resetState();\n $scope.loadGraphConfig(config);\n };\n\n $window.onpopstate = function (event) {\n $scope.resetState();\n\n if (event.state) {\n if (event.state.config) {\n $scope.loadGraphConfig(event.state.config);\n if (event.state.uri) {\n $scope.openUri(event.state.uri, true);\n }\n } else if (event.state.savedGraph) {\n $scope.loadSavedGraph(event.state.savedGraph, true);\n }\n }\n };\n\n const initGraphFromQueryParam = function () {\n // view sparql\n if ($location.search().query) {\n $scope.searchVisible = false;\n $scope.queryResultsMode = true;\n loadGraphForQuery($location.search().query,\n $location.search().sameAs,\n $location.search().inference);\n } else {\n // broadcasted event from view resource directive to take input value\n $scope.$on('onRootNodeChange', function (e, inputValue) {\n $scope.loading = true;\n if (angular.isDefined(inputValue)) {\n $scope.rootNodeIri = inputValue;\n $http({\n url: 'rest/explore-graph/node',\n method: 'GET',\n params: {\n iri: inputValue,\n config: $scope.configLoaded ? $scope.configLoaded.id : $scope.defaultGraphConfig.id,\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n includeInferred: $scope.saveSettings['includeInferred'],\n sameAsState: $scope.saveSettings['sameAsState']\n }\n }).then(function (response) {\n $scope.nodeSelected = true;\n $scope.searchVisible = false;\n if (response.data.types === null) {\n response.data.types = \"greyColor\";\n }\n graph = new Graph();\n const rootNode = graph.addNode(response.data, width / 2, height / 2);\n\n transformValues = \"translate(0, -70) scale(1)\";\n panAndZoom.translate([0, -70]);\n panAndZoom.scale(1);\n\n expandNode(rootNode, true);\n }).catch(function (err) {\n $scope.loading = false;\n toastr.error(getError(err), $translate.instant('graphexplore.error.could.not.load.graph'));\n });\n }\n });\n }\n\n if ($location.search().uri) {\n $scope.openUri($location.search().uri);\n }\n\n if ($location.search().saved) {\n SavedGraphsRestService.getSavedGraph($location.search().saved)\n .success(function (data) {\n $scope.loadSavedGraph(data);\n })\n .error(function (data) {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.could.not.open'));\n });\n }\n };\n\n const loadGraphFromQueryParam = function () {\n // view graph config\n if ($location.search().config) {\n $scope.loadConfigForId($location.search().config, initGraphFromQueryParam);\n } else if ($location.search().query || $location.search().uri) {\n $scope.loadGraphConfig($scope.defaultGraphConfig);\n initGraphFromQueryParam();\n } else {\n initGraphFromQueryParam();\n }\n };\n\n $scope.replaceIRIWithPrefix = function (iri) {\n const namespaces = $scope.namespaces;\n const namespacePrefix = _.findLast(namespaces, function (o) {\n return iri.indexOf(o.uri) === 0;\n });\n return namespacePrefix ? (namespacePrefix.prefix + \":\" + iri.substring(namespacePrefix.uri.length)) : iri;\n };\n\n function expandPrefix(str, namespaces) {\n const ABS_URI_REGEX = /^<?(http|urn).*>?/;\n if (!ABS_URI_REGEX.test(str)) {\n const uriParts = str.split(':');\n const uriPart = uriParts[0];\n const localName = uriParts[1];\n if (!angular.isUndefined(localName)) {\n const expandedUri = ClassInstanceDetailsService.getNamespaceUriForPrefix(namespaces, uriPart);\n if (expandedUri) {\n return expandedUri + localName;\n }\n }\n }\n return str;\n }\n\n $scope.addedTag = function (tag) {\n if (tag.text.indexOf(':') < 0) {\n toastr.warning($translate.instant('graphexplore.absolute.prefixed.iri'));\n return null;\n }\n tag.text = expandPrefix(tag.text, $scope.namespaces);\n $scope.pageslideExpanded = true;\n return tag;\n };\n\n $scope.validateTag = function (tag, category, wildcardOK) {\n if (tag.text.indexOf(':') < 0) {\n if (wildcardOK) {\n toastr.warning($translate.instant('graphexplore.absolute.prefixed.iri.option'), category);\n } else {\n toastr.warning($translate.instant('graphexplore.absolute.prefixed.iri'), category);\n }\n return false;\n }\n const wildcardPos = tag.text.indexOf('*');\n if (wildcardPos >= 0) {\n if (!wildcardOK) {\n toastr.warning($translate.instant('graphexplore.wildcards.not.allowed'), category);\n return false;\n } else if (wildcardPos < tag.text.length - 1) {\n toastr.warning($translate.instant('graphexplore.wildcards.last.char'), category);\n return false;\n }\n }\n return true;\n };\n\n $scope.getTagClass = function (tagText) {\n if (tagText.endsWith('*')) {\n return 'tag-item-wildcard';\n }\n return null;\n };\n\n $scope.getActiveRepository = function () {\n return $repositories.getActiveRepository();\n };\n\n $scope.isLicenseValid = function() {\n return $licenseService.isLicenseValid();\n }\n\n // Flag to avoid calling repo init logic twice\n $scope.hasInitedRepository = false;\n\n // This method may be called twice - once by us explicitly and once by the repositoryInit event.\n // In some race conditions getActiveRepository() will be already set when we enter it the first\n // time but then we'll be called again by the event, so we need the above flag to avoid double\n // initialization and weirdness.\n function initForRepository(newRepo) {\n if (!$repositories.getActiveRepository() || $scope.hasInitedRepository && !newRepo) {\n return;\n }\n\n $scope.hasInitedRepository = true;\n\n if (!newRepo) {\n // Process params only if this isn't a repo that was just selected from the dropdown menu\n $scope.getGraphConfigs(loadGraphFromQueryParam);\n }\n\n // Inits namespaces for repo\n $scope.getNamespacesPromise = RDF4JRepositoriesRestService.getNamespaces($scope.getActiveRepository())\n .success(function (data) {\n const nss = _.map(data.results.bindings, function (o) {\n return {\"uri\": o.namespace.value, \"prefix\": o.prefix.value};\n });\n $scope.namespaces = _.sortBy(nss, function (n) {\n return n.uri.length;\n });\n\n checkAutocompleteStatus();\n }).error(function (data) {\n toastr.error(getError(data), $translate.instant('graphexplore.error.view.will.not.work'));\n });\n }\n\n function checkAutocompleteStatus() {\n if ($licenseService.isLicenseValid()) {\n $scope.getAutocompletePromise = AutocompleteRestService.checkAutocompleteStatus();\n }\n }\n\n $scope.$on('autocompleteStatus', function() {\n checkAutocompleteStatus();\n });\n\n $scope.$on('repositoryIsSet', function (event, args) {\n // New repo set from dropdown, clear init state\n if (args.newRepo) {\n $scope.hasInitedRepository = false;\n }\n\n initForRepository(args.newRepo);\n\n // New repo set from dropdown, clear state and go to home page\n if (args.newRepo) {\n $scope.resetState();\n // Quick-n-dirty way to get rid of the existing vis\n $('.graph-visualization svg').empty();\n\n // When we come from the sparql view and then change the repo though the dropdown,\n // should goToHome and reinit the view, for the search to view on the home page\n if ($location.search().query) {\n $scope.goToHome();\n initGraphFromQueryParam();\n }\n\n }\n });\n\n initForRepository();\n\n const multiClickDelay = 500; // max delay between clicks for multiple click events\n\n const nodeLabelRectScaleX = 1.75;\n\n const color1 = d3.scale.linear()\n .domain([0, 9])\n .range([\"hsl(0, 100%, 75%)\", \"hsl(360, 90%, 82%)\"])\n .interpolate(d3.interpolateHslLong);\n\n const color2 = d3.scale.linear()\n .domain([0, 9])\n .range([\"hsl(180, 50%, 75%)\", \"hsl(540, 40%, 82%)\"])\n .interpolate(d3.interpolateHslLong);\n\n $scope.getColor = function (type) {\n if (angular.isUndefined(type2color[type])) {\n type2color[type] = colorIndex;\n colorIndex++;\n }\n\n const index = type2color[type];\n if (index > 39) {\n return \"#c2c2c2\";\n } else if (index % 2 === 0) {\n return color1(index / 2);\n } else {\n return color2(index / 2);\n }\n };\n\n const force = d3.layout.force()\n .gravity(0.07)\n .size([width, height]);\n\n const svg = d3.select(\".main-container .graph-visualization\").append(\"svg\")\n .attr(\"viewBox\", \"0 0 \" + width + \" \" + height)\n .attr(\"preserveAspectRatio\", \"xMidYMid meet\");\n\n let showNodeTipAndIconsTimer = 0;\n let removeIconsTimer = 0;\n\n const loader = new Loader();\n\n function draw(resetRootNode) {\n // remove all group elements and rec to rebuild the graph when the user clicks on it\n d3.selectAll(\"svg g\").remove();\n d3.selectAll(\"svg rect\").remove();\n d3.selectAll('.d3-tip').remove();\n d3.selectAll('.menu-events').remove();\n\n // zoom and drag event\n panAndZoom.on(\"zoom\", panAndZoomed);\n\n // building rectangular so we can bind zoom and drag effects\n svg.append(\"rect\")\n .attr(\"width\", width * 10)\n .attr(\"height\", height * 10)\n .attr(\"x\", -(width * 10 - width) / 2)\n .attr(\"y\", -(height * 10 - height) / 2)\n .style(\"fill\", \"none\")\n .style(\"pointer-events\", \"all\")\n .call(panAndZoom)\n .on(\"click\", function () {\n d3.event.stopPropagation();\n removeMenuIfVisible();\n // Clicking outside the graph stops the layout\n force.stop();\n });\n\n\n const container = svg.append(\"g\").attr(\"class\", \"nodes-container\")\n .attr(\"transform\", function () {\n if (angular.isDefined(transformValues) && !resetRootNode) {\n return transformValues;\n }\n return '';\n });\n\n const tip = d3tip()\n .attr('class', 'd3-tip')\n .customPosition(function () {\n const bbox = tipElement.getBoundingClientRect();\n return {\n top: (bbox.bottom + 10) + 'px',\n left: (bbox.left - 30) + 'px'\n };\n })\n .html(function (d) {\n let html = '';\n\n if (d.fixed) {\n // add pin icon if pinned down\n html += '<i class=\"icon-pin\"></i> ';\n }\n\n if (d.types.length > 0) {\n // mid-dot delimited types\n html += _.join(_.map(d.types, function (t) {\n return $scope.replaceIRIWithPrefix(t);\n }), ' \\u00B7 ');\n } else {\n html += '<i>No types</i>';\n }\n\n return html;\n });\n\n const numberOfPredLeft = function (d) {\n return d.predicates.length - 10;\n };\n\n // This will create text that will appear in d3tip\n const createTipText = function (d) {\n let html = '';\n html += _.join(_.map(d.predicates, function (p, index) {\n if (index === 0) {\n return getShortPredicate(p);\n // If we have less than or ten predicates should show them with middle dot separated\n } else if (index < 10) {\n return ' \\u00B7 ' + getShortPredicate(p);\n // On eleventh predicate just append how many more predicates left to show to the user\n } else if (index === 10) {\n const numOfPredLeft = numberOfPredLeft(d);\n // Show how many predicates left\n const textToShow = numOfPredLeft > 1 ? numOfPredLeft + ' predicates'\n : numOfPredLeft + ' predicate';\n return ' \\u00B7 ' + $translate.instant('graphexplore.tip.text', {textToShow: textToShow});\n }\n }), '');\n\n return html;\n };\n\n const calculateWidth = function (d) {\n const text = createTipText(d);\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext(\"2d\");\n ctx.font = \"13px Arial\";\n\n if (d.predicates.length < 10) {\n return ctx.measureText(text).width;\n } else {\n return ctx.measureText(text).width / 2;\n }\n };\n\n let tipPredicateElement;\n let tipPredicateTimer;\n\n const tipPredicates = d3tip()\n .attr('class', 'd3-tip')\n .customPosition(function (d) {\n const bbox = tipPredicateElement.getBoundingClientRect();\n const textWidth = calculateWidth(d);\n return {\n top: (bbox.top - 30) + 'px',\n left: (bbox.left - 30) + 'px',\n width: textWidth + 'px'\n };\n })\n .html(function (d) {\n return createTipText(d);\n });\n\n let tipTimer;\n // Shows the tooltip for a node but with a slight delay\n const showTipForNode = function (d, event) {\n $timeout.cancel(tipTimer);\n const thisTipElement = tipElement = event.target;\n $timeout(function () {\n if (tipElement === thisTipElement) {\n tip.show(d, tipElement);\n }\n }, 300);\n };\n\n // Hides the tooltip for the node and resets some variables\n const hideTipForNode = function () {\n $timeout.cancel(tipTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n tipElement = null;\n tip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n };\n\n // Updates the text in the tooltip if already visible\n const updateTipForNode = function (d) {\n if (tipElement) {\n tip.show(d, tipElement);\n }\n };\n\n svg.call(tip);\n\n // Shows like tooltip list of predicates but with a slight delay\n const showPredicateToolTip = function (d) {\n $timeout.cancel(tipPredicateTimer);\n const thisPredicateTipElement = tipPredicateElement = d3.event.target;\n $timeout(function () {\n if (tipPredicateElement === thisPredicateTipElement && d.predicates.length > 1) {\n tipPredicates.show(d, tipPredicateElement);\n }\n }, 300);\n };\n\n // Hides the tooltip with predicates and resets some variables\n const hidePredicateToolTip = function () {\n $timeout.cancel(tipPredicateTimer);\n tipPredicateElement = null;\n tipPredicates.hide();\n };\n\n svg.call(tipPredicates);\n\n let link = svg.selectAll(\".link\");\n let node = svg.selectAll(\".node\");\n\n force.nodes(graph.nodes).charge(-3000);\n\n force.links(graph.links).linkDistance(function (l) {\n if (l.source.isTriple || l.target.isTriple) {\n return 0;\n }\n // link distance depends on length of text with an added bonus for strongly connected nodes,\n // i.e. they will be pushed further from each other so that their common nodes can cluster up\n return getPredicateTextLength(l) + 30 * l.connectedness;\n });\n\n // arrow markers\n container.append(\"defs\").selectAll(\"marker\")\n .data(force.links())\n .enter().append(\"marker\")\n .attr(\"class\", \"arrow-marker\")\n .attr(\"id\", function (d) {\n return createArrowMarkerUniqueID(d);\n })\n .attr(\"viewBox\", \"0 -5 10 10\")\n .attr(\"refX\", function (d) {\n // The positioning of the arrow for triple target nodes differ from normal ones\n return d.target.isTriple ? 11 : d.target.size + 11;\n })\n .attr(\"refY\", 0)\n .attr(\"markerWidth\", 10)\n .attr(\"markerHeight\", 10)\n .attr(\"orient\", \"auto\")\n .append(\"path\")\n .attr(\"d\", \"M0,-5L10,0L0,5 L10,0 L0, -5\");\n\n // add the links, nodes, predicates and node labels\n link = container.selectAll(\".link\")\n .data(graph.links)\n .enter().append(\"g\")\n .attr(\"class\", \"link-wrapper\")\n .attr(\"id\", function (d) {\n return removeSpecialChars(convertLinkDataToLinkId(d));\n })\n .append(\"line\")\n .attr(\"class\", \"link\")\n .style(\"stroke-width\", 1)\n .style(\"fill\", \"transparent\")\n .style(\"marker-end\", function (d) {\n let targetArrowId = createArrowMarkerUniqueID(d);\n return `url(#${targetArrowId})`;\n });\n\n const predicate = container.selectAll(\".link-wrapper\")\n .append(\"text\")\n .text(function (d) {\n return getPredicate(d);\n })\n .attr(\"class\", function (d) {\n if (d.predicates.length > 1 || graph.tripleNodes.has(convertLinkDataToLinkId(d))) {\n return \"predicates\";\n }\n return \"predicate\";\n })\n .attr(\"dy\", \"-0.5em\")\n .style(\"text-anchor\", \"middle\")\n .style(\"display\", $scope.saveSettings.showLinksText ? \"\" : \"none\")\n .on(\"mouseover\", function (d) {\n d3.event.stopPropagation();\n showPredicateToolTip(d);\n })\n .on('mouseout', hidePredicateToolTip)\n .on(\"click\", function (d) {\n d3.event.stopPropagation();\n linkActions(d);\n });\n\n // node events and variables\n let mouseEventTimer;\n let upEventLast = 0;\n let virtualClickEventTimer = 0;\n let moveEventCount = 0;\n\n // tracks mousedown and touchstart events in order to count single or double click\n // (checked in upEventHandler)\n const downEventHandler = function () {\n if (d3.event.button && d3.event.button !== 0) {\n return;\n }\n\n hideTipForNode();\n $timeout.cancel(mouseEventTimer);\n $scope.showPredicates = false;\n if (d3.event.timeStamp - upEventLast < multiClickDelay) {\n virtualClickEventTimer++;\n } else {\n virtualClickEventTimer = 1;\n }\n\n upEventLast = d3.event.timeStamp;\n\n d3.event.preventDefault();\n };\n\n // builds upon downEventHandler and adds additional functionality for touch devices\n const touchStartEventHandler = function (d) {\n downEventHandler();\n\n // for touch devices we track touch and hold for 1s in order to remove a node\n moveEventCount = 0;\n mouseEventTimer = $timeout(function () {\n if (moveEventCount < 5) {\n // remove the node only if not many move events were fired,\n // this avoids conflict with dragging nodes\n hideNode(d);\n }\n mouseEventTimer = null;\n virtualClickEventTimer = 0;\n }, 1000);\n };\n\n // tracks the number of move events (checked in the touchend event handler)\n const moveEventHandler = function () {\n moveEventCount++;\n };\n\n const showNodeTipAndIcons = function (d) {\n if (!d.isBeingDragged) {\n const event = d3.event;\n $timeout.cancel(removeIconsTimer);\n showNodeTipAndIconsTimer = $timeout(() => {\n if (expandNodeIcons(d, this)) {\n showTipForNode(d, event);\n }\n }, 400);\n }\n };\n\n const upEventHandler = function (d) {\n if (d3.event.button && d3.event.button !== 0) {\n return;\n }\n\n $timeout.cancel(mouseEventTimer);\n\n const event = d3.event;\n const element = this;\n if (d3.event.timeStamp - upEventLast < multiClickDelay) {\n if (virtualClickEventTimer === 1) {\n mouseEventTimer = $timeout(function () {\n clickedNode(d, element, event);\n }, 40 + multiClickDelay - (d3.event.timeStamp - upEventLast));\n } else if (virtualClickEventTimer === 2) {\n // expand node\n const shownLinks = graph.countLinks(d, graph.links);\n if (shownLinks <= $scope.saveSettings['linksLimit']) {\n expandNode(d, false, element.parentNode);\n } else {\n toastr.info($translate.instant('graphexplore.increase.limit'), $translate.instant('graphexplore.node.at.max'));\n }\n $scope.closeInfoPanel();\n }\n }\n\n d3.event.preventDefault();\n };\n\n // Shows growing or shrinking pin animation\n function showPinAnimation(d, type) {\n let startSize;\n let endSize;\n let startOpacity;\n let endOpacity;\n let animate = true;\n\n if (type === 'down') {\n startSize = d.size * 2;\n endSize = d.size / 3;\n startOpacity = 0.8;\n endOpacity = 0.3;\n } else if (type === 'down-fixed') {\n startSize = d.size * 2;\n endSize = d.size;\n startOpacity = 0.8;\n endOpacity = 0.66;\n } else if (type === 'up') {\n startSize = d.size / 3;\n endSize = d.size * 2;\n startOpacity = 0.3;\n endOpacity = 0.8;\n } else if (type === 'fixed') {\n startSize = d.size;\n startOpacity = 0.66;\n animate = false;\n } else {\n return; // unknown\n }\n\n let pin = container.selectAll('.node-wrapper')\n .filter(function (innerD) {\n return innerD === d;\n })\n .append('text')\n .text('\\ue90f') // pin icon\n .classed('icon-any pinned', true)\n .style('font-size', startSize + 'px')\n .attr('x', function (d) {\n return d.x;\n })\n .attr('y', function (d) {\n return d.y;\n })\n .attr('opacity', startOpacity);\n\n if (type === 'fixed' || type === 'down-fixed') {\n d.pin = pin;\n }\n\n if (animate) {\n pin = pin.transition()\n .duration(1000)\n .style('font-size', function () {\n return endSize + 'px';\n })\n .attr('opacity', endOpacity);\n\n if (type !== 'down-fixed') {\n pin.remove();\n }\n }\n }\n\n function removePin() {\n d3.select('.pinned').remove();\n }\n\n // Unfixes nodes that were dragged previously\n const rightClickHandler = function (d) {\n if (d3.event.shiftKey) {\n // Do nothing with shift key, use to access context menu\n return;\n }\n\n d3.event.preventDefault();\n\n removeMenuIfVisible();\n $scope.closeInfoPanel();\n\n if (d.fixed) {\n // unpin\n $scope.numberOfPinnedNodes--;\n d.fixed = false;\n showPinAnimation(d, 'up');\n force.resume();\n } else {\n // pin down\n $scope.numberOfPinnedNodes++;\n d.fixed = true;\n showPinAnimation(d, 'down');\n }\n // update pin in tooltip\n updateTipForNode(d);\n };\n\n const drag = d3.behavior.drag()\n .origin(function (d) {\n return d;\n })\n .on(\"dragstart\", dragstarted)\n .on(\"drag\", dragged)\n .on(\"dragend\", dragended);\n\n\n function dragstarted(d) {\n if (d3.event.sourceEvent.button === 0) {\n d.fixedBeforeDrag = d.fixed;\n d.isBeingDragged = true;\n d.beginDragging = true;\n removeMenuIfVisible();\n d3.event.sourceEvent.stopPropagation();\n d3.select(this).classed(\"dragging\", true);\n }\n }\n\n function dragged(d) {\n if (d.isBeingDragged) {\n // reset click counter to avoid conflicts between clicks and drags\n virtualClickEventTimer = 0;\n\n d.px = d3.event.x;\n d.py = d3.event.y;\n if (!d.fixed) {\n $scope.numberOfPinnedNodes++;\n d.fixed = true;\n showPinAnimation(d, 'down-fixed');\n } else if (d.beginDragging) {\n showPinAnimation(d, 'fixed');\n }\n d.pinWasFixed = true;\n d.beginDragging = null;\n\n force.resume();\n }\n }\n\n function dragended(d) {\n if (d.isBeingDragged) {\n if (d.pinWasFixed) {\n d.pinWasFixed = null;\n removePin();\n }\n d.isBeingDragged = false;\n d3.select(this).classed(\"dragging\", false);\n }\n }\n\n node = container.selectAll(\".node\")\n .data(graph.nodes)\n .enter().append(\"g\")\n .attr(\"class\", \"node-wrapper\")\n .attr(\"id\", function (d) {\n return d.iri;\n })\n .append(\"circle\")\n .attr(\"class\", \"node\")\n .attr(\"r\", function (d) {\n return d.size;\n })\n .style(\"fill\", function (d) {\n if (d.types === \"greyColor\") {\n return \"c2c2c2\";\n }\n return $scope.getColor(d.types[0]);\n })\n .call(drag)\n .on('mouseover', showNodeTipAndIcons)\n .on('mouseout', hideTipForNode)\n .on(\"mousedown\", downEventHandler)\n .on(\"touchstart\", touchStartEventHandler)\n // no need to track move for mouse\n .on(\"touchmove\", moveEventHandler)\n .on(\"mouseup\", upEventHandler)\n .on(\"touchend\", upEventHandler)\n .on(\"contextmenu\", rightClickHandler);\n\n const nodeLabels = container.selectAll(\".node-wrapper\").append(\"foreignObject\")\n .style(\"pointer-events\", \"none\")\n .attr(\"width\", function (d) {\n return d.size * 2 * nodeLabelRectScaleX;\n });\n // height will be computed by updateNodeLabels\n\n container.insert(\"g\").attr(\"class\", \"menu-events\");\n\n updateNodeLabels(nodeLabels);\n\n force.on(\"tick\", function () {\n // recalculate nodes positions and repel them if they collide\n let q = d3.geom.quadtree(graph.nodes);\n let i = 0;\n const n = graph.nodes.length;\n // FIXME while (++i < n) q.visit(collide(graph.nodes[i]));\n\n // recalculate links attributes\n link.attr(\"x1\", function (d) {\n return getNodeX(d.source);\n }).attr(\"y1\", function (d) {\n return getNodeY(d.source);\n }).attr(\"x2\", function (d) {\n return getNodeX(d.target);\n }).attr(\"y2\", function (d) {\n return getNodeY(d.target);\n });\n\n // recalculate predicates attributes\n predicate.attr(\"x\", function (d) {\n let sourceX = getNodeX(d.source);\n let targetX = getNodeX(d.target);\n return d.x = (sourceX + targetX) * 0.5;\n }).attr(\"y\", function (d) {\n let sourceY = getNodeY(d.source);\n let targetY = getNodeY(d.target);\n return d.y = (sourceY + targetY) * 0.5;\n }).attr(\"transform\", function (d) {\n const angle = findAngleBetweenNodes(d, d.direction);\n return \"rotate(\" + angle + \", \" + d.x + \", \" + d.y + \")\";\n });\n\n // recalculate nodes attributes\n node.attr(\"cx\", function (d) {\n return d.x;\n }).attr(\"cy\", function (d) {\n return d.y;\n });\n\n // update node loader position\n container.select(\".node-loader\").attr(\"x\", function (d) {\n return d.x - d.size + 3; //square svg is not perfectly centered and need +3 units on x ordinate to fit in circle\n }).attr(\"y\", function (d) {\n return d.y - d.size;\n });\n\n container.select(\".loader-container\").attr(\"cx\", function (d) {\n return d.x;\n }).attr(\"cy\", function (d) {\n return d.y;\n });\n\n nodeLabels.attr(\"x\", function (d) {\n return d.x - (d.size * nodeLabelRectScaleX);\n }).attr(\"y\", function (d) {\n // the height of the nodeLabel box is 3 times the fontSize computed by updateNodeLabels\n // and we want to offset it so that its middle matches the centre of the circle, hence divided by 2\n return d.y - 3 * d.fontSize / 2;\n });\n\n // Update position of shrinking pin animation (if any)\n d3.select('.pinned').attr(\"x\", function (d) {\n return d.x;\n }).attr(\"y\", function (d) {\n return d.y;\n });\n });\n\n function panAndZoomed() {\n transformValues = \"translate(\" + d3.event.translate + \") scale(\" + d3.event.scale + \")\";\n container.attr(\"transform\", transformValues);\n }\n\n if (angular.isDefined(loader)) {\n loader.setLoadingState(false);\n }\n\n if ($scope.loading) {\n $scope.loading = false;\n }\n\n d3.selectAll('.link-wrapper').each(function () {\n const source = $(this).attr(\"id\").split(\">\")[0];\n const target = $(this).attr(\"id\").split(\">\")[1];\n d3.selectAll('.link').each(function (link) {\n let sourceId = removeSpecialChars(link.source.iri);\n let targetId = removeSpecialChars(link.target.iri);\n if (sourceId === target && targetId === source) {\n let twoWayLinkID = sourceId;\n twoWayLinkID += \">\";\n twoWayLinkID += targetId;\n const textNode = document.createTextNode(' \\u27F6');\n document.getElementById(twoWayLinkID).lastChild.appendChild(textNode);\n link.direction = \"double\";\n }\n });\n });\n\n d3.selectAll('.d3-actions-tip').remove();\n\n force.start();\n }\n\n /* FIXME\n // check for collision of the nodes\n function collide(node, bigger) {\n return function (quad, x1, y1, x2, y2) {\n if (quad.point && (quad.point !== node)) {\n var x = node.x - quad.point.x,\n y = node.y - quad.point.y,\n l = Math.sqrt(x * x + y * y),\n r = node.size + quad.point.size;\n if (l < r) {\n l = (l - r) / l * .5;\n node.x -= x *= l;\n node.y -= y *= l;\n quad.point.x += x;\n quad.point.y += y;\n }\n }\n return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;\n };\n }\n */\n\n draw();\n\n // find angle between pair of nodes so we can position predicates\n function findAngleBetweenNodes(linkedNodes, direction) {\n const p1 = {\n x: getNodeX(linkedNodes.source),\n y: getNodeY(linkedNodes.source)\n };\n\n const p2 = {\n x: getNodeX(linkedNodes.target),\n y: getNodeY(linkedNodes.target)\n };\n if (direction) {\n return Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;\n } else {\n const angleDeg = Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;\n if (angleDeg <= 90 && angleDeg >= -90) {\n return angleDeg;\n }\n return (angleDeg > 0 ? -1 : 1) * (180 - Math.abs(angleDeg));\n }\n }\n\n const menuEvents = new MenuEvents();\n\n // expanding and collapsing of the nodes\n function clickedNode(d, element, event) {\n $scope.showInfoPanel = false;\n $scope.showPredicates = false;\n $scope.showNodeInfo = false;\n\n // shift + ctrl/cmd + click focuses node\n if (event.shiftKey && (event.ctrlKey || event.metaKey)) {\n $rootScope.$broadcast(\"onRootNodeChange\", d.iri);\n return false;\n }\n\n // ctrl/cmd + click hides the node\n if (event.ctrlKey || event.metaKey) {\n hideNode(d);\n return false;\n }\n\n // If value of openedNodeInfoPanel is different than \"undefined\"\n // we evaluate if clicked node value is the same and close it\n if (typeof $scope.openedNodeInfoPanel !== \"undefined\" && $scope.openedNodeInfoPanel === d) {\n $scope.pageslideExpanded = false;\n $scope.openedNodeInfoPanel = undefined;\n return false;\n }\n\n showNodeInfo(d);\n return true;\n }\n\n function expandNodeIcons(d, element) {\n if ($scope.showInfoPanel) {\n return false;\n }\n\n if (menuEvents.closeIcon || menuEvents.expandIcon || menuEvents.focusIcon || menuEvents.copyURIIcon) {\n menuEvents.removeIcons();\n }\n\n // If nodes are still rearranging result of force.alpha() is more than 0.05\n // and we don't want to show node's icons on mouse over and stop rearrangement\n if (force.alpha() < 0.05) {\n menuEvents.initIcons(d, element.parentNode);\n force.stop();\n\n return true;\n }\n\n return false;\n }\n\n function hideNode(d) {\n graph.removeNode(d);\n draw();\n }\n\n function collapseNode(d) {\n d.isExpanded = false;\n graph.removeNodeLeafLinks(d);\n draw();\n }\n\n function initGraph(response) {\n $scope.nodeSelected = true;\n if (response.data.types === null) {\n response.data.types = \"greyColor\";\n }\n graph = new Graph();\n transformValues = \"translate(0, -70) scale(1)\";\n panAndZoom.translate([0, -70]);\n panAndZoom.scale(1);\n }\n\n function initGraphFromResponse(response) {\n initGraph(response);\n renderGraphFromResponse(response);\n }\n\n function renderGraphFromResponse(response, d, isStartNode) {\n let linksFound = response.data;\n // filter existing links\n linksFound = _.filter(linksFound, function (newLink) {\n return _.findIndex(graph.links,\n function (existingLink) {\n return newLink.source === existingLink.source.iri && newLink.target === existingLink.target.iri;\n }) === -1;\n });\n let linksCopy = [];\n const tripleLinksIt = graph.tripleLinksCopy.values();\n for (let i = 0; i < graph.tripleLinksCopy.size; i++) {\n let linkCopy = tripleLinksIt.next().value;\n linkCopy.forEach(link => {\n linksCopy.push(link);\n });\n }\n // filter existing shadow links\n linksFound = _.filter(linksFound, function (newLink) {\n return _.findIndex(linksCopy,\n function (existingLink) {\n return newLink.source === existingLink.source.iri && newLink.target === existingLink.target.iri;\n }) === -1;\n });\n // filter reflexive links until we find a way to render them GDB-1853\n linksFound = _.filter(linksFound, function (newLink) {\n return newLink.source !== newLink.target;\n });\n const nodesFromLinks = distinctBy('iri',_.union(_.flatten(_.map(response.data, function (link) {\n return [\n { iri: link.source,\n isTriple: link.isTripleSource },\n {\n iri: link.target,\n isTriple: link.isTripleTarget }];\n }))));\n const existingNodes = _.map(graph.nodes, function (n) {\n return {\n iri: n.iri,\n isTriple: Boolean(n.isTriple)\n };\n });\n const tripleNodesIt = graph.tripleNodes.values();\n for (let i = 0; i < graph.tripleNodes.size; i++) {\n let nodes = tripleNodesIt.next().value;\n nodes.forEach(node => {\n existingNodes.push({\n iri: node.iri,\n isTriple: node.isTriple\n });\n });\n }\n const newNodes = _.reject(nodesFromLinks, function (n) {\n return _.some(existingNodes, n);\n });\n\n if (newNodes.length === 0) {\n if (isStartNode) {\n toastr.info($translate.instant('graphexplore.error.node.connections'));\n } else if (linksFound.length === 0) {\n toastr.info($translate.instant('graphexplore.error.node.connections'));\n }\n\n graph.addAndMatchLinks(linksFound);\n draw();\n } else {\n const promises = [];\n const newNodesData = [];\n\n _.forEach(newNodes, function (newNode, index) {\n promises.push($http({\n url: 'rest/explore-graph/node',\n method: 'GET',\n params: {\n iri: newNode.isTriple ? createTriple(newNode.iri) : newNode.iri,\n config: $scope.configLoaded.id,\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n includeInferred: $scope.saveSettings['includeInferred'],\n sameAsState: $scope.saveSettings['sameAsState']\n }\n }).then(function (res) {\n // Save the data for later\n newNodesData[index] = res.data;\n }));\n });\n\n // Waits for all of the collected promises and then:\n // - adds each new node\n // - redraws the graph\n $q.all(promises).then(function () {\n _.forEach(newNodesData, function (newNodeData, index) {\n // Calculate initial positions for the new nodes based on spreading them evenly\n // on a circle around the node we came from.\n const theta = 2 * Math.PI * index / newNodesData.length;\n const x = (d ? d.x : 0) + Math.cos(theta) * height / 3;\n const y = (d ? d.y : 0) + Math.sin(theta) * height / 3;\n if (newNodeData.isTriple) {\n graph.addTriple(newNodeData, x, y);\n } else {\n graph.addNode(newNodeData, x, y);\n }\n });\n\n graph.addAndMatchLinks(linksFound);\n if (d) {\n d.isExpanded = true;\n }\n draw();\n });\n }\n }\n\n function expandNode(d, isStartNode, parentNode) {\n if (loader.getLoadingState()) {\n return;\n }\n loader.init(d, parentNode);\n\n const expandIri = d.iri;\n $http({\n url: 'rest/explore-graph/links',\n method: 'GET',\n params: {\n iri: expandIri, linksLimit: $scope.saveSettings['linksLimit'],\n includeInferred: $scope.saveSettings['includeInferred'],\n config: $scope.configLoaded.id,\n preferredTypes: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['preferredTypes'],\n rejectedTypes: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['rejectedTypes'],\n preferredPredicates: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['preferredPredicates'],\n rejectedPredicates: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['rejectedPredicates'],\n preferredTypesOnly: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['preferredTypesOnly'],\n preferredPredicatesOnly: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['preferredPredicatesOnly'],\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n sameAsState: $scope.saveSettings['sameAsState'],\n includeSchema: $scope.saveSettings['includeSchema']\n }\n }).then(function (response) {\n renderGraphFromResponse(response, d, isStartNode);\n }, function (response) {\n const msg = getError(response.data);\n toastr.error(msg, $translate.instant('graphexplore.error.exploring.node'));\n $scope.loading = false;\n loader.setLoadingState(false);\n });\n }\n\n function removeMenuIfVisible() {\n if (angular.isDefined(menuEvents) && menuEvents.expandedState) {\n menuEvents.removeIcons();\n }\n }\n\n function MenuEvents() {\n this.closeIcon = undefined;\n this.expandIcon = undefined;\n this.collapseIcon = undefined;\n this.focusIcon = undefined;\n this.copyURIIcon = undefined;\n this.actionsTip = undefined;\n\n this.removeIcons = function () {\n this.closeIcon.remove(\"g\");\n if (this.expandIcon) {\n this.expandIcon.remove(\"g\");\n }\n\n if (this.collapseIcon) {\n this.collapseIcon.remove(\"g\");\n }\n\n this.focusIcon.remove(\"g\");\n this.copyURIIcon.remove(\"g\");\n this.closeIcon = undefined;\n this.expandIcon = undefined;\n this.collapseIcon = undefined;\n this.focusIcon = undefined;\n this.copyURIIcon = undefined;\n\n this.expandedState = false;\n };\n\n this.expandedState = false;\n\n function getPositionAndAngle(angle, d) {\n const x = d.x - 14 + (d.size + 15) * Math.cos(angle * Math.PI / 180 - Math.PI / 2);\n const y = d.y - 14 + (d.size + 15) * Math.sin(angle * Math.PI / 180 - Math.PI / 2);\n return \"translate(\" + x + \",\" + y + \")\";\n }\n\n this.initIcons = function (node, parentNode) {\n // init action tips on hover of the icons\n const actionsTip = d3tip()\n .attr('class', 'd3-tip d3-actions-tip')\n .customPosition(function () {\n const bbox = d3.event.target.getBoundingClientRect();\n return {\n top: (bbox.top - 20) + 'px',\n left: (bbox.right + 10) + 'px'\n };\n })\n .html(function (name) {\n return name;\n });\n svg.call(actionsTip);\n const angle = 20;\n if (node.isExpanded) {\n this.collapseIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"collapse-icon\")\n .attr(\"name\", \"collapse\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.collapseIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.collapseIcon.append(\"path\")\n .attr(\"d\", \"M22.67,12a.59.59,0,0,1-.53.65l-6.88.72H15.2a.59.59,0,0,1-.59-.65l.72-6.88A.58.58,0,0,1,16,5.33a.59.59,0,0,1,.53.65L16,11.11,21.3,5.79a.64.64,0,0,1,.91.91L16.89,12,22,11.49A.59.59,0,0,1,22.67,12ZM12.59,14.75l-6.75.85a.59.59,0,0,0-.51.66.58.58,0,0,0,.66.51l4.95-.62-5.2,5.2a.64.64,0,1,0,.91.91l5.2-5.2L11.23,22a.59.59,0,0,0,.51.66h.07a.59.59,0,0,0,.59-.52l.85-6.75a.59.59,0,0,0-.17-.49A.58.58,0,0,0,12.59,14.75Z\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.collapseIcon.on(\"click\", function () {\n collapseNode(node);\n }).on('mouseover', function () {\n actionsTip.show(this.getAttribute(\"name\"));\n $timeout.cancel(showNodeTipAndIconsTimer);\n $timeout.cancel(removeIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n } else {\n this.expandIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"expand-icon\")\n .attr(\"name\", \"expand\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.expandIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.expandIcon.append(\"path\")\n .attr(\"d\", \"M22.37,6.28l-.72,6.88a.59.59,0,0,1-.59.53H21a.59.59,0,0,1-.53-.65L21,7.9l-5.32,5.32a.64.64,0,0,1-.91-.91L20.1,7,15,7.53a.59.59,0,0,1-.12-1.18l6.88-.72a.59.59,0,0,1,.65.65ZM12.89,20.34,7.95,21l5.2-5.2a.64.64,0,0,0-.91-.91L7,20.05l.62-4.95A.59.59,0,0,0,6.48,15l-.85,6.75a.59.59,0,0,0,.59.67h.07L13,21.52a.59.59,0,1,0-.15-1.18Z\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.expandIcon.on(\"click\", function () {\n expandNode(node, false, parentNode);\n }).on('mouseover', function () {\n actionsTip.show(this.getAttribute(\"name\"));\n $timeout.cancel(removeIconsTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n }\n\n\n this.focusIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"focus-icon\")\n .attr(\"name\", \"focus\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.focusIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.focusIcon.append(\"path\")\n .attr(\"d\", \"M14.2,23.81a9.8,9.8,0,1,1,6.93-2.87h0A9.74,9.74,0,0,1,14.2,23.81Zm0-18.17a8.37,8.37,0,1,0,5.92,14.29h0A8.37,8.37,0,0,0,14.2,5.64Zm1.42,6.95a2,2,0,1,0,0,2.85A2,2,0,0,0,15.62,12.59Z\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.focusIcon.on(\"click\", function () {\n $rootScope.$broadcast(\"onRootNodeChange\", node.iri);\n }).on('mouseover', function () {\n actionsTip.show(this.getAttribute(\"name\"));\n $timeout.cancel(removeIconsTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n\n this.copyURIIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"icon-link\")\n .attr(\"name\", \"link\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.copyURIIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.copyURIIcon.append(\"path\")\n .attr(\"d\", \"M 13.457031 10.164062 C 13.648438 10.164062 13.820312 10.242188 13.941406 10.363281 L 15.492188 11.859375 C 15.984375 12.332031 16.292969 12.992188 16.292969 13.714844 C 16.292969 14.441406 15.984375 15.097656 15.492188 15.574219 L 10.394531 20.496094 C 9.902344 20.972656 9.222656 21.265625 8.472656 21.265625 C 7.71875 21.265625 7.039062 20.972656 6.546875 20.496094 L 4.996094 19 C 4.507812 18.523438 4.203125 17.867188 4.203125 17.144531 C 4.203125 16.421875 4.507812 15.765625 4.996094 15.289062 L 7.542969 12.824219 C 7.667969 12.707031 7.84375 12.628906 8.035156 12.628906 C 8.417969 12.628906 8.726562 12.929688 8.726562 13.300781 C 8.726562 13.484375 8.648438 13.652344 8.523438 13.773438 L 5.976562 16.234375 C 5.738281 16.46875 5.589844 16.792969 5.589844 17.148438 C 5.589844 17.503906 5.738281 17.824219 5.976562 18.058594 L 7.527344 19.566406 C 7.773438 19.792969 8.105469 19.929688 8.472656 19.929688 C 8.835938 19.929688 9.167969 19.792969 9.414062 19.566406 L 14.511719 14.644531 C 14.753906 14.410156 14.90625 14.089844 14.90625 13.730469 C 14.90625 13.375 14.753906 13.054688 14.511719 12.820312 L 12.964844 11.324219 C 12.839844 11.203125 12.761719 11.039062 12.761719 10.855469 C 12.761719 10.488281 13.070312 10.1875 13.449219 10.1875 Z M 17.082031 3.976562 C 17.082031 3.976562 17.085938 3.976562 17.085938 3.976562 C 17.824219 3.976562 18.492188 4.261719 18.980469 4.722656 L 20.535156 6.203125 C 21.042969 6.679688 21.355469 7.34375 21.355469 8.082031 C 21.355469 8.792969 21.058594 9.441406 20.582031 9.914062 L 18.0625 12.402344 C 17.9375 12.527344 17.761719 12.605469 17.566406 12.605469 C 17.183594 12.605469 16.875 12.304688 16.875 11.9375 C 16.875 11.753906 16.949219 11.589844 17.070312 11.46875 L 19.605469 8.984375 C 19.847656 8.75 19.996094 8.429688 19.996094 8.070312 C 19.996094 7.714844 19.847656 7.394531 19.605469 7.160156 L 18.019531 5.667969 C 17.773438 5.445312 17.4375 5.304688 17.070312 5.300781 C 16.703125 5.304688 16.367188 5.453125 16.128906 5.691406 L 11.085938 10.667969 C 10.84375 10.898438 10.695312 11.222656 10.695312 11.578125 C 10.695312 11.933594 10.84375 12.257812 11.085938 12.488281 L 12.675781 13.980469 C 12.804688 14.101562 12.882812 14.273438 12.882812 14.457031 C 12.882812 14.828125 12.574219 15.128906 12.191406 15.128906 C 12.003906 15.128906 11.832031 15.054688 11.707031 14.9375 L 10.140625 13.457031 C 9.636719 12.980469 9.324219 12.316406 9.324219 11.582031 C 9.324219 10.863281 9.621094 10.214844 10.101562 9.742188 L 15.140625 4.765625 C 15.625 4.285156 16.304688 3.980469 17.054688 3.976562 Z M 17.082031 3.976562\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.copyURIIcon.on(\"click\", function () {\n copyToClipboard(node.iri);\n removeMenuIfVisible();\n actionsTip.hide();\n }).on('mouseover', function () {\n actionsTip.show(\"<div style='text-align: center;'><b>Copy to ClipBoard</b><br>\" + node.iri + \"</div>\");\n $timeout.cancel(removeIconsTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n\n this.closeIcon = d3.select('.menu-events').append(\"g\")\n .attr(\"class\", \"close-icon\")\n .attr(\"name\", \"remove\")\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n });\n this.closeIcon.append(\"circle\")\n .attr(\"cx\", 14)\n .attr(\"cy\", 14)\n .attr(\"r\", 13)\n .style(\"fill\", \"#eee\");\n this.closeIcon.append(\"path\")\n .attr(\"d\", \"M14.94,14l5.87-5.87a.66.66,0,1,0-.94-.94L14,13.06,8.13,7.19a.66.66,0,0,0-.94.94L13.06,14,7.19,19.87a.66.66,0,1,0,.94.94L14,14.94l5.87,5.87a.66.66,0,1,0,.94-.94Z\")\n .style(\"fill\", \"var(--onto-orange)\");\n\n this.closeIcon.on(\"click\", function () {\n hideNode(node);\n }).on('mouseover', function () {\n actionsTip.show(this.getAttribute(\"name\"));\n $timeout.cancel(removeIconsTimer);\n $timeout.cancel(showNodeTipAndIconsTimer);\n }).on('mouseout', function () {\n actionsTip.hide();\n removeIconsTimer = $timeout(function () {\n removeMenuIfVisible();\n }, 500);\n });\n\n this.animateMenu(node);\n };\n\n this.animateMenu = function (node) {\n const animationDuration = 100;\n const easeEffects = [\"linear\", \"quad\", \"cubic\", \"sin\", \"exp\", \"circle\", \"elastic\", \"back\", \"bounce\"]; // https://github.com/d3/d3-3.x-api-reference/blob/master/Transitions.md#easing\n const easeEffect = easeEffects[3];\n let delay = 0;\n const dellayAddition = 35;\n let angle = 20; // angle of the first icon 0 is at 12 o'clock\n\n if (this.expandIcon) {\n this.expandIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n }\n\n if (this.collapseIcon) {\n this.collapseIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n }\n\n this.copyURIIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n angle += 30;\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n\n this.focusIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n angle += 30;\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n\n\n this.closeIcon\n .transition()\n .duration(animationDuration)\n .style(\"opacity\", 1)\n .ease(easeEffect)\n .attr(\"transform\", function () {\n angle += 30;\n return getPositionAndAngle(angle, node);\n })\n .delay(delay += dellayAddition);\n\n this.expandedState = true;\n };\n }\n\n function Loader() {\n this.state = false;\n\n this.setLoadingState = function (state) {\n this.state = state;\n };\n\n this.getLoadingState = function () {\n return this.state;\n };\n\n this.init = function (node, parentNode) {\n d3.select(parentNode).append(\"circle\")\n .attr(\"cx\", function () {\n return node.x;\n })\n .attr(\"cy\", function () {\n return node.y;\n })\n .attr(\"class\", \"loader-container\")\n .attr(\"r\", function () {\n return node.size;\n })\n .style(\"fill\", \"fff\")\n .style(\"opacity\", \"0.7\");\n\n d3.select(parentNode).append(\"image\")\n .attr(\"xlink:href\", \"js/angular/templates/loader/ot-loader.svg?v=2.0.1\")\n .attr(\"x\", function () {\n return node.x - node.size + 5;\n })\n .attr(\"y\", function () {\n return node.y - node.size;\n })\n .attr(\"width\", function () {\n return node.size * 2;\n })\n .attr(\"height\", function () {\n return node.size * 2;\n })\n .attr(\"class\", \"node-loader\");\n };\n }\n\n function showNodeInfo(d) {\n force.stop();\n // Assign value of node, which info panel has been opened\n $scope.openedNodeInfoPanel = d;\n $scope.showNodeInfo = true;\n $scope.showFilter = false;\n $scope.showPredicates = false;\n $scope.nodeLabels = d.labels;\n $scope.nodeTypes = d.types;\n $scope.rdfRank = d.rdfRank;\n $scope.nodeIri = d.iri;\n $scope.resourceType = d.isTriple ? 'triple' : 'uri';\n $scope.encodedIri = d.isTriple ? encodeURI(createTriple(d.iri)) : encodeURI(d.iri);\n $scope.showInfoPanel = true;\n\n $scope.rdfsLabel = d.labels[0].label;\n $scope.rdfsComment = d.comment;\n $scope.expanded = false;\n\n $scope.propertiesQueryObj.query = '';\n $scope.dataNodeKeysQuery = '';\n $http.get('rest/explore-graph/properties', {\n params: {\n iri: d.isTriple ? createTriple(d.iri) : d.iri,\n config: $scope.configLoaded.id,\n languages: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['languages'],\n includeInferred: $scope.saveSettings['includeInferred'],\n sameAsState: $scope.saveSettings['sameAsState'],\n rejectedPredicates: !$scope.shouldShowSettings() ? [] : $scope.saveSettings['rejectedPredicates']\n }\n }).then(function (response) {\n $scope.data = _.mapKeys(response.data, function (value, key) {\n return $scope.replaceIRIWithPrefix(key);\n });\n $scope.propertiesObj.items = [];\n\n _.forEach($scope.data, function (value, key) {\n $scope.propertiesObj.items.push({key: key, value: value});\n });\n $scope.nodeImage = undefined;\n\n $scope.propertiesNotFiltered = $scope.propertiesObj.items;\n\n const imageVal = _.find($scope.propertiesObj.items, function (o) {\n return o.key === 'image';\n });\n if (imageVal) {\n $scope.nodeImage = imageVal['value'][0].v;\n }\n $scope.propertiesObj.items = _.reject($scope.propertiesObj.items, function (o) {\n return o.key === 'image';\n });\n $scope.propertiesNotFiltered = $scope.propertiesObj.items;\n }, function (response) {\n toastr.warning(getError(response.data), \"Error\");\n });\n }\n\n $scope.toggleSidePanel = function () {\n $scope.pageslideExpanded = !$scope.pageslideExpanded;\n };\n\n $scope.closeInfoPanel = function () {\n $scope.pageslideExpanded = false;\n $scope.openedNodeInfoPanel = undefined;\n $scope.predicates = [];\n openedLink = null;\n // o, angular, o, miracle\n $timeout(function () {\n $scope.showInfoPanel = false;\n });\n };\n\n function applyElementsStyleChanges(tripleNode) {\n updatePredicatesColor('predicate', 'var(--onto-orange-dark)', tripleNode);\n updatePredicatesColor('predicates', 'var(--onto-orange-dark)', tripleNode);\n\n let links = document.getElementsByClassName('link');\n if (links) {\n _.each(links, function (link) {\n let linkLink = link.__data__;\n if (linkLink.source.iri.indexOf(tripleNode.iri) >= 0 || linkLink.target.iri.indexOf(tripleNode.iri) >= 0) {\n link.style.stroke = 'var(--onto-orange-dark)';\n link.style.strokeWidth = 4;\n }\n })\n }\n\n let markers = document.getElementsByClassName('arrow-marker');\n if (markers) {\n _.each(markers, function (marker) {\n let markerLink = marker.__data__;\n if (markerLink.source.iri.indexOf(tripleNode.iri) >= 0 || markerLink.target.iri.indexOf(tripleNode.iri) >= 0) {\n marker.style.stroke = 'var(--onto-orange-dark)';\n if (!marker.__data__.target.isTriple) {\n marker.setAttribute(\"refX\", \"23\");\n }\n }\n });\n }\n }\n\n $scope.clickLink = function (predData) {\n if (graph.tripleNodes.has(predData.linkId)) {\n revertElementsStyleToDefault();\n let tripleNode = graph.tripleNodes.get(predData.linkId)[predData.nodeIndex];\n // Shows selected triple and its properties\n showNodeInfo(tripleNode);\n $scope.showPredicates = true;\n\n let clickedEl = document.getElementById(predData.linkId + predData.nodeIndex);\n if (clickedEl) {\n clickedEl.style.fontWeight = \"bold\";\n }\n\n let nodeCopy = {};\n const tripleLinksIt = graph.tripleLinksCopy.values();\n for (let i = 0; i < graph.tripleLinksCopy.size; i++) {\n let links = tripleLinksIt.next().value;\n if (links.length > 1) {\n links.every(link => {\n if (link.source.iri === tripleNode.iri) {\n nodeCopy.iri = links[0].source.iri;\n if (link.target.isTriple) {\n nodeCopy.oppLinkIRI = convertTripleToLinkId(link.target.iri);\n nodeCopy.oppTriplePred = getShortPredicate(link.target.iri.split(' ')[1]);\n }\n nodeCopy.pred = getShortPredicate(tripleNode.iri.split(' ')[1]);\n if (link.predicates.length === 1) {\n nodeCopy.linkPred = link.predicates[0];\n }\n return false;\n }\n if (link.target.iri === tripleNode.iri) {\n nodeCopy.iri = links[0].target.iri;\n if (link.source.isTriple) {\n nodeCopy.oppLinkIRI = convertTripleToLinkId(link.source.iri);\n nodeCopy.oppTriplePred = getShortPredicate(link.source.iri.split(' ')[1]);\n }\n nodeCopy.pred = getShortPredicate(tripleNode.iri.split(' ')[1]);\n if (link.predicates.length === 1) {\n nodeCopy.linkPred = link.predicates[0];\n }\n return false;\n }\n return true;\n });\n }\n }\n\n if (!nodeCopy.iri) {\n nodeCopy.iri = tripleNode.iri;\n nodeCopy.pred = getShortPredicate(tripleNode.iri.split(' ')[1]);\n }\n\n applyElementsStyleChanges(nodeCopy);\n }\n }\n\n function updatePredicatesColor(className, color, tripleNode) {\n let preds = document.getElementsByClassName(className);\n\n if (preds) {\n _.each(preds, function (pred) {\n let predLink = pred.__data__;\n if (tripleNode) {\n if (predLink.source.iri.indexOf(tripleNode.iri) >= 0 || predLink.target.iri.indexOf(tripleNode.iri) >= 0) {\n pred.style.fill = color;\n }\n if (convertTripleToLinkId(tripleNode.iri) === convertLinkDataToLinkId(predLink)) {\n pred.textContent = tripleNode.pred;\n pred.style.fill = color;\n }\n if (tripleNode.oppLinkIRI && tripleNode.oppLinkIRI === convertLinkDataToLinkId(predLink)) {\n pred.textContent = tripleNode.oppTriplePred;\n pred.style.fill = color;\n }\n } else {\n pred.style.fill = color;\n pred.textContent = getPredicate(predLink);\n }\n })\n }\n }\n\n function revertElementsStyleToDefault() {\n _.each($scope.predicates, function (pred) {\n let currEl = document.getElementById(pred.linkId + pred.nodeIndex);\n if (currEl) {\n currEl.style.fontWeight = \"normal\";\n }\n });\n let links = document.getElementsByClassName('link');\n if (links) {\n _.each(links, function (link) {\n link.style.stroke = '#999';\n link.style.strokeWidth = 1;\n })\n }\n updatePredicatesColor('predicate', '');\n updatePredicatesColor('predicates', '');\n\n let markers = document.getElementsByClassName('arrow-marker');\n\n if (markers) {\n _.each(markers, function (marker) {\n marker.style.stroke = '#999';\n // RefX for triple targets isn't changed, because they are not affected by increasing of stroke-width\n if (!marker.__data__.target.isTriple) {\n marker.setAttribute(\"refX\", \"59\");\n }\n });\n }\n }\n\n function linkActions(d) {\n revertElementsStyleToDefault();\n let linkId = convertLinkDataToLinkId(d);\n if (d.predicates.length === 1 && graph.tripleNodes.has(linkId)) {\n openedLink = null;\n let tripleNode = graph.tripleNodes.get(linkId)[0];\n // If there is a triple in this link, show its properties\n if (clickedNode(tripleNode, this, d3.event.button)) {\n let nodeCopy = {};\n nodeCopy.iri = tripleNode.iri;\n nodeCopy.pred = getShortPredicate(tripleNode.iri.split(' ')[1]);\n applyElementsStyleChanges(nodeCopy);\n }\n return;\n }\n openPredicates(d);\n }\n\n function openPredicates(d) {\n $scope.showNodeInfo = false;\n // open predicates sidebar if they are more than one\n $scope.showPredicates = d.predicates.length > 1;\n $scope.showFilter = false;\n $scope.showInfoPanel = false;\n\n if (openedLink === d) {\n $scope.showNodeInfo = false;\n $scope.showInfoPanel = false;\n openedLink = null;\n return;\n }\n\n openedLink = d;\n\n if ($scope.showPredicates) {\n $scope.predicates = _.map(d.predicates, function (p) {\n let foundNodeIndex = getTripleNodeIndex(p, d);\n let isPartOfTriple = foundNodeIndex > -1;\n return {\n value: getShortPredicate(p),\n partOfTriple: isPartOfTriple,\n linkId: isPartOfTriple ? convertLinkDataToLinkId(d) : '',\n nodeIndex: foundNodeIndex\n };\n });\n $scope.showInfoPanel = true;\n }\n }\n\n function getTripleNode(triple) {\n let linkId = convertTripleToLinkId(triple);\n if (graph.tripleNodes.has(linkId)) {\n return graph.tripleNodes.get(linkId).find(el => el.iri === triple);\n }\n }\n\n function getTripleNodeIndex(pred, d) {\n let linkId = convertLinkDataToLinkId(d);\n if (graph.tripleNodes.has(linkId)) {\n return graph.tripleNodes.get(linkId).findIndex(el => el.iri.indexOf(pred) >= 0);\n } else {\n return -1;\n }\n }\n\n // get each predicate and check if there are more than one for same source and target\n function getPredicate(d) {\n if (d.predicates.length > 1) {\n return d.predicates.length + \" predicates\";\n }\n return getShortPredicate(d.predicates[0]);\n }\n\n function getShortPredicate(p) {\n const shortIRI = $scope.replaceIRIWithPrefix(p);\n if (shortIRI.length === p.length) {\n return p.split('/')[p.split('/').length - 1];\n } else {\n return shortIRI;\n }\n }\n\n // calculate predicate text length so we can have dynamic link lengths\n function getPredicateTextLength(link) {\n const span = $('<span></span>');\n const splitedLink = link.predicates[0].split('/');\n const predicateText = splitedLink[splitedLink.length - 1];\n span.addClass('predicate-text').text(predicateText);\n $('body').append(span);\n const textLength = span.width() + link.source.size * 2 + link.target.size * 2 + 50;\n span.remove();\n return textLength * 0.75;\n }\n\n $scope.splitPredicate = function (predicate) {\n return predicate.split('/')[predicate.split('/').length - 1];\n };\n\n $scope.getActiveRepository = function () {\n return $repositories.getActiveRepository();\n };\n\n $scope.isLoadingLocation = function () {\n return $repositories.isLoadingLocation();\n };\n\n $scope.hasActiveLocation = function () {\n return $repositories.hasActiveLocation();\n };\n\n $scope.rotate = function (isLeft) {\n removeMenuIfVisible();\n\n // compute common rotation math such as the angle, its sine and cosine and the pivot point\n const theta = (isLeft ? 1 : -1) * 2 * Math.PI / 180; // + rotates left, - rotates right\n const cos = Math.cos(theta);\n const sin = Math.sin(theta);\n const pivotX = width / 2; // i.e. centre of viewport\n const pivotY = height / 2;\n\n // rotates each node around the pivot\n d3.selectAll(\".node-wrapper\")\n .each(function (d) {\n d.x = pivotX + (cos * (d.x - pivotX) + sin * (d.y - pivotY));\n d.y = pivotY + (-sin * (d.x - pivotX) + cos * (d.y - pivotY));\n if (d.fixed) {\n // Fixed nodes need their px and py updated too\n d.px = d.x;\n d.py = d.y;\n }\n });\n\n force.resume();\n };\n\n $scope.openUri = function (uri, noHistory) {\n if (!noHistory) {\n const searchParams = {};\n if ($scope.configLoaded.id !== $scope.defaultGraphConfig.id) {\n searchParams.config = $scope.configLoaded.id;\n }\n searchParams.uri = uri;\n $scope.pushHistory(searchParams, {uri: uri, config: $scope.configLoaded});\n }\n $scope.$broadcast(\"onRootNodeChange\", uri);\n };\n\n function saveGraphHttp(graph) {\n if ($scope.configLoaded) {\n graph.config = $scope.configLoaded.id;\n }\n SavedGraphsRestService.addNewSavedGraph(graph)\n .success(function (data, status, headers) {\n $scope.lastSavedGraphName = graph.name;\n $scope.lastSavedGraphId = headers()['x-saved-graph-id'];\n $scope.shared = graph.shared;\n $scope.refreshSavedGraphs();\n toastr.success($translate.instant('graphexplore.saved.graph', {name: graph.name}));\n })\n .error(function (data, status) {\n if (status === 422) {\n $scope.saveGraphModal('new', graph, true);\n } else {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.cannot.create.graph'));\n }\n });\n }\n\n $scope.saveOrUpdateGraph = function () {\n const data = JSON.stringify(graph.copyState());\n const graphToSave = {id: $scope.lastSavedGraphId, name: $scope.lastSavedGraphName, data: data, shared: $scope.shared};\n\n if (graphToSave.id) {\n $scope.saveGraphModal('update', graphToSave);\n } else {\n $scope.saveGraphModal('new', graphToSave);\n }\n };\n\n $scope.renameSavedGraph = function (graphToRename) {\n // By not sending the 'data' part of a graph we only change the name\n $scope.saveGraphModal('rename', {id: graphToRename.id, name: graphToRename.name, config: graphToRename.config, shared: graphToRename.shared});\n };\n\n const editSavedGraphHttp = function (savedGraph) {\n SavedGraphsRestService.editSavedGraph(savedGraph)\n .success(function () {\n $scope.lastSavedGraphName = savedGraph.name;\n $scope.shared = savedGraph.shared;\n $scope.refreshSavedGraphs();\n toastr.success($translate.instant('graphexplore.saved.graph.was.edited', {name: savedGraph.name}));\n })\n .error(function (data) {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.cannot.edit'));\n });\n };\n\n $scope.saveGraphModal = function (mode, graphToSave, graphExists) {\n const modalInstance = $modal.open({\n templateUrl: 'js/angular/graphexplore/templates/modal/save-graph.html',\n controller: 'SaveGraphModalCtrl',\n resolve: {\n data: function () {\n return {\n mode: mode,\n graph: graphToSave,\n graphExists: graphExists,\n shared: graphToSave.shared\n };\n }\n }\n });\n\n modalInstance.result.then(function (data) {\n if (data.restart) {\n $scope.saveGraphModal(data.mode, data.graph, false);\n return;\n }\n switch (data.mode) {\n case 'new':\n saveGraphHttp(data.graph);\n break;\n case 'update':\n editSavedGraphHttp(data.graph);\n break;\n case 'rename':\n editSavedGraphHttp(data.graph);\n break;\n }\n });\n };\n\n $scope.refreshSavedGraphs = function () {\n SavedGraphsRestService.getSavedGraphs()\n .success(function (data) {\n $scope.savedGraphs = data;\n })\n .error(function (data) {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.getting.saved.graphs'));\n });\n };\n\n\n $scope.loadSavedGraph = function (graphToLoad, noHistory) {\n if (graphToLoad.owner) {\n // Own saved graph\n $scope.lastSavedGraphName = graphToLoad.name;\n $scope.lastSavedGraphId = graphToLoad.id;\n $scope.shared = graphToLoad.shared;\n $scope.configLoaded = $scope.findConfigById(graphToLoad.config);\n } else {\n // Someone else's saved graph\n $scope.lastSavedGraphName = null;\n $scope.lastSavedGraphId = null;\n $scope.shared = graphToLoad.shared;\n }\n\n if (!$scope.configLoaded) {\n // Fallback to default config, either because config is gone or because graph isn't owned\n $scope.configLoaded = $scope.defaultGraphConfig;\n }\n\n $location.url(\"?saved=\" + graphToLoad.id);\n graph.restoreState(JSON.parse(graphToLoad.data));\n if (!noHistory) {\n $scope.pushHistory({saved: graphToLoad.id}, {savedGraph: graphToLoad});\n }\n };\n\n $scope.copyToClipboardSavedGraph = function (savedGraph) {\n const url = [location.protocol, '//', location.host, location.pathname, '?saved=', savedGraph.id].join('');\n copyToClipboard(url);\n };\n\n function deleteSavedGraphHttp(savedGraph) {\n SavedGraphsRestService.deleteSavedGraph(savedGraph)\n .success(function () {\n $scope.refreshSavedGraphs();\n toastr.success($translate.instant('graphexplore.saved.graph.was.deleted', {name: savedGraph.name}));\n })\n .error(function (data) {\n const msg = getError(data);\n toastr.error(msg, $translate.instant('graphexplore.error.cannot.delete'));\n });\n }\n\n $scope.deleteSavedGraph = function (savedGraph) {\n ModalService.openSimpleModal({\n title: $translate.instant('common.confirm'),\n message: $translate.instant('graphexplore.confirm.delete.graph', {graphName: savedGraph.name}),\n warning: true\n }).result\n .then(function () {\n deleteSavedGraphHttp(savedGraph);\n });\n };\n\n $scope.openIRI = function (link, event) {\n if (event.shiftKey) {\n $scope.$broadcast(\"onRootNodeChange\", link);\n } else {\n window.open(link, '_blank');\n }\n return false;\n };\n\n $scope.togglePinAllNodes = function () {\n removeMenuIfVisible();\n\n const value = $scope.numberOfPinnedNodes <= 0;\n\n $scope.numberOfPinnedNodes = 0;\n d3.selectAll('.node').each(function (d) {\n d.fixed = value;\n if (value) {\n $scope.numberOfPinnedNodes++;\n }\n });\n\n force.resume();\n };\n\n // event for capturing left and right arrows used for rotation\n $('body').on(\"keydown\", function (event) {\n if (event.target.nodeName === 'input' || !$scope.nodeSelected) {\n // don't do anything when the target is an input field or no node is selected\n } else if (event.keyCode === 37) {\n // left arrow rotates left\n $scope.rotate(true);\n } else if (event.keyCode === 39) {\n // right arrow rotates right\n $scope.rotate(false);\n }\n });\n\n $scope.getLiteralFromPropValue = function (value) {\n return value.substring(value.indexOf(':') + 1);\n }\n}\n\nSaveGraphModalCtrl.$inject = ['$scope', '$modalInstance', 'data', '$translate'];\n\nfunction SaveGraphModalCtrl($scope, $modalInstance, data, $translate) {\n $scope.mode = data.mode;\n $scope.graph = angular.copy(data.graph);\n $scope.graphExists = data.graphExists;\n\n switch ($scope.mode) {\n case 'new':\n $scope.title = $translate.instant('graphexplore.create.new.graph');\n $scope.okButtonText = $translate.instant('common.create.btn');\n break;\n case 'update':\n $scope.title = $translate.instant('graphexplore.update');\n $scope.okButtonText = $translate.instant('common.save.btn');\n break;\n case 'rename':\n $scope.title = $translate.instant('graphexplore.rename');\n $scope.okButtonText = $translate.instant('common.save.btn');\n }\n\n $scope.ok = function () {\n if ($scope.form.$valid) {\n $modalInstance.close({graph: $scope.graph, mode: $scope.mode});\n }\n };\n\n $scope.saveNew = function () {\n $scope.graph.name = $scope.graph.name + ' (new)';\n $modalInstance.close({graph: $scope.graph, mode: 'new', restart: true});\n };\n\n $scope.cancel = function () {\n $modalInstance.dismiss('cancel');\n };\n}\n"],"sourceRoot":""}
|