1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
import Completion from '../../services/completion/completion.js'
import EmojiSelector from '../emoji-selector/emoji-selector.vue'
import { take, filter, map } from 'lodash'
const EmojiInput = {
props: [
'value',
'placeholder',
'type',
'classname'
],
data () {
return {
highlighted: 0,
caret: 0
}
},
components: {
EmojiSelector
},
computed: {
suggestions () {
const firstchar = this.textAtCaret.charAt(0)
if (firstchar === ':') {
if (this.textAtCaret === ':') { return }
const matchedEmoji = filter(this.emoji.concat(this.customEmoji), (emoji) => emoji.shortcode.startsWith(this.textAtCaret.slice(1)))
if (matchedEmoji.length <= 0) {
return false
}
return map(take(matchedEmoji, 5), ({shortcode, image_url, utf}, index) => ({
shortcode: `:${shortcode}:`,
utf: utf || '',
// eslint-disable-next-line camelcase
img: utf ? '' : this.$store.state.instance.server + image_url,
highlighted: index === this.highlighted
}))
} else {
return false
}
},
textAtCaret () {
return (this.wordAtCaret || {}).word || ''
},
wordAtCaret () {
const word = Completion.wordAtPosition(this.value, this.caret - 1) || {}
return word
},
emoji () {
return this.$store.state.instance.emoji || []
},
customEmoji () {
return this.$store.state.instance.customEmoji || []
}
},
methods: {
replace (replacement) {
const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement)
this.$emit('input', newValue)
this.caret = 0
},
replaceEmoji (e) {
const len = this.suggestions.length || 0
if (this.textAtCaret === ':' || e.ctrlKey) { return }
if (len > 0) {
e.preventDefault()
const emoji = this.suggestions[this.highlighted]
const replacement = emoji.utf || (emoji.shortcode + ' ')
const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement)
this.$emit('input', newValue)
this.caret = 0
this.highlighted = 0
}
},
cycleBackward (e) {
const len = this.suggestions.length || 0
if (len > 0) {
e.preventDefault()
this.highlighted -= 1
if (this.highlighted < 0) {
this.highlighted = this.suggestions.length - 1
}
} else {
this.highlighted = 0
}
},
cycleForward (e) {
const len = this.suggestions.length || 0
if (len > 0) {
if (e.shiftKey) { return }
e.preventDefault()
this.highlighted += 1
if (this.highlighted >= len) {
this.highlighted = 0
}
} else {
this.highlighted = 0
}
},
onKeydown (e) {
e.stopPropagation()
},
onInput (e) {
this.$emit('input', e.target.value)
},
setCaret ({target: {selectionStart}}) {
this.caret = selectionStart
},
onEmoji (emoji) {
const newValue = this.value.substr(0, this.caret) + emoji + this.value.substr(this.caret)
this.$refs.input.focus()
this.$emit('input', newValue)
this.caret += emoji.length
setTimeout(() => {
this.updateCaretPos()
})
},
updateCaretPos () {
const elem = this.$refs.input
if (elem.createTextRange) {
const range = elem.createTextRange()
range.move('character', this.caret)
range.select()
} else {
if (elem.selectionStart) {
elem.focus()
elem.setSelectionRange(this.caret, this.caret)
} else {
elem.focus()
}
}
}
}
}
export default EmojiInput
|