Created
June 14, 2024 20:35
-
-
Save audinue/872a8acd740585c7caf0baa74c2ed974 to your computer and use it in GitHub Desktop.
Restore selection after changing the innerHTML (DOM diffing alternative)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var html = function (text) { | |
return text | |
.replace(/&/g, '&') | |
.replace(/</g, '<') | |
.replace(/>/g, '>') | |
.replace(/"/g, '"') | |
.replace(/'/g, ''') | |
} | |
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
}) | |
})() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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