Range.extractContents()提取并删除选中的对象

2023-08-011493次阅读原生Jsjavascript

Range.extractContents()提取并删除选中的Range对象,返回一个document.fragment对象,相当于我们的剪切功能。使用这个方法的话,剪切后跨标签会自动补全开始和闭合标签。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"
    />
    <title>Web 富文本编辑器 iframe 实现方式</title>
    <meta content="black" name="apple-mobile-web-app-status-bar-style" />
    <meta content="telephone=no" name="format-detection" />
    <style>
      html,
      body {
        height: 100%;
      }
    </style>
  </head>
  <body>
    源码显示区
    <textarea id="txtYuan" style="width:600px;height:200px"> </textarea>
    <p>
      实时编辑区
      <iframe
        id="editor"
        width="600px"
        height="200px"
        style="border: solid 1px"
      ></iframe>
    </p>
    <input
      type="text"
      id="path"
      value="./da335beafec55b073589aaf536d4d3ef.jpg"
    />
    <p>
      <input type="button" id="insert_img" value="插入图片" />
      <!-- <input type="button" id="preview" value="预览" />
      <input type="button" id="btnYuan" value="显示源码" /> -->
      <input type="button" id="btnB" value="加粗/正常" />
      <!-- <input type="button" id="btnLink" value="添加链接" /> -->
      <input type="button" id="btnBg" value="添加背景色" />
      <input type="button" id="btnItalic" value="斜体字" />
      <input type="button" id="btnUnderline" value="加下划线" />
      <input type="button" id="btnOpenType" value="openType字体" />
      <input type="button" id="btn2pdf" value="转pdf" />
    </p>

    预览区
    <div style="border: 1px dashed #ccc; padding: 20px" id="preview_area"></div>
    canvas视图
    <div id="canvasEle"></div>
    <script src="//cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.22/pdfmake.min.js"></script>
    <script src="//html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
    <script>
      const iframe = document.getElementById("editor");
      iframe.contentWindow.document.designMode = "on";
      iframe.contentWindow.document.contentEditable = true;

      // 在iframe中插入一张图片
      document
        .getElementById("insert_img")
        .addEventListener("click", function () {
          // iframe.contentWindow.document.execCommand(
          //   "insertImage",
          //   false,
          //   document.getElementById("path").value
          // );
          // return;
          // 返回插入符号当前位置的selection对象
          const selection = iframe.contentWindow.getSelection();
          // 获取包含当前节点的文档片段
          const range = selection.getRangeAt(0);
          // 创建需追加到光标处节点的文档片段
          const fragment = range.createContextualFragment(
            `<img src="${
              document.getElementById("path").value
            }" crossOrigin="anonymous" alt="">`
          );
          // 将创建的文档片段插入到光标处
          range.insertNode(fragment.lastChild);
        });

      // DOM 变动观察器(Mutation observer)
      const fun = function () {
        document.getElementById("preview_area").innerHTML =
          iframe.contentWindow.document.body.innerHTML;
        document.getElementById("txtYuan").innerHTML =
          iframe.contentWindow.document.body.innerHTML;
      };
      const observerOptions = {
        childList: true, // 观察目标子节点的变化,是否有添加或者删除
        attributes: true, // 观察属性变动
        subtree: true, // 观察后代节点,默认为 false
        characterData: true, //观察文本内容
      };
      const observer = new MutationObserver(function (MutationRecord) {
        console.log("MutationRecord", MutationRecord);
        window.requestAnimationFrame(fun);
      });
      observer.observe(iframe.contentWindow.document.body, observerOptions);

      //加粗/正常
      document.getElementById("btnB").addEventListener("click", function () {
        iframe.contentWindow.document.execCommand("bold", false, null);
      });

      //加下划线
      document
        .getElementById("btnUnderline")
        .addEventListener("click", function () {
          iframe.contentWindow.document.execCommand("underline", false, null);
        });

      //添加背景色
      document.getElementById("btnBg").addEventListener("click", function () {
        iframe.contentWindow.document.execCommand(
          "hiliteColor",
          false,
          "#ff0000"
        );
      });
      //斜体字
      document
        .getElementById("btnItalic")
        .addEventListener("click", function () {
          iframe.contentWindow.document.execCommand("italic", false, null);
        });

      //openType字体
      document
        .getElementById("btnOpenType")
        .addEventListener("click", function () {
          // 返回插入符号当前位置的selection对象
          const selection = iframe.contentWindow.getSelection();
          // 获取包含当前节点的文档片段
          const range = selection.getRangeAt(0);
          // 创建节点
          const span = document.createElement("span");
          span.style.color = "#f00";
          // span标签appendChild添加range.extractContents提取并删除range对象
          span.appendChild(range.extractContents());
          range.insertNode(span);
        });

      //转PDF
      document.getElementById("btn2pdf").addEventListener("click", function () {
        //Convert Table to PDF.
        html2canvas(iframe.contentWindow.document.body).then(function (canvas) {
          console.log(
            'document.getElementById("canvasEle")',
            document.getElementById("canvasEle")
          );
          document.getElementById("canvasEle").appendChild(canvas);

          const data = canvas.toDataURL();
          const docDefinition = {
            content: [
              {
                image: data,
                width: 500,
              },
            ],
          };
          pdfMake.createPdf(docDefinition).download("JSON.pdf");
        });
      });
    </script>
  </body>
</html>

 

上一篇: MutationObserver监听文本是否修改  下一篇: structuredClone可以直接实现深拷贝了  

Range.extractContents()提取并删除选中的对象相关文章