3
votes

TLDR: Injecting and then replacing popup components into a div via AJAX is causing jQM to insert its own overlay elements outside of the div without removing them.

I have a jQM web page which dynamically loads the contents of a div tag on success of an ajax call:

$("#contentPane").html(data).trigger("create");

The ajax call can be made several times, each one replacing the previous contents of the div. The contents which are loaded vary: they may have identical components to what was previously there or, they may be completely different.

What I'm noticing is that if the contents I inject contain UI components which "popup" from the page (for example a dialog, or a selectmenu with data-native-menu = "false") JQM inserts overlay elements directly into the body tag or the active page tag, outside my active page's main content div.

For example:

<body>
    ...
    <div class="ui-page ui-body-b ui-page-header-fixed ui-page-active" position="fixed" data-theme="b" data-role="page">
        <div id="contentHeader" class="ui-header ui-bar-b ui-header-fixed slidedown" data-theme="b" data-position="fixed" data-role="header" role="banner">...</div>
        <div id="contentPane" class="ui-content ui-body-b" data-theme="b" data-role="content" role="main">...</div>
        <div class="ui-selectmenu ui-overlay-shadow ui-corner-all ui-body-a pop ui-selectmenu-hidden">...</div>
        <div class="ui-selectmenu-screen ui-screen-hidden"></div>
    </div>
    ...
    <div class="ui-page ui-body-c ui-dialog ui-overlay-a" data-overlay-theme="a" data-theme="c" data-role="dialog" tabindex="0" style="min-height: 399px;">
</body>

The problem is that whenever I replace the contents of my "contentPane" div, these overlay elements stay in the DOM. If the new contents I inject require overlay elements as well, JQM creates new ones without removing the stale ones. So eventually my DOM looks like this:

<div class="ui-page ui-body-b ui-page-header-fixed ui-page-active" position="fixed" data-theme="b" data-role="page">
    <div id="contentHeader" class="ui-header ui-bar-b ui-header-fixed slidedown" data-theme="b" data-position="fixed" data-role="header" role="banner">...</div>
    <div id="contentPane" class="ui-content ui-body-b" data-theme="b" data-role="content" role="main">...</div>
    <div class="ui-selectmenu-screen ui-screen-hidden" style="height: 3150px;"></div>
    <div class="ui-selectmenu ui-overlay-shadow ui-corner-all ui-body-a pop ui-selectmenu-hidden">...</div>
    <div class="ui-selectmenu-screen ui-screen-hidden"></div>
    <div class="ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-a pop">...</div>
    <div class="ui-selectmenu-screen ui-screen-hidden"></div>
    <div class="ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-a pop">...</div>
    <div class="ui-selectmenu-screen ui-screen-hidden"></div>
    <div class="ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-a pop">...</div>
    <div class="ui-selectmenu-screen ui-screen-hidden"></div>
    <div class="ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-a pop">...</div>
</div>

Now this isn't a HUGE issue, as it doesn't break any functionality, but seeing how this is a mobile app, bloating up the DOM can lead to slow performance if it gets out of hand.

What I'm wondering is if there is some way I can tell JQM to clean up any of these stale DOM elements, or if there is a way I can check if any of these overlays have gone stale myself, say by using $(".ui-overlay-shadow, .ui-overlay-a") and then checking some property.

1

1 Answers

0
votes

You could save the elements you inject into your page into a variable then use the .remove() operator from jQuery, Documentation.

var injectedDomElement = ...;
$(document).one("pagehide", function(){
    injectedDomElement.remove();
}