How to wait until an element exists?

How to wait until an element exists?

I’m working on an Extension in Chrome, and I’m wondering: what’s the best way to find out when an element comes into existence? Using plain javascript, with an interval that checks until an element exists, or does jQuery have some easy way to do this?

Solutions/Answers:

Solution 1:

DOMNodeInserted is being deprecated, along with the other DOM mutation events, because of performance issues – the recommended approach is to use a MutationObserver to watch the DOM. It’s only supported in newer browsers though, so you should fall back onto DOMNodeInserted when MutationObserver isn’t available.

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if (!mutation.addedNodes) return

    for (var i = 0; i < mutation.addedNodes.length; i++) {
      // do things to your newly added nodes here
      var node = mutation.addedNodes[i]
    }
  })
})

observer.observe(document.body, {
    childList: true
  , subtree: true
  , attributes: false
  , characterData: false
})

// stop watching using:
observer.disconnect()

Solution 2:

I was having this same problem, so I went ahead and wrote a plugin for it.

Related:  Get width in pixels from element with style set with %?

$(selector).waitUntilExists(function);

Code:

;(function ($, window) {

var intervals = {};
var removeListener = function(selector) {

    if (intervals[selector]) {

        window.clearInterval(intervals[selector]);
        intervals[selector] = null;
    }
};
var found = 'waitUntilExists.found';

/**
 * @function
 * @property {object} jQuery plugin which runs handler function once specified
 *           element is inserted into the DOM
 * @param {function|string} handler 
 *            A function to execute at the time when the element is inserted or 
 *            string "remove" to remove the listener from the given selector
 * @param {bool} shouldRunHandlerOnce 
 *            Optional: if true, handler is unbound after its first invocation
 * @example jQuery(selector).waitUntilExists(function);
 */

$.fn.waitUntilExists = function(handler, shouldRunHandlerOnce, isChild) {

    var selector = this.selector;
    var $this = $(selector);
    var $elements = $this.not(function() { return $(this).data(found); });

    if (handler === 'remove') {

        // Hijack and remove interval immediately if the code requests
        removeListener(selector);
    }
    else {

        // Run the handler on all found elements and mark as found
        $elements.each(handler).data(found, true);

        if (shouldRunHandlerOnce && $this.length) {

            // Element was found, implying the handler already ran for all 
            // matched elements
            removeListener(selector);
        }
        else if (!isChild) {

            // If this is a recurring search or if the target has not yet been 
            // found, create an interval to continue searching for the target
            intervals[selector] = window.setInterval(function () {

                $this.waitUntilExists(handler, shouldRunHandlerOnce, true);
            }, 500);
        }
    }

    return $this;
};

}(jQuery, window));

Solution 3:

Here is a core JavaScript function to wait for the display of an element.

Related:  Does HTML Hidden control have any events? Like onchange or something?

Parameters:

  1. selector: This function looks for the element ${selector}
  2. time: This function checks whether this element exists every ${time} milliseconds.

    function waitForElementToDisplay(selector, time) {
            if(document.querySelector(selector)!=null) {
                alert("The element is displayed, you can put your code instead of this alert.")
                return;
            }
            else {
                setTimeout(function() {
                    waitForElementToDisplay(selector, time);
                }, time);
            }
        }
    

As an example, setting selector="#div1" and time=5000 will look for the HTML tag whose id="div1" every 5000 milliseconds.

Solution 4:

You can listen to DOMNodeInserted or DOMSubtreeModified events which fire whenever a new element is added to the DOM.

There is also LiveQuery jQuery plugin which would detect when a new element is created:

$("#future_element").livequery(function(){
    //element created
});

Solution 5:

You can do

$('#yourelement').ready(function() {

});

Please note that this will only work if the element is present in the DOM when being requested from the server. If the element is being dynamically added via JavaScript, it will not work and you may need to look at the other answers.

Related:  Difference between using Array.isArray and instanceof Array

Solution 6:

I used this approach to wait for an element to appear so I can execute the other functions after that.

Let’s say doTheRestOfTheStuff(parameters) function should only be called after the element with ID the_Element_ID appears or finished loading, we can use,

var existCondition = setInterval(function() {
 if ($('#the_Element_ID').length) {
    console.log("Exists!");
    clearInterval(existCondition);
    doTheRestOfTheStuff(parameters);
 }
}, 100); // check every 100ms