function hoverCode(target_id) { const target = document.getElementById(target_id) if(target == null) { console.log("Couldn't find target: " + target_id) return; } if(target.childElementCount != 2){ console.log("Invalid child count"); return; } const children = target.children; const code1 = code_block(children[0]); const code2 = code_block(children[1]); const spans1 = spans_with_data(code1); const spans2 = spans_with_data(code2); var transformed = target.getAttribute("transformed") if(transformed == "true") { target.setAttribute("transformed", false) transformed = "false" // delay showing the first one code1.style.setProperty("transition", "visibility 0s 1s"); code1.style.setProperty("visibility", "visible"); // dont delay when hiding the second one code2.style.setProperty("transition", "visibility 0s"); code2.style.setProperty("visibility", "hidden"); } else { target.setAttribute("transformed", true) transformed = "true" // dont delay hiding the first one code1.style.setProperty("transition", "visibility 0s"); code1.style.setProperty("visibility", "hidden"); // delay when making the second block visible again code2.style.setProperty("transition", "visibility 0s 1s"); code2.style.setProperty("visibility", "visible"); } for(let span_id in spans1) { const span1 = spans1[span_id] const span2 = spans2[span_id] if(span2 == undefined) { console.log("Differing codeblock contents. " + span_id + " not found in second block.") return; } if(transformed != "true"){ span1.style.setProperty("transition", "transform 1s, visibility 0s"); span1.style.setProperty("transform", ""); span1.style.setProperty("visibility", "visible"); continue; } const span1_offset_top = span1.getBoundingClientRect().top; const span1_offset_left = span1.getBoundingClientRect().left; const span2_offset_top = span2.getBoundingClientRect().top; const span2_offset_left = span2.getBoundingClientRect().left; const offset_top = span2_offset_top - span1_offset_top; const offset_left = span2_offset_left - span1_offset_left; const translate = "translate(" + offset_left + "px," + offset_top + "px)"; span1.style.setProperty("transition", "transform 1s, visibility 0s 1s"); span1.style.setProperty("transform", translate); span1.style.setProperty("visibility", "hidden"); } } function spans_with_data(code) { return Array.from(code.children).filter((span) => { if(span.tagName != "SPAN") return false; if(span.attributes["data-self"] == undefined) return false; return true; }).reduce((acc, span) => { acc[span.attributes["data-self"].value] = span; return acc; }, {}) } function code_block(child) { if(child.tagName != "PRE") { console.log("Invalid child " + child.tagName) return undefined; } const codeBlock = child.children[0]; if(codeBlock == undefined) { console.log("Pre is missing codeblock"); return undefined; } if(codeBlock.tagName != "CODE") { console.log("Invalid " + codeBlock.tagName + " inside PRE. Expected CODE") return undefined; } return codeBlock; }