1 line
No EOL
68 KiB
Text
1 line
No EOL
68 KiB
Text
{"version":3,"sources":["portfolio.js"],"names":["data","graph","getLabelAttribute","node","getNodeLabel","label","getNodeYear","n","substr","getDisplayAttr","attr","jsonLdToGraph","nodes","links","replace","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","createBreadcrumbs","srcId","crumbs","createBreadcrumbLayer","newPath","slice","push","nextSrcIds","_iteratorNormalCompletion2","_didIteratorError2","_iteratorError2","_step2","_iterator2","firstNodeId","nextIds","newNextIds","getSizeForNode","_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","console","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","min","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 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 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(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"]} |