Wie kann man warten, bis ein Element existiert?

236

Ich arbeite an einer Erweiterung in Chrome und frage mich: Wie kann ich am besten herausfinden, wann ein Element entsteht? Verwenden Sie einfaches Javascript mit einem Intervall, das prüft, bis ein Element vorhanden ist, oder hat jQuery eine einfache Möglichkeit, dies zu tun?

mattsven
quelle
1
Es sieht so aus, als ob jede einzelne Option hier heute (einschließlich der Kommentare) entweder veraltet oder unvollständig ist. Sie betrachten @ hughsk 'großartige Eingabe, das Kompatibilitätsargument, nicht vollständig. In der Zwischenzeit würde ich empfehlen, einfach Brandons Update für Ryans Antwort zu verwenden, um die Einfachheit zu vereinfachen und das Risiko eines Overheads zu verringern.
Cregox
4
MutationObserver> DOM Mutation Events> setTimeout.
Mattsven
2
Nicht von wo ich stehe. setTimeoutist kompatibel, einfach zu implementieren, einfach zu warten und hat einen vernachlässigbaren Overhead.
Cregox
setTimeout+ jQueryist meiner Meinung nach aus zwei Gründen weniger als ideal: 1.) jQuery bloat 2.) Sie fragen das DOM unnötig manuell nach Elementen ab, Ereignisse schlagen diese Geschwindigkeit leicht, 3.) es wird immer langsamer sein als jedes native Implementierung. Wenn Sie relativ schnell etwas tun müssen, das auf dem Vorhandensein eines Elements basiert, insbesondere wenn eine nahtlose Benutzererfahrung Ihr Ziel ist, ist dies minderwertig.
Mattsven
3
Es gibt drei Arten von Menschen: diejenigen, die zählen können und diejenigen, die nicht zählen können. ; P
Cregox

Antworten:

148

DOMNodeInsertedwird zusammen mit den anderen DOM-Mutationsereignissen aufgrund von Leistungsproblemen veraltet. Der empfohlene Ansatz besteht darin, einen MutationObserver zum Überwachen des DOM zu verwenden. Es wird jedoch nur in neueren Browsern unterstützt, daher sollten Sie darauf zurückgreifen, DOMNodeInsertedwenn MutationObserveres nicht verfügbar ist.

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()
hughsk
quelle
50
Ich habe die API von MutationObserver immer als etwas komplex empfunden , daher habe ich eine Bibliothek erstellt, arret.js , um eine einfachere API zum Abhören der Erstellung / Entfernung von Elementen bereitzustellen.
Uzair Farooq
15
Ich empfehle die Verwendung von @UzairFarooq ausgezeichnete Bibliothek github.com/uzairfarooq/arrive
Dennis
3
Zwei Dinge zu beachten: (1) Es wäre besser, dies zu tun, if (mutation.addedNodes.length)da if (mutation.addedNodes)immer noch true zurückgegeben wird, selbst wenn es sich um ein leeres Array handelt. (2) mutation.addedNodes.forEach()Dies ist nicht möglich, da addedNodes eine Knotenliste ist und Sie mit forEach keine Knotenliste durchlaufen können. Eine Lösung hierfür finden Sie unter toddmotto.com/ditch-the-array-foreach-call-nodelist-hack
am
3
Können Sie ein Beispiel geben, wie man dies verwenden würde? Ich bin nicht sicher, wo ich meinen JQuery-Selektor oder Code ablegen soll, den ich ausführen möchte, wenn ein DOM-Element vorhanden ist.
Superdooperhero
1
@ Superdooperhero Ich gab eine Antwort mit einfachem Beispiel. Prüfen Sie. stackoverflow.com/a/57395241/6542186
Silversurfer
112

Ich hatte das gleiche Problem, also habe ich ein Plugin dafür geschrieben.

