How to use XPath in a newly opened window? - javascript

With the code below (intended for a bookmarklet), I am trying to open a new window, look for certain span-elements, and click each of them. However, I cannot access the code of the new window through XPath.
Inserting the code (copy & paste) of the clickElem function directly in the new tab works fine
CORS is not a problem since it's the same domain/subdomain/protocol
I've been also following this answer.
JavaScript:
const w = window.open('https://example.com', 'Example', 'width=500, height=500');
w.clickElem = () => {
const xpath = '//span[text()="Click here"]';
const selectedNodeElements = w.document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);
let currentNode = selectedNodeElements.iterateNext();
while (currentNode) {
currentNode.click();
currentNode = selectedNodeElements.iterateNext();
}
}
setTimeout(w.clickElem, 8000);
When I try to access the text via currentNode.textContent I receive following error:
"Error in protected function: Cannot read properties of null (reading 'textContent')"
Grateful for every hint!

Are you sure you are already inside your tab? I'm thinking about something you need to get the active tab like this one?

I finally found my own mistake after going through my code on and on and coming across this answer. The .iterateNext() didn't work because the context node was wrongly set to document. Instead, it should be w.document to reference the newly opened window.
const selectedNodeElements = w.document.evaluate(xpath, w.document, null, XPathResult.ANY_TYPE, null);

Related

Sending a text to a text field of a new window using Javascript

I have a requirement to automate certain scenario. For that I want to open up a new window and perform some operations there.
For example: I want to open a website in a separate window and login via that window. Appreciate help to get this done using java script?
I tried as given below, but it doesn't seems working.
function newwin(){
var w = window.open("xxxxxxxx/login", "MsgWindow");
w.focus();
w.opener.document.getElementById('identifier').value="ab#test.com";
w.opener.document.getElementById('secret').value="abc#123";
w.opener.document.querySelector("p.css-1vtb8v1.eu2rrzg1").click();
}
newwin();
gives the following error.
371:25 TypeError: Cannot set property 'value' of null
at newwin (<anonymous>:366:53)
at <anonymous>:371:1
at <anonymous>:372:59
at callFunction (<anonymous>:352:33)
at <anonymous>:362:23
at <anonymous>:363:3
For that I want to open up a new window and perform some operations there.
You're using w.opener.document to get your elements. That's the current document, not the document in the new window.
Separately, you have to give the window time to load. You can't refer to the elements within the window before they're created.
So:
function newwin(){
var w = window.open("xxxxxxxx/login", "MsgWindow");
w.addEventListener("DOMContentLoaded", function() { // *** Wait for it to load
w.document.getElementById('identifier').value="ab#test.com";
// *** ^^^^^^^^^^----- use the new document, not `w.opener.document` (which is the same as `document`)
w.document.getElementById('secret').value="abc#123";
w.document.querySelector("p.css-1vtb8v1.eu2rrzg1").click();
});
w.focus();
}

How do I navigate to bing.com and enter a search text using the chrome console?

Below is my code.
It is resulting in unexpected behaviour.
It navigates to bing.com but it does not fill in the text field. Also, I have noticed that the console get cleared after navigating to a new webpage.
window.location = "https://www.bing.com";
window.onload = function(){
var editSearch = document.getElementById("sb_form_q");
editSearch.value = "Quux";
}
You are binding the onload function to the existing window object.
When the browser loads the new page, it will make a new window object which won't have your property set on it.
JavaScript run in one page (even when you are running it through developer tools) can't persist variables onto a different page.
(Storage mechanisms like localStorage and cookies are available, but you would need code in the subsequent page to look for them).
JavaScript is only valid for the current page you are on. When you are executing code from DevTools console, you are executing code on that page itself. So, when you navigate to another page using window.location you loose the onload handler you have defined.
To add handlers to a different page, it must be connected to your page (the parent) in some way, like an iframe or a popup.
ifrm = document.getElementById('frame');
ifrm.src = 'http://example.com';
ifrm.contentWindow.onload = function () {
// do something here with
// ifrm.contentWindow.document.getElementById('form')
}
As #Quentin said.
But you can do another way like ..
var keyword = "Quux";
window.location = "https://www.bing.com/search?q="+keyword;

Under Chrome - Mootools inject fails with null element

I have this weird problem on Chrome - on my page I am injecting elements using Mootools specifically a lightbox that contains a jwplayer video. The problem on chrome is that referring to an element ie. $('grid_01'); returns null the second time I click on it. To get around this I'm trying to test the element is null and re-inject it
var ss = $('holderdiv');
var x = $('mb_inline_0_-1');
if(x == null)
{
var el = new Element("div", {id: "mb_inline_0_-1"});
//if this line below runs without error...
ss.inject(el);
}
//.........why would x2 be null?
var x2 = $('mb_inline_0_-1');
Chrome says its null. Is there something I can do to ensure the DOM is updated ?
Thanks
You mean to use grab, not inject.
ss.grab(el); // Or el.inject(ss);
Your code has ss being injected into el, which is never attached to the DOM.
Injecting a newly created Element is written in the format newElement.inject(existingElement, position);.
So in your case, if you are planning to inject the newly created div (contained in el) into $('holderdiv'), it should be done thusly:
var el = new Element('div', {
. . .
});
el.inject('holderdiv', 'bottom'); // Although 'bottom' is assumed if nothing is passed

Accessing contents of NativeWindow in a HTML AIR application?

