醉美水芙蓉 发表于 7 天前

马黑黑《初识 Selection 对象》

<style>
    .artBox { margin: 20px auto; font: normal 18px/28px sans-serif; max-width: 1200px; }
    .artBox mark { padding: 2px 6px; background: lightblue; }
    .artBox blockquote { padding: 14px; border: solid lightblue; border-width: 0 4px; border-radius: 10px; background: beige; }
    .artBox p { margin: 10px 0; }
    .mama { margin: 30px; width: 600px; border: 1px solid gray; border-radius: 10px; padding: 10px; }
</style>

<div class="artBox">
    <blockquote id="bq1" onclick="getSelectedText();">Selection 对象表示用户选择的文本范围或插入符号的当前位置。它代表页面中的文本选区,可能横跨多个元素。文本选区由用户按下鼠标左键不放并拖拽鼠标经过文字而产生。调用 window.getSelection() 方法可以获取 Selection 对象。</blockquote>
    <p><button onclick="showSelection();">演示:点击此按钮将会在上面的文本段落中随机创建选区</button></p>
    <p>正如文本开头引用框所介绍的,你也可以在上面的文本段落中自行选择任意文本。上面介绍 Selection 对象的引用框集成有一个功能:用鼠标手动选择任意文本,都会弹出一个 alert 窗口,窗口上展现被选择文本的相关信息。功能的实现仅使用了一个方法:<mark>selection.toString()</mark>,该方法返回选区内的完整文本,toString 是<b>转换为字符串</b>的意思。</p>
    <p><mark>window.getSelection()</mark> 方法返回的是一个 Selection(选区)对象,该对象拥有如下主要<b>属性</b>:</p>
    <ul>
      <li><b>anchorNode</b> :只读,返回选区<b>起点</b>所在的节点(Node)。anchor是“锚”之意,指选区开始时的定位点(鼠标按下时的那个点)</li>
      <li><b>anchorOffset</b> :只读,返回选区起点在 anchorNode 中的位置偏移量。需要注意两种情形:
            <ol>
                <li>如果 anchorNode 是文本节点、注释节点,返回锚点(anchor)到该节点中第一个字的字符个数</l>
                <li>如果 anchorNode 是元素节点,返回锚点(anchor)之前的同级节点总数</li>
            </ol>
      </li>
      <li><b>focusNode</b> :只读,返回选区终点所在的节点。focus意味“焦点”,这里指选区起点到终点的高亮区域</li>
      <li><b>focusOffset</b> :只读,返回选区终点在 focusNode 中的位置偏移量。需要注意两种情形:
            <ol>
                <li>如果 focusNode 是文本节点、注释节点,返回焦点(focus)到该节点中的第一个字的字符个数</li>
                <li>如果 focusNode 是元素节点,返回焦点(focus)之前的同级节点总数</li>
            </ol>
      </li>
      <li><b>isCollapsed</b> :只读,返回布尔值,表示选区的起始点和终点是否在同一个位置</li>
      <li><b></b> :只读,选区方向,返回forward(自左向右)或 backward(自右向左)</li>
      <li><b>rangeCount</b> :只读,返回选区所包含的连续范围(range)的数量</li>
    </ul>
    <p>【注意】选区有方向(direction),可以自左向右或自右向左,取决于用户按下左键后往左或往右拖曳。选区的方向直接影响锚和焦点的位置,自左向右时锚前、焦点后,自右向左锚后、焦点前。</p>
    <p>下面是获取选区对象属性值的简单演示:</p>
    <div class="mama" onmouseup="getSelectionAttributes();">
      <h3>请选择任意文本</h3>
      <p>这行是 <mark>id="mama"</mark> div 的p标签文本,里面有两个<mark>mark</mark>元素节点</p>
      <div>这行是 div 标签,里面的内容是纯文本</div>
    </div>
    <p>选区(Selection)对象的主要<b>方法</b>则有:</p>
    <ul>
      <li>getRangeAt :返回选区包含的指定区域(Range)的引用,即获取指定选区的范围</li>
      <li>collapse :将当前的选区折叠为一个点</li>
      <li>extend :将选区的焦点移动到一个特定的位置</li>
      <li>modify :修改当前的选区</li>
      <li>collapseToStart :将当前的选区折叠到起始点</li>
      <li>collapseToEnd :将当前的选区折叠到最末尾的一个点</li>
      <li>selectAllChildren :将某一指定节点的子节点框入选区</li>
      <li>addRange :一个区域(Range)对象将被加入选区</li>
      <li>removeRange :从选区中移除一个区域</li>
      <li>removeAllRanges :将所有的区域都从选区中移除</li>
      <li>deleteFromDocument :从页面中删除选区中的内容</li>
      <li>toString :返回当前选区的纯文本内容</li>
      <li>containsNode :判断某一个 Node 是否为当前选区的一部分</li>
    </ul>
    <p>选区(Selection)对象的方法很多需要配合 range 对象使用,如开头随机选择选区就用上了 range 对象。下例仅演示 toStrong 和 delecteFromDocument 方法:</p>
    <div id="mama" class="mama" onmouseup="getTextAndDelete(this);">选择本此方框内的任意文本会获取所选择的文本然后删除掉,直至删完为止(选择后如果没有弹出alert窗口,请再单击一下此方框)。全部删除文本内容后可单击下方按钮重置。</div>
    <p><button id="btnResetText">重置方框文本</button></p>
    <p><br></p>
    <p>【附】本文基于选区的核心JS代码(自动获取)</p>
    <div class="hEdiv"><pre id="pre1" class="hEpre"></pre></div>
