Digit linkifier
by dipish
HTML
<h1>Digit linkifier</h1>
<p><i>Hacking div contenteditable with caret positioning madness...</i></p>
<p class="toolbar">
<button id="btn-0">0</button>
<button id="btn-1">1</button>
<button id="btn-2">2</button>
<button id="btn-3">3</button>
<button id="btn-4">4</button>
<button id="btn-5">5</button>
<button id="btn-6">6</button>
<button id="btn-7">7</button>
<button id="btn-8">8</button>
<button id="btn-9">9</button>
</p>
<div id="myeditor" class="editor-wrapper">
<div class="editor" contenteditable>
1 banana<br />
2 banana<br />
3 banana<br />
four<br />
4 make a bunch<br />
and so do many more<br />
</div>
<div class="editor-ghost" contenteditable>
1 banana<br />
2 banana<br />
3 banana<br />
four<br />
4 make a bunch<br />
and so do many more<br />
</div>
</div>
CSS
* {
box-sizing: border-box;
}
body {
margin: 20px;
}
h1 {
font-size: 2em;
font-family: sans-serif;
margin: 0.3em 0;
}
.editor-wrapper {
position: relative;
width: 400px;
height: 200px;
}
.editor {
border: solid 1px black;
width: 100%;
height: 100%;
padding: 5px;
overflow: auto;
line-height: 1.5;
}
.editor a {
background: rgb(169, 214, 255);
text-decoration: none;
padding: 0px 4px;
margin: 1px;
color: #000;
border: solid 1px rgb(0, 122, 255);
border-radius: 5px;
}
.editor-ghost {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: solid 1px black;
padding: 5px;
z-index: -1;
overflow: auto;
line-height: 1.5;
}
.toolbar {
margin-top: 10px;
}
.toolbar button {
}
.toolbar .active {
background: #55D155;
}
JavaScript
var wrapper = $('#myeditor'),
editor = wrapper.find('.editor'),
ghost = wrapper.find('.editor-ghost'),
usedDigits = {},
selection, range;
// See http://stackoverflow.com/questions/1181700/set-cursor-position-on-contenteditable-div
var captureSelection = function(e) {
// Don't capture selection outside editable region
var isOrContainsAnchor = false,
isOrContainsFocus = false,
sel = window.getSelection(),
parentAnchor = sel.anchorNode,
parentFocus = sel.focusNode;
while(parentAnchor && parentAnchor != document.documentElement) {
if(parentAnchor == editor[0]) {
isOrContainsAnchor = true;
}
parentAnchor = parentAnchor.parentNode;
}
while(parentFocus && parentFocus != document.documentElement) {
if(parentFocus == editor[0]) {
isOrContainsFocus = true;
}
parentFocus = parentFocus.parentNode;
}
if(!isOrContainsAnchor || !isOrContainsFocus) {
return;
}
selection = window.getSelection();
// Get range (standards)
if(selection.getRangeAt !== undefined) {
range = selection.getRangeAt(0);
// Get range (Safari 2)
} else if(
document.createRange &&
selection.anchorNode &&
selection.anchorOffset &&
selection.focusNode &&
selection.focusOffset
) {
range = document.createRange();
range.setStart(selection.anchorNode, selection.anchorOffset);
range.setEnd(selection.focusNode, selection.focusOffset);
} else {
// Failure here, not handled by the rest of the script.
// Probably IE or some older browser
}
//////////////////////////////////////
// pushing cursor element to find it later
var cursorStart = document.createElement('span'),
collapsed = !!range.collapsed;
cursorStart.id = 'cursorStart';
...