TheMagician
TheMagician

Reputation: 1856

Modifying inserted element inside DOMNodeInserted event produces "too much recursion"

I'm writing code for a message board and when the user is writing a post and clicks "preview" it creates a new DIV element that contains the parsed post. I need to detect when this preview element is created and modify its contents. The following code creates infinite recursion in Chrome, Firefox halts after 5 recursions.

$('#c_post').on('DOMNodeInserted', function(){
    var $preview = $('#c_post-preview');
    if($preview.length) { 
        $preview.html(applyForEach(funcs, $preview.html())); 
    }
});

It's not related to applyForEach because I just added that code and I was getting the recursion error before that but here's the code for that anyway:

function applyForEach(arr, s) {
    for(var i = 0; i < arr.length; ++i) {
        s = arr[i](s);
    }
    return s;
}

var funcs = [createGifvVideo, createGfycatVideo, createHtml5Video];

The functions simply take a string, call replace on it, and returns the string.

Upvotes: 5

Views: 675

Answers (3)

wiesion
wiesion

Reputation: 2445

Most probably you have nested #c_post-preview inside of #c_post, but i can't tell for sure, since you didn't post the HTML source. Of course this would lead to an infinite loop of triggering and catching events. But besides that, i don't think you want to applyForEach the content of the post preview, but the one of the post itself.

Consider the following: http://jsfiddle.net/wpb18pyu/ compared to: http://jsfiddle.net/wpb18pyu/1/

Upvotes: 0

Magus
Magus

Reputation: 15104

I suppose #c_post-preview is inside #c_post. So when you modify #c_post-preview, the event DOMNodeInserted is triggered again. And you catch it again, and you modify #c_post-preview, and so on ...

Upvotes: 1

Rohit Kumar
Rohit Kumar

Reputation: 1958

You may break the infinite recursion by unbinding and binding event . so it would not go into infinite call.Try following-

$('#c_post').on('DOMNodeInserted',DomInsCallback);

function DomInsCallback(){
    var $preview = $('#c_post-preview');
    if($preview.length) {
        $('#c_post').off('DOMNodeInserted');//here unbind first 
        $preview.html(applyForEach(funcs, $preview.html())); 
        $('#c_post').on('DOMNodeInserted',DomInsCallback);//bind again
    }
}

Upvotes: 9

Related Questions