Skip to content

Instantly share code, notes, and snippets.

@mzechmeister
Last active October 3, 2021 06:46
Show Gist options
  • Save mzechmeister/78fb1f2af80115a6b59f813407892186 to your computer and use it in GitHub Desktop.
Save mzechmeister/78fb1f2af80115a6b59f813407892186 to your computer and use it in GitHub Desktop.
autosuggest for contentEditable
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<style>
li {
display: block;
padding: 0 2px;
}
li.hover {
background: lightblue;
}
li:not(.show) {
display: none;
}
span {
padding: 0 0px;
background-color: #DDF;
}
span:not(:focus) + ul { /*the next sibiling*/
display: none;
}
</style>
<body>
<div id="edit" contentEditable style="width:400px; border: 1px solid">
wwwwww++++++ press $ to insert here a span</div>
<div id="suggest_div" style="display:inline-block; position: relative;">
<ul id="suggest" style="position: absolute; z-index:99; top: 9px; left: 1px; padding: 0; width: 60.333px; background: white; border: 1px solid #ccc">
<li style="color:blue">Edge</li>
<li style="color:red">Firefox</li>
<li style="color:purple">Firefo</li>
<li style="color:green">Chrome</li>
<li style="color:orange">Opera</li>
<li style="color:cyan">Safari</li>
</ul>
</div>
<span id="browser" tabindex=-1>$</span>
<script>
handle_hover = function(e){
console.log('hover', e)
if (e.key=="ArrowDown" || e.key=="ArrowUp") {
active = document.querySelector('.show.hover')
if (active) {
while (active = active[(e.key=="ArrowUp"? 'previous':'next') + 'ElementSibling']) {
if (active.classList.contains('show')) break
}
if (!active) { // stick to the element (first/last if not found)
e.preventDefault()
return
}
}
else {
active = document.querySelector('.show')
}
old = document.querySelector('.hover')
old && old.classList.remove('hover')
active && active.classList.add('hover')
e.preventDefault()
}
if (!e.key) {
console.log(e)
old = document.querySelector('.hover')
old && old.classList.remove('hover')
e.target.classList.add('hover')
}
if (e.key == "Enter") {
apply_hit(active)
e.preventDefault()
}
}
function apply_hit(e) {
active = e.target || e
if (active) {
uu.innerHTML = '' //'$' + active.innerHTML
uu.style.color = active.style.color
insertNodeAtCursor(document.createTextNode("$"+active.innerHTML))
}
suggest.style.display = "none"
e.preventDefault && e.preventDefault(); // do not insert newline
return // prevent caret movement
}
browser.onkeydown = handle_hover
suggest.onmouseover = handle_hover
suggest.onmousedown = apply_hit
handle_suggestentries = function(e) {
if (!["Enter", "ArrowLeft", "ArrowRight"].includes(e.key))
suggest.style.display = ""
for (x of suggest.children) {
if (x.innerHTML.toLowerCase().match(uu.innerHTML.toLowerCase().replace("$","")))
x.classList.add('show')
else x.classList.remove('show')
}
}
browser.onkeyup = handle_suggestentries
edit.onkeydown = function(e){
if (e.key == "$") {
//browser.innerHTML = "$"
uu = document.createElement('span')
//uu.id="browser"
uu.tabIndex = -1
uu.innerHTML = "$"
uu.onkeydown = handle_hover
uu.onkeyup = handle_suggestentries
//edit.insertAdjacentHTML(suggest, uu.nextsibling)
insertNodeAtCursor(uu)
uu.before(suggest_div)
return false
}
}
function insertNodeAtCursor(node) {
let selection = window.getSelection();
let range = selection.getRangeAt(0);
range.deleteContents();
range.insertNode(node);
setEndOfContenteditable(uu);
uu.focus()
}
function setEndOfContenteditable(contentEditableElement) {
var range = document.createRange(); //Create a range (a range is a like the selection but invisible)
range.selectNodeContents(contentEditableElement); //Select the entire contents of the element with the range
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
var selection = window.getSelection();//get the selection object (allows you to change selection)
selection.removeAllRanges();//remove any selections already made
selection.addRange(range);//make the range you have just created the visible selection
}
</script>
<p onclick="browser.focus()"><strong>Note:</strong> The datalist tag is not supported in Safari 12.0 (or earlier).</p>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment