95150
↓確認しました。  
[getselection contenteditable
特定のdiv内でユーザーが選択した範囲を取得する](https://ja.stackoverflow.com/questions/69756/getselection-
contenteditable-%e7%89%b9%e5%ae%9a%e3%81%aediv%e5%86%85%e3%81%a7%e3%83%a6%e3%83%bc%e3%82%b6%e3%83%bc%e3%81%8c%e9%81%b8%e6%8a%9e%e3%81%97%e3%81%9f%e7%af%84%e5%9b%b2%e3%82%92%e5%8f%96%e5%be%97%e3%81%99%e3%82%8b)

下記のようにrange.toString()で選択範囲の文字列を取得できたのですが、HTMLタグも含めて取得するにはどうしたらよいでしょうか？

```

    function onSelectionChange() {
    let selection = window.getSelection();
    if(selection.rangeCount != 1) {
        return;
    }
    
    const range = selection.getRangeAt(0);
    
    if(!range.collapsed){
      document.getElementById('result').textContent = range.toString();
    }
    
    }
    
    document.addEventListener('selectionchange', onSelectionChange);
    onSelectionChange();
```

```

    <html>
    <body>
    <div id="text" contenteditable="true"><b>bold</b> and <i>italic</i></div>
    <div id="result"></div>
    </body>
    </html>
```
CC BY-SA 4.0
2023-06-08T10:50:55.360
95149
2023-06-11T23:56:29.373
58654
question
javascript
contenteditable="true"のdiv要素内で、HTMLタグを含めて選択範囲の文字列を取得したい
`getSelection().getRangeAt(0).cloneContents()` で `DocumentFragment`
ノードが得られます。その子ノードをループして、`Element` だったら `outerHTML` を呼ぶ、`Text` だったら `<` と `&`
をエスケープ、のようにシリアライズしてください。

`new
XMLSerializer().serializeToString(getSelection().getRangeAt(0).cloneContents())`
という手もありますが、こちらは XML としてシリアライズするので `xmlns` がついたりします。

* * *

> > もし ol が選択されてたら
>
> はい、`<b>ol</b>`で取得したいです。

選択範囲を `document.execCommand('copy', ...)` でクリップボードにコピーして、[Clipboard API
で読み出す](https://developer.mozilla.org/ja/docs/Web/API/Clipboard/read)という手法が可能かもしれません。  
[【JavaScript】クリップボードの内容を読み取る方法](https://webfrontend.ninja/js-clipboard-read/)  
読み取る方法はこのページが参考になるかもしれません。

コピーしたくない場合は、簡単な方法はなさそうです。`getSelection().getRangeAt(0)` で得られた `Range`
オブジェクトの始点と終点の情報から必要なタグやテキストを自力で判定してHTMLソースを組み立てます。そういうことをしてくれるライブラリなどが存在するかもしれませんね。
CC BY-SA 4.0
2023-06-08T12:27:14.970
95150
2023-06-11T23:56:29.373
2023-06-11T23:56:29.373
3475
3475
95149
answer