जैसा कि कई अन्य उत्तरों में उल्लेख किया गया है, उत्परिवर्तन घटनाओं को हटा दिया गया है, इसलिए आपको इसके बजाय MutationObserver का उपयोग करना चाहिए । चूँकि किसी ने उस पर अभी तक कोई विवरण नहीं दिया है, यहाँ यह है ...
मूल जावास्क्रिप्ट एपीआई
MutationObserver के लिए एपीआई काफी सरल है। यह उत्परिवर्तन घटनाओं के रूप में काफी सरल नहीं है, लेकिन यह अभी भी ठीक है।
function callback(records) {
records.forEach(function (record) {
var list = record.addedNodes;
var i = list.length - 1;
for ( ; i > -1; i-- ) {
if (list[i].nodeName === 'SELECT') {
console.log(list[i]);
}
}
});
}
var observer = new MutationObserver(callback);
var targetNode = document.body;
observer.observe(targetNode, { childList: true, subtree: true });
<script>
setTimeout(function() {
var $el = document.createElement('select');
document.body.appendChild($el);
}, 500);
</script>
चलो कि नीचे तोड़ो।
var observer = new MutationObserver(callback);
इससे प्रेक्षक का निर्माण होता है। पर्यवेक्षक अभी तक कुछ भी नहीं देख रहा है; यह वह जगह है जहाँ इवेंट श्रोता संलग्न होता है।
observer.observe(targetNode, { childList: true, subtree: true });
इससे प्रेक्षक को शुरुआत होती है। पहला तर्क नोड है जो पर्यवेक्षक बदलावों के लिए देखेगा। दूसरा तर्क क्या देखना है इसके लिए विकल्प हैं ।
childList
इसका मतलब है कि मैं बाल तत्वों को जोड़ा या हटाया जाना देखना चाहता हूं।
subtree
एक ऐसा संशोधक है जो इस तत्व के सबट्री में कहीं भी बदलावों को देखने के लिए विस्तारित childList
होता है (अन्यथा, यह केवल सीधे परिवर्तनों को देखेगा targetNode
)।
इसके अलावा अन्य दो मुख्य विकल्प childList
हैं , attributes
और characterData
इसका मतलब है कि वे क्या पसंद करते हैं। आपको उन तीन में से एक का उपयोग करना होगा।
function callback(records) {
records.forEach(function (record) {
कॉलबैक के अंदर चीजें थोड़ी मुश्किल हो जाती हैं। कॉलबैक में MutationRecord s की एक सरणी मिलती है । प्रत्येक MutationRecord एक प्रकार के कई परिवर्तनों का वर्णन कर सकते हैं ( childList
, attributes
, या characterData
)। चूंकि मैंने केवल पर्यवेक्षक को देखने के लिए कहा था childList
, इसलिए मैं प्रकार की जांच करने से परेशान नहीं होगा।
var list = record.addedNodes;
यहाँ मैं सभी बच्चे नोड्स के एक नोडलिस्ट को जोड़ता हूं जो जोड़े गए थे। यह उन सभी रिकॉर्डों के लिए रिक्त होगा जहां नोड्स नहीं जोड़े गए हैं (और ऐसे कई रिकॉर्ड हो सकते हैं)।
वहां से, मैं जोड़े गए नोड्स के माध्यम से लूप करता हूं और किसी भी <select>
तत्व को ढूंढता हूं ।
यहां वास्तव में कुछ भी जटिल नहीं है।
jQuery
... लेकिन आपने jQuery के लिए कहा। ठीक।
(function($) {
var observers = [];
$.event.special.domNodeInserted = {
setup: function setup(data, namespaces) {
var observer = new MutationObserver(checkObservers);
observers.push([this, observer, []]);
},
teardown: function teardown(namespaces) {
var obs = getObserverData(this);
obs[1].disconnect();
observers = $.grep(observers, function(item) {
return item !== obs;
});
},
remove: function remove(handleObj) {
var obs = getObserverData(this);
obs[2] = obs[2].filter(function(event) {
return event[0] !== handleObj.selector && event[1] !== handleObj.handler;
});
},
add: function add(handleObj) {
var obs = getObserverData(this);
var opts = $.extend({}, {
childList: true,
subtree: true
}, handleObj.data);
obs[1].observe(this, opts);
obs[2].push([handleObj.selector, handleObj.handler]);
}
};
function getObserverData(element) {
var $el = $(element);
return $.grep(observers, function(item) {
return $el.is(item[0]);
})[0];
}
function checkObservers(records, observer) {
var obs = $.grep(observers, function(item) {
return item[1] === observer;
})[0];
var triggers = obs[2];
var changes = [];
records.forEach(function(record) {
if (record.type === 'attributes') {
if (changes.indexOf(record.target) === -1) {
changes.push(record.target);
}
return;
}
$(record.addedNodes).toArray().forEach(function(el) {
if (changes.indexOf(el) === -1) {
changes.push(el);
}
})
});
triggers.forEach(function checkTrigger(item) {
changes.forEach(function(el) {
var $el = $(el);
if ($el.is(item[0])) {
$el.trigger('domNodeInserted');
}
});
});
}
})(jQuery);
यह jQuery के विशेष ईवेंट APIdomNodeInserted
का उपयोग करके एक नया ईवेंट बनाता है । आप इसे इस तरह से उपयोग कर सकते हैं:
$(document).on("domNodeInserted", "select", function () {
$(this).combobox();
});
मैं व्यक्तिगत रूप से एक वर्ग की तलाश करने का सुझाव दूंगा क्योंकि कुछ पुस्तकालय select
परीक्षण उद्देश्यों के लिए तत्व बनाएंगे ।
स्वाभाविक रूप से, आप .off("domNodeInserted", ...)
इस तरह से डेटा पास करके देखने का उपयोग कर सकते हैं या ठीक कर सकते हैं :
$(document.body).on("domNodeInserted", "select.test", {
attributes: true,
subtree: false
}, function () {
$(this).combobox();
});
यह एक select.test
तत्व की उपस्थिति के लिए जाँच को ट्रिगर करेगा जब भी तत्व सीधे शरीर के अंदर के लिए बदल जाते हैं।
आप इसे नीचे या jsField पर लाइव देख सकते हैं ।
(function($) {
$(document).on("domNodeInserted", "select", function() {
console.log(this);
});
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
setTimeout(function() {
var $el = document.createElement('select');
document.body.appendChild($el);
}, 500);
</script>
<script>
(function($) {
var observers = [];
$.event.special.domNodeInserted = {
setup: function setup(data, namespaces) {
var observer = new MutationObserver(checkObservers);
observers.push([this, observer, []]);
},
teardown: function teardown(namespaces) {
var obs = getObserverData(this);
obs[1].disconnect();
observers = $.grep(observers, function(item) {
return item !== obs;
});
},
remove: function remove(handleObj) {
var obs = getObserverData(this);
obs[2] = obs[2].filter(function(event) {
return event[0] !== handleObj.selector && event[1] !== handleObj.handler;
});
},
add: function add(handleObj) {
var obs = getObserverData(this);
var opts = $.extend({}, {
childList: true,
subtree: true
}, handleObj.data);
obs[1].observe(this, opts);
obs[2].push([handleObj.selector, handleObj.handler]);
}
};
function getObserverData(element) {
var $el = $(element);
return $.grep(observers, function(item) {
return $el.is(item[0]);
})[0];
}
function checkObservers(records, observer) {
var obs = $.grep(observers, function(item) {
return item[1] === observer;
})[0];
var triggers = obs[2];
var changes = [];
records.forEach(function(record) {
if (record.type === 'attributes') {
if (changes.indexOf(record.target) === -1) {
changes.push(record.target);
}
return;
}
$(record.addedNodes).toArray().forEach(function(el) {
if (changes.indexOf(el) === -1) {
changes.push(el);
}
})
});
triggers.forEach(function checkTrigger(item) {
changes.forEach(function(el) {
var $el = $(el);
if ($el.is(item[0])) {
$el.trigger('domNodeInserted');
}
});
});
}
})(jQuery);
</script>
ध्यान दें
यह jQuery कोड एक काफी बुनियादी कार्यान्वयन है। यह उन मामलों में ट्रिगर नहीं होता है जहां संशोधन कहीं और आपके चयनकर्ता को वैध बनाते हैं।
उदाहरण के लिए, मान लीजिए कि आपका चयनकर्ता है .test select
और दस्तावेज में पहले से ही ए <select>
। चयनकर्ता को मान्य test
करने के लिए वर्ग जोड़ने से <body>
, लेकिन क्योंकि मैं केवल जाँच करता हूँ record.target
और record.addedNodes
, घटना नहीं होगी। परिवर्तन उस तत्व के साथ होना है जिसे आप स्वयं चुनना चाहते हैं।
जब भी म्यूटेशन होता है, तो चयनकर्ता के लिए क्वेरी करने से बचा जा सकता है। मैंने ऐसा नहीं करने का फैसला किया, जो पहले से ही संभाल चुके तत्वों के लिए डुप्लिकेट घटनाओं से बचने के लिए नहीं था। आसन्न या सामान्य सहोदर संयोजकों के साथ उचित व्यवहार करने से चीजें और भी पेचीदा हो जाएंगी।
अधिक व्यापक समाधान के लिए, https://github.com/pie6k/jquery.initialize देखें , जैसा कि डेमियन s Ceallaigh के उत्तर में वर्णित है । हालाँकि, उस पुस्तकालय के लेखक ने घोषणा की है कि पुस्तकालय पुराना है और सुझाव देता है कि आपको इसके लिए jQuery का उपयोग नहीं करना चाहिए।
$(select).ready(function() { });