$(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));
Ryan Lester
quelle
5
Danke für das Plugin. Ich gabelte und verbesserte es ein bisschen. Fühlen Sie sich frei, was Sie wollen von meinem Update zu nehmen. Ich habe noch ein paar weitere Verbesserungen geplant: aktualisiertes Plugin
Brandon Belvin
8
wäre auch schön ohne jquery dep ...;)
knutole
4
Vielleicht sollten Sie erwähnen, wie es funktioniert: Sie fragen alle 500 ms, ob das Element vorhanden ist (mit a window.setInterval). Ich weiß nicht, ob die MutationObserverAntwort auch durch Umfragen funktioniert ...
Sport
2
Es funktioniert nicht richtig, wenn sich das Element bereits auf der Seite befindet. Hier ist die richtige Version dieser Funktion: gist.github.com/PizzaBrandon/5709010
Roland Soós
2
Können Sie bitte erklären, was ;am Anfang der Funktion ( ;(function ($, window) {) verwendet wird?
Mrid
76

Hier ist eine JavaScript-Kernfunktion, die auf die Anzeige eines Elements wartet.

Parameter:

  1. selector: Diese Funktion sucht nach dem Element $ {Selektor}
  2. time: Diese Funktion prüft alle $ {time} Millisekunden, ob dieses Element vorhanden ist.

    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);
            }
        }

Beispiel: Suchen selector="#div1"und time=5000suchen Sie nach dem HTML-Tag, dessen id="div1"alle 5000 Millisekunden.

Etienne Tonnelier
quelle
Nett! Können Sie dies so schreiben, dass jeder Selektor akzeptiert werden kann?
Mattsven
Ich bezweifle, dass ich es schaffen kann. Aber bitte schauen Sie sich diesen Beitrag an, um den getElementByXpath zu erhalten: stackoverflow.com/questions/10596417/…
Etienne Tonnelier
1
Können Sie es schreiben, um stattdessen den Mutationsbeobachter zu verwenden?
SuperUberDuper
oder könnten Sie dieses umschreiben, um ein Versprechen zu verwenden?
SuperUberDuper
25

Sie können Ereignisse anhören DOMNodeInsertedoder DOMSubtreeModifiedauslösen, die ausgelöst werden, wenn dem DOM ein neues Element hinzugefügt wird.

Es gibt auch das LiveQuery jQuery-Plugin, das erkennt , wenn ein neues Element erstellt wird:

$("#future_element").livequery(function(){
    //element created
});
serg
quelle
1
Sehr schönes Plugin! Gibt es eine solche Funktion direkt in jquery? Ich frage mich, dass es dafür keine Funktion gibt. Und wenn dies DAS Plugin ist, stimme bitte für diese Antwort;) Für mich funktioniert es perfekt. Vielen Dank.
Samuel
1
Hinweis IE 9 implementiert DOMNodeInserted, hat jedoch einen schwerwiegenden Fehler, bei dem es nicht ausgelöst wird, wenn Sie ein Element für die Zeit hinzufügen. Dies ist meistens der Fall, wenn Sie es verwenden möchten. Details finden Sie unter: help.dottoro.com/ljmcxjla.php
mikemaccana
23

Ich habe diesen Ansatz verwendet, um auf das Erscheinen eines Elements zu warten, damit ich die anderen Funktionen danach ausführen kann.

Angenommen, die doTheRestOfTheStuff(parameters)Funktion sollte erst aufgerufen werden, nachdem das Element mit der ID the_Element_IDangezeigt oder das Laden beendet wurde.

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

Du kannst tun

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

});

Bitte beachten Sie, dass dies nur funktioniert, wenn das Element im DOM vorhanden ist, wenn es vom Server angefordert wird. Wenn das Element dynamisch über JavaScript hinzugefügt wird, funktioniert es nicht und Sie müssen sich möglicherweise die anderen Antworten ansehen.

Splynx
quelle
7
Die .ready()Funktion funktioniert für fast alles (wenn nicht für alles), nicht nur document. Es funktioniert einfach nicht mit dynamisch erstellten Elementen, auch nicht .live().
Richard Neil Ilagan
7
@Bery, wie Richard betonte, funktioniert dies nur für Elemente, die bereits im HTML vorhanden sind, wenn es zum ersten Mal vom Server angefordert wird. Wenn Javascript verwendet wird, um ein Element dynamisch zum DOM hinzuzufügen, funktioniert dies nicht.
Chandranshu
6
@ Sam, können Sie bitte klarstellen, wie Sie es an die Referenz des Elements im Speicher anhängen können?
Vikas Singhal
3
Diese Antwort ist falsch. Was Sie hier tatsächlich überprüfen, ist ein reguläres $(document).ready()Element, nicht das Element, von dem Sie glauben, dass es auch zutreffen wird. So funktioniert dieser spezielle Hörer. Beispiel
Shikkediel
1
Diese Verwendung wird laut api.jquery.com/ready
splintor
14

