{% extends 'base.html' %} {% block content %} <div id="settings"> <h1>Differences</h1> <form class="pure-form " action="" method="GET"> <fieldset> <label for="diffWords" class="pure-checkbox"> <input type="radio" name="diff_type" id="diffWords" value="diffWords"/> Words</label> <label for="diffLines" class="pure-checkbox"> <input type="radio" name="diff_type" id="diffLines" value="diffLines" checked=""/> Lines</label> <label for="diffChars" class="pure-checkbox"> <input type="radio" name="diff_type" id="diffChars" value="diffChars"/> Chars</label> {% if versions|length >= 1 %} <label for="diff-version">Compare newest (<span id="current-v-date"></span>) with</label> <select id="diff-version" name="previous_version"> {% for version in versions %} <option value="{{version}}" {% if version== current_previous_version %} selected="" {% endif %}> {{version}} </option> {% endfor %} </select> <button type="submit" class="pure-button pure-button-primary">Go</button> {% endif %} </fieldset> </form> <del>Removed text</del> <ins>Inserted Text</ins> </div> <div id="diff-jump"> <a onclick="next_diff();">Jump</a> </div> <div id="diff-ui"> <table> <tbody> <tr> <!-- just proof of concept copied straight from github.com/kpdecker/jsdiff --> <td id="a" style="display: none;">{{previous}}</td> <td id="b" style="display: none;">{{newest}}</td> <td id="diff-col"> <span id="result"></span> </td> </tr> </tbody> </table> Diff algorithm from the amazing <a href="https://github.com/kpdecker/jsdiff">github.com/kpdecker/jsdiff</a> </div> <script type="text/javascript" src="{{url_for('static_content', group='js', filename='diff.js')}}"></script> <script defer=""> var a = document.getElementById('a'); var b = document.getElementById('b'); var result = document.getElementById('result'); function changed() { var diff = JsDiff[window.diffType](a.textContent, b.textContent); var fragment = document.createDocumentFragment(); for (var i=0; i < diff.length; i++) { if (diff[i].added && diff[i + 1] && diff[i + 1].removed) { var swap = diff[i]; diff[i] = diff[i + 1]; diff[i + 1] = swap; } var node; if (diff[i].removed) { node = document.createElement('del'); node.classList.add("change"); node.appendChild(document.createTextNode(diff[i].value)); } else if (diff[i].added) { node = document.createElement('ins'); node.classList.add("change"); node.appendChild(document.createTextNode(diff[i].value)); } else { node = document.createTextNode(diff[i].value); } fragment.appendChild(node); } result.textContent = ''; result.appendChild(fragment); // Jump at start inputs.current=0; next_diff(); } window.onload = function() { /* Convert what is options from UTC time.time() to local browser time */ var diffList=document.getElementById("diff-version"); if (typeof(diffList) != 'undefined' && diffList != null) { for (var option of diffList.options) { var dateObject = new Date(option.value*1000); option.label=dateObject.toLocaleString(); } } /* Set current version date as local time in the browser also */ var current_v = document.getElementById("current-v-date"); var dateObject = new Date({{ newest_version_timestamp }}*1000); current_v.innerHTML=dateObject.toLocaleString(); onDiffTypeChange(document.querySelector('#settings [name="diff_type"]:checked')); changed(); }; a.onpaste = a.onchange = b.onpaste = b.onchange = changed; if ('oninput' in a) { a.oninput = b.oninput = changed; } else { a.onkeyup = b.onkeyup = changed; } function onDiffTypeChange(radio) { window.diffType = radio.value; // Not necessary // document.title = "Diff " + radio.value.slice(4); } var radio = document.getElementsByName('diff_type'); for (var i = 0; i < radio.length; i++) { radio[i].onchange = function(e) { onDiffTypeChange(e.target); changed(); } } var inputs = document.getElementsByClassName('change'); inputs.current=0; function next_diff() { var element = inputs[inputs.current]; var headerOffset = 80; var elementPosition = element.getBoundingClientRect().top; var offsetPosition = elementPosition - headerOffset + window.scrollY; window.scrollTo({ top: offsetPosition, behavior: "smooth" }); inputs.current++; if(inputs.current >= inputs.length) { inputs.current=0; } } </script> {% endblock %}