</div>

<script id="js_1">
    // 创建随机选区
    function showSelection() {
      const sel = window.getSelection();
      const range = new Range();
      const len = bq1.textContent.length; // blockquote的文本长度
      let begin = Math.floor(Math.random() * len / 2);
      let end = Math.floor(Math.random() * len);
      if (begin === end) end += 2;
      if (begin > end) = ;
      range.setStart(bq1.firstChild, begin);
      range.setEnd(bq1.firstChild, end);
      sel.removeAllRanges();
      sel.addRange(range);
    }
   
    // 获取选区文本
    function getSelectedText() {
      const sel = window.getSelection();
      const msg = sel.isCollapsed ? '你没有选择任何文字' : `你选择的文字是:${sel.toString()}`;
      alert(msg);
    }
   
    // 获取选区属性信息
    function getSelectionAttributes() {
      const sel = window.getSelection();
      let res = '未选择任何文本';
      // 若有选择文本
      if (sel.rangeCount) {
            const dir = {forward: '自左向右', backward: '自右向左'}
            res = `选区相关属性信息 :
            
                anchorNode(起始节点):${sel.anchorNode}
                anchorOffset(选区起点在起始节点中的偏移量):${sel.anchorOffset}
                focusNode(终点节点):${sel.focusNode}
                focusOffset(选区终点在结束节点中的偏移量):${sel.focusOffset}
                direction(选区方向):${sel.direction}(${dir})
                isCollapsed(起始和结束节点是否同一个):${sel.anchorNode === sel.focusNode ? '同' : '不同'}
                rangeCount(选区范围):${sel.rangeCount}`;
      }
      alert(res);
    }
   
    // 获取选区文本并删除
    function getTextAndDelete() {
      const sel = window.getSelection();
      let str = '没有选择任何内容';
      if (sel.isCollapsed) return;
      alert(`选择的文本“${sel.toString()}”将被删除!`);
      sel.deleteFromDocument();
    }
</script>

<script type="module">
    import hl from 'https://638183.freep.cn/638183/web/js/hl.js';
    pre1.innerHTML = js_1.outerHTML.replaceAll('<', '&lt;').replaceAll('>', '&gt;');
    const divs = document.querySelectorAll('.hEdiv');
    const pres = document.querySelectorAll('.hEpre');
    divs.forEach((div,idx) => hl.hl(div, pres));
   
    const rawtext = mama.innerText;
   
    btnResetText.onclick = () => mama.innerText = rawtext;
</script>

klxf 发表于 4 天前

长知识了,谢谢分享
页: [1]
查看完整版本: 马黑黑《初识 Selection 对象》