;(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));
let observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (!mutation.addedNodes) return
for (let i = 0; i < mutation.addedNodes.length; i++) {
// do things to your newly added nodes here
let node = mutation.addedNodes[i]
}
})
})
observer.observe(document.body, {
childList: true
, subtree: true
, attributes: false
, characterData: false
})
// stop watching using:
observer.disconnect()
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);
});
/**
* @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);
}
要调用它,例如在jQuery中,使用如下代码:
waitUntil(function(){
return $('#myelement').length > 0;
}, function(){
alert("myelement now exists");
}, function(){
alert("I'm bored. I give up.");
});
// 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");
});
});
"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);
});
}
对于多个元素(类型为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);
});
}
例子:
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
});
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);
});
});
// 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);
cont elementExist = setInterval(() => {
var elm = document.getElementById("elementId")
if (elm!=null)
// call your function here to do something
clearInterval(elementExist);
}
}, 100);