I'm currently building a HTML/JS AIR application. The application needs to display to the user a different 'window' - dependant on whether this is the first time they've launched the application or not. This part is actually fine and I have the code below to do that:
if(!startUp()) { // this simply returns a boolean from a local preferences database that gets shipped with the .air
// do first time stuff
var windowOptions = new air.NativeWindowInitOptions();
windowOptions.systemChrome = 'none';
windowOptions.type = 'lightweight';
windowOptions.transparent = 'true';
windowOptions.resizable = 'false';
var windowBounds = new air.Rectangle(300, 300, 596, 490);
var newHtmlLoader = air.HTMLLoader.createRootWindow(true, windowOptions, true, windowBounds);
newHtmlLoader.load(new air.URLRequest('cover.html'));
}
else {
// display default window
// just set nativeWindow.visible = true (loaded from application.xml)
}
However, what I want to be able to do is manipulate the html content from within cover.html after it has loaded up. There seems to be plenty of tutorials online of how to move, resize, etc. the NativeWindow, but I simply want access to the NativeWindow's HTML content.
For example, how would I add a new paragraph to that page? I've tried the following:
newHtmlLoader.window.opener = window;
var doc = newHtmlLoader.window.opener.document.documentElement;
Using AIR's Introspector console, ....log(doc) returns [object HTMLHtmlElement].
Hmm, seems promising right? I then go on to try:
var p = document.createElement('p');
var t = document.createTextNode('Insert Me');
p.appendChild(t);
doc.appendChild(p);
...but nothing gets inserted. I've also tried the following replacements for doc:
var doc = newHtmlLoader.window.opener.document.body; // .log(doc) -> [object HTMLBodyElement]
var doc = newHtmlLoader.window.opener.document; // .log(doc) -> Error: HIERARCHY_REQUEST_ERR: DOM Exception 3
...as well as the following with jQuery:
$(doc).append('<p>Insert Me</p>'); // again, nothing
So, anyone had any experience in accessing a NativeWindow's inner content programmatically? Any help will be greatly appreciated.
Hmm, so I think I may have found out how to do it...If we amend the original code and add an event listener on the loader:
var newHtmlLoader = air.HTMLLoader.createRootWindow(true, windowOptions, true, windowBounds);
newHtmlLoader.addEventListener(air.Event.COMPLETE, doEventComplete);
newHtmlLoader.load(new air.URLRequest('cover.html'));
You can then interact (assuming you're using jQuery) with the contents of the newly created window by using:
function doEventComplete(event) {
doc = $(event.currentTarget.window.document.body);
doc.append('<p>Insert Me!</p>')
}
:)
I'm not sure this has the effect you intended:
newHtmlLoader.window.opener = window;
var doc = newHtmlLoader.window.opener.document.documentElement;
What is does is set var doc = window.document.documentElement;, so 'doc' is your local document, not the one in the other window.
I think what you want is
var doc = newHtmlLoader.window.document.documentElement;
Do note that this will not work until the document has loaded.

Accessing an iFrame's dom from a Firefox Extension

I've spent a long time trying different things to get this to work but nothing does and documentation is not helping much.
I'm trying to populate a form inside an iframe that I dynamically inject into a page. To inject that iframe I do:
myObject.iframe = document.createElement("iframe");
myObject.iframe.setAttribute("src", data.url);
myObject.iframe.setAttribute("id","extension-iframe");
myObject.window.document.getElementById('publisher').appendChild(myObject.iframe);
myObject.iframe.addEventListener("load", function(){
myObject.populate(data);
}, false);
which works fine and DOES trigger the populate() method. My problem is getting the document or window objects for that iframe. I've tried all of the following:
myObject.iframe.window
myObject.iframe.document
myObject.iframe.content
but these are all undefined.
I also tried passing the event object to that iframe's load event listener and then doing:
event.originalTarget
But that didn't work either.
I am reading the following documentation:
https://developer.mozilla.org/En/Working_with_windows_in_chrome_code
https://developer.mozilla.org/en/Code_snippets/Interaction_between_privileged_and_non-privileged_pages
But either I'm not understanding it or it's just not properly explained.
Can anyone shed some light?
Thanks!
Have you tried using the contentWindow property?
var doc = iframe.contentWindow.document;
Try myObject.iframe.contentDocument
Something along the lines of this:
// For accessing browser window from sidebar code.
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
var gBrowser = mainWindow.gBrowser;
var iframes = gBrowser.contentDocument.getElementsByTagName("iframe");
for (var i=0; i < iframes.length; i++) {
var check_elem = iframes[i].contentDocument.getElementById('myid');
if (check_elem) {
...;
}
}
I'm passing in the event object and then event.originalTarget (like you mentioned) and it's working fine. Although I had to set useCapture parameter of addEventListener to true in order to get my event called.
So if I understand correctly you need to access document in populate method...
I would pass event.originalTarget as a parameter to your method
or
in load event I would set for example myObject.document property and then use it in populate method.
myObject.iframe.addEventListener("load", function(event){
var doc = event.originalTarget;
myObject.populate(data,doc);
}, false);
I almost had the same problem. Using the following code gets me the iframe (Firebug is used for debugging):
iframes = window.content.document.getElementsByTagName('iframe')
for (var i = 0; i < iframes.length; i++) {
var elmInput = iframes[i];
Firebug.Console.log(elmInput);
}

Categories

Resources