Ich denke, dass es hier immer noch keine Antwort mit einem einfachen und lesbaren Arbeitsbeispiel gibt. Verwenden Sie MutationObserver interface , um DOM-Änderungen wie folgt zu erkennen:

var observer = new MutationObserver(function(mutations) {
    if ($("p").length) {
        console.log("Exist, lets do something");
        observer.disconnect(); 
        //We can disconnect observer once the element exist if we dont want observe more changes in the DOM
    }
});

// Start observing
observer.observe(document.body, { //document.body is node target to observe
    childList: true, //This is a must have for the observer with subtree
    subtree: true //Set to true if changes must also be observed in descendants.
});
            
$(document).ready(function() {
    $("button").on("click", function() {
        $("p").remove();
        setTimeout(function() {
            $("#newContent").append("<p>New element</p>");
        }, 2000);
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button>New content</button>
<div id="newContent"></div>

Hinweis: Spanische Mozilla- Dokumente MutationObserversind detaillierter, wenn Sie weitere Informationen wünschen.

Silberner Surfer
quelle
2
Hinterlasse einen Kommentar, in dem der Grund für die Ablehnung erklärt wird, damit ich meine Antwort verbessern kann. Vielen Dank.
SilverSurfer
12

Fügen Sie einfach den gewünschten Selektor hinzu. Sobald das Element gefunden wurde, können Sie in der Rückruffunktion darauf zugreifen.

const waitUntilElementExists = (selector, callback) => {
const el = document.querySelector(selector);

if (el){
    return callback(el);
}

setTimeout(() => waitUntilElementExists(selector, callback), 500);
}

waitUntilElementExists('.wait-for-me', (el) => console.log(el));
Diego Fortes
quelle
2
PossessWithin stimme zu, dies ist eine sehr saubere Lösung und funktioniert für mich.
Jstafford
3
Diese Antwort funktioniert sowohl mit IE8-10 als auch mit modernen Browsern. Das Hauptproblem besteht darin, dass es weiter ausgeführt wird, wenn das Element nicht vorhanden ist. Daher ist es am besten, wenn Sie sicher sind, dass das Element dort sein wird. Andernfalls können Sie einen Zähler hinzufügen.
Für den Namen
1
Arbeitete perfekt für mich
James Stewart
1
Arbeitete wie Charme !!
Aman
1
Sie waren ähnlich, nicht identisch. Darüber hinaus tun viele Menschen das Gleiche. Zuletzt habe ich diese Lösung selbst codiert. Das ist eine schlechte Argumentation, aber selbst wenn es tatsächlich der Fall wäre, würde ich mich über einen Kommentar freuen, der mich darüber informiert. Die Antwort löst das Problem von OP und hat keine offensichtlichen Gründe, herabgestimmt zu werden.
Diego Fortes
11

Für einen einfachen Ansatz mit jQuery habe ich festgestellt, dass dies gut funktioniert:

  // Wait for element to exist.
  function elementLoaded(el, cb) {
    if ($(el).length) {
      // Element is now loaded.
      cb($(el));
    } else {
      // Repeat every 500ms.
      setTimeout(function() {
        elementLoaded(el, cb)
      }, 500);
    }
  };

  elementLoaded('.element-selector', function(el) {
    // Element is ready to use.
    el.click(function() {
      alert("You just clicked a dynamically inserted element");
    });
  });

Hier überprüfen wir einfach alle 500 ms, ob das Element geladen ist, wenn es ist, können wir es verwenden.

Dies ist besonders nützlich, um Elementen, die dem Dokument dynamisch hinzugefügt wurden, Klick-Handler hinzuzufügen.

Hedley Smith
quelle
8

Wie wäre es mit der insertionQuery- Bibliothek?

insertionQuery verwendet CSS-Animationsrückrufe, die an die angegebenen Selektoren angehängt sind, um einen Rückruf auszuführen, wenn ein Element erstellt wird. Mit dieser Methode können Rückrufe ausgeführt werden, wenn ein Element erstellt wird, nicht nur beim ersten Mal.

Vom Github:

Nicht-Dom-Event-Methode zum Abfangen von Knoten, die angezeigt werden. Und es verwendet Selektoren.

Es ist nicht nur für eine breitere Browserunterstützung, es kann für bestimmte Dinge besser sein als DOMMutationObserver.

Warum?

  • Weil DOM-Ereignisse den Browser verlangsamen und insertionQuery nicht
  • Weil DOM Mutation Observer weniger Browserunterstützung bietet als insertionQuery
  • Denn mit insertionQuery können Sie DOM-Änderungen mithilfe von Selektoren ohne Leistungsaufwand filtern!

Breite Unterstützung!

IE10 + und meistens alles andere (einschließlich Handy)

b3wii
quelle
7

Hier ist eine Funktion, die als Thin Wrapper um MutationObserver fungiert. Die einzige Voraussetzung ist, dass der Browser MutationObserver unterstützt. Es besteht keine Abhängigkeit von JQuery. Führen Sie das folgende Snippet aus, um ein funktionierendes Beispiel anzuzeigen.

function waitForMutation(parentNode, isMatchFunc, handlerFunc, observeSubtree, disconnectAfterMatch) {
  var defaultIfUndefined = function(val, defaultVal) {
    return (typeof val === "undefined") ? defaultVal : val;
  };

  observeSubtree = defaultIfUndefined(observeSubtree, false);
  disconnectAfterMatch = defaultIfUndefined(disconnectAfterMatch, false);

  var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      if (mutation.addedNodes) {
        for (var i = 0; i < mutation.addedNodes.length; i++) {
          var node = mutation.addedNodes[i];
          if (isMatchFunc(node)) {
            handlerFunc(node);
            if (disconnectAfterMatch) observer.disconnect();
          };
        }
      }
    });
  });

  observer.observe(parentNode, {
    childList: true,
    attributes: false,
    characterData: false,
    subtree: observeSubtree
  });
}

