简体   繁体   English

range.setStart只使用字符偏移?

[英]range.setStart using only character offset?

I'm quite new to Javascript, and I've been reading the documentation for the last couple of days trying to figure this out. 我对Javascript很陌生,过去几天我一直在阅读文档,试图解决这个问题。 I've finally had to resort to parading my ignorance here. 我终于不得不诉诸于在这里炫耀我的无知。

I have an integer, which is the index of a character within a paragraph. 我有一个整数,它是段落中字符的索引。 I want to find the bounding rect of this character. 我想找到这个角色的边界矩形。 I have been trying to do this by making a range that contains the character. 我一直试图通过制作包含角色的范围来做到这一点。

So I have tried: 所以我试过了:

var range = document.createRange();
range.setStart (node, offsetInsideNode);

and for node I tried passing in the paragraph element, and for the offsetInsideNode I passed in the characterOffset integer. 对于节点我尝试传入段落元素,而对于offsetInsideNode我传入了characterOffset整数。

But then I found: "If the node element can have child nodes, then the offsetInsideNode parameter specifies the position of a child node in the childNodes collection of the node element, else it specifies a character position in the text content of the node element." 但后来我发现:“如果节点元素可以有子节点,则offsetInsideNode参数指定节点元素的childNodes集合中子节点的位置,否则它指定节点元素的文本内容中的字符位置。 “

But I want to ONLY use the character position. 但我想只使用角色位置。 And I can't figure out how to do this, as it only seems to want to use child node position. 我无法弄清楚如何做到这一点,因为它似乎只想使用子节点位置。 I'm guessing I'm missing something. 我猜我错过了什么。

Say I have a paragraph: 说我有一个段落:

<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>

And I want to find the bounding rect of the nth character, how would I go about this? 我想找到第n个角色的边界矩形,我该怎么做呢? Am I barking up the wrong tree and there is a much simpler way that I have overlooked? 我咆哮着错误的树,有一种我忽略的简单方法吗?

Thanks. 谢谢。

notes: 笔记:

  • javascript only 仅限javascript
  • no libraries 没有图书馆
  • no jquery 没有jquery
  • for UIWebview on an iOS device 适用于iOS设备上的UIWebview

I hope this is what you're looking for. 我希望这就是你要找的东西。 This function basically takes the content of the element you want to find nth in, splits it into characters, finds nth without counting the HTML tags, wraps nth in a temporary span and reads the offsetTop and offsetLeft before replacing it with the original content. 此函数基本上获取要在其中找到的元素的内容,将其拆分为字符,在不计算HTML标记的情况下查找nth ,在临时范围内包装nth并在将其替换为原始内容之前读取offsetTopoffsetLeft The offset x and y is then returned as an object. 然后将偏移量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;
}

Use it like this: 像这样使用它:

nthCharOffset(10, document.getElementById('element'));

I've made a fiddle so you can test it here . 我做了一个小提琴,所以你可以在这里测试一下

This fiddle uses the function to position and scale a red rectangle to nth character. 这个小提琴使用该功能将红色矩形定位并缩放到nth字符。

As far as I understand you want 据我所知,你想要的

ONLY the character position 只有角色位置

in order to specify a range for a selection, rather than some node-offset. 为了指定选择的范围,而不是某些节点偏移。 I believe I just had the same problem. 我相信我遇到了同样的问题。 The offset can be created by addressing nodes or characters. 可以通过寻址节点或字符来创建偏移量。 The Range.setStart method does two things at once, which is a pain, but the documentation gives away what you have to do: Range.setStart方法一次完成两件事,这很痛苦,但文档提供了你必须做的事情:

If the startNode is a Node of type Text, Comment, or CDATASection, then startOffset is the number of characters from the start of startNode. 如果startNode是Text,Comment或CDATASection类型的节点,则startOffset是startNode开头的字符数。

See: https://developer.mozilla.org/en-US/docs/Web/API/Range/setStart 请参阅: https//developer.mozilla.org/en-US/docs/Web/API/Range/setStart

Therefore you can specify a character-indexed range by addressing the text node of an element. 因此,您可以通过寻址元素的文本节点来指定字符索引范围。 Here is an (optimistic) solution I came up with. 这是我提出的(乐观)解决方案。

Assume you have a document and you want to add sticky CSS-styled, yellow hightlights to a piece of selected text. 假设您有一个文档,并且您想要将粘性的CSS样式的黄色高光添加到一段选定的文本中。 In Javascript, create a range and select the element. 在Javascript中,创建一个范围并选择该元素。 Add range but select the textnode first. 添加范围,但首先选择textnode。 The offset will then refer to the characters, rather than the nodes. 然后,偏移将引用字符,而不是节点。

// 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. 

First, the given p element is selected. 首先,选择给定的p元素。 Then, we extract the textNode using the function getTextNodeFrom(element) . 然后,我们使用函数getTextNodeFrom(element)提取textNode。 Note that this function is really optimistic. 请注意,此功能非常乐观。 It assumes that the list of nodes contains a textNode as the first element which doesn't have to be the case. 它假定节点列表包含textNode作为第一个元素,但不一定是这种情况。 How you obtain this node is up to you and here only a simple approach is shown. 您如何获得此节点取决于您,此处仅显示一个简单的方法。 I would assume iterating over the list and checking the nodes' types for Text or CDATA would suffice. 我会假设迭代列表并检查节点的Text或CDATA类型就足够了。

The range is created and the start and end are set. 创建范围并设置开始和结束。 When the 'node' object is a textNode, the offset addresses the characters. 当'node'对象是textNode时,偏移量对字符进行寻址。 Take a look at this fiddle to see it in action. 看看这个小提琴,看看它在行动。

As an example, the shown code takes the selected range and surrounds it with a styled span element to highlight the range from character 50 to 200 . 例如,显示的代码采用所选范围并用样式化的span元素围绕它,以突出显示从字符50200的范围。

https://jsfiddle.net/cessor/t6sroob1/2/ https://jsfiddle.net/cessor/t6sroob1/2/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何删除使用Range.setStart / setEnd选择的字符? - How to delete a character selected with Range.setStart/setEnd? dom range.setStart / setEnd - dom range.setStart / setEnd javascript:range.setStart()INDEX_SIZE_ERR(1) - javascript: range.setStart() INDEX_SIZE_ERR(1) 如何突出显示桌面 Safari 文本选择<div>在 Range.setStart / Range.setEnd 之后? - How to highlight desktop Safari text selection in <div> after Range.setStart / Range.setEnd? 未捕获的 DOMException:无法在“Range”上执行“setStart”:偏移量大于节点的长度 - Uncaught DOMException: Failed to execute 'setStart' on 'Range': The offset is larger than the node's length JavaScript 范围 setStart 不适用于“粗体”文本 - JavaScript Range setStart not working on "Bold" Text 获取范围以将第一个元素设置为setStart - Get Range to set first element as setStart 尝试在范围上使用setStart和setEnd时出现错误:未捕获IndexSizeError:无法在&#39;Range&#39;上执行&#39;setEnd&#39; - Erro when try use setStart and setEnd on Range: Uncaught IndexSizeError: Failed to execute 'setEnd' on 'Range' CK编辑器的查找和替换将仅在第一次时起作用,然后将给出范围为[0]的索引错误。setStart函数 - CK editor find and replace will works only first time then it will gives index error in ranges[0].setStart function 如何使用Javascript在文本区域中选择字符范围? - How to select a character range in a textarea using Javascript?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM