<!--
 * @FileDescription: MDN Range
 * @Date: 2023-06-05
 * @LastEditTime: 2023-06-06
-->
<script setup lang="ts">
import { onMounted, ref } from 'vue';

const _inputRef = ref<any>(null);
// const state = reactive({
//   lastEditRange: null as any, // 定义最后光标对象
// });

onMounted(() => {
  //
});

function rangeTest() {
  let html;
  const showRangeDiv = document.getElementById('showRange') as HTMLElement;
  const selection = document.getSelection() as Selection;

  if (selection.type === 'Range' && selection.rangeCount > 0) {
    html = '你选取了' + selection.rangeCount + '段内容<br/>';
    for (let i = 0; i < selection.rangeCount; i++) {
      let range = selection.getRangeAt(i);
      html += '第' + (i + 1) + '段内容为：' + range + '<br/>';
    }
    showRangeDiv.innerHTML = html;
  } else {
    showRangeDiv.innerHTML = '你没有选择内容';
  }
}

function rangeSet() {
  const oP1 = document.getElementById('p1') as HTMLElement;
  const oB1 = document.getElementById('b1') as HTMLElement;
  const oRange = document.createRange();

  oRange.setStart(oB1.firstChild as ChildNode, 2); // 设置range的“起点”
  oRange.setEnd(oP1.lastChild as ChildNode, 3); // 设置range的“结束点”

  // Range.startContainer 只读；
  // 返回包含 Range 开始的节点。【返回的是一个文本节点】
  console.log(oRange.startContainer); // 元素oB1.firstChild，文本节点
  // Range.startOffset 只读；
  // 返回一个数字，表示 Range 在 startContainer 中的起始位置。
  console.log(oRange.startOffset); // 2，可看到“起点”在<b id="b1">Hello</b>应是第三个字符。
}

// function getCursor() {
//   // 编辑框设置焦点
//   const inputDom = _inputRef.value;
//   inputDom.focus();

//   const selection = document.getSelection() as Selection;
//   const rangeCount = selection.rangeCount;
//   if (rangeCount > 0) {
//     // 设置最后光标对象
//     state.lastEditRange = selection.getRangeAt(0);
//     state.lastEditRange.deleteContents(); // 从 Document 中移除 Range 内容
//     console.log('最后光标对象', state.lastEditRange);

//     // 创建标签
//     const el = document.createElement('span');
//     el.innerHTML = '这是我创建的内容';

//     // 在 Range 开头插入一个节点
//     state.lastEditRange.insertNode(el);
//   }
// }

// 插入话题
function insertTopic() {
  insertHtmlAtCaret('#');
  insertHtmlAtCaret('插入话题');
  insertHtmlAtCaret('#');
  const range = (window.getSelection() as Selection).getRangeAt(0);
  range.selectNodeContents(
    range.startContainer.childNodes[range.startOffset - 2]
  );
}

// 插入标签
function insertEmoji() {
  // 编辑框设置焦点
  const inputDom = _inputRef.value;
  inputDom.focus();

  const selection = document.getSelection() as Selection;
  const rangeCount = selection.rangeCount;
  if (rangeCount > 0) {
    // 设置最后光标对象
    let range = selection.getRangeAt(0);
    range.deleteContents(); // 从 Document 中移除 Range 内容

    // 创建标签
    const img = document.createElement('img');
    img.setAttribute('class', 'img');
    img.src = require('./imgs/angel.png');
    img.style.height = '24px';
    img.style.width = '24px';
    // img.alt = item.label;

    // 在 Range 开头插入一个节点
    range.insertNode(img);
    range = range.cloneRange();
    range.setStartAfter(img);

    range.collapse(true);
    selection.removeAllRanges();
    selection.addRange(range);
  }
}

function insertHtmlAtCaret(html: any) {
  // 编辑框设置焦点
  const inputDom = _inputRef.value;
  inputDom.focus();

  const selection = document.getSelection() as Selection;
  const rangeCount = selection.rangeCount;
  if (rangeCount > 0) {
    // 设置最后光标对象
    let range = selection.getRangeAt(0);
    range.deleteContents(); // 从 Document 中移除 Range 内容

    // 创建标签
    const el = document.createElement('span');
    el.innerHTML = html;

    const frag = document.createDocumentFragment();
    let node;
    let lastNode;
    while ((node = el.firstChild)) {
      lastNode = frag.appendChild(node);
    }
    range.insertNode(frag);

    if (lastNode) {
      range = range.cloneRange();
      range.setStartAfter(lastNode);
      range.collapse(true);
      selection.removeAllRanges();
      selection.addRange(range);
    }
  }
}

function getVal() {
  const re = getDomValue(_inputRef.value);
  console.log(re);
}
// 获取纯文本内容
function getDomValue(elem: any) {
  let res = '';
  Array.from(elem.childNodes).forEach((child: any) => {
    if (child.nodeName === '#text') {
      res += child.nodeValue;
    } else if (child.nodeName === 'BR') {
      res += '\n';
    } else if (child.nodeName === 'BUTTON') {
      res += getDomValue(child);
    } else if (child.nodeName === 'IMG') {
      res += child.alt;
    } else if (child.nodeName === 'DIV') {
      res += '\n' + getDomValue(child);
    }
  });
  return res;
}
</script>
<template>
  <div class="q-pa-md">
    <div class="reference q-pa-md q-mb-md rounded-borders">
      <p>参考链接：</p>
      <a
        href="https://developer.mozilla.org/zh-CN/docs/Web/API/Range"
        target="_blank"
        rel="noopener noreferrer"
        >MDN Range</a
      >
      <br />
      <a
        href="http://www.jianshu.com/p/ad2f818cc3b0"
        target="_blank"
        rel="noopener noreferrer"
        >html5之Range对象详解</a
      >
      <br />
      <a
        href="https://segmentfault.com/a/1190000005869372"
        target="_blank"
        rel="noopener noreferrer"
        >html元素contenteditable属性如何定位光标和设置光标</a
      >
      <br />
      <a
        href="https://juejin.cn/post/6844903793864212494"
        target="_blank"
        rel="noopener noreferrer"
        >div+contenteditable 实现富文本发布框的小结</a
      >
    </div>
    <input type="button" value="点击我" @click="rangeTest" />
    <div id="showRange"></div>

    <br />
    <button @click="rangeSet">点我查看节点</button>
    <p id="p1"><span>span</span><b id="b1">Hello</b> World</p>

    <br />
    <button @click="insertTopic">点我插入话题</button>
    <img
      src="./imgs/angel.png"
      alt=""
      style="width: 25px; height: 25px"
      @click="insertEmoji"
    />
    <button @click="getVal">点我获取纯文本内容</button>
    <div class="_input" contenteditable="true" ref="_inputRef">输入文字</div>
  </div>
</template>

<style lang="scss" scoped>
.reference {
  border: 1px solid $border-color;
  background: $primary-bg-light;
}

._input {
  min-width: 200px;
  min-height: 60px;
  font-size: 14px;
  padding: 5px 8px;
  border: 1px solid #ddd;
}
</style>
