Skip to content

Commit a7e8b19

Browse files
committed
add cursor.ts
1 parent 246154c commit a7e8b19

File tree

2 files changed

+113
-6
lines changed

2 files changed

+113
-6
lines changed

cursor.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
type Position = {
2+
top: string
3+
left: string
4+
}
5+
6+
/**
7+
* Returns position of cursor on the page.
8+
* @param toStart Position of beginning of selection or end of selection.
9+
*/
10+
export function cursorPosition(toStart = true): Position | undefined {
11+
const s = window.getSelection()!
12+
if (s.rangeCount > 0) {
13+
const cursor = document.createElement("span")
14+
cursor.textContent = "|"
15+
16+
const r = s.getRangeAt(0).cloneRange()
17+
r.collapse(toStart)
18+
r.insertNode(cursor)
19+
20+
const {x, y, height} = cursor.getBoundingClientRect()
21+
const top = (window.scrollY + y + height) + "px"
22+
const left = (window.scrollX + x) + "px"
23+
cursor.parentNode!.removeChild(cursor)
24+
25+
return {top, left}
26+
}
27+
return undefined
28+
}
29+
30+
/**
31+
* Returns selected text.
32+
*/
33+
export function selectedText() {
34+
const s = window.getSelection()!
35+
if (s.rangeCount === 0) return ''
36+
return s.getRangeAt(0).toString()
37+
}
38+
39+
/**
40+
* Returns text before the cursor.
41+
* @param editor Editor DOM node.
42+
*/
43+
export function textBeforeCursor(editor: Node) {
44+
const s = window.getSelection()!
45+
if (s.rangeCount === 0) return ''
46+
47+
const r0 = s.getRangeAt(0)
48+
const r = document.createRange()
49+
r.selectNodeContents(editor)
50+
r.setEnd(r0.startContainer, r0.startOffset)
51+
return r.toString()
52+
}
53+
54+
/**
55+
* Returns text after the cursor.
56+
* @param editor Editor DOM node.
57+
*/
58+
export function textAfterCursor(editor: Node) {
59+
const s = window.getSelection()!
60+
if (s.rangeCount === 0) return ''
61+
62+
const r0 = s.getRangeAt(0)
63+
const r = document.createRange()
64+
r.selectNodeContents(editor)
65+
r.setStart(r0.endContainer, r0.endOffset)
66+
return r.toString()
67+
}

index.html

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,57 @@
3636
padding: 10px;
3737
tab-size: 4;
3838
}
39+
40+
.popup {
41+
background: #fff;
42+
border-radius: 4px;
43+
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
44+
display: none;
45+
font-family: "Source Code Pro", monospace;
46+
font-size: 14px;
47+
font-weight: 400;
48+
letter-spacing: normal;
49+
line-height: 20px;
50+
max-width: 500px;
51+
overflow: hidden;
52+
padding: 5px;
53+
pointer-events: none;
54+
position: absolute;
55+
z-index: 2;
56+
}
3957
</style>
4058
</head>
4159
<body>
4260
<main>
4361
<div class="editor language-js"></div>
62+
<div class="popup"></div>
4463
</main>
4564
<script type="module">
46-
import {CodeJar} from "./codejar.js"
47-
import {withLineNumbers} from "./linenumbers.js"
65+
import {CodeJar} from './codejar.js'
66+
import {withLineNumbers} from './linenumbers.js'
67+
import {cursorPosition, selectedText, textBeforeCursor, textAfterCursor} from './cursor.js'
68+
69+
const editor = document.querySelector('.editor')
70+
const popup = document.querySelector('.popup')
71+
72+
const updatePopup = () => {
73+
const pos = cursorPosition()
74+
popup.style.top = pos.top
75+
popup.style.left = pos.left
76+
77+
const before = textBeforeCursor(editor).match(/\b\w+$/)
78+
const after = textAfterCursor(editor).match(/^\w+\b/)
79+
let word = (before && before[0]) || ''
80+
word += selectedText()
81+
word += (after && after[0]) || ''
82+
if (word) {
83+
popup.style.display = 'block'
84+
popup.textContent = word
85+
} else popup.style.display = 'none'
86+
}
4887

49-
const editor = document.querySelector(".editor")
88+
editor.addEventListener('click', updatePopup)
89+
editor.addEventListener('keyup', updatePopup)
5090

5191
const highlight = editor => {
5292
// highlight.js does not trim old tags,
@@ -55,11 +95,11 @@
5595
hljs.highlightBlock(editor)
5696
}
5797

58-
const jar = new CodeJar(editor, withLineNumbers(highlight), {tab: " "})
98+
const jar = new CodeJar(editor, withLineNumbers(highlight), {tab: ' '})
5999

60-
jar.updateCode(localStorage.getItem("code"))
100+
jar.updateCode(localStorage.getItem('code'))
61101
jar.onUpdate(code => {
62-
localStorage.setItem("code", code)
102+
localStorage.setItem('code', code)
63103
})
64104
</script>
65105
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.1/highlight.min.js"></script>

0 commit comments

Comments
 (0)