Search code examples
javascripthtmlcsstextselection

get line where selection is in javascript


I have a div contentEditable=true where multi-line text is entered. Whenever the user press enter, I would like to inspect the line in which the user was to see what is the context of that line (preferably, of all lines).

Is it possible to have something like window.getSelection().lineContent ?

I can use window.getSelection().anchorNode.textContent, but it will only work for the current node (not the line). I'm assuming the user will press enter to go to next line and I'd like to know if next line should or not be indented (my main goal is to know whether there is a "tab" in the beginning of the line, so far).

EDIT: Current code:

document.getElementById('sampleeditor').addEventListener("keydown", fSubsTab );

function fSubsTab () {      
    e = window.event
    if ( false ) {
    } else if ( e.keyCode == 13 ) {
        e.preventDefault();
        if (!window.getSelection) return;
        sel = window.getSelection();
        node_offset = sel.anchorOffset
        node_text = sel.anchorNode.textContent

        // The problem is how would I get the content of the
        // current line between last line break and next one,
        // or until the end
    }
}

EDIT 2: SOLVED. See answer below.


Solution

  • I've solved it by using a custom function to generate a uuid, add it to the text and then remove it back. The code is a little messy because of the quantity of functions used, but it goes something like this

    // function for replacing characters without case sensitivity
    String.prototype.replaces = function(str, replace, incaseSensitive) {
        if(!incaseSensitive){
            return this.split(str).join(replace);
        } else { 
            // Replace this part with regex for more performance
    
            var strLower = this.toLowerCase();
            var findLower = String(str).toLowerCase();
            var strTemp = this.toString();
    
            var pos = strLower.length;
    
            
    
            while((pos = strLower.lastIndexOf(findLower, pos)) != -1){
                tcounter++
            
                strTemp = strTemp.substr(0, pos) + replace + strTemp.substr(pos + findLower.length);
                pos--;
                if (pos<0) {
                    break
                }
    
            }
            return strTemp;
        }
    };
    
    // function for generating uuid to be used after
    function uuidv4() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }
    
    // function for dealing with linebreaks from innerhtml and returning as text with line breaks
    function innerHTMLtoText ( inner ) {
            text = inner
            prelb = uuidv4() + uuidv4() + uuidv4() + uuidv4()
            
            prelb_list = [];
    
                        
            lb = prelb + "ddd" + prelb; prelb_list.push(lb);
            tag_ = "<div>"; text = text.replaces ( tag_, lb + tag_, true );
            tag_ = "</div>"; text = text.replaces ( tag_, lb + tag_, true );
            tag_ = "<div "; text = text.replaces ( tag_, lb + tag_, true );
            lb = prelb + "ppp" + prelb; prelb_list.push(lb);
            tag_ = "<p>"; text = text.replaces ( tag_, lb + tag_, true );
            tag_ = "</p>"; text = text.replaces ( tag_, lb + tag_, true );
            tag_ = "<p "; text = text.replaces ( tag_, lb + tag_, true );
            lb = prelb + "bbb" + prelb; prelb_list.push(lb);
            tag_ = "<br>"; text = text.replaces ( tag_, lb + tag_, true );
            tag_ = "<br "; text = text.replaces ( tag_, lb + tag_, true );
            // tag_ = "<br />"; text = text.replaces ( tag_, lb + tag_, true );
            tag_ = "<br/>"; text = text.replaces ( tag_, lb + tag_, true );
            tag_ = "</br>"; text = text.replaces ( tag_, lb + tag_, true );
            
            var temporalDivElement = document.createElement("div");
            temporalDivElement.innerHTML = text;
            text = temporalDivElement.textContent
            
            list_ = prelb_list
            for ( let i = 0 ; i<list_.length ; i++ ) {
                this_ = list_[i]
                
                text = text.replaces ( this_, "\n", true );
            }
            return text
        }
    
    // main function, that generates a uuid, inserts at caret position, checks text of line, and removes the uuid 
    document.getElementById('sampleeditor').addEventListener("keyup", function(e) {
        if(e.keyCode == 13) {
            texteditor = document.getElementById('sampleeditor')
      
            e.preventDefault();
    
            if (!window.getSelection) return;
                
            sel = window.getSelection();
    
            if (!sel.rangeCount) return;
        
            range = sel.getRangeAt(0);
            range.collapse(true);
                
            span = document.createElement('span');
            span.appendChild(document.createTextNode(' '));
            theSpanId = "span_" + uuidv4() + uuidv4() + uuidv4() + uuidv4()
            span.id = theSpanId
            outerInclude = span.outerHTML
                
            changeText = document.createElement('span');
            idToRemove = uuidv4() + uuidv4() + uuidv4() + uuidv4()
            changeText.innerHTML = idToRemove
            outerRemove = changeText.outerHTML
            range.insertNode(changeText);
    
            theinner = texteditor.innerHTML
            
            plainText = innerHTMLtoText ( theinner )
            
            posLineBreak = plainText.indexOf (idToRemove)
            textBefore = plainText.substring(0, posLineBreak)
            textBefore = textBefore.split ("\n")
            linePart1 = textBefore[textBefore.length-1]
                
            textAfter = plainText.substring(posLineBreak)
            textAfter = textAfter.split ("\n")
            linePart2 = textAfter[0]
            fullLine = linePart1 + linePart2
    
            fullLine = fullLine.split ( idToRemove ).join ("")
            texteditor.innerHTML  = texteditor.innerHTML.split(outerRemove).join("<br>" + outerInclude)
    
            range = sel.getRangeAt(0);
            range.collapse(true);
    
            span = document.getElementById(theSpanId)
    
            range.setStartAfter(span);
            range.collapse(true);
    
            var startNode = span.firstChild;
            var endNode = span.firstChild;
    
            var range = document.createRange();
    
            range.setStart(startNode, 0);
    
            range.setEnd(endNode, 0+1);
            var sel = window.getSelection();
    
            sel.removeAllRanges();
            sel.addRange(range);
    
        }
    });