// Example
waitForMutation(
  // parentNode: Root node to observe. If the mutation you're looking for
  // might not occur directly below parentNode, pass 'true' to the
  // observeSubtree parameter.
  document.getElementById("outerContent"),
  // isMatchFunc: Function to identify a match. If it returns true,
  // handlerFunc will run.
  // MutationObserver only fires once per mutation, not once for every node
  // inside the mutation. If the element we're looking for is a child of
  // the newly-added element, we need to use something like
  // node.querySelector() to find it.
  function(node) {
    return node.querySelector(".foo") !== null;
  },
  // handlerFunc: Handler.
  function(node) {
    var elem = document.createElement("div");
    elem.appendChild(document.createTextNode("Added node (" + node.innerText + ")"));
    document.getElementById("log").appendChild(elem);
  },
  // observeSubtree
  true,
  // disconnectAfterMatch: If this is true the hanlerFunc will only run on
  // the first time that isMatchFunc returns true. If it's false, the handler
  // will continue to fire on matches.
  false);

// Set up UI. Using JQuery here for convenience.

$outerContent = $("#outerContent");
$innerContent = $("#innerContent");

$("#addOuter").on("click", function() {
  var newNode = $("<div><span class='foo'>Outer</span></div>");
  $outerContent.append(newNode);
});
$("#addInner").on("click", function() {
  var newNode = $("<div><span class='foo'>Inner</span></div>");
  $innerContent.append(newNode);
});
.content {
  padding: 1em;
  border: solid 1px black;
  overflow-y: auto;
}
#innerContent {
  height: 100px;
}
#outerContent {
  height: 200px;
}
#log {
  font-family: Courier;
  font-size: 10pt;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Create some mutations</h2>
