मैं एक फ़ंक्शन निष्पादित करना चाहता हूं जब HTML में कुछ div या इनपुट जोड़े जाते हैं। क्या यह संभव है?
उदाहरण के लिए, एक पाठ इनपुट जोड़ा जाता है, फिर फ़ंक्शन को बुलाया जाना चाहिए।
मैं एक फ़ंक्शन निष्पादित करना चाहता हूं जब HTML में कुछ div या इनपुट जोड़े जाते हैं। क्या यह संभव है?
उदाहरण के लिए, एक पाठ इनपुट जोड़ा जाता है, फिर फ़ंक्शन को बुलाया जाना चाहिए।
जवाबों:
MutationObserver
आधुनिक ब्राउज़रों द्वारा समर्थित है:क्रोम 18+, फ़ायरफ़ॉक्स 14+, IE 11+, सफारी 6+
यदि आपको पुराने का समर्थन करने की आवश्यकता है, तो आप नीचे दिए गए अन्य दृष्टिकोणों की तरह गिरने की कोशिश कर सकते हैं जैसे कि इस 5 (!) वर्ष पुराने उत्तर में नीचे दिए गए हैं। ड्रेगन हो। का आनंद लें :)
कोई और दस्तावेज़ बदल रहा है? क्योंकि अगर domChanged
किसी फ़ंक्शन या कस्टम ईवेंट के साथ आपको केवल अपने स्वयं के API बनाने के लिए आवश्यक परिवर्तनों पर पूर्ण नियंत्रण है - और हर जगह आप चीजों को संशोधित करते हुए इसे ट्रिगर / कॉल करते हैं।
डोम स्तर -2 है उत्परिवर्तन घटना प्रकार है, लेकिन IE के पुराने संस्करण इसका समर्थन नहीं करते। ध्यान दें कि म्यूटेशन ईवेंट्स को DOM3 ईवेंट्स स्पेक में दर्शाया गया है और एक परफॉर्मेंस पेनल्टी है ।
आप onpropertychange
IE में उत्परिवर्तन घटना का अनुकरण करने की कोशिश कर सकते हैं (और यदि उनमें से कोई भी उपलब्ध है तो ब्रूट-फोर्स दृष्टिकोण पर वापस आ सकते हैं)।
एक के लिए पूरा domChange अंतराल एक से अधिक को मार हो सकता है। कल्पना करें कि आपको पूरे दस्तावेज़ की वर्तमान स्थिति को संग्रहीत करने की आवश्यकता है, और प्रत्येक तत्व की प्रत्येक संपत्ति की जांच करने के लिए समान होना चाहिए।
हो सकता है कि यदि आप केवल तत्वों और उनके आदेश (जैसा कि आपने अपने प्रश्न में उल्लेख किया है) में रुचि रखते हैं, getElementsByTagName("*")
काम कर सकते हैं। यह स्वचालित रूप से आग लगाएगा यदि आप एक तत्व जोड़ते हैं, एक तत्व निकालते हैं, तत्वों को प्रतिस्थापित करते हैं या दस्तावेज़ की संरचना को बदलते हैं।
मैंने अवधारणा का प्रमाण लिखा:
(function (window) {
var last = +new Date();
var delay = 100; // default delay
// Manage event queue
var stack = [];
function callback() {
var now = +new Date();
if (now - last > delay) {
for (var i = 0; i < stack.length; i++) {
stack[i]();
}
last = now;
}
}
// Public interface
var onDomChange = function (fn, newdelay) {
if (newdelay) delay = newdelay;
stack.push(fn);
};
// Naive approach for compatibility
function naive() {
var last = document.getElementsByTagName('*');
var lastlen = last.length;
var timer = setTimeout(function check() {
// get current state of the document
var current = document.getElementsByTagName('*');
var len = current.length;
// if the length is different
// it's fairly obvious
if (len != lastlen) {
// just make sure the loop finishes early
last = [];
}
// go check every element in order
for (var i = 0; i < len; i++) {
if (current[i] !== last[i]) {
callback();
last = current;
lastlen = len;
break;
}
}
// over, and over, and over again
setTimeout(check, delay);
}, delay);
}
//
// Check for mutation events support
//
var support = {};
var el = document.documentElement;
var remain = 3;
// callback for the tests
function decide() {
if (support.DOMNodeInserted) {
window.addEventListener("DOMContentLoaded", function () {
if (support.DOMSubtreeModified) { // for FF 3+, Chrome
el.addEventListener('DOMSubtreeModified', callback, false);
} else { // for FF 2, Safari, Opera 9.6+
el.addEventListener('DOMNodeInserted', callback, false);
el.addEventListener('DOMNodeRemoved', callback, false);
}
}, false);
} else if (document.onpropertychange) { // for IE 5.5+
document.onpropertychange = callback;
} else { // fallback
naive();
}
}
// checks a particular event
function test(event) {
el.addEventListener(event, function fn() {
support[event] = true;
el.removeEventListener(event, fn, false);
if (--remain === 0) decide();
}, false);
}
// attach test events
if (window.addEventListener) {
test('DOMSubtreeModified');
test('DOMNodeInserted');
test('DOMNodeRemoved');
} else {
decide();
}
// do the dummy test
var dummy = document.createElement("div");
el.appendChild(dummy);
el.removeChild(dummy);
// expose
window.onDomChange = onDomChange;
})(window);
उपयोग:
onDomChange(function(){
alert("The Times They Are a-Changin'");
});
यह IE 5.5+, FF 2+, क्रोम, सफारी 3+ और ओपेरा 9.6+ पर काम करता है
IE9 +, FF, वेबकिट:
का उपयोग करते हुए MutationObserver और पदावनत करने के लिए गिरने वापस उत्परिवर्तन घटनाओं अगर जरूरत:
(उदाहरण नीचे है, तो केवल के लिए डोम परिवर्तन विषय में नोड्स संलग्न या निकाला गया)
var observeDOM = (function(){
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
return function( obj, callback ){
if( !obj || !obj.nodeType === 1 ) return; // validation
if( MutationObserver ){
// define a new observer
var obs = new MutationObserver(function(mutations, observer){
callback(mutations);
})
// have the observer observe foo for changes in children
obs.observe( obj, { childList:true, subtree:true });
}
else if( window.addEventListener ){
obj.addEventListener('DOMNodeInserted', callback, false);
obj.addEventListener('DOMNodeRemoved', callback, false);
}
}
})();
//------------< DEMO BELOW >----------------
// add item
var itemHTML = "<li><button>list item (click to delete)</button></li>",
listElm = document.querySelector('ol');
document.querySelector('body > button').onclick = function(e){
listElm.insertAdjacentHTML("beforeend", itemHTML);
}
// delete item
listElm.onclick = function(e){
if( e.target.nodeName == "BUTTON" )
e.target.parentNode.parentNode.removeChild(e.target.parentNode);
}
// Observe a specific DOM element:
observeDOM( listElm, function(m){
var addedNodes = [], removedNodes = [];
m.forEach(record => record.addedNodes.length & addedNodes.push(...record.addedNodes))
m.forEach(record => record.removedNodes.length & removedNodes.push(...record.removedNodes))
console.clear();
console.log('Added:', addedNodes, 'Removed:', removedNodes);
});
// Insert 3 DOM nodes at once after 3 seconds
setTimeout(function(){
listElm.removeChild(listElm.lastElementChild);
listElm.insertAdjacentHTML("beforeend", Array(4).join(itemHTML));
}, 3000);
<button>Add Item</button>
<ol>
<li><button>list item (click to delete)</button></li>
<li><button>list item (click to delete)</button></li>
<li><button>list item (click to delete)</button></li>
<li><button>list item (click to delete)</button></li>
<li><em>…More will be added after 3 seconds…</em></li>
</ol>
mutations, observer
अधिक नियंत्रण के लिए कॉलबैक फ़ंक्शन के मापदंडों को पास करें ।
मैंने हाल ही में एक प्लगइन लिखा है जो बिल्कुल ऐसा करता है - jquery.initialize
आप इसे .each
फंक्शन की तरह ही इस्तेमाल करते हैं
$(".some-element").initialize( function(){
$(this).css("color", "blue");
});
इससे अंतर .each
यह है कि यह आपके चयनकर्ता को इस मामले में ले जाता है .some-element
और भविष्य में इस चयनकर्ता के साथ नए तत्वों की प्रतीक्षा करता है, यदि ऐसा तत्व जोड़ा जाएगा, तो इसे भी प्रारंभ किया जाएगा।
हमारे मामले में फंक्शन इनिशियलाइज़ करें बस एलिमेंट कलर को ब्लू में बदलें। इसलिए अगर हम नया तत्व जोड़ेंगे (कोई फर्क नहीं पड़ता अगर अजाक्स या एफ 12 इंस्पेक्टर या कुछ भी साथ):
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
प्लगिन इसे तुरंत init करेगा। इसके अलावा प्लगइन यह सुनिश्चित करता है कि एक तत्व केवल एक बार इनिशियलाइज़ हो। इसलिए यदि आप तत्व जोड़ते हैं, तो .detach()
यह शरीर से है और फिर इसे फिर से जोड़ें, इसे फिर से प्रारंभ नहीं किया जाएगा।
$("<div/>").addClass('some-element').appendTo("body").detach()
.appendTo(".some-container");
//initialized only once
प्लगइन पर आधारित है MutationObserver
- यह IE9 और 10 पर निर्भरता पृष्ठ पर विस्तृत के रूप में निर्भरता के साथ काम करेगा ।
या आप बस अपना स्वयं का ईवेंट बना सकते हैं , जो हर जगह चलता है
$("body").on("domChanged", function () {
//dom is changed
});
$(".button").click(function () {
//do some change
$("button").append("<span>i am the new change</span>");
//fire event
$("body").trigger("domChanged");
});
पूरा उदाहरण http://jsfiddle.net/hbmaam/Mq7NX/
यह इस ब्लॉग पोस्ट से अनुकूलित मोज़िला से MutationObserver का उपयोग करने वाला एक उदाहरण है
क्रोम 18+, फ़ायरफ़ॉक्स 14+, IE 11+, सफारी 6+
// Select the node that will be observed for mutations
var targetNode = document.getElementById('some-id');
// Options for the observer (which mutations to observe)
var config = { attributes: true, childList: true };
// Callback function to execute when mutations are observed
var callback = function(mutationsList) {
for(var mutation of mutationsList) {
if (mutation.type == 'childList') {
console.log('A child node has been added or removed.');
}
else if (mutation.type == 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
};
// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
// Later, you can stop observing
observer.disconnect();
गैब्रिएल रोमानो के ब्लॉग में दिखाए गए अनुसार MutationObserver इंटरफ़ेस का उपयोग करें
क्रोम 18+, फ़ायरफ़ॉक्स 14+, IE 11+, सफारी 6+
// The node to be monitored
var target = $( "#content" )[0];
// Create an observer instance
var observer = new MutationObserver(function( mutations ) {
mutations.forEach(function( mutation ) {
var newNodes = mutation.addedNodes; // DOM NodeList
if( newNodes !== null ) { // If there are new nodes added
var $nodes = $( newNodes ); // jQuery set
$nodes.each(function() {
var $node = $( this );
if( $node.hasClass( "message" ) ) {
// do something
}
});
}
});
});
// Configuration of the observer:
var config = {
attributes: true,
childList: true,
characterData: true
};
// Pass in the target node, as well as the observer options
observer.observe(target, config);
// Later, you can stop observing
observer.disconnect();
कैसे इसके लिए एक jquery का विस्तार करने के बारे में?
(function () {
var ev = new $.Event('remove'),
orig = $.fn.remove;
var evap = new $.Event('append'),
origap = $.fn.append;
$.fn.remove = function () {
$(this).trigger(ev);
return orig.apply(this, arguments);
}
$.fn.append = function () {
$(this).trigger(evap);
return origap.apply(this, arguments);
}
})();
$(document).on('append', function (e) { /*write your logic here*/ });
$(document).on('remove', function (e) { /*write your logic here*/ ) });
Jquery 1.9+ ने इसके लिए समर्थन का निर्माण किया है (मैंने सुना है कि परीक्षण नहीं किया गया है)।