2

The title may not seem that self-explanatory, but the question is actually pretty simple. Imagine the following code:

<div class="line">
    Some text node here. <span>Some nodeType 3 here.</span> 
    More text here. <span>And here as well.</span>
</div>

Now, using javascript I'd like to delete the contents of the div. So something like:

function deleteContent(from, to) { 
    // Some code to execute here
}

and the result will be something like:

<div class="line">
    Some text node here. <span>Some nodeType</span>
</div>

So basically, in theory, it's like using the slice function div.innerHTML.slice(from, to) except that this would only work if there were no tags within the div. I've already thought about creating a text range and deleting the contents with deleteContent but I don't know if it is the simplest way to go. What are your suggestions?

PS: I'd like to have a code that is neat and logical.

EDIT

As a response to Felix: Yes, I treat from and to as two integers. And for whitespaces, in my application I'll have to understand each whitespace seperately. That is, &nbsp;&nbsp; are two characters.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Savas Vedova
  • 5,622
  • 2
  • 28
  • 44
  • `from` and `two` are numbers then? How do you treat the whitespace before `More text here.` or `Some text node here.`? Collapse into one, like HTML is doing it? Could you give a concrete example with actual input and expected output? – Felix Kling Apr 24 '12 at 13:12
  • I actually didn't mean ` ` (although that's good to know as well). I meant if your text contains e.g. ``foo___bar`` (`_` is a space). HTML would display it as `foo_bar`. Do you consider all white spaces or not? – Felix Kling Apr 24 '12 at 13:22
  • @FelixKling yes I'll treat it as foo___bar – Savas Vedova Apr 24 '12 at 13:25

1 Answers1

2

I'm working on exactly this for my Rangy library and I'm almost ready to release it. In the meantime, you can use something like the following that will work in most situations but has drawbacks:

  • doesn't work in IE < 9
  • doesn't take into account implicit line breaks from block elements and <br>s
  • doesn't ignore invisible text, such as contents of <script> and <style> element or text inside elements with CSS display set to none
  • doesn't collapse spaces as they would appear on the rendered page
  • other subtleties

Live demo: http://jsfiddle.net/nT28h/

Code:

function createRangeFromCharacterIndices(containerEl, start, end) {
    var charIndex = 0, range = document.createRange(), foundStart = false, stop = {};
    range.setStart(containerEl, 0);
    range.collapse(true);

    function traverseTextNodes(node) {
        if (node.nodeType == 3) {
            var nextCharIndex = charIndex + node.length;
            if (!foundStart && start >= charIndex && start <= nextCharIndex) {
                range.setStart(node, start - charIndex);
                foundStart = true;
            }
            if (foundStart && end >= charIndex && end <= nextCharIndex) {
                range.setEnd(node, end - charIndex);
                throw stop;
            }
            charIndex = nextCharIndex;
        } else {
            for (var i = 0, len = node.childNodes.length; i < len; ++i) {
                traverseTextNodes(node.childNodes[i]);
            }
        }
    }

    try {
        traverseTextNodes(containerEl);
    } catch (ex) {
        if (ex == stop) {
            return range;
        } else {
            throw ex;
        }
    }
}

function deleteBetweenCharacterIndices(el, from, to) {
    var range = createRangeFromCharacterIndices(el, from, to);
    range.deleteContents();
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Thanks Tim. Apparently using Range is the best way to go. – Savas Vedova Apr 24 '12 at 15:31
  • @SavasVedova: Yes, I definitely agree with that. – Tim Down Apr 24 '12 at 15:40
  • @TimDown is there any update for this that takes into account line breaks? Thanks – Rafael Jun 10 '14 at 04:16
  • 1
    @RafaelDiaz: There's the TextRange module in Rangy 1.3, which I'm still bugfixing but essentially works. Demo: http://rangy.googlecode.com/svn/trunk/demos/textrange.html – Tim Down Jun 10 '14 at 08:36
  • @TimDown That demo doesn't seem to answer my question at all – Rafael Jun 10 '14 at 12:38
  • 1
    @RafaelDiaz: I intended to link to the documentation as well: https://code.google.com/p/rangy/wiki/TextRangeModule. In particular, see the Range methods `selectCharacters()` and `toCharacterRange()`. The demo uses selection-based versions of these. – Tim Down Jun 10 '14 at 15:42
  • I have tried to select the characters like this: `var range = rangy.createRange(); range.selectCharacters(el, from, to);` But it's not selecting, I'm not sure if I'm using the library correctly – Rafael Jun 11 '14 at 03:07