<div id="main">
  <button id="addOuter">Add outer node</button>
  <button id="addInner">Add inner node</button>
  <div class="content" id="outerContent">
    <div class="content" id="innerContent"></div>
  </div>
</div>
<h2>Log</h2>
<div id="log"></div>

Ivan Karajas
quelle
6

Hier ist eine vielversprechende Lösung in Vanille-Javascript (keine unordentlichen Rückrufe). Standardmäßig werden alle 200 ms überprüft.

function waitFor(selector) {
    return new Promise(function (res, rej) {
        waitForElementToDisplay(selector, 200);
        function waitForElementToDisplay(selector, time) {
            if (document.querySelector(selector) != null) {
                res(document.querySelector(selector));
            }
            else {
                setTimeout(function () {
                    waitForElementToDisplay(selector, time);
                }, time);
            }
        }
    });
}
Blaster
quelle
5

Hier ist eine reine Javascript-Funktion, mit der Sie auf alles warten können. Stellen Sie das Intervall länger ein, um weniger CPU-Ressourcen zu verbrauchen.

/**
 * @brief Wait for something to be ready before triggering a timeout
 * @param {callback} isready Function which returns true when the thing we're waiting for has happened
 * @param {callback} success Function to call when the thing is ready
 * @param {callback} error Function to call if we time out before the event becomes ready
 * @param {int} count Number of times to retry the timeout (default 300 or 6s)
 * @param {int} interval Number of milliseconds to wait between attempts (default 20ms)
 */
function waitUntil(isready, success, error, count, interval){
    if (count === undefined) {
        count = 300;
    }
    if (interval === undefined) {
        interval = 20;
    }
    if (isready()) {
        success();
        return;
    }
    // The call back isn't ready. We need to wait for it
    setTimeout(function(){
        if (!count) {
            // We have run out of retries
            if (error !== undefined) {
                error();
            }
        } else {
            // Try again
            waitUntil(isready, success, error, count -1, interval);
        }
    }, interval);
}

Um dies beispielsweise in jQuery aufzurufen, verwenden Sie Folgendes:

waitUntil(function(){
    return $('#myelement').length > 0;
}, function(){
    alert("myelement now exists");
}, function(){
    alert("I'm bored. I give up.");
});
xgretsch
quelle
3

Eine Lösung, die a zurückgibt Promise zurückgibt und die Verwendung eines Timeouts ermöglicht (kompatibler IE 11+).

Für ein einzelnes Element (Typ Element):

"use strict";

function waitUntilElementLoaded(selector) {
    var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

    var start = performance.now();
    var now = 0;

    return new Promise(function (resolve, reject) {
        var interval = setInterval(function () {
            var element = document.querySelector(selector);

            if (element instanceof Element) {
                clearInterval(interval);

                resolve();
            }

            now = performance.now();

            if (now - start >= timeout) {
                reject("Could not find the element " + selector + " within " + timeout + " ms");
            }
        }, 100);
    });
}

Für mehrere Elemente (Typ NodeList):

"use strict";

function waitUntilElementsLoaded(selector) {
    var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

    var start = performance.now();
    var now = 0;

    return new Promise(function (resolve, reject) {
        var interval = setInterval(function () {
            var elements = document.querySelectorAll(selector);

            if (elements instanceof NodeList) {
                clearInterval(interval);

                resolve(elements);
            }

            now = performance.now();

            if (now - start >= timeout) {
                reject("Could not find elements " + selector + " within " + timeout + " ms");
            }
        }, 100);
    });
}

Beispiele:

waitUntilElementLoaded('#message', 800).then(function(element) {
    // element found and available

    element.innerHTML = '...';
}).catch(function() {
    // element not found within 800 milliseconds
});

waitUntilElementsLoaded('.message', 10000).then(function(elements) {
    for(const element of elements) {
        // ....
    }
}).catch(function(error) {
    // elements not found withing 10 seconds
});

Funktioniert sowohl für eine Liste von Elementen als auch für ein einzelnes Element.

