1

I have something very weird going on which I can't seem to figure out.

I have 2 ajax calls that fetch me some html that has to be written either to the element with the passed ElementID or to the document body. If both the responses come back in the same order as the calls were launched, there is no problem. If both the responses have to be written to an Element which we get by Id, there is no problem either.

However, if the responses come back in a different order from the order they are launched in and one of the responses is written to the document body, the container object seems to lose its link to the DOM Element.

Here is the JS fiddle: JS fiddle

You'll see that if you change

Resengo({
    CompanyID: '350034',
    Call: 'B',
    Time: '60',
    ElementID: 'B'
});

to

Resengo({
    CompanyID: '350034',
    Call: 'B',
    Time: '60'
});

, its response isn't written to the page and the pageContainer has completely lost its link to its DOM Element.

Edit: of course this can easily be fixed by changing

function renderWidget(html) {
    if (pageContainer) {
        pageContainer.innerHTML += html;
        console.log(pageContainer);
    } 
}

to

function renderWidget(html) {
    if (settings.ElementID) {
        pageContainer = document.getElementById(settings.ElementID);
    }
    if(pageContainer) {
        pageContainer.innerHTML += html;
        console.log(pageContainer);
    } 
}

but I'm intrigued by why this doesn't work as it seems illogical

Edit 2: here is the relevant javascript

var Resengo = (function () {

// constructor
var Resengo = function resengo(settings) {

    jQuery = window.jQuery;
    getWidget();

    // private class variable
    var settings = settings;
    var pageContainer;

    function getWidget() {
        jQuery(document).ready(function ($) {
            /******* Create and add loader *******/
            if (settings.ElementID) {
                pageContainer = document.getElementById(settings.ElementID);
            } else {
                pageContainer = document.body;
            }

            /******* Load HTML *******/
            var url;
            if (settings.ElementID) {
                carouselWidth = $('#' + settings.ElementID).outerWidth();
            }
            if (settings.ElementID) {
                carouselHeight = $('#' + settings.ElementID).outerHeight();
            }
            if (settings.Time) {
                doOpenReservationPopup = settings.Time * 1000;
            }
            if (settings.Language) {
                language = settings.Language;
            }

            url = '/echo/html/';
            var delay = 0;
            if(settings.Call == 'A') {
                delay = 1;
            }
            $.ajax({
                url: url,
                type: 'POST', // form submit method get/post
                data: {
                    html: "<p>Text echoed back to request</p>",  
                    delay: delay
                },
                dataType: 'html', // request type html/json/xml
                success: function (data) {
                    renderWidget(data);
                }
            });                
        });
    };
    function renderWidget(html) {
        if (pageContainer) {
            pageContainer.innerHTML += html;
            console.log(pageContainer);
        } 
    }
};

return Resengo;

})();
Resengo({
    CompanyID: '350034',
    Call: 'A',
    ElementID: 'A'
});
Resengo({
    CompanyID: '350034',
    Call: 'B',
    Time: '60',
    ElementID: 'B'
});

And the relevant html:

<body bgcolor="#999999">
<div id="Feedbacks">

</div>
<br /><br />
<div id="A">

</div>
<div id="B">

</div>    
</body>
Mats Raemen
  • 1,781
  • 1
  • 28
  • 41
  • 1
    You need to include the relevant code IN THE QUESTION. not in JSFiddle. Read [ask] – Amit Aug 14 '15 at 08:48

1 Answers1

1

However, if the responses come back in a different order from the order they are launched in and one of the responses is written to the document body, the container object seems to lose its link to the DOM Element.

Yes, that is because when setting the innerHTML attribute of a node, all child nodes are deleted, the HTML string is parsed, and new nodes are created from it.
Therefore, all references to child nodes of body are broken. Nodes aren't just the same because they happen to have the same id attribute or something.

var div1 = document.getElementById('test');
document.body.innerHTML = '<div id="test">Test</div>';
var div2 = document.getElementById('test');
document.write(div1 == div2);
<div id="test">Test</div>

It's basically the same thing that happens when JSON-serializing and unserializing objects in JS:

var obj =
{
    'a': 'AAA'
};
var obj2 = JSON.parse(JSON.stringify(obj));
obj.b = 'BBB';
document.write(JSON.stringify(obj2));

Why doesn't it print {"a":"AAA", "b":"BBB"}?
Because obj and obj2 are two different objects.

Siguza
  • 21,155
  • 6
  • 52
  • 89
  • That makes sense, I had no idea appending something to the innerHTML of an element caused it to delete and recreate its child nodes. Thanks! – Mats Raemen Aug 14 '15 at 09:06
  • See also [Why is “element.innerHTML+=” bad code?](https://stackoverflow.com/q/11515383) (for better ways to do the same). – Siguza Aug 14 '15 at 09:16