I'm building a chrome extension where I have to access the innerText of some span elements. I can safely get them using simple document.querySelector commands.
But for some spans, it returns null because they don't exist yet in the DOM> (For security reasons, I cannot disclose which website this happens with but to make it more clear, LinkedIn does a similar thing where the Experience block is only loaded if you scroll down to it.)
Now, to quote the problem using that example: I want to get the value of a span which is inside that Experience section. If I run the script inside window.onload, it returns null because the span isn't there yet.
One solution is to simply scroll the page, (or even worse, ask the users of the extension to first scroll the page before running the extension.) However, I do not want to do that.
Is there a way in JS to scroll the page in the background without visual feedback to the user so that I can get the value of the HTML elements that are initially hidden?
Assume that the span I want to get has the following class: defense-rc4
Related
I'm doing a chrome extension that allows user to click on some links. The extension should analyze the page (1 time per 1 hour, server-side) and if the link is changed - notify. The extension should work on any "normal" web page.
My chrome extension just allows to select element. All other job is done on server side.
What I tried:
ID - the most obvious way, but a lot of web pages don't use ID for elements.
a tag with exact href. But I also need some notifications for position changes. And there is a big chance that the extension will work not only with links.
e.path - Should I keep it like html.child(0).child(2).child(1)... or identify them with their classes and types?
So, is there any good way to identify an element on some unknown page? How should I serialize the identifier?
I'm ok if it will not work after any major changes to html template.
Thank you :)
Assuming I'm reading your question right: You want to select some element on a webpage and have a server re-read that element on a timer loop to see if the element (text, for example) has changed.
Something like an ID would be easiest but, barring that, you might consider XPath, a standard for navigating through XML (or HTML) documents.
W3Schools Reference on XPath
Just a note: from a design perspective, this is going to be challenging because you don't have control over other pages. There's nothing stopping a website from changing IDs, reorganizing elements, etc.
On this page https://detail.1688.com/offer/548835845261.html
I want to scrape shipping price and shipping weight as highlighted in image.
I dont know how is this being loaded into DOM.
Its not included in DOM. Its not even loaded by an AJAX call.
Not sure whats going on.
The only relevent part I see on initial page source is
data-unit-config="{"calculationUrl":"https://laputa.1688.com/offer/ajax/CalculateFreight.do","freightTemplateId":"10342228","beginAmount":"1","unitWeight":"1","refPrice":"88.00","isCodOffer":""}"
I tried making GET request to that URL
https://laputa.1688.com/offer/ajax/CalculateFreight.do?freightTemplateId=10342228&beginAmount=1&unitWeight=1&refPrice&88.00&isCodOffer
but not luck.
I want to ask is there any way I can check what part of JavaScript code is rendering a specific Html element?
My recommendation would be:
When the element appears, inspect it.
In the Elements panel, find the first ancestor element to the mystery element that has no mysterious origins (an element that you know how it is getting on the page).
Right-click the ancestor element from step #2 and navigate and select Break on... ==> Subtree modification
Refresh the page _with the devtools on the Elements panel (seems to not work otherwise)
Now anytime JavaScript modifies descendants of the element you set the breakpoint on, the sources panel will pause and allow you to inspect what is going on.
I am currently working on writing the test automation for a web application that loads as an SWF file for our end-users, but a fully functioning Javascript version exists for the sole purpose of automation.
I have means to navigate through the application with keyboard shortcuts, but when it comes to executing click commands, I have no luck at all. Upon inspecting with Firebug/Firepath, the only value that I could find was an xpath (no id exists, no class, no anything really).
The next issue is the xpath itself.
It is:
Really brittle.
.//*[#id='flow']/div[1]/div/div[7]/div/div[3]/div[4]/div/div/div/div/div/div/div/div[3]/div[1]/img
This appears to be the xpath to the image that represents the button, not the button itself.
Executing .click() commands on the above type of xpath will do nothing until you manually hover your mouse over the button (regardless of moveToElement commands), where it will "click" the image but no functionality will run.
So I'm wondering after digging around in the actual JavaScript looking for identifiers, is there any way to select an element through any other properties? Or is there any way I can better "identify" a function? Perhaps find the xpath to the button that the image represents?
Using JUnit and Java, if that helps.
Thanks
Apparently, my comments answered the OP's question, so here goes, for reference sake:
If you need "the button itself", as you wrote in your question, use Inspect Element from the browser to find out what the actual element is you need and then simply remove from the right-hand side of your XPath expression enough axis steps until the part that remains selects the ancestor element that is the actual button element.
Now you should be able to send it a click event.
I'm afraid there won't be much we can do about the XPath statement to be "brittle", simply because you do not have an identifier to go on. That means that if the structure of the page changes, you will have to change the XPath (unless some of the ancestor elements have some notable identifiers).
I orginally asked this question and at the time I was grasping at straws. I created the following fiddle that is closely related to what I'm actually seeing on my internal application:
http://jsfiddle.net/uwtj9/10/
There is a normal index.asp page. On that page I can open a div that includes an iFrame (so a popup). Then from that iFrame I can then open another div that includes another iFrame. However, when the second div opens I am trying to close the 1st div. Hopefully that makes sense.
However, when I try to open the second div, the code to create the iframe never gets run. I think it has to do with the "top." that is currently in my internal application code. When I try to add top.hidepopwin I get an error in Firebug:
Permission denied to access property 'hidePopWin'
However, in my code internally I don't get that error message, but I don't get into the doPopWin code.
Unfortunately for whatever reason when I take out the top. in my code internally it doesn't quite work the way I'm expecting (and I can't replicate it on the fiddle). Basically the second div gets created but it remains the same size and not all the elements are getting cleared (i.e the original menu is still showing up under the new menu).
Anyone have any idea's on this? The fiddle seems to be working as I expect but this "top." thing is kind of weird.
UPDATE:
SLaks answer of why the "top." doesn't work for jsFiddle is acceptable. I'm still left wondering about this issue:
Unfortunately for whatever reason when I take out the top. in my code internally it doesn't quite work the way I'm expecting (and I can't replicate it on the fiddle). Basically the second div gets created but it remains the same size and not all the elements are getting cleared (i.e the original menu is still showing up under the new menu).
Any ideas?
top returns the window object for the outermost frame hosting your page.
In jsFiddle, that's the root jsfiddle.com page, which is in a different domain than your user code. (user submissions in jsFiddle run in http://fiddle.jshell.net)
Knowing that my document.activeElement is an input field (I don't know exactly the name of the component, but may be the Google's search input field, for example), how can I set a text on it programmatically?
--update
I'm trying it from a xul application, via javascript after the page is loaded. A paste command works fine, so I know the field have the focus. (and I didn't put the Xul tag becouse it's just about the javascript)
See the mozilla reference. This is the same type as document.getElementById()
document.activeElement.value = 'new value';
If you are sure it is a input text field, just set the value:
document.activeElement.value = 'value'
Without seeing your code and the context it is running in, I can only speculate. However, my guess is that you are calling document.activeElement from your XUL app, which means document is the chrome document, not the content page. In this case, the active element is likely to be the browser or iframe element you are using to display the content.
I think there's a little more trouble because I'm in a Xul app. Javascript was supposed to work like in the browsers, but it didn't.
What I did to make it work was (after put the content in the clipboard):
controller.doCommand('cmd_selectAll');
controller.doCommand('cmd_paste');
If you want the focused element wherever it may be relative to the given application window, e.g. it may be inside a <browser> element, use document.commandDispatcher.focusedElement.value which is the same as document.commandDispatcher.focusedWindow.document.activeElement.value. This gives you the element that cmd_paste operates on.