Skip to content

Instantly share code, notes, and snippets.

@audinue
Created June 14, 2024 20:35
Show Gist options
  • Save audinue/872a8acd740585c7caf0baa74c2ed974 to your computer and use it in GitHub Desktop.
Save audinue/872a8acd740585c7caf0baa74c2ed974 to your computer and use it in GitHub Desktop.
Restore selection after changing the innerHTML (DOM diffing alternative)
var html = function (text) {
return text
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;')
}
var userName = 'John'
var render = function () {
return ''
+ '<p>Name: <input value="' + html(userName) + '" oninput="setUserName()"></p>'
+ '<p>Hello ' + html(userName) + '!</p>'
}
var setUserName = function () {
userName = event.target.value
flush()
}
var flush = function () {
setInnerHTML(document.body, render())
}
addEventListener('DOMContentLoaded', flush)
var setInnerHTML = (() => {
var DOCUMENT = document
var ROOT = DOCUMENT.documentElement
var PARENT_NODE = 'parentNode'
var CHILD_NODES = 'childNodes'
var SELECTION_START = 'selectionStart'
var SELECTION_END = 'selectionEnd'
var getElementPath = (element) => {
return element === ROOT
? []
: [...getElementPath(element[PARENT_NODE]), [...element[PARENT_NODE][CHILD_NODES]].indexOf(element)]
}
var getElementFromPath = (element, path) =>
!path.length
? element
: getElementFromPath(element[CHILD_NODES][path[0]], path.slice(1))
return (element, html) =>
setTimeout(() => {
var active = DOCUMENT.activeElement
var path = getElementPath(active)
var start = active[SELECTION_START]
var end = active[SELECTION_END]
element.innerHTML = html
active = getElementFromPath(ROOT, path)
active[SELECTION_START] = start
active[SELECTION_END] = end
active.focus()
})
})()
var setInnerHTML=(()=>{var e=document,n=e.documentElement,t="parentNode",r="childNodes",c="selectionStart",i="selectionEnd",o=e=>e===n?[]:[...o(e[t]),[...e[t][r]].indexOf(e)],d=(e,n)=>n.length?d(e[r][n[0]],n.slice(1)):e;return(t,r)=>setTimeout((()=>{var l=e.activeElement,s=o(l),a=l[c],m=l[i];t.innerHTML=r,(l=d(n,s))[c]=a,l[i]=m,l.focus()}))})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment