Skip to content

Commit a5a9241

Browse files
authored
Merge pull request #78 from Maks1mS/fix-51
fix match validation to prevent stale matches
2 parents 2036654 + 18e440c commit a5a9241

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

examples/index.html

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,51 @@ <h2>Multiword text-expander element</h2>
3030
<textarea autofocus rows="10" cols="40"></textarea>
3131
</text-expander>
3232

33+
<h2>Multiword and multikey text-expander element</h2>
34+
<text-expander keys=": #" multiword="#">
35+
<textarea autofocus rows="10" cols="40"></textarea>
36+
</text-expander>
37+
38+
<h2>Multiword and multikey text-expander element with random delay</h2>
39+
<text-expander keys=": #" multiword="#" _random_delay="">
40+
<textarea autofocus rows="10" cols="40"></textarea>
41+
</text-expander>
42+
3343
<script type="text/javascript">
44+
const emojis = [
45+
{ emoji: "😀", names: ["smile", "happy"] },
46+
{ emoji: "❤️", names: ["heart", "love"] },
47+
{ emoji: "🔥", names: ["fire", "hot"] },
48+
{ emoji: "⭐", names: ["star", "favorite"] },
49+
{ emoji: "🚀", names: ["rocket", "fast"] }
50+
];
51+
3452
const expanders = document.querySelectorAll('text-expander')
3553
for (const expander of expanders) {
3654
expander.addEventListener('text-expander-change', event => {
3755
const {key, provide, text} = event.detail
38-
if (key === '#') {
56+
if (key === ':') {
57+
const menu = document.createElement('ul')
58+
menu.classList.add('menu')
59+
menu.role = 'listbox'
60+
for (const {emoji, names} of emojis) {
61+
if (names.some(name => name.includes(text.toLowerCase()))) {
62+
const item = document.createElement('li')
63+
item.setAttribute('role', 'option')
64+
item.textContent = `${emoji} ${names[0]}`
65+
item.setAttribute('data-value', emoji)
66+
menu.append(item)
67+
}
68+
}
69+
// Async test with random delay
70+
if (expander.hasAttribute('_random_delay')) {
71+
provide(new Promise(resolve => {
72+
setTimeout(() => resolve({matched: true, fragment: menu}), Math.random() * 1000)
73+
}))
74+
} else {
75+
provide(Promise.resolve({matched: true, fragment: menu}))
76+
}
77+
} else if (key === '#') {
3978
const menu = document.createElement('ul')
4079
menu.classList.add('menu')
4180
menu.role = 'listbox'
@@ -55,13 +94,25 @@ <h2>Multiword text-expander element</h2>
5594
menu.append(item)
5695
}
5796
}
58-
provide(Promise.resolve({matched: true, fragment: menu}))
97+
// Async test with random delay
98+
if (expander.hasAttribute('_random_delay')) {
99+
provide(new Promise(resolve => {
100+
setTimeout(() => resolve({matched: true, fragment: menu}), Math.random() * 1000)
101+
}))
102+
} else {
103+
// For normal expander - synchronous response
104+
provide(Promise.resolve({matched: true, fragment: menu}))
105+
}
59106
}
60107
})
61108

62109
expander.addEventListener('text-expander-value', function(event) {
63110
const {key, item} = event.detail
64-
if (key === '#') event.detail.value = item.getAttribute('data-value') || item.textContent
111+
if (key === '#') {
112+
event.detail.value = item.getAttribute('data-value') || item.textContent
113+
} else if (key === ':') {
114+
event.detail.value = item.getAttribute('data-value')
115+
}
65116
})
66117
}
67118
</script>

src/text-expander-element.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ class TextExpander {
201201
this.justPasted = true
202202
}
203203

204+
private isMatchStillValid(match: TextExpanderMatch): boolean {
205+
return match.position <= this.input.value.length
206+
}
207+
204208
async onInput() {
205209
if (this.justPasted) {
206210
this.justPasted = false
@@ -213,7 +217,11 @@ class TextExpander {
213217
const menu = await this.notifyProviders(match)
214218

215219
// Text was cleared while waiting on async providers.
216-
if (!this.match) return
220+
if (!this.match || !this.isMatchStillValid(match)) {
221+
this.match = null
222+
this.deactivate()
223+
return
224+
}
217225

218226
if (menu) {
219227
this.activate(match, menu)

0 commit comments

Comments
 (0)