在HTML源代码中获取被点击元素的插入符号[开始,结束]位置

时间:2015-09-09 02:42:51

标签: javascript html dom

这是一个非常具有挑战性的问题。我还没有看到它在Stack Overflow上的任何地方都能解决。所以我决定发布它。

0      ----17----+           +---30---
|                |           |                +----47
|                |           |                |
<div>ABC<b>B Elem<i>Italic</i>ent</b> DEF</div>
        |                           |
        +---8---             ---37--+

操作:让我们点击元素&lt; i&gt; 标记。

问题:创建一个返回坐标[17,30]

的函数

注意:坐标为 开始 结束 插入位置,代表作为基于0的索引,在原始HTML源代码中,仅包含被单击的元素。可以假设规范化的HTML节点,如id =&#34;&#34;成为id =&#34;&#34;。 (但是,如果它没有额外的功劳,那么。)

示例2:如果&lt; b&gt;标签被点击了。该脚本应返回[8,37],因为它是包含B标记的开始/结束插入符号位置。

示例3:如果单击了ABC文本或DEF文本,则返回值为[0,47]

3 个答案:

答案 0 :(得分:0)

走父链,直到你点击你认为是容器的任何标记(显然你的情况为<div>)。

如果您有两个或更多相同的孩子,请使用父母的孩子找到您来自的特定孩子,例如from <i>two</i> to <i>two</i> to <i>two</i> <i>two</i>。 这应该给你父母的子偏移。然后,您可以累计偏移量,直到您点击div标记或其他任何容器元素 结束位置只是这个偏移加上点击的元素长度。

答案 1 :(得分:0)

经过两天的解决,我发布了自己的解决方案。

我首先尝试解析DOM并手动计算字符数。但这比以前更加复杂。

信用:感谢kuroi neko,他建议最终插入位置只是包含点击标记的HTML的起始位置+长度。

注意:我手动删除&lt; tbody&gt;标签,在计算插入符号值之前。这是因为,即使原始HTML不包含它们,在规范化过程中(在innerHTML或outerHTML调用期间发生),它们也会自动插入。如果您正在构建需要此功能的文本编辑器,那么这是个人偏好 - 让他们独自一人并更新原始HTML。

另一方面,如果您更喜欢纯粹主义方法,并且想要完整地考虑原始HTML,因为它是由所述HTML的作者编写的,那么您可能希望删除&lt; tbody&gt;手动。这也假设您负责处理所有其他类似的案件。无论他们是什么。 (未包含在以下解决方案中。

解决方案:考虑 textarea (HTML源代码编辑器)和 #preview 是表示相同HTML的两个独立元素。

$(document).ready(function() {

            // Normalize source code
            var normalized_html = document.getElementById("preview").innerHTML;

            // Remove all TBODY tags (they are auto-inserted, even if not present in original HTML)
            normalized_html = normalized_html.replace(/<tbody>/g, '');

            $("#textarea").html(normalized_html);

            $("#preview").on("click", function(event) {

                // Get clicked tag HTML
                var tag = event.target.outerHTML;

                // Get original HTML before split character is inserted
                var orig_html = document.getElementById("preview").innerHTML;//.replace(/<preview>/g, '').replace(/<\/preview>/g, '');

                // Insert unique separator just before the tag that was clicked, to mark beginning
                $(event.target).before("[*-*]");

                // Get preview source code
                var html = document.getElementById("preview").innerHTML;

                // Remove line breaks
                html = html.replace(/\r|\n/g, '');

                // Remove tags that were auto-inserted by native normalization process that did not exist in original HTML.
                html = html.replace(/<tbody>/g, '');

                var before_split = html;

                // Split HTML at the tag that was clicked
                html = html.split("[*-*]")[0];

                // Restore preview to original HTML
                $("#preview")[0].innerHTML = orig_html;

                // Get start and end of caret in source code
                var caret_start = html.length;
                var caret_end = caret_start + tag.length;

                console.log("caret start = " + caret_start + " end = " + caret_end);

            });

        });

答案 2 :(得分:0)

只需使用Descop库就可以实现这一目标。

// Get the source html code of target document
var html = yourFunctionToGetHTML();

// Get the target document itself
var dom = yourFunctionToGetDocument();

// Get the element you want to found in source code
var element = document.getElementById("target-element");

// Create an instance of Descop
var descop = new Descop();

// Connect document
descop.connectDocument(dom);

// Connect source code
descop.connectSource(html);

// Get element position in source code
var position = descop.getElementPosition(element);
// eg. position => { start: 320, end: 480 }