i am using mutationObserver to detect changes using bellow code
var target = document.querySelector('body');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
var config = { attributes: true, childList: true, characterData: true };
observer.observe(target, config);
in this i am able to detect changes if changes happen inside the targeted element right now i am targeting body
what i exactly want is the mutationObserver event only fires when the element i had specified is added to the DOM
You can have a good example of Mutation Observer on this page:
http://www.htmlgoodies.com/beyond/javascript/respond-to-dom-changes-with-mutation-observers.html
The working example add the observer on the body, and if you add, remove, or change an attribute you can capture the change.
But to be sure that all things are well capture use this observerConfig.
var observerConfig = {
attributes: true,
childList: true,
characterData: true,
subtree : true
};
Related
I am attempting to check every mutation on a page using MutationObserver.
Is there a simple way to fix the following so I don't have to include it in the body (i.e. include it in the <head>) as an inline script?
The issue comes with the fact that I need the bodyList variable to be able to start monitoring items added to the page.
Obviously I can't use the onLoad event or anything as by then the mutations have all occurred (unless there is a way of accessing them after the fact I am unaware of?).
Or is there a way to attach the mutation observer to the document itself rather than an element?
I am sure the answer is simple but I can't find any documentation that covers this.
<body>
<script>
//I want to move this inline script into the <head>
var bodyList = document.querySelector("body"),
observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
console.log("MUTATION", mutation)
});
});
observer.observe(bodyList, {childList: true, subtree: true});
</script>
....all the HTML elements that I want to monitor
You can attach an observer to the HTML document itself, wait for the <body> to appear, then attach an observer to the body:
// In the <head>:
new MutationObserver((_, observer) => {
const { body } = document;
if (!body) return;
// Remove this observer, since it's not needed anymore; body exists
observer.disconnect();
new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
console.log("MUTATION", mutation)
});
})
.observe(body, { childList: true, subtree: true });
})
.observe(document.documentElement, { childList: true });
I have the following script that runs on page load. It's meant to observe every td element on the page and check if it changes.
I was just logging the mutation to console to see my next steps, as I want to see what values change in each td element (the div refreshes every 15 seconds that houses the table).
Here's what I've got so far:
jQuery(document).ready(function( $ ) {
/** Change URL */
setInterval(function() {
$.ajax({
url: 'http://localhost:8888/profitmanager/wp-content/plugins/football-stats/update.php'
}).done(function(){
$('.fbs_results').load(
location.href+" .fbs_results>*", function(){
var hidden = [];
$.each(JSON.parse(localStorage.getItem("table_state")), function(index, value) {
if(value == 'hidden'){
$('tr[data-index="'+index+'"]').hide();
}
});
// console.log(hidden);
$('tr').each(function(index){
});
}
);
});
}, 15000);
const config = {
characterData: true,
characterDataOldValue: true,
childList: true,
subtree: true
};
function tdChanges(mutations) {
mutations.forEach((mutation) => {
console.log(mutation);
// if (mutation.addedNodes.value) {
// console.log();
// }
});
}
const tds = document.querySelectorAll('td');
Array.from(tds).forEach(function(td) {
const observer = new MutationObserver(tdChanges);
observer.observe(td, config);
});
});
But it doesn't work, nothing logs. Weird.
Can anyone fix my code?
TIA
querySelector() returns only a single Element. To look at all of them you need to use querySelectorAll() then loop over the result:
const tds = document.querySelectorAll('td');
Array.from(tds).forEach(function(td) {
const observer = new MutationObserver(tdChanges);
observer.observe(td, config);
});
Here's a working example in a jsFiddle, as the SO snippet editor is sandboxed and has issues running MutationObservers.
One thing to note here is that MutationObservers are not fast, and if you have a lot of td elements in your page you may see a performance hit. You may be better served by placing a single MutationObserver on the parent table and letting the event bubble up, like this.
I want a (preferably pure javascript but jquery is acceptable too) way to run a function when the disabled="disabled" property is removed from a button.
You can get notified of DOM changes by implementing a MutationObserver.
var observer = new MutationObserver(function(mutations) {
if(mutations.some(function(m) { return m.attributeName == 'disabled' && !m.target.disabled; }))
{
alert('Button was enabled');
}
});
observer.observe(targetButton, { attributes: true, childList: false, characterData: false });
Demo
The MutationObserver API lets you monitor elements for changes on the element.
var btnElement = document.getElementById("buttonId");
var observer = new MutationObserver(observerChanges);
observer.observe(btnElement, {
attributes: true,
subtree: opt.watchChildren,
childList: opt.watchChildren,
characterData: true
});
/// when you're done observing
observer.disconnect();
function observerChanges(mutationRecord, mutationObserver) {
console.log(mutationRecord);
}
You can use Object.prototype.watch(). It's supported in Firefox only, but here's a polyfill:
HTML:
<button id="myButton" disabled="disabled">Click</button>
JavaScript:
var myButton = document.getElementById('myButton');
myButton.watch("disabled", function() {
console.log("myButton changed!");
});
myButton.disabled = false; // "myButton changed" will be logged
JSFiddle: https://jsfiddle.net/6ofvutwh/1/
More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/watch
Can you give us the code on how you remove disabled? But here is an example from the top of my head.
<button class="class" id="btn1" disabled>
function remove_disable()
{
document.getElementById('btn1').disabled = false;
function2();
}
then function2
function function2()
{
//somecode
}
Here, when we call remove_disable we remove the disabled feature on the button then run another function.
Hope this helps in a way
If you have control over when this change is done, a simple callback function would be the easiest solution.
Otherwise, you can use Mutation Observers to watch for when disabled property on inputs are changed.
I know there is no such event, but is there something similar I can use?
I have ASP.NET usercontrols which are loaded dynamically into a container, which gives a very smooth effect.
The downside of doing this is that I want to run some client-side javascript when a control has finished loading, and I don't know how.
It took me a while to figure out why my jQuery scripts weren't running, then I realised they only ran on $(document).ready() and that only occurs when the entire page loads! (Duh!)
Can anyone think of a way of doing this?
Thanks :)
Getting more complicated now!
I'm trying to use a DOM Mutation Observer to watch the container so I can run a script when it changes.
But I'm getting an error: An attempt was made to reference a Node in a context where it does not exist.
The DOM element does exist, but I'm not sure I understand the error correctly.
Here is my observer code:
$(document).ready(function () {
// select the target node
var target = $('#contentPanel');
if (typeof (target) != 'undefined') {
// create an observer instance
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
console.log(mutation.type);
if (mutation.addedNodes) {
alert('New nodes');
}
//rememberMe();
})
});
// configuration of the observer:
var config = { attributes: false, childList: true, characterData: true }
// pass in the target node, as well as the observer options
observer.observe(target, config); // <== error occurs here
}
});
The final observer code:
$(document).ready(function () {
// select the target node
var target = $('#contentPanel');
if (typeof (target) != 'undefined') {
// create an observer instance
var observer = new MutationObserver(function (mutations) {
var doRememberMe = false;
mutations.forEach(function (mutation) {
if (mutation.addedNodes) {
doRememberMe = true;
}
})
if (doRememberMe) rememberMe();
});
// configuration of the observer:
var config = { attributes: false, childList: true, characterData: true }
// pass in the target node, as well as the observer options
//observer.observe(target, config);
observer.observe(document.body, config); // <== apply observer to whole document! (could be done nicer)
}
});
Got it, in that case try this at the end of your container (you can define CallLoadedEvent in a separate JS file):
<asp:Panel id="Container" runat="server">
<!-- controls dynamically load here -->
<script>
CallLoadedEvent();
</script>
</asp:Panel>
I was eventually able to get it working using the DOM Mutation code added above.
However the only way it would work was if I applied the listener to the whole document.
For some reason I wasn't able to apply it just to the element that was being modified; perhaps for some reason it was going out of scope, even though I was able to test it existed first! Oh well.
This question already has answers here:
How to listen for changes to the title element?
(6 answers)
Closed 3 years ago.
Is there any way to detect a change to document.title / head > title via Javascript? I want to detect this via a Google Chrome extension content script, so I can't really wire up code in the target page's JS where the actual title change is performed.
I've found WebKitMutationObserver which theoretically should be able to detect a change to head > title, but it doesn't work for all cases:
// set up an observer for the title element
var target = document.querySelector('title');
var observer = new WebKitMutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
});
});
var config = { attributes: true, childList: true, characterData: true };
observer.observe(target, config);
// this jQuery statement fires the observer as expected ...
$('head > title').text('foo');
// ... but this doesn't:
document.querySelector('title').innerText = 'cheezburger';
// ... and neither does this:
document.title = 'lorem ipsum';
Any ideas?
I have found a fully working solution which is only a small modification to the example I posted in the original post.
// set up an observer for the title element
var target = document.querySelector('head > title');
var observer = new window.WebKitMutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log('new title:', mutation.target.textContent);
});
});
observer.observe(target, { subtree: true, characterData: true, childList: true });
// all three of these methods correctly fire the mutation observer
setTimeout(function() { document.title = 'foo'; }, 1000); // the usual method
setTimeout(function() { document.querySelector('head > title').innerText = 'bar'; }, 2000); // DOM method
setTimeout(function() { $('head > title').text('cheezburger'); }, 3000); // jQuery-only method
The addition of subtree: true was all that was needed to get this working right.
The wrapping of the three title-changing methods in setTimeout calls at the end is just for demonstration purposes; without this the title value changes so quickly that the WebKitMutationObserver doesn't report each change individually, since MutationObserver is designed to accumulate changes over a short period before executing the observer callback.
If one does not need to detect title changes made via the last jQuery-only method, the childList: true property can be omitted from the observer.observe line; only characterData: true is needed to detect the first two title-changing methods.
You have both JQuery and Javascript in your code example. Not sure if your only restricted to JavaScript, but here's how you can do it with jQuery
If you want to trigger the change, take a look at: http://api.jquery.com/trigger/
jQuery
$(document).ready(function () {
$("title", "head").change(function () {
console.log("Title has changed");
});
//Trigger Change
$("title","head").text("New Title").trigger("change");
});