LoginSignup
2

More than 5 years have passed since last update.

Safari + contenteditable で日本語変換が二重に入力されてしまう症状の回避方法

Posted at

Safari 12.0.1 で contenteditable な入力欄でキャレットの座標を取得するために空の <span> などをいれて node をいじると、日本語入力時の変換が二重に入力されてしまう現象に出会った。Chrome や Firefox では再現しなかった。

dup.gif

<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>

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2