portfolio/assets/js/portfolio.min.js.map

1 line
68 KiB
Plaintext

{"version":3,"sources":["portfolio.js"],"names":["data","graph","getLabelAttribute","node","getNodeLabel","label","getNodeYear","n","substr","console","match","getDisplayAttr","attr","replace","jsonLdToGraph","nodes","links","nodeId","nodeAttr","Array","isArray","key","i","currentId","name","Object","keys","length","source","target","nodeMap","linkMap","breadcrumbs","requestPromise","values","then","startGraph","fetch","Math","abs","dx","r","dxAbs","dyAbs","pow","dy","_iteratorNormalCompletion","_didIteratorError","_iteratorError","undefined","_step","_iterator","Symbol","iterator","next","done","link","value","id","err","return","nodeSize","selectedNodeSize","hasOwnProperty","firstNodeId","min","createBreadcrumbs","srcId","crumbs","createBreadcrumbLayer","newPath","slice","push","nextSrcIds","_iteratorNormalCompletion2","_didIteratorError2","_iteratorError2","_step2","_iterator2","nextIds","getSizeForNode","newNextIds","_iteratorNormalCompletion3","_didIteratorError3","_iteratorError3","_step3","_iterator3","concat","nodePositions","currentNodePositionRadius","types","nodeIdx","createLinkMap","type","document","getElementById","typeLinksEl","showMoreTypeLinksEl","moreTypeLinksEl","typeCounts","map","sort","first","second","_loop","typeCountIdx","typeName","createElement","typeLinkCountEl","classList","add","typeLinkAEl","innerHTML","title","addEventListener","centerByType","typeNodeEls","_iteratorNormalCompletion7","_didIteratorError7","_iteratorError7","_iterator7","getElementsByClassName","_iteratorNormalCompletion8","_didIteratorError8","_iteratorError8","_step8","_iterator8","remove","typeLinkEl","append","appendChild","body","hideMoreTypeLinks","e","preventDefault","stopPropagation","forceCx","forceCy","container","svg","simulation","d3","forceSimulation","d","strength","force","forceManyBody","graphControlsEl","selectAll","enter","l","linkLine","baseClasses","typeNodeEl","lastIndexOf","slashpos","getViewbox","split","parseFloat","positionNodesInCenter","idxs","setViewboxForceCenter","_typeof","positionNodesInCircle","nodeEls","nIdx","viewBox","select","max","zoom","sin","stepSize","cos","alpha","updateHistory","linkText","idx","deselectNode","log","history","join","transition","ease","easeLinear","createRelationshipEl","relNode","el","titleEl","indexOf","selectNode","typeEl","nodeEl","nodeDatum","listEl","startsWith","valueHtml","nodeDetailEl","pushState","replaceState","currentCrumbs","linkedIdxs","relDown","linkEls","relUp","setAttribute","filter","a","fnodeIdx","classed","attrEl","relsEl","rel","posTrg","ddEl","posSrc","getElementsByTagName","poster","splice","hasChildNodes","removeChild","lastChild","nodeDetailScalerEl","width","innerWidth","drag","nodeDetails","breadcrumbsEl","_loop2","crumbNodeId","crumbWrapEl","crumbEl","nodeYear","pageTitles","_iteratorNormalCompletion4","_didIteratorError4","_iteratorError4","_step4","_iterator4","titleAttr","skipNodeAttributes","setDetails","scrollToY","videoType","window","event","state","firstNode","find","closeDetails","getZoomValues","zoomContainer","scale","transform","baseVal","_iteratorNormalCompletion5","_didIteratorError5","_iteratorError5","_step5","_iterator5","SVGTransform","SVG_TRANSFORM_TRANSLATE","matrix","f","SVG_TRANSFORM_SCALE","graphInitialised","each","k","fy","x","vy","vx","y","fx","self","titleText","textLength","getComputedTextLength","restart","active","alphaTarget","on","q","hoverLinkEls","call","scaleExtent","text","this","titleTexts","mid","floor","splitPos","_iteratorNormalCompletion6","_didIteratorError6","_iteratorError6","_step6","_iterator6","char","tmid","splitPosChar","text1","trim","splitText","dragstarted","tspan","textLength1","textLength2","rightX","midX","angle","leftX","targetX","isCircle","sourceX","atan2","srcSize","tgtSize","sourceY","nodeTitle","targetY","PI","tspan1","deg","location","ticked","pathname","t","startNodeId","search","setTimeout","reqAnimFrame","callback","scrollTargetY","speed","easing","finishFunction","scrollY","currentTime","time","pos","easeInOutSine","easeInOutQuint","p","easingEquations","tick","scrollTo"],"mappings":"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","file":"portfolio.min.js","sourcesContent":["var data;\n\nfunction getLabelAttribute(node) {\n if(typeof node['https://schema.org/name'] !== \"undefined\"){\n return 'https://schema.org/name';\n }\n switch (node['@type']) {\n case \"https://schema.org/WebSite\":\n if(typeof node['https://schema.org/url'] !== \"undefined\") {return 'https://schema.org/url';}\n break;\n case \"https://schema.org/ImageObject\":\n if(typeof node['https://schema.org/caption'] !== \"undefined\") {return 'https://schema.org/caption';}\n if(typeof node['https://schema.org/contentUrl'] !== \"undefined\") {return 'https://schema.org/contentUrl';}\n break;\n case \"https://schema.org/PostalAddress\":\n if(typeof node['https://schema.org/addressLocality'] !== \"undefined\") {return 'https://schema.org/addressLocality';}\n break;\n }\n return '@id';\n}\nfunction getNodeLabel(node){\n let labelAttr = getLabelAttribute(node);\n let label = node[labelAttr];\n if(typeof label == \"undefined\") label = node[\"@id\"];\n if(typeof label == \"undefined\") label = \"\";\n return label;\n}\nfunction getNodeYear(n){\n if(typeof n['https://schema.org/dateCreated'] !== 'undefined') {\n return n['https://schema.org/dateCreated'].substr(0,4);\n }\n if(typeof n['https://schema.org/datePublished'] !== 'undefined') {\n return n['https://schema.org/datePublished'].substr(0,4);\n }\n if(typeof n['https://schema.org/startDate'] !== 'undefined') {\n console.log(n['https://schema.org/startDate']);\n return n['https://schema.org/startDate'].substr(0,4);\n }\n if(typeof n['https://schema.org/endDate'] !== 'undefined') {\n return n['https://schema.org/endDate'].substr(0,4);\n }\n if(typeof n['https://schema.org/foundingDate'] !== 'undefined') {\n return n['https://schema.org/foundingDate'].substr(0,4);\n }\n if(typeof n['https://schema.org/temporalCoverage'] !== 'undefined') {\n if(n['https://schema.org/temporalCoverage'].match(/\\d{4}-\\d{4}/)) {\n return n['https://schema.org/temporalCoverage'].substr(5,4);\n }\n }\n return null;\n}\nfunction getDisplayAttr(attr) {\n return attr.replace(/.*[#|\\/]/, \"\");\n}\n/**\nTransform a flattened jsonld into a d3 compatible graph\n@param Object data flattened jsonld data\n@return Object graph has keys \"nodes\" and \"links\"\n*/\nfunction jsonLdToGraph(data){\n let nodes = {};\n let links = [];\n\n // collect all nodes\n for(let nodeId in data){\n // data[nodeId][\"@type\"][0] = data[nodeId][\"@type\"][0];\n nodes[data[nodeId][\"@id\"]] = data[nodeId];\n }\n\n // collect all links (separate loop as we need to check nodes)\n for(let nodeId in data) {\n let node = data[nodeId];\n let currentId = node[\"@id\"];\n for(let key in node){\n let nodeAttr = Array.isArray(node[key]) ? node[key] : [node[key]];\n // // relations should always be lists (eases assumptions)\n // if(typeof node[key] !== \"Array\" && typeof node[key]['id'] !== \"undefined\") {\n // node[key] = [node[key]];\n // }\n // every attribute is an Array after flatten(), loop them\n for(let i in nodeAttr) {\n if(key !== \"@id\" && typeof nodeAttr[i] === \"string\" && nodes[nodeAttr[i]]) {\n links[links.length] = {\n \"source\": currentId,\n \"target\": nodeAttr[i],\n \"name\": key\n };\n }\n else if(typeof nodeAttr[i][\"@id\"] !== \"undefined\") {\n // if there is just one item, flatten/expand has turned urls in objects with just an id\n // reverse this, as we don't want these separate for this project\n if (Object.keys(nodeAttr[i]).length == 1 && typeof nodes[nodeAttr[i][\"@id\"]] === \"undefined\") {\n // skip\n // nodeAttr = nodeAttr[i][\"id\"];\n } else {\n links[links.length] = {\n \"source\": currentId,\n \"target\": nodeAttr[i][\"@id\"],\n \"name\": key\n };\n }\n }\n }\n }\n }\n return {\n \"nodes\": Object.values(nodes),\n \"links\": links\n };\n}\n\nvar graph;\n// map nodes to their ID\nvar nodeMap = {};\nvar linkMap = {};\nvar breadcrumbs = {};\n// load the flattened jsonld file\nconst requestPromise = fetch('/assets/js/rubenvandeven.jsonld')\n .then(r => r.json())\n .then(data => {\n graph = jsonLdToGraph(data['@graph']);\n // create a map of nodes by id.\n for(let i in graph.nodes) {\n nodeMap[graph.nodes[i]['@id']] = graph.nodes[i];\n }\n startGraph(graph);\n });\n\nfunction inCircle(dx, dy, r) {\n // fastest check if in circle: https://stackoverflow.com/a/7227057\n let dxAbs = Math.abs(dx);\n let dyAbs = Math.abs(dy);\n\n if(dxAbs > r || dyAbs > r) {\n return false;\n } else if(dxAbs + dyAbs <= r){\n return true;\n } else if( Math.pow(dx,2) + Math.pow(dy, 2) <= Math.pow(r,2)){\n return true;\n } else {\n return false;\n }\n}\n\nfunction createLinkMap(graph) {\n let linkMap = {};\n for(let link of graph['links']){\n if(typeof linkMap[link['source']] == 'undefined') {\n linkMap[link['source']] = [];\n }\n linkMap[link['source']][linkMap[link['source']].length] = {'id': link['target'], 'name': link['name']};\n\n\n if(typeof linkMap[link['target']] == 'undefined') {\n linkMap[link['target']] = [];\n }\n\n linkMap[link['target']][linkMap[link['target']].length] = {'id': link['source'], 'name': link['name']};\n }\n return linkMap;\n}\n\n\n // config\nvar nodeSize = 40;\nvar selectedNodeSize = 140;\nvar firstNodeId = \"https://rubenvandeven.com/\";\n\nfunction getSizeForNode(node) {\n if(node.hasOwnProperty('https://schema.org/thumbnailUrl'))\n return nodeSize;\n //if(weights[node['@id']])\n // return nodeSize * weights[node['@id']];\n if(node['@id'] == firstNodeId)\n return nodeSize*1.2;\n // everynode has at least one link. these should equal 1\n return nodeSize * (.7 + Math.min(20, linkMap[node['@id']].length) / 40)\n return nodeSize;\n}\n\n// TODO: make sure, 'shortest' path is favoured.\nfunction createBreadcrumbs(linkMap, srcId) {\n let crumbs = {};\n\n let createBreadcrumbLayer = function(srcId) {\n let path = crumbs[srcId];\n let newPath = path.slice();\n newPath.push(srcId);\n\n let nextSrcIds = [];\n for (let link of linkMap[srcId]) {\n if(typeof crumbs[link['id']] !== 'undefined') continue;\n crumbs[link['id']] = newPath;\n nextSrcIds.push(link['id']);\n }\n\n return nextSrcIds;\n }\n crumbs[srcId] = [];\n let nextIds = [srcId];\n while(nextIds.length > 0) {\n let newNextIds = [];\n for (let nextId of nextIds) {\n let r = createBreadcrumbLayer(nextId);\n newNextIds = newNextIds.concat(r);\n }\n nextIds = newNextIds;\n }\n return crumbs;\n}\n\nvar nodePositions = {};\nfunction startGraph(graph){\n\n\n// set some vars\nvar currentNodeIdx = 0;\nvar currentNodePositionRadius = 0;\nvar types = {};\n\nlinkMap = createLinkMap(graph);\nbreadcrumbs = createBreadcrumbs(linkMap, firstNodeId);\n\nfor (let nodeIdx in graph['nodes']) {\n let type = graph['nodes'][nodeIdx][\"@type\"];\n if(typeof types[type] == 'undefined') {\n types[type] = [];\n }\n types[type].push(nodeIdx);\n}\nvar graphControlsEl = document.getElementById('graphControls');\nvar typeLinksEl = document.getElementById('typeLinks');\nvar showMoreTypeLinksEl = document.getElementById('showMoreTypeLinks');\nvar moreTypeLinksEl = document.getElementById('moreTypeLinks');\nvar relLinksEl = document.getElementById('relLinks');\n\n// sort types by count:\nvar typeCounts = Object.keys(types).map(function(key) {\n return [key, types[key].length];\n});\ntypeCounts.sort(function(first, second) {\n return second[1] - first[1];\n});\n\n// make controls\nlet i = 0;\nfor (let typeCountIdx in typeCounts) {\n let typeName = typeCounts[typeCountIdx][0];\n let typeLinkEl = document.createElement(\"li\");\n let typeLinkAEl = document.createElement(\"a\");\n let typeLinkCountEl = document.createElement(\"span\");\n typeLinkCountEl.innerHTML = typeCounts[typeCountIdx][1];\n typeLinkCountEl.classList.add('typeCount');\n typeLinkAEl.innerHTML = getDisplayAttr(typeName);\n typeLinkAEl.title = typeName;\n typeLinkAEl.addEventListener('click', function(){\n centerByType(typeName);\n // positionNodesInCenter(types[typeName]);\n });\n typeLinkAEl.addEventListener('mouseover', function() {\n let typeNodeEls = document.getElementsByClassName(typeName);\n for(let typeNodeEl of typeNodeEls) {\n typeNodeEl.classList.add('typeHighlight');\n }\n });\n typeLinkAEl.addEventListener('mouseout', function() {\n let typeNodeEls = document.getElementsByClassName(typeName);\n for(let typeNodeEl of typeNodeEls) {\n typeNodeEl.classList.remove('typeHighlight');\n }\n });\n typeLinkEl.append(typeLinkAEl);\n typeLinkEl.append(typeLinkCountEl);\n (i < 5 ? typeLinksEl: moreTypeLinksEl).appendChild(typeLinkEl);\n i++;\n // typeLinksEl.appendChild(typeLinkEl);\n}\n\nshowMoreTypeLinksEl.addEventListener('click', function () {\n document.body.classList.add('showMoreLinks');\n var hideMoreTypeLinks = function(e) {\n e.preventDefault();\n e.stopPropagation();\n document.body.removeEventListener('mouseup', hideMoreTypeLinks, true);\n document.body.classList.remove('showMoreLinks');\n }\n document.body.addEventListener('mouseup', hideMoreTypeLinks, true);\n}, false)\n\n\n// make svg\nvar svg = d3.select(\"svg\"),\n width = +svg.attr(\"width\"),\n height = +svg.attr(\"height\");\nvar container = svg.append(\"g\")\n .attr(\"id\", \"container\")\n ;\n\nvar simulation = d3.forceSimulation()\n .force(\"link\", d3.forceLink().id(function(d) { return d[\"@id\"]; }).strength(.005))\n .force(\"charge\", d3.forceManyBody()) // doesn't seem necessary?\n .force(\"collision\", d3.forceCollide(function(d){\n return getSizeForNode(d) * 1.1; // avoid overlapping nodes\n }))\n // .force(\"center\", d3.forceCenter(width / 2, height / 2)) // position around center\n\n // .force(\"x\", d3.forceX())\n // .force(\"y\", d3.forceY())\n // .force(\"y\", d3.forceY())\n ;\n\n\nvar link = container.append(\"g\")\n .attr(\"class\", \"links\")\n .selectAll(\".relationship\")\n .data(graph['links'])\n .enter().append(\"g\")\n .attr(\"class\", function(l){return \"relationship \"+l.name;})\n ;\nvar linkLine = link\n // .append(\"line\");\n .append(\"line\").attr(\"marker-end\", \"url(#arrowHead)\")\n ;\nvar linkText = link\n .append(\"text\")\n .text(function(l){\n // l == Object { source: \"https://rubenvandeven.com/#codesandmodes\", target: \"_:b34\", name: \"https://schema.org/location\" }\n return getDisplayAttr(l.name);\n })\n ;\n\n var node = container.append(\"g\")\n .attr(\"class\", \"nodes\")\n .selectAll(\".node\")\n .data(graph.nodes)\n .enter().append(\"g\")\n .attr(\"class\", function(d) {\n let baseClasses = 'node ' + d['@type'];\n if(d['@type']) {\n let slashpos = d['@type'].lastIndexOf('/');\n if(slashpos > -1) {\n baseClasses += ' ' + d['@type'].substr(slashpos + 1);\n }\n }\n return baseClasses;\n })\n ;\nvar getViewbox = function() {\n return svg.attr(\"viewBox\").split(\" \").map(parseFloat);\n}\nvar positionNodesInCenter = function(idxs) {\n setViewboxForceCenter(); // sets forceCx & forceCy\n if(typeof idxs == \"object\" && idxs !== null && idxs.length == 1) {\n idxs = idxs[0];\n }\n\n nodePositions = {}; // reset\n if(idxs === null) {\n return;\n }\n else if(typeof idxs == \"object\") {\n // array or object -> each\n // calculate grid:\n // let itemsX = 4;\n // let itemsY = Math.ceil(idxs.length/itemsX);\n // console.log(itemsX,itemsY);\n // let rowDiffX = viewBox[3] * (1/(itemsX+1));\n // let rowDiffY = viewBox[2] * (1/(itemsY+1));\n // console.log(rowDiffX, rowDiffY);\n // for (var i = 0; i < idxs.length; i++) {\n // nodePositions[idxs[i]] = [\n // cx - itemsX/2*rowDiffX + rowDiffX * ((i % itemsX)),\n // cy - itemsY/2*rowDiffY + rowDiffY * (Math.floor(i / itemsX))\n // ];\n // }\n positionNodesInCircle(idxs);\n // console.log(nodePositions);\n }\n else{\n nodePositions[idxs] = [\n forceCx,\n forceCy\n ];\n // console.log(\"singleNode\", idxs, nodePositions);\n }\n\n node.each(function(d,nIdx,nodeEls){\n if(typeof nodePositions[nIdx] != 'undefined') {\n nodeEls[nIdx].classList.add('centeredNode');\n nodeEls[nIdx].classList.add('visibleNode');\n } else {\n nodeEls[nIdx].classList.remove('centeredNode');\n nodeEls[nIdx].classList.remove('visibleNode');\n }\n });\n\n // restart animation (they call that 'alpha' in d3 force)\n simulation.alpha(1);\n simulation.restart();\n}\nvar positionNodesInCircle = function(idxs, r) {\n let viewBox = getViewbox();\n let zoom = getZoomValues();\n setViewboxForceCenter(); // sets forceCx & forceCy\n if(typeof r == 'undefined') {\n if(idxs.length == 1) {\n r = viewBox[2] / 6;\n } else {\n r = viewBox[2] / (4 + Math.max(0, 2.5 - idxs.length));\n }\n }\n currentNodePositionRadius = r;\n let forceCx = viewBox[0] + viewBox[2]/2 - zoom['dx'];\n let forceCy = viewBox[1] + viewBox[3]/2 - zoom['dy'];\n\n let stepSize = 2*Math.PI / idxs.length;\n\n for (var i = 0; i < idxs.length; i++) {\n nodePositions[idxs[i]] = [\n forceCx + Math.sin(stepSize * i) * r,\n forceCy + Math.cos(stepSize * i) * r\n ];\n }\n\n // restart animation (they call that 'alpha' in d3 force)\n simulation.alpha(1);\n simulation.restart();\n}\nvar centerByType = function(types, updateHistory) {\n if(typeof updateHistory == 'undefined') {\n updateHistory = true;\n }\n if(!Array.isArray(types)) {\n types = [types];\n }\n let idxs = [];\n for(let idx in graph.nodes) {\n if(types.indexOf(graph.nodes[idx]['@type']) > -1) {\n idxs[idxs.length] = idx;\n }\n }\n deselectNode();\n if(updateHistory) {\n // TODO: working\n console.log(types[0], getDisplayAttr(types[0]),types.map(getDisplayAttr));\n history.pushState({types: types}, \"\", \"/@type/\"+(types.map(getDisplayAttr).join(\"+\")));\n } else {\n history.replaceState({types: types}, \"\", \"/@type/\"+(types.map(getDisplayAttr).join(\"+\")));\n }\n positionNodesInCenter(idxs.length ? idxs : null);\n}\n\nvar selectedNodeTransition = d3.transition()\n .duration(750)\n .ease(d3.easeLinear);\n\nvar nodeDetailEl = document.getElementById(\"nodeDetails\");\n\nvar createRelationshipEl = function(relNode, i) {\n let el = document.createElement(\"dd\");\n el.classList.add('relLink');\n let titleEl = document.createElement('a');\n titleEl.innerHTML = getNodeLabel(relNode)\n let year = getNodeYear(relNode);\n if(year !== null) {\n titleEl.innerHTML += `<span class='nodeYear'>${getNodeYear(relNode)}</span>`;\n }\n titleEl.classList.add('nodeTitle');\n titleEl.classList.add('nodeTitleNr'+i);\n titleEl.addEventListener('click',function(e){\n let idx = graph.nodes.indexOf(relNode);\n selectNode(idx);\n });\n let typeEl = document.createElement('a');\n typeEl.classList.add('nodeType');\n typeEl.innerHTML = getDisplayAttr(relNode['@type']);\n typeEl.title = relNode['@type'];\n typeEl.addEventListener('click',function(e){\n centerByType(relNode['@type']);\n });\n el.appendChild(titleEl);\n el.appendChild(typeEl);\n return el;\n}\n\nvar setDetails = function(nodeDatum, nodeIdx) {\n document.body.classList.add(\"detailsOpen\");\n scrollToY(0, 4000);\n while (nodeDetailEl.hasChildNodes()) {\n nodeDetailEl.removeChild(nodeDetailEl.lastChild);\n }\n\n // TODO: replace relUp & relDown with linkMap\n let relUp = [];\n let relDown = [];\n let pageTitles = [];\n let nodeDetailScalerEl = document.createElement('div');\n // nodeDetailScalerEl.innerHTML = `<div id='scalarbar'></div>`;\n nodeDetailScalerEl.id = 'nodeDetailsScaler';\n nodeDetailScalerEl.addEventListener('mousedown', function(e){\n // console.log('go');\n let drag = function(e) {\n // 5px for padding\n nodeDetailEl.style.width = (window.innerWidth - e.clientX + 5) +'px';\n }\n document.body.addEventListener('mousemove', drag);\n document.body.addEventListener('mouseup', function(){\n document.body.removeEventListener('mousemove', drag);\n });\n });\n nodeDetails.appendChild(nodeDetailScalerEl);\n\n let breadcrumbsEl = document.createElement('ul');\n breadcrumbsEl.classList.add('breadcrumbs');\n for(let crumbNodeId of breadcrumbs[nodeDatum['@id']]) {\n let crumbWrapEl = document.createElement('li');\n let crumbEl = document.createElement('span');\n crumbEl.classList.add('crumb');\n crumbEl.addEventListener('click', function(e){\n let idx = graph.nodes.indexOf(nodeMap[crumbNodeId]);\n selectNode(idx);\n });\n crumbEl.innerHTML = `${getNodeLabel(nodeMap[crumbNodeId])}`;\n let nodeYear = getNodeYear(nodeMap[crumbNodeId]);\n if(nodeYear !== null) {\n crumbEl.innerHTML += `<span class='nodeYear'>${nodeYear}</span>`;\n }\n crumbWrapEl.appendChild(crumbEl);\n breadcrumbsEl.appendChild(crumbWrapEl);\n pageTitles.push(getNodeLabel(nodeMap[crumbNodeId]));\n }\n nodeDetailEl.appendChild(breadcrumbsEl);\n pageTitles.push(getNodeLabel(nodeDatum));\n\n let titleAttr = getLabelAttribute(nodeDatum);\n let titleEl = document.createElement('h2');\n titleEl.innerHTML = getNodeLabel(nodeDatum);\n\n let typeEl = document.createElement('span');\n typeEl.classList.add('nodeType')\n typeEl.innerHTML = getDisplayAttr(nodeDatum['@type']);\n typeEl.title = nodeDatum['@type']\n typeEl.addEventListener('click',function(e){\n centerByType(nodeDatum['@type']);\n });\n titleEl.appendChild(typeEl);\n nodeDetailEl.appendChild(titleEl);\n\n let listEl = document.createElement(\"dl\");\n // listEl.innerHTML += `<dt>type</dt><dd>${nodeDatum['@type']}</dd>`;\n\n let skipNodeAttributes = [\n '@id','x','y','index','@type','vy','vx','fx','fy','leftX','rightX'\n ];\n if(titleAttr !== 'https://schema.org/contentUrl') {\n skipNodeAttributes[skipNodeAttributes.length] = titleAttr;\n }\n for (let attr in nodeDatum) {\n if(skipNodeAttributes.indexOf(attr) != -1) {\n continue;\n }\n\n // approach all as array\n let nodeAttr = Array.isArray(nodeDatum[attr]) ? nodeDatum[attr] : [nodeDatum[attr]];\n for (let i in nodeAttr) {\n // check if relationship:\n if(typeof nodeAttr[i] === \"string\" && nodeMap[nodeAttr[i]]) {\n continue;\n } else if(typeof nodeAttr[i]['@id'] !== 'undefined') {\n continue;\n }\n if(attr == 'https://schema.org/url' || attr == 'http://www.w3.org/2000/01/rdf-schema#seeAlso') {\n listEl.innerHTML += `<dt class='dt-${getDisplayAttr(attr)}' title='${attr}'>${getDisplayAttr(attr)}</dt><dd class='dd-${getDisplayAttr(attr)}'><a href='${nodeAttr[i]}'>${nodeAttr[i]}</a></dd>`;\n } else if(attr == 'https://schema.org/embedUrl') {\n listEl.innerHTML += `<dt class='dt-${getDisplayAttr(attr)}' title='${attr}'>${getDisplayAttr(attr)}</dt><dd class='dd-${getDisplayAttr(attr)}'><a href='${nodeAttr[i]}'>${nodeAttr[i]}</a></dd>`;\n listEl.innerHTML += `<dd class='dd-embed'><embed src='${nodeAttr[i]}'></embed></dd>`;\n } else if(attr == 'https://schema.org/contentUrl') {\n listEl.innerHTML += `<dt class='dt-${getDisplayAttr(attr)}' title='${attr}'>${getDisplayAttr(attr)}</dt><dd class='dd-${getDisplayAttr(attr)}'><a href='${nodeAttr[i]}'>${nodeAttr[i]}</a></dd>`;\n if(nodeDatum['@type'] == 'https://schema.org/VideoObject') {\n let videoType = nodeAttr['https://schema.org/encodingFormat'] ? `type='${nodeAttr['https://schema.org/encodingFormat']}'`: \"\";\n let poster = nodeAttr['https://schema.org/thumbnailUrl'] ? `poster='${nodeAttr['https://schema.org/thumbnailUrl']}'`: \"\";\n listEl.innerHTML += `<dd class='dd-contentobject'><video controls ${poster} autoplay><source src='${nodeAttr[i]}' ${videoType}></video></dd>`;\n } else{\n listEl.innerHTML += `<dd class='dd-contentobject'><object data='${nodeAttr[i]}'></object></dd>`;\n }\n } else {\n let valueHtml = nodeAttr[i].replace(/\\n/g,\"<br>\");\n listEl.innerHTML += `<dt class='dt-${getDisplayAttr(attr)}' title='${attr}'>${getDisplayAttr(attr)}</dt><dd class='dd-${getDisplayAttr(attr)}'>${valueHtml}</dd>`;\n }\n }\n }\n nodeDetailEl.appendChild(listEl);\n\n // let relTitleEl = document.createElement(\"h4\");\n // relTitleEl.classList.add('linkTitle');\n // relTitleEl.innerHTML = \"links\";\n // nodeDetailEl.appendChild(relTitleEl);\n\n let relsEl = document.createElement(\"dl\");\n // collect relationships\n for (var i = 0; i < graph.links.length; i++) {\n let link = graph.links[i];\n if(link['source']['@id'] == nodeDatum['@id']) {\n if(typeof relDown[link['name']] == \"undefined\") {\n relDown[link['name']] = [];\n }\n relDown[link['name']][relDown[link['name']].length] = link['target'];\n }\n if(link['target']['@id'] == nodeDatum['@id']) {\n if(typeof relUp[link['name']] == \"undefined\") {\n relUp[link['name']] = [];\n }\n relUp[link['name']][relUp[link['name']].length] = link['source'];\n }\n }\n\n // relationships / links in <dl>\n for(let attr in relDown) {\n let attrEl = document.createElement(\"dt\");\n attrEl.innerHTML = getDisplayAttr(attr);\n relsEl.appendChild(attrEl);\n for(let i in relDown[attr]) {\n let rel = relDown[attr][i];\n relsEl.appendChild(createRelationshipEl(rel));\n if(typeof rel['https://schema.org/contentUrl'] != 'undefined') {\n let ddEl = document.createElement('dd')\n ddEl.classList.add('dd-contentobject');\n if(rel['@type'] == 'https://schema.org/VideoObject') {\n let videoType = rel['https://schema.org/encodingFormat'] ? `type='${rel['https://schema.org/encodingFormat']}'`: \"\";\n let poster = rel['https://schema.org/thumbnailUrl'] ? `poster='${rel['https://schema.org/thumbnailUrl']}'`: \"\";\n ddEl.innerHTML += `<video controls preload=\"none\" ${poster}><source src='${rel['https://schema.org/contentUrl']}' ${videoType}></video>`;\n } else{\n ddEl.innerHTML = `<object data='${rel['https://schema.org/contentUrl']}'></object>`\n }\n relsEl.appendChild(ddEl);\n }\n }\n }\n\n for(let attr in relUp) {\n let attrEl = document.createElement(\"dt\");\n attrEl.innerHTML = getDisplayAttr(attr);\n relsEl.appendChild(attrEl);\n for(let i in relUp[attr]) {\n let rel = relUp[attr][i];\n relsEl.appendChild(createRelationshipEl(rel, i));\n if(typeof rel['https://schema.org/contentUrl'] != 'undefined') {\n let ddEl = document.createElement('dd')\n ddEl.classList.add('dd-contentobject');\n ddEl.innerHTML = `<object data='${rel['https://schema.org/contentUrl']}'></object>`\n relsEl.appendChild(ddEl);\n }\n }\n }\n\n nodeDetailEl.appendChild(relsEl);\n\n node.each(function(d,nIdx,nodeEls){\n if(nIdx == nodeIdx) {\n nodeEls[nIdx].classList.add('selectedNode');\n } else {\n nodeEls[nIdx].classList.remove('selectedNode');\n }\n });\n\n // TODO: update history & title\n document.title = pageTitles.join(\" :: \");\n};\nvar closeDetails = function() {\n document.body.classList.remove(\"detailsOpen\");\n scrollToY(0, 4000); // for mobile\n}\n\n/**\n * Select a node, and center it + show details\n * @param int idx The index of the node in the graph.nodes array\n * @param Element|null nodeEl Optional, provide node element, so loop doesn't have to be used to change the Element\n * @return void\n */\nvar selectNode = function(idx, updateHistory){\n if(typeof updateHistory == 'undefined') {\n updateHistory = true;\n }\n\n let nodeEl = null;\n let nodeDatum = null;\n\n node.each(function(d,nIdx,nodeEls){\n if(nIdx == idx) {\n nodeEl = nodeEls[idx];\n nodeDatum = d;\n }\n });\n if(!nodeEl) {\n return;\n }\n\n\n if(true) { // always set history state, but replace instead of update on 'updatehistory'\n let id = null;\n if(nodeDatum['@id'].startsWith(/*location.origin*/'https://rubenvandeven.com/')){\n id = nodeDatum['@id'].substr(26);\n } else {\n id = '?id=' + nodeDatum['@id'];\n }\n\n if(updateHistory) {\n history.pushState({node: idx}, getNodeLabel(nodeDatum), \"/\"+id);\n } else {\n history.replaceState({node: idx}, getNodeLabel(nodeDatum), \"/\"+id);\n }\n }\n\n // set global var\n positionNodesInCenter(idx);\n\n let currentCrumbs = breadcrumbs[nodeDatum['@id']].slice();\n currentCrumbs[currentCrumbs.length] = nodeDatum['@id'];\n\n // set active links.\n let linkedIdxs = [];\n link.each(function(d,idx,linkEls,q){\n // set nodes 'visible'/highlighted when linked to active node\n if(d.source == nodeDatum || d.target == nodeDatum) {\n linkEls[idx].classList.add('activeLink','visibleLink');\n linkEls[idx].getElementsByTagName(\"line\")[0].setAttribute(\"marker-end\", \"url(#arrowHeadSelected)\");\n node.filter(function(a, fnodeIdx){\n let r = a['@id'] == d.source['@id'] || a['@id'] == d.target['@id']; //connected node: true/false\n if(r && linkedIdxs.indexOf(fnodeIdx) === -1){\n linkedIdxs[linkedIdxs.length] = fnodeIdx;\n }\n return r;\n }).classed('visibleNode', true);\n } else {\n linkEls[idx].classList.remove('activeLink');\n linkEls[idx].getElementsByTagName(\"line\")[0].setAttribute(\"marker-end\", \"url(#arrowHead)\");\n }\n // check if link is part of breadcrumb trail\n let posSrc = currentCrumbs.indexOf(d.source['@id']);\n let posTrg = currentCrumbs.indexOf(d.target['@id']);\n if(posSrc > -1 && posTrg > -1 && Math.abs(posSrc - posTrg) == 1) {\n linkEls[idx].classList.add('breadcrumbLink');\n linkEls[idx].getElementsByTagName(\"line\")[0].setAttribute(\"marker-end\", \"url(#arrowHeadCrumbTrail)\");\n } else {\n linkEls[idx].classList.remove('breadcrumbLink');\n }\n });\n\n let i = linkedIdxs.indexOf(idx);\n\n if(i !== -1) {\n linkedIdxs.splice(i, 1);\n }\n\n positionNodesInCircle(linkedIdxs);\n\n setDetails(nodeDatum ,idx);\n}\nvar deselectNode = function() {\n positionNodesInCenter(null);\n link.each(function(d,idx,linkEls,q){\n linkEls[idx].classList.remove('activeLink');\n linkEls[idx].classList.remove('breadcrumbLink');\n linkEls[idx].getElementsByTagName(\"line\")[0].setAttribute(\"marker-end\", \"url(#arrowHead)\")\n });\n closeDetails();\n}\n\n\nwindow.addEventListener('popstate', function(event) {\n if(event.state.hasOwnProperty('node')) {\n selectNode(event.state['node'], false);\n }\n else {\n // if not sure what to do, fall back to first node (also used to return to opening page)\n let firstNode = graph['nodes'].find(n => n['@id'] === firstNodeId);\n selectNode(graph['nodes'].indexOf(firstNode), false);\n }\n});\n\nvar forceCx, forceCy;\nvar setViewboxForceCenter = function() {\n let viewBox = getViewbox();\n let zoom = getZoomValues();\n forceCx = viewBox[0] + viewBox[2]/2 - zoom['dx'];\n forceCy = viewBox[1] + viewBox[3]/2 - zoom['dy'];\n}\n\nvar getZoomValues = function(){\n let zoomContainer = document.getElementById(\"container\");\n let dx = 0, dy = 0, scale = 1;\n if(zoomContainer.transform.baseVal.length > 0) {\n for(let transform of zoomContainer.transform.baseVal) {\n if(transform.type == SVGTransform.SVG_TRANSFORM_TRANSLATE) {\n dx += transform.matrix.e;\n dy += transform.matrix.f;\n }\n else if (transform.type == SVGTransform.SVG_TRANSFORM_SCALE) {\n scale *= transform.matrix.a; // assume simple scale\n }\n }\n }\n\n return {'dx': dx, 'dy': dy, 'scale': scale};\n}\n\nsetViewboxForceCenter(); // sets forceCx & forceCy\n\nvar graphInitialised = false;\nsimulation.force('centerActive', function force(alpha) {\n // let currentNode = node.selectAll('.detail');\n // console.log(currentNode);\n // console.log(forceCx, forceCy);\n node.each(function(d, idx, nodes){\n let n = d;\n let k = alpha * 0.1;\n n.fx = null;\n n.fy = null;\n if(typeof nodePositions[idx] != 'undefined') {\n if(graphInitialised == false) {\n n.x = nodePositions[idx][0];\n n.y = nodePositions[idx][1];\n n.vx = 0;\n n.vy = 0;\n } else {\n n.vx -= (n.x - nodePositions[idx][0]) * k * 5;\n n.vy -= (n.y - nodePositions[idx][1]) * k * 5;\n }\n } else {\n // if it's not positioned, move it out of the circle\n if(currentNodePositionRadius < 1) {\n return;\n }\n\n let dx = n.x - forceCx;\n let dy = n.y - forceCy;\n if(!inCircle(dx, dy, currentNodePositionRadius)) {\n return;\n }\n\n if(graphInitialised == false) {\n // on init, fixate items outside of circle\n n.fx = n.x + dx * (2+Math.random());\n n.fy = n.y + dy * (2+Math.random());\n } else {\n // if initialised, gradually move them outwards\n n.vx += dx * k*4;\n n.vy += dy * k*4;\n }\n }\n });\n});\n\n//path to curve the tile\nvar nodePath = node.append(\"path\")\n .attr(\"id\", function(d,idx){return \"nodePath\"+idx;})\n .attr(\"d\", function(d){\n var r = getSizeForNode(d) * 0.9;\n var startX = getSizeForNode(d);\n // M cx cy\n // m -r, 0\n // a r,r 0 1,0 (r * 2),0\n // a r,r 0 1,0 -(r * 2),0\n // return 'M' + nodeSize/2 + ' ' + nodeSize/2 + ' ' +\n return 'M' + 0 + ' ' + 0 + ' ' +\n 'm -' + r + ', 0'+' ' +\n 'a ' + r +','+r+' 0 1,0 '+ (r*2) +',0 '+\n 'a ' + r +','+r+' 0 1,0 -'+ (r*2) +',0'\n ;\n // return 'm' + startX + ',' + nodeSize + ' ' +\n // 'a' + r + ',' + r + ' 0 0 0 ' + (2*r) + ',0';\n })\n ;\n\nnode.call(d3.drag()\n .on(\"start\", dragstarted)\n .on(\"drag\", dragged)\n .on(\"end\", dragended))\n .on(\"click\", function(d, idx, nodes){\n let node = nodes[idx];\n selectNode(idx, node, d);\n })\n .on('mouseover', function(n, nIdx){\n link.each(function(l,idx,linkEls,q){\n // set nodes 'visible'/highlighted when linked to active node\n if(l.source == n || l.target == n) {\n linkEls[idx].classList.add('hoverLink');\n }\n });\n })\n .on('mouseout', function(){\n let hoverLinkEls = document.getElementsByClassName('hoverLink');\n while(hoverLinkEls.length > 0){\n hoverLinkEls[0].classList.remove('hoverLink');\n }\n });\n\n// svg.call(d3.drag()\n// .on(\"start\", function(d){\n// if(d3.event.sourceEvent.type == 'touchstart' && d3.event.sourceEvent.touches.length > 1) {\n// } else {\n// d3.event.sourceEvent.stopPropagation();\n// svg.node().classList.add(\"dragging\");\n// }\n// })\n// .on(\"drag\", function(){\n// moveViewboxPx(d3.event.dx, d3.event.dy);\n// })\n// .on(\"end\", function(){\n// svg.node().classList.remove(\"dragging\");\n// }));\nsvg.call(d3.zoom()\n .scaleExtent([0.3,3])\n .on(\"start\", function(){\n svg.node().classList.add(\"dragging\");\n })\n .on(\"end\", function(){\n svg.node().classList.remove(\"dragging\");\n })\n .on(\"zoom\", function(a,b,c){\n container.attr(\"transform\", d3.event.transform);\n })\n);\n\n// svg.call(d3.zoom.transform, d3.zoomIdentity);\n\nnode.append('circle')\n .attr(\"r\", (d) => getSizeForNode(d))\n .attr(\"class\", \"nodeBg\")\n ;\nnode.append('circle')\n .attr(\"r\", (d) => getSizeForNode(d) * 1.08) // nodeSize + margin\n .attr(\"class\", \"highlightCircle\")\n ;\n\nnode.append('text')\n .attr(\"class\", \"nodeType\")\n .text(function(n){\n return n['@type'];\n })\n\nnode.append('text')\n .attr(\"class\", \"nodeYear\")\n .attr(\"y\", \"22\")\n .text(function(n){\n return getNodeYear(n);\n })\n ;\nlet splitText = function(text){\n let characters = [\" \",\"-\",\"\\u00AD\"];\n let charSplitPos = {};\n let mid = Math.floor(text.length / 2);\n let splitPos = false;\n let splitPosChar = false;\n // split sentences\n for(let char of characters) {\n if(text.indexOf(char) < 0) {\n continue;\n }\n let tmid = text.substr(0,mid).lastIndexOf(char);\n if(tmid === -1) {\n tmid = text.indexOf(char);\n }\n tmid += 1; // we want to cut _after_ the character\n // console.log(\"Char\", char, tmid);\n if(splitPos === false || Math.abs(tmid-mid) < Math.abs(splitPos - mid)){\n // console.log(\"least!\");\n splitPos = tmid;\n splitPosChar = char;\n }\n }\n // console.log(\"pos\",splitPos)\n\n\n if(splitPos === false) {\n return false;\n }\n\n let text1 = text.substr(0, splitPos).trim();\n let text2 = text.substr(splitPos).trim();\n\n if(splitPosChar == \"\\u00AD\") {\n text1 += \"-\";\n }\n\n // find most equal split\n return [text1, text2];\n}\nlet nodeTitle = node.append('text')\n .attr(\"class\", \"nodeTitle\")\n .attr(\"y\", \"5\")\n ;\nnodeTitle\n // .append(\"textPath\")\n // .attr( \"xlink:href\",function(d, idx){return '#nodePath'+idx;})\n // .text(getNodeLabel)\n .each(function(node, nodes){\n let textLength;\n let self = d3.select(this);\n let titleText = getNodeLabel(node);\n let titleTexts = false;\n if(titleText.length > 20) {\n titleTexts = splitText(titleText);\n }\n if(titleTexts !== false) {\n let tspan1 = self.append(\"tspan\")\n .text(titleTexts[0])\n .attr(\"y\", \"-10\")\n .attr(\"x\", \"0\")\n ;\n let tspan = self.append(\"tspan\")\n .text(titleTexts[1])\n .attr(\"y\", \"10\")\n .attr(\"x\", \"0\")\n ;\n let textLength1 = tspan.node().getComputedTextLength();\n let textLength2 = tspan.node().getComputedTextLength();\n textLength = Math.max(textLength1, textLength2);\n } else {\n self.text(titleText);\n textLength = self.node().getComputedTextLength();\n }\n\n // scale according to text length:\n if(textLength > getSizeForNode(node) * 2) {\n self.attr('transform', `scale(${(getSizeForNode(node) * 2) / textLength / 1.05})`);\n }\n })\n ;\n\nnode.each(function(d) {\n if(!d['https://schema.org/thumbnailUrl']) {\n return;\n }\n d3.select(this).append('svg:image')\n .attr(\"xlink:href\", d['https://schema.org/thumbnailUrl'])\n .attr(\"width\", (d) => getSizeForNode(d)*2)\n .attr(\"height\", (d) => getSizeForNode(d)* 2)\n .attr(\"transform\",(d) => \"translate(-\"+getSizeForNode(d)+\" -\"+getSizeForNode(d)+\")\")\n .attr(\"clip-path\",\"url(#clipNodeImage)\")\n .attr(\"preserveAspectRatio\",\"xMidYMid slice\")\n ;\n });\n\nsimulation\n .nodes(graph.nodes)\n .on(\"tick\", ticked);\n\nsimulation.force(\"link\")\n .links(graph.links)\n .distance(function(l){\n switch (l.name) {\n // case 'publishedAt':\n // return 200;\n // case 'image':\n // return 200;\n default:\n return 300;\n }\n }) // distance between the nodes / link length\n // .charge(-100)\n;\n\n// run on each draw\nfunction ticked() {\n graph.nodes.forEach(function (d, idx) {\n d.leftX = d.rightX = d.x;\n\n // fix first node on center\n // if(idx === 0) {\n // d.fx = width/2;\n // d.fy = height/2;\n // return;\n // }\n });\n\n linkLine.each(function (d) {\n var sourceX, targetX, midX, dx, dy, angle;\n\n // This mess makes the arrows exactly perfect.\n // thanks to http://bl.ocks.org/curran/9b73eb564c1c8a3d8f3ab207de364bf4\n if( d.source.rightX < d.target.leftX ){\n sourceX = d.source.rightX;\n targetX = d.target.leftX;\n } else if( d.target.rightX < d.source.leftX ){\n targetX = d.target.rightX;\n sourceX = d.source.leftX;\n } else if (d.target.isCircle) {\n targetX = sourceX = d.target.x;\n } else if (d.source.isCircle) {\n targetX = sourceX = d.source.x;\n } else {\n midX = (d.source.x + d.target.x) / 2;\n if(midX > d.target.rightX){\n midX = d.target.rightX;\n } else if(midX > d.source.rightX){\n midX = d.source.rightX;\n } else if(midX < d.target.leftX){\n midX = d.target.leftX;\n } else if(midX < d.source.leftX){\n midX = d.source.leftX;\n }\n targetX = sourceX = midX;\n }\n\n dx = targetX - sourceX;\n dy = d.target.y - d.source.y;\n angle = Math.atan2(dx, dy);\n\n /* DISABLED\n srcSize = (typeof nodePositions[d.source.index] != 'undefined') ? selectedNodeSize : nodeSize;\n tgtSize = (typeof nodePositions[d.target.index] != 'undefined') ? selectedNodeSize : nodeSize;\n */\n let srcSize = getSizeForNode(d.source)+3.2;\n let tgtSize = getSizeForNode(d.target)+3.2;\n\n // Compute the line endpoint such that the arrow\n // is touching the edge of the node rectangle perfectly.\n d.sourceX = sourceX + Math.sin(angle) * srcSize;\n d.targetX = targetX - Math.sin(angle) * tgtSize;\n d.sourceY = d.source.y + Math.cos(angle) * srcSize;\n d.targetY = d.target.y - Math.cos(angle) * tgtSize;\n })\n .attr(\"x1\", function(d) { return d.sourceX; })\n .attr(\"y1\", function(d) { return d.sourceY; })\n .attr(\"x2\", function(d) { return d.targetX; })\n .attr(\"y2\", function(d) { return d.targetY; });\n linkText.attr(\"transform\", function(d){\n let dx = (d.target.x - d.source.x) /2;\n let dy = (d.target.y - d.source.y) /2;\n let x = d.source.x + dx;\n let y = d.source.y + dy;\n let deg = Math.atan(dy / dx) * 180 / Math.PI;\n // if dx/dy == 0/0 -> deg == NaN\n if(isNaN(deg)) {\n return \"\";\n }\n return \"translate(\"+x+\" \"+y+\") rotate(\"+deg+\") translate(0, -10)\";\n });\n\n node.attr(\"transform\", function(d) { return \"translate(\" + d.x + \",\" + d.y + \")\"; });\n}\n\nfunction dragstarted(d,idx,nodes) {\n if (!d3.event.active) simulation.alphaTarget(0.3).restart();\n let nodeEl = nodes[idx];\n d.fx = d.x;\n d.fy = d.y;\n // nodeEl.style.fill = '#00f';\n nodeEl.classList.add('drag');\n}\n\n// use to validate drag\n// function validate(x, a, b) {\n// if (x =< a) return a;\n// return b;\n// }\n\nfunction dragged(d, idx) {\n d.fx = d3.event.x;\n d.fy = d3.event.y;\n}\n\nfunction dragended(d, idx, nodes) {\n if (!d3.event.active) simulation.alphaTarget(0);\n let nodeEl = nodes[idx];\n d.fx = null;\n d.fy = null;\n nodeEl.classList.remove('drag');\n}\n\nfunction moveViewboxPx(dx, dy){\n let viewBox = svg.attr(\"viewBox\").split(\" \").map(parseFloat);\n viewBox[0] -= dx * 1;\n viewBox[1] -= dy * 1;\n svg.attr(\"viewBox\", viewBox.join(\" \"));\n}\n\n// start by selecting the first node :-)\n// selectNode(currentNodeIdx+1);\n// positionNodesInCenter(currentNodeIdx);\n\nif(location.pathname.startsWith('/@type/')) {\n for(let t in types) {\n if(getDisplayAttr(t) == location.pathname.substr(7)) {\n centerByType(t, false);\n }\n }\n} else{\n let startNodeId = location.search.startsWith(\"?id=\") ? location.search.substr(4) : 'https://rubenvandeven.com'+location.pathname;\n let firstNode = graph['nodes'].find(n => n['@id'] === startNodeId);\n selectNode(graph['nodes'].indexOf(firstNode), false);\n}\n\n\n\n// closeDetails(); // hide details at first\n// positionNodesInCenter(currentNodeIdx+1);\n\n// setTimeout(function(){\n // document.body.classList.add('graphInitialised');\n// }, 10);\n\nlet initPlaceholder = document.getElementById('initPlaceholder');\nsvg.node().removeChild(initPlaceholder);\nsetTimeout(function(){\n graphInitialised = true;\n document.body.classList.add('graphInitialised');\n }, 500);\n}\n\n\n// Detect request animation frame\nvar reqAnimFrame = window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.msRequestAnimationFrame ||\n window.oRequestAnimationFrame ||\n // IE Fallback, you can even fallback to onscroll\n function(callback){ window.setTimeout(callback, 1000/60) };\n// all credits go to https://stackoverflow.com/a/26798337\nfunction scrollToY(scrollTargetY, speed, easing, finishFunction) {\n // scrollTargetY: the target scrollY property of the window\n // speed: time in pixels per second\n // easing: easing equation to use\n\n var scrollY = window.scrollY,\n scrollTargetY = scrollTargetY || 0,\n speed = speed || 2000,\n easing = easing || 'easeOutSine',\n currentTime = 0,\n finishFunction = finishFunction || false;\n\n // min time .1, max time .8 seconds\n let time = Math.max(.1, Math.min(Math.abs(scrollY - scrollTargetY) / speed, .8));\n\n // easing equations from https://github.com/danro/easing-js/blob/master/easing.js\n let PI_D2 = Math.PI / 2,\n easingEquations = {\n easeOutSine: function (pos) {\n return Math.sin(pos * (Math.PI / 2));\n },\n easeInOutSine: function (pos) {\n return (-0.5 * (Math.cos(Math.PI * pos) - 1));\n },\n easeInOutQuint: function (pos) {\n if ((pos /= 0.5) < 1) {\n return 0.5 * Math.pow(pos, 5);\n }\n return 0.5 * (Math.pow((pos - 2), 5) + 2);\n }\n };\n\n // add animation loop\n function tick() {\n currentTime += 1 / 60;\n\n var p = currentTime / time;\n var t = easingEquations[easing](p);\n\n if (p < 1) {\n reqAnimFrame(tick);\n\n window.scrollTo(0, scrollY + ((scrollTargetY - scrollY) * t));\n } else {\n window.scrollTo(0, scrollTargetY);\n if(finishFunction) {\n finishFunction();\n }\n }\n }\n\n // call it once to get started\n tick();\n}\n"]}