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();
Related
I am running a Javascript file on this url. I am interested in changes in the red outlined elements:
I wrote the following script
const $xpath = xp => {
const snapshot = document.evaluate(
xp, document, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
);
return [...Array(snapshot.snapshotLength)]
.map((_, i) => snapshot.snapshotItem(i));
};
const xpathOdds = './/div[#col-id="bestOdds"]/descendant::div[#class="d-flex justify-content-between align-items-center"]';
var odds = $xpath(xpathOdds);
var config = {characterData: true,
attributes: true,
childList: true,
subtree: true
};
odds.forEach(function(target, idx) {
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
});
});
observer.observe(target, config);
})
I am not sure why the MutationObserver is not triggered.
It is triggered if I edit an element using rightmouse click - "Inspect".
However, it is not triggered if the website itself makes changes to the elements in question.
When an element changes it becomes yellow, so I know there should have been mutations
What am I doing wrong?
I checked the link you posted, and I think the problem is you are attaching the observers to the wrong objects. The thing is, when there is an update and the color of the cell becomes yellow, the whole table get replaced and not just the cells. So the cells you were observing are no longer there to be observed. You should attach the observer to a higher element in the hierarchy that does not get replaced, like that one with the class ag-center-cols-viewport or the document itself.
It probably has to do with the config for mutation observer.
var config = {
attributes: true,
childList: true,
subtree: true, // Because you're watching for changes made to one of the children element.
characterData: true // The changes you're looking for are in the content and not at element level.
});
The changes you expect triggering the observer are related to the element's style. You have to set the the observer to monitor changes to the element's attributes, including all its style attributes.
attributeFilter: ['style']
var config = {
attributes: true,
attributeFilter: ['style'],
childList: true,
subtree: true
};
Maybe its caused because site rendered using Next.js and Virtulal DOM. And mutationObserver doesnt react with changes on virtual dom.
And to check changes that make the site itself you can use some other way. For example with setInterval.
Something like this problem I viewed recently here https://copyprogramming.com/howto/why-isn-t-the-mutationobserver-working
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.
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.
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()