Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript range.setStart是否仅使用字符偏移量?_Javascript_Html_Ios - Fatal编程技术网

Javascript range.setStart是否仅使用字符偏移量?

Javascript range.setStart是否仅使用字符偏移量?,javascript,html,ios,Javascript,Html,Ios,我对Javascript非常陌生,过去几天我一直在阅读文档,试图弄明白这一点。我终于不得不在这里炫耀我的无知了 我有一个整数,它是段落中字符的索引。我想找到这个角色的边界矩形。我一直试图通过创建一个包含字符的范围来实现这一点 所以我试过: var range = document.createRange(); range.setStart (node, offsetInsideNode); 对于节点,我尝试传入段落元素,对于OffsetSideNode,我传入characterOffset整数

我对Javascript非常陌生,过去几天我一直在阅读文档,试图弄明白这一点。我终于不得不在这里炫耀我的无知了

我有一个整数,它是段落中字符的索引。我想找到这个角色的边界矩形。我一直试图通过创建一个包含字符的范围来实现这一点

所以我试过:

var range = document.createRange();
range.setStart (node, offsetInsideNode);
对于节点,我尝试传入段落元素,对于OffsetSideNode,我传入characterOffset整数

但是后来我发现:“如果node元素可以有子节点,那么offsetInsideNode参数指定node元素的childNodes集合中的子节点的位置,否则它指定node元素文本内容中的字符位置。”

但我只想使用角色的位置。我不知道怎么做,因为它似乎只想使用子节点位置。我猜我错过了什么

假设我有一段话:

<p xmlns="http://www.w3.org/1999/xhtml" class="s12" style="color: rgb(0, 0, 0);"><span class="mySpanClass">The</span> quick brown <b>fox</b> jumps over the lazy dog</p>

敏捷的棕色狐狸跳过了懒狗

我想找到第n个字符的边界矩形,我该怎么做呢?我是不是找错了方向,有一个更简单的方法我忽略了

谢谢

