Is there a way to fire a function when element loses some custom attribute? For example, when custom_attribute is removed, then show me some alert. What's the way to do it? Plain JS is preferable, although jQuery is also okay.
<div class="someclass" custom_attribute>...</div>
You can use MutationObserver:
// select the target node
var target = document.querySelector('.someclass');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
fire_function();
console.log(mutation.type);
});
});
// configuration of the observer:
var config = { attributes: true };
// pass in the target node, as well as the observer options
observer.observe(target, config);
// later, you can stop observing
observer.disconnect();
This fires the fire_function() every time an attribute is changed. So you can check, if the particular attribute is missing or changed.
Related
I have a single page application where a div with a class "abc" is getting loaded dynamically. I want to run a script only after that particular element and all its children have been loaded in the DOM. I don't want to use a timer which calls the function again and again. How do I go about this. This is probably related to mutation observer but I am not understanding how to use that.
Example with mutation observer
var target = document.querySelector('.class');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// 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);
So for each mutation of the target element
this code console.log(mutation.type);
will be execute
$(document).on('DOMNodeInserted', '.abc', function() {
});
This will wait until the DOM element is ready and then run your code.
I am using mutation observer on a target node. It fires if any of the child nodes or properties change. But I have a case where I had to handle the target node itself being removed. This is not working. Is there a way to handle this?
MutationObservers can watch for 3 things:
An attribute change
A text content change
A child list change
Then optionally those change events can be bubbled up, so if you want to changes on both the target and all of the target's children, you can do that.
This means what you want cannot be done by listening to your target. You would need to attach an observer to the target's parent node, and listen for a childList change on the parent that removes the node you want to track.
e.g. instead of this fake example of what you were hoping for
var observer = new MutationObserver(callback);
observer(target, {
// Fake non-existent option
parent: true
});
you do
var observer = new MutationObserver(function(mutations){
var targetRemoved = mutations.some(function(mutation){
return mutation.removedNodes.indexOf(target) !== -1;
});
if (targetRemoved) callback();
});
observer(target.parentNode, {
childList: true
});
can-dom-mutate can do this:
import domMutate from "can-dom-mutate";
domMutate.onNodeRemoval(yourEleement, function(){
})
It does this by listening on the entire document for element removal.
I'm working on a small chrome extension for fun, and one thing I need it to be able to do, is to detect when the text inside a div is changed by the webpage itself.The code I'm using is:
var status = document.getElementById("status").innerHTML;
status.onchange = function() {
console.log("CHANGE DETECTED")
And this doesn't seem to work, so what should I use instead?
NOTE: I'd prefer not to use jquery, as I am not even very proficient with javascript at the moment, but if it would be that much simpler/easier, that would be fine.
use this trick
source:https://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/
// select the target node
var target = document.querySelector('#some-id');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// 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();
You can't do what you want using change event. On newer browsers, you can use Mutation Observers. On older browsers... well, you ask people to upgrade to newer browsers. :P
I'm trying to scan all text on a page and selectively create tooltips on pieces of text. I have working code that does this, but it only works on text that's on the page when the DOM ready event fires. Since the .live() function has been deprecated, we're supposed to use .on(), but that function only applies to elements that existed when it was called. Delegate event handlers apply to both current and future elements, but require the bound event to bubble up to the parent and the load event doesn't bubble.
So how can I scan all text--or even all the elements for that matter--as it's dynamically loaded?
UPDATE:
Per Makaze's comment, I tried several approaches. This one seems closest so far, but not quite:
$('body').on('DOMNodeInserted', '*:not("script")', function(e){
console.dir(e.target); //drill in here, I can see the nodeType==3 nodes
//var find = $(e.target);
var nodes = flattenTree(e.target.childNodes, 0); //recursively get all child nodes
for(var i in nodes){
var elem = $(nodes[i]);
var parent = elem.parent();
var txt = elem.text();
if(txt!==undefined && !txt.match(/^\s*$/)){
var refs = txt.match(versePattern);
if(refs!==null){
//var i = 0;
console.log(refs); //I never see the text node here, but I see it above when I manually drill into e.target
The versePattern matches as I expect in the static version of this code (which is working correctly), so I don't think that's the issue. Also, the '*:not("script")' doesn't seem to work as I'm still seeing <script> tags, but that's a minor thing that I can deal with later.
The MutationObserver constructor is what you want. Bind it to the parent element or document and filter your mutations from there.
// select the target node
var target = document.querySelector('#some-id');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.addedNodes);
});
});
// 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);
setTimeout(function() {
target.appendChild(document.createTextNode('There!'));
// later, you can stop observing
// observer.disconnect();
}, 1000);
<div id="some-id">Wait for it...</div>
Side note: You can use .on() on the document and use a selector to filter the targets similar to .delegate(): $(parentSelectors).on(types, childSelectors, function).
Just initialized all your textboxes that you want to put tooltip on your js file.
Sample;
//Initialize Tooltip
$('#Name').tooltip()
$('#Age').tooltip()
$('#Address').tooltip()
How would I change the following code (which makes the timeago plugin work) to use the on() function (or others) so that it can be used live? I can't quite seem to figure it out (I'm fairly new to JQuery).
jQuery(document).ready(function() {
jQuery("a.timeago").timeago();
});
How would this be done?
You can use MutationObserver to check when the DOM was modified: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
You pick a node to observe. For your project you should observe the container the a.timeago elements will be created into. <body> is fine but will incur more work for the browser. Then, whenever the dom changes, a callback will be fired. Catch the elements you care about.
Modified from the documentation:
// select the target node
var target = document.querySelector('#your-container');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(addedNode) {
// if the addedNode matches $('a.timeago')
// $(addedNode).timeago();
});
});
});
// 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();