50820
Android端末のWebViewにて。

例えばですが、以下のようなHTMLの時に  
bタグで囲まれている「いいい」にカーソルが移動した時、  
何かイベントが起きてくれたらと考えています。

実現したい事は、そのイベントを元に太字設定ボタンの状態を変更することです。

【表示】  
  
  
あああ **いいい** ううう  
  

【内部ソース】

```

    <html>
     <head>
       //略
     </head>
     <body contenteditable="true">
      <div>
        あああ<b>いいい</b>ううう
      </div>
     </body>
    </html>
    
```

調べてはみたのですがなかなかそれらしきイベントも見つからず、  
ダメ元でフォーカス関連のイベントを試したりしましたが反応なしで・・・

そこでこちらに質問させて頂きました。

少しでも情報を得られればと思っています。  
どうかよろしくお願いします。
CC BY-SA 4.0
2018-12-01T12:14:37.597
50815
2018-12-02T01:21:50.453
9939
question
javascript android
ContentEditable属性の中で、現在のカーソル位置(キャレット)が、特定のタグの中かどうか知りたい。
`selectionchange`イベントを捕まえて、Selection APIでキャレットの位置を調べればよさそうです。

ざっとコードを書いてみましたが、このコードだと選択した範囲の始点と終点が別々のB要素の中のときでもOKとしています。実用上はOKにしないほうが良いかもしれません。

```

    function updateStatus(msg) {
      document.querySelector('#status').textContent = msg;
    }
    
    function isOrInTag(element, tag) {
      for (; element; element = element.parentNode) {
        if (element.tagName == tag)
          return true;
      }
      return false;
    }
    
    function onSelectionChange() {
      const selection = getSelection();
      if (selection.rangeCount == 0) {
        updateStatus('キャレットまたはテキスト選択がありません');
        return;
      }
      const range = selection.getRangeAt(0);
      if (isOrInTag(range.startContainer, 'B') && isOrInTag(range.endContainer, 'B'))
        updateStatus('Bタグの中です');
      else
        updateStatus('Bタグの中ではありません');
    }
    
    document.addEventListener('selectionchange', onSelectionChange);
    // selectionchangeイベントが起きなくてもメッセージ初期化
    onSelectionChange();
```

```

    div[contenteditable] {
      border: 1px solid gray;
    }
```

```

    <pre id="status"></pre>
    
    <div contenteditable=true>
    normal text
    <b>bold text <i>italic in bold</i> bold again</b>
    normal text again
    <i>italic text <b>bold in italic</b></i>
    normal text again and again
    </div>
```
CC BY-SA 4.0
2018-12-02T01:21:50.453
50820
2018-12-02T01:21:50.453
3475
50815
answer