Get line number of HTML element

I wonder if there is a better way to find the line number of items in the source code.

Here's what I got this far:

// Get the item that the user is clicking on:
var focused = doc.getSelection().anchorNode;
if(focused.nodeType == 3){ // text node
    focused = focused.parentNode;
}

// Get the entire page as a string
// NOTE: <!doctype> is not included in this!
var pageStr = doc.documentElement.outerHTML;

// Get the focused node parent and 
// find where it begins in the page.
var parentNodeStr   = focused.outerHTML;
var parentNodeIndex = pageStr.indexOf(parentNodeStr);

// Find where the focused node begins in it parent.
var focusedStr      = focused.outerHTML;
var focusedIndex    = parentNodeStr.indexOf(focusedStr);

// Now find where the focused node begins in the overall page.
var actualIndex     = parentNodeIndex - focusedIndex;

// Grab the text above the focused node
// and count the number of lines.
var contentAbove    = pageStr.substr(0, actualIndex);
var lineNumbers     = contentAbove.split("\n").length;

console.log("lineCount", lineNumbers);

      

+3


source to share


1 answer


Here's the best solution I have come up with, hopefully it helps someone in the future using Ace or CodeMirror in combination with contenteditable:

Setting (for beginners)

We can get where the user selects using:

var sel = document.getSelection();

      

The beginning of the selection is called "anchor" and the end is called "focus". For example, when you select multiple words of text, the start and end of the selection.

var anchorPoint = elementPointInCode(sel.anchorNode, sel.anchorOffset);
var focusPoint = elementPointInCode(sel.focusNode, sel.focusOffset);

      

Since HTML contains tags and readable text, there is an offset. For example:



<p>abcdefgh</p>
// ...^

      

The offset is the index in the text string node. In our example, the letter "d" is offset by 4 characters from the tag entry point → <lt. But the offset is zero-based, so the offset is actually 3.

We get the offset using:

var offset = sel.anchorOffset;
// -- or --
var offset = sel.focusOffset;

      

... depending on what we want, the beginning of the end.

Function

function elementPointInCode(element, offset) {

    // There may or may not be an offset.
    offset =  offset || 0;

    var node = element;

    // Process first node because it'll more-than-likely be a text node.
    // And we don't want to go matching text against any of the node HTML.
    //  e.g. <a href="page.html">page 1</a>
    //      where the text "page" sould match the "page" within the <a> attributes.

    var strIndex;
    var str;

    // Bump text nodes up to parent
    if(node.nodeType == 3) {
        node = node.parentNode;
        str = node.outerHTML;
        strIndex = str.indexOf(">") + offset + 1;
    } else {
        strIndex = ;
    }

    // This will ultimately contain the HTML string of the root node.
    var parentNodeStr = "";
    while(node){

        // Get the current node HTML.
        var str = node.outerHTML;

        // Preemptively snag the parent
        var parent = node.parentNode;

        if(parent && str){

            // The <html> root, we won't have a parent.
            var outer = parent.outerHTML;

            if(outer){

                // Stash the node HTML for post processing.
                parentNodeStr = outer;

                // Cumulatively count the offset within each node
                strIndex += parentNodeStr.indexOf( str );

            }

        }

        // Work our way up to the root
        node = parent;

    }

    // Chop the root HTML by our cumulative string index
    var str = parentNodeStr.substr(0, strIndex);

    var Astr = str.split("\n" );

    return {
        row : Astr.length,
        col : Astr.pop().length
    }

};

      

+1


source







All Articles