У меня есть div, содержимое которого постоянно меняется, будь то ajax requests
, jquery functions
, blur
т.д. И т.д.
Есть ли способ, которым я могу обнаружить любые изменения в моем div в любой момент времени?
Я не хочу использовать интервалы или значение по умолчанию.
Нечто подобное сделало бы
$('mydiv').contentchanged() {
alert('changed')
}
Если вы не хотите использовать таймер и проверить innerHTML, вы можете попробовать это событие
$('mydiv').bind("DOMSubtreeModified",function(){
alert('changed');
});
Более подробная информация и данные о поддержке браузера находятся здесь.
Внимание: в новых версиях jQuery bind() устарел, поэтому вместо него следует использовать on():
$("body").on('DOMSubtreeModified', "mydiv", function() {
alert('changed');
});
Вы можете попробовать это
$('.myDiv').bind('DOMNodeInserted DOMNodeRemoved', function() {
});
но это может не работать в Internet Explorer, не проверял его
Поскольку $("#selector").bind()
устарел, вы должны использовать:
$("body").on('DOMSubtreeModified', "#selector", function() {
// code here
});
#
указывающий, что символ должен идти перед селектором.
Вы ищете MutationObserver или События мутации. Ни одна из них не поддерживается повсюду и не слишком ласкает мир разработчиков.
Если вы знаете (и можете убедиться, что) размер div изменится, вы можете использовать событие изменения размера кроссбраузера.
Использование Javascript MutationObserver
//More Details https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
// select the target node
var target = document.querySelector('mydiv')
// create an observer instance
var observer = new MutationObserver(function(mutations) {
console.log($('mydiv').text());
});
// 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);
Следующий код работает для меня.
$("body").on('DOMSubtreeModified', "mydiv", function() {
alert('changed');
});
Надеюсь, это поможет кому-то:)
Нет встроенного решения этой проблемы, это проблема с вашим шаблоном проектирования и кодирования.
Вы можете использовать шаблон издателя/подписчика. Для этого вы можете использовать специальные события jQuery или собственный механизм событий.
Во-первых,
function changeHtml(selector, html) {
var elem = $(selector);
jQuery.event.trigger('htmlchanging', { elements: elem, content: { current: elem.html(), pending: html} });
elem.html(html);
jQuery.event.trigger('htmlchanged', { elements: elem, content: html });
}
Теперь вы можете подписаться на события divhtmlchanging/divhtmlchanged, как показано ниже,
$(document).bind('htmlchanging', function (e, data) {
//your before changing html, logic goes here
});
$(document).bind('htmlchanged', function (e, data) {
//your after changed html, logic goes here
});
Теперь вы должны изменить свои изменения содержимого div с помощью этой функции changeHtml()
. Таким образом, вы можете отслеживать или делать необходимые изменения соответственно, потому что аргумент данных обратного вызова привязки содержит информацию.
Вы должны изменить свой div html следующим образом:
changeHtml('#mydiv', '<p>test content</p>');
А также вы можете использовать это для любых элементов html, кроме элемента ввода. В любом случае вы можете изменить это для использования с любым элементом (ами).
Используйте MutationObserver, как показано в этом фрагменте, предоставленном Mozilla, и адаптирован из этого поста в блоге.
Кроме того, вы можете использовать пример JQuery, показанный в этой ссылке
Chrome 18+, Firefox 14+, IE 11+, Safari 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();
Вы можете сохранить старый innerHTML div в переменной. Установите интервал, чтобы проверить, совпадает ли старый контент с текущим контентом. Когда это не так, сделайте что-нибудь.
Попробуйте MutationObserver:
поддержка браузера: http://caniuse.com/#feat=mutationobserver
<html>
<!-- example from Microsoft https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/dev-guide/dom/mutation-observers/ -->
<head>
</head>
<body>
<script src="/jquery.min.js"></script>
<script type="text/javascript">
// Inspect the array of MutationRecord objects to identify the nature of the change
function mutationObjectCallback(mutationRecordsList) {
console.log("mutationObjectCallback invoked.");
mutationRecordsList.forEach(function(mutationRecord) {
console.log("Type of mutation: " + mutationRecord.type);
if ("attributes" === mutationRecord.type) {
console.log("Old attribute value: " + mutationRecord.oldValue);
}
});
}
// Create an observer object and assign a callback function
var observerObject = new MutationObserver(mutationObjectCallback);
// the target to watch, this could be #yourUniqueDiv
// we use the body to watch for changes
var targetObject = document.body;
// Register the target node to observe and specify which DOM changes to watch
observerObject.observe(targetObject, {
attributes: true,
attributeFilter: ["id", "dir"],
attributeOldValue: true,
childList: true
});
// This will invoke the mutationObjectCallback function (but only after all script in this
// scope has run). For now, it simply queues a MutationRecord object with the change information
targetObject.appendChild(document.createElement('div'));
// Now a second MutationRecord object will be added, this time for an attribute change
targetObject.dir = 'rtl';
</script>
</body>
</html>
Добавление некоторого содержимого в div, будь то через jQuery или через DOM-API напрямую, по умолчанию используется функция .appendChild()
. Что вы можете сделать, это переопределить функцию .appendChild()
текущего объекта и реализовать в ней наблюдателя. Теперь, переопределив нашу функцию .appendChild()
, нам нужно взять эту функцию из другого объекта, чтобы иметь возможность добавлять содержимое. Поэтому мы вызываем .appendChild()
другого div, чтобы, наконец, добавить содержимое. Конечно, это также относится к .removeChild()
.
var obj = document.getElementById("mydiv");
obj.appendChild = function(node) {
alert("changed!");
// call the .appendChild() function of some other div
// and pass the current (this) to let the function affect it.
document.createElement("div").appendChild.call(this, node);
}
};
Здесь вы можете найти наивный пример. Думаю, вы можете продлить его самостоятельно. http://jsfiddle.net/RKLmA/31/
Кстати: это показывает, что JavaScript соответствует принципу OpenClosed.:)
keypress
с contenteditable элементом<div>
. Я не уверен, что решения там применимы к этому. Они определенно не поймут никаких программных изменений в содержании элемента.