How to get refreshed and new DOM element using Javascript? - javascript

I am using Web Application to automate using Javascript and selenium. There is a dropdown which has different portals and if I change the value from the dropdown entire page will get changed based on what portal we select. Say, Developer portal, Tester portal etc,.. but URL is same.
I can change the portal easily, but if I try to fetch the elements after changing the portal, I am getting the previous portal elements.
I am using JS with selenium,
String id = (String)jse.executeScript("var x = document.getElementsByTagName(\""+ tag +"\");var e=''; for(i=0; i<x.length; i++) { e+=x[i].innerText + \",\";if(x[i].innerText.trim()===\""+searchObject+"\"){x[i].click();}} return e;");
Note: If I use the refresh action, application navigates back to the previous portal(It is an application behavior).
Is there a way to get the elements?

Use mutation observer for the above quest.
// select the target node
var target = document.querySelector('#some-id');
// In your case this will body or the parent where you are adding elements
// 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);
The observer will notify you when some element added or any attribute changed or you have changed the text. If you want to observe only children just remove the other two.

Related

Call back on window object initialization (dynamic inclusion of iframes in page)

What I need:
My requirement is to inject script in to all windows that are presented in a web page.
I know we can find all windows by using window.frames property, but that won't be sufficient in my case since new windows can be added later to the page via iframes (inclusion of iframes in to the DOM)
So I need a mechanism to track windows in a page, something like callback on new window initialization.
What I tried:
I used Object.observe API to track the window.frames object changes. But I came to know that Object.observe API is going to be removed as per this link (https://esdiscuss.org/topic/an-update-on-object-observe).
So, is it good to use this API. Or if any alternate way is there please let me know
Here is a way using MutationObserver API, you can use the api to detect any element injected into your target element, even when a text is change or element is appended somewhere in your target tree
function createIframeOnDemand(wait) {
var iframe = document.createElement('iframe')
iframe.src = 'about:blank';
setTimeout(function() {
document.body.appendChild(iframe)
}, wait || 2000);
}
var body = document.body;
var observer = new MutationObserver(function(mutations) {
for(mutationIdx in mutations) {
var mutation = mutations[mutationIdx];
for(childIndex in mutation.addedNodes) {
var child = mutation.addedNodes[childIndex];
if(child.tagName && child.tagName.toLowerCase() == 'iframe') {
console.log(child);
//child is your iframe element
//inject your script to `child` here
}
}
}
});
var config = { attributes: false, childList: true, characterData: false };
observer.observe(body, config);
createIframeOnDemand();

Fire a function when element loses attribute

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.

detect div change in javascript

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

Detect with Javascript when a elelment has recieved content

When is clicked, div with id button makes a AJAX request and adds new content inside div with id newContent.
I am trying to launch a function, after the the div button get's clicks and the div with id newContent receives the content.
<div id="button"> </div>
<div id="newContent"></div>
Unfortunatelly I can't make changes to the .js file, that contains the AJAX function.
I didn't succed with:
var contentdiv = document.getElementById('newContent');
window.onload = function() {
contentdiv.onreadystatechange = function () {
if (contentdiv.readyState == "interactive") {
myFunction();
}
}
}
What could I do, to launch my function after the content has successfully added to the newContent div?
For modern browsers I would recommend mutation observers:
var observer = new MutationObserver( myFunction );
// configuration of the observer:
var config = { attributes: false, childList: true, characterData: true, subtree: true };
// pass in the target node, as well as the observer options
observer.observe(contentDiv, config);
This adds a mutation observer to your element. You can configure the options to which the observer needs to listen. Jquery doesn't support this natively (yet). This will fire when there is content added to the contentDiv. Or changes to the child elements in the contentDiv.
childList Set to true if additions and removals of the target node's child elements (including text nodes) are to be observed.
attributes Set to true if mutations to target's attributes are to be observed.
characterData Set to true if mutations to target's data are to be observed.
subtree Set to true if mutations to not just target, but also target's descendants are to be observed.
attributeOldValue Set to true if attributes is set to true and target's attribute value before the mutation needs to be recorded.
characterDataOldValue Set to true if characterData is set to true and target's data before the mutation needs to be recorded.
attributeFilter Set to an array of attribute local names (without namespace) if not all attribute mutations need to be observed.
Source: MDN
Which browsers support this: CanIuse
Read more here: MDN
MutationObserver is a powerful tool. It also provides information about the changes in the element. I suggest to read up with the possibilities. For now it will do the thing you want.
As a fall back for IE9 and 10 you can use:
contentDiv.addEventListener ('DOMNodeInserted', myFunction, false);
This, however, will not host the same functionality as the mutation observer and its use is discouraged by MDN.
Another way, you can use the setInterval function and checked every X millisecond your content div.
var oldString = document.getElementById("DivId").innerHTML;
var checkContentDiv = setInterval(function() {
if(document.getElementById("DivId").innerHTML != oldString) {
//your div is updated.
clearInterval(checkContentDiv);
}
}, 500);

How to scan dynamically added text with jQuery

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()

Categories