注:

  • 仅限javascript
  • 没有图书馆
  • 没有jquery
  • 对于iOS设备上的UIWebview

    • 我希望这就是您要找的。此函数基本上获取要在中查找第n个元素的内容,将其拆分为字符,在不计算HTML标记的情况下查找第n个
      nth
      ,将第n个
      nth
      包装在临时范围内,并读取
      offsetTop
      offsetLeft
      ,然后将其替换为原始内容。然后将偏移量x和y作为对象返回

      function nthCharOffset(nth, element){
          var orgContent = element.innerHTML;   // Save the original content.
          var arr = orgContent.split('');         // Split every character.
      
          // Few vars to control the upcoming loop
          var content = '';
          var tag = false;
          var count = 0;
      
          // Loop through every character creating a new string and wrapping the nth in a temporary span
          for (var i = 0; i < arr.length; i++) {
      
              // if inside tag, don't count this in the nth count
              if (arr[i] == '<') tag = true
              if (!tag) count++;
              if (arr[i] == '>') tag = false;
      
              // If this charactar is nth, wrap it in a temporary span
              if (nth == count) content += '<span id="offset-check">' + arr[i] + '</span>';
              else content += arr[i];
          }
      
          // Set the content with the temporary span.
          element.innerHTML = content;
      
          // Get the offset of the temporary span.
          var offsetCheck = document.getElementById('offset-check');
          var offset = {x: offsetCheck.offsetLeft , y: offsetCheck.offsetTop }
      
          // Remove the span.
          element.innerHTML = orgContent;
      
          // Return the result.
          return offset;
      }
      
      我做了一把小提琴,你可以试一下


      使用该函数定位红色矩形并将其缩放到第n个字符。

      据我所知,您需要

      只有字符位置

      以指定选择的范围,而不是某些节点偏移。我相信我也有同样的问题。偏移量可以通过寻址节点或字符来创建。
      Range.setStart
      方法一次可以做两件事,这是一件痛苦的事情,但是文档给出了您必须做的事情:

      如果startNode是Text、Comment或CDATA节类型的节点,则startOffset是startNode开头的字符数

      见:

      因此,可以通过寻址元素的文本节点来指定字符索引范围。下面是我提出的一个(乐观的)解决方案

      假设您有一个文档,并且希望向选定的文本片段添加粘性CSS样式的黄色高亮。在Javascript中,创建一个范围并选择元素。添加范围,但首先选择文本节点。偏移量将引用字符,而不是节点

      // Magic happens here
      function getTextNodeFrom(element) {
      
        // replace with more sophisticated method
        return element.childNodes[0];
      
      }
      
      // Create the range as you normally would
      function createRange(node, start, end) {
        var range = document.createRange();
        range.setStart(node, start);
        range.setEnd(node, end);
        return range;
      }
      
      // Give it a nice name 
      function createRangeByCharacterOffset(element, start, end) {
      
        // Rather than passing the element directly to createRange,  
        // extract the node first.
        var textNode = getTextNodeFrom(element)
        var range = createRange(textNode, start, end);
      
        return range;
      }
      
      // To illustrate, let's surround the range with a highlighting span
      function highlight () {
          var span = document.createElement('span');
          span.setAttribute('class', 'highlight');
          return span;
      }
      
      var p = document.getElementsByTagName('p')[0];
      
      createRangeByCharacterOffset(p, 50, 200)
      .surroundContents(highlight()); // This performs the actual highlight. 
      
      首先,选择给定的
      p
      元素。然后,我们使用函数
      getTextNodeFrom(元素)
      提取textNode。注意,这个函数非常乐观。它假定节点列表包含一个textNode作为第一个元素,而不必是这样。如何获得该节点取决于您,这里只显示了一种简单的方法。我假设迭代列表并检查节点的文本或CDATA类型就足够了

      将创建范围并设置起点和终点。当“node”对象是textNode时,偏移量对字符进行寻址。看看这把小提琴,看看它在演奏

      例如,所示代码获取所选范围,并用样式化的span元素将其包围,以突出显示从字符
      50
      200
      的范围


      我不确定你到底想得到什么。特定角色相对于窗口的x和y坐标?哇,我真的很感谢你的努力!我确实做了一个小改动,以修复当字符是html标记前的最后一个字符时的错误,我添加了:“if(nth==count&&&!tag&&arr[I]!='>')”。这样看来,一切都正常(尽管我还没有彻底检查)。再次感谢:)很高兴你觉得它有用。当你彻底测试了它之后,如果你发现有些东西不起作用,请随意更新你认为合适的答案。酷。我还注意到它也必须是“nthCharacterNumber==count-1”,才能使整个过程以零为基础。(因为for循环在实际使用它之前增加计数)。我无法对if语句进行重新排序以纠正这一问题,因为我现在在第一条评论中提到的最后一条if语句中使用了“tag”。我也可以通过将count初始化为-1来解决这个问题,但我认为这种方式更为明显。
      // Magic happens here
      function getTextNodeFrom(element) {
      
        // replace with more sophisticated method
        return element.childNodes[0];
      
      }
      
      // Create the range as you normally would
      function createRange(node, start, end) {
        var range = document.createRange();
        range.setStart(node, start);
        range.setEnd(node, end);
        return range;
      }
      
      // Give it a nice name 
      function createRangeByCharacterOffset(element, start, end) {
      
        // Rather than passing the element directly to createRange,  
        // extract the node first.
        var textNode = getTextNodeFrom(element)
        var range = createRange(textNode, start, end);
      
        return range;
      }
      
      // To illustrate, let's surround the range with a highlighting span
      function highlight () {
          var span = document.createElement('span');
          span.setAttribute('class', 'highlight');
          return span;
      }
      
      var p = document.getElementsByTagName('p')[0];
      
      createRangeByCharacterOffset(p, 50, 200)
      .surroundContents(highlight()); // This performs the actual highlight.