Anwar
quelle
1
Meine Lieblingslösung! Warum überprüfen element instanceof HTMLElement? Kann es jemals etwas anderes sein als nulloder HTMLElement?
Leeroy
1
Sie sprechen einen interessanten Punkt an. Ich hätte es durch die Verwendung breiter machen sollenElement stattdessen (fest) verwendet hätte. Ich mache nur die Prüfung, weil ich sicher sein möchte, dass die Variable elementdie Eigenschaft hat, innerHTMLwie in der Element MDN-Dokumentation angegeben . Fühlen Sie sich frei, es zu entfernen, wenn Sie sich nicht darum kümmern!
Anwar
2

Ein saubereres Beispiel mit MutationObserver:

new MutationObserver( mutation => {
    if (!mutation.addedNodes) return
    mutation.addedNodes.forEach( node => {
        // do stuff with node
    })
})
Zaz
quelle
2

Dies ist eine einfache Lösung für diejenigen, die an Versprechen gewöhnt sind und keine Bibliotheken oder Timer von Drittanbietern verwenden möchten.

Ich benutze es seit einer Weile in meinen Projekten

function waitForElm(selector) {
    return new Promise(resolve => {
        if (document.querySelector(selector)) {
            return resolve(document.querySelector(selector));
        }

        const observer = new MutationObserver(mutations => {
            if (document.querySelector(selector)) {
                resolve(document.querySelector(selector));
                observer.disconnect();
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    });
}

Um es zu benutzen:

waitForElm('.some-class').then(elm => console.log(elm.textContent));

oder mit async / warten

const elm = await waitForElm('.some-classs')
Yong Wang
quelle
Das ist ordentlich! Das Coole daran ist, dass man es auch mit async/ verwenden kann await. Sie könnten auch in der Lage sein, mehr Leistung herauszuholen, indem Siemutations.addedNodes.find(node => node.matchesSelector("..."))
mattsven
@mattsven Guter Punkt! Das Überprüfen nur der Knoten in den Mutationen ist leistungsfähiger als das Ausführen von document.querySelector.
Yong Wang
Bitte korrigieren Sie den Rechtschreibfehler, watiForElm to waitForElm
dalvir
1

Wenn Sie möchten, dass es nach einer Weile nicht mehr funktioniert (Zeitüberschreitung), funktioniert die folgende jQuery. Nach 10 Sekunden tritt eine Zeitüberschreitung auf. Ich musste diesen Code anstelle von reinem JS verwenden, da ich eine Eingabe über den Namen auswählen musste und Probleme bei der Implementierung einiger anderer Lösungen hatte.

 // Wait for element to exist.

    function imageLoaded(el, cb,time) {

        if ($(el).length) {
            // Element is now loaded.

            cb($(el));

            var imageInput =  $('input[name=product\\[image_location\\]]');
            console.log(imageInput);

        } else if(time < 10000) {
            // Repeat every 500ms.
            setTimeout(function() {
               time = time+500;

                imageLoaded(el, cb, time)
            }, 500);
        }
    };

    var time = 500;

    imageLoaded('input[name=product\\[image_location\\]]', function(el) {

     //do stuff here 

     },time);
S-Thomas
quelle
0

Normalerweise verwende ich dieses Snippet für den Tag Manager:

<script>
(function exists() {
  if (!document.querySelector('<selector>')) {
    return setTimeout(exists);
  }
  // code when element exists
})();  
</script>
Alejo JM
quelle
0

Wenn Sie asynchrone Dom-Änderungen haben, prüft diese Funktion (mit Zeitlimit in Sekunden), ob die DOM-Elemente für das DOM und seine Promise-basierten Elemente nicht schwer sind :)

function getElement(selector, i = 5) {
  return new Promise(async (resolve, reject) => {
    if(i <= 0) return reject(`${selector} not found`);
    const elements = document.querySelectorAll(selector);
    if(elements.length) return resolve(elements);
    return setTimeout(async () => await getElement(selector, i-1), 1000);
  })
}

// Now call it with your selector

try {
  element = await getElement('.woohoo');
} catch(e) { // catch the e }

//OR

getElement('.woohoo', 5)
.then(element => { // do somthing with the elements })
.catch(e => { // catch the error });
Meni Edri
quelle