Safari 12.0.1 で contenteditable な入力欄でキャレットの座標を取得するために空の <span>
などをいれて node をいじると、日本語入力時の変換が二重に入力されてしまう現象に出会った。Chrome や Firefox では再現しなかった。
<template>
<div class="content-editable-page">
<div contenteditable="true" class="editable"
ref="editable"
@keyup="moveCaret"
><p>test</p></div>
</div>
</template>
<script>
import Vue from 'vue'
export default Vue.extend({
components: {
},
data () {
return {
}
},
computed: {
},
methods: {
moveCaret () {
const anchor = document.createElement('span')
const sel = window.getSelection()
const range = sel.getRangeAt(0)
range.insertNode(anchor)
const pos = anchor.getBoundingClientRect()
anchor.parentElement.removeChild(anchor)
}
},
mounted() {
}
})
</script>
良い回避方法が思いつかなかったので、IME 変換中は座標位置を取得しないように composition を見ることにした。これで二重に入力されることはなくなったが、代わりに変換中にはキャレット位置が分からないというデメリットが…。
<template>
<div class="content-editable-page">
<div contenteditable="true" class="editable"
ref="editable"
@compositionstart="compositionstart"
@compositionend="compositionend"
@keyup="moveCaret"
><p>test</p></div>
</div>
</template>
<script>
import Vue from 'vue'
export default Vue.extend({
components: {
},
data () {
return {
compositing: false
}
},
computed: {
},
methods: {
moveCaret () {
if (!this.compositing) {
const anchor = document.createElement('span')
const sel = window.getSelection()
const range = sel.getRangeAt(0)
range.insertNode(anchor)
const pos = anchor.getBoundingClientRect()
anchor.parentElement.removeChild(anchor)
}
},
compositionstart () {
this.compositing = true
},
compositionend () {
this.compositing = false
}
},
mounted() {
}
})
</script>