Web Element "Grows" After Being Scrolled into View - javascript

I recently posted a question on SO where I observed a different element height and width being returned by Chrome Inspector tool vs. Selenium WebDriver when calling element.getSize().getWidth() and element.getSize().getHeight(). With Chrome Inspector I get dimensions of w = 979, h = 1961. With Selenium I get dimensions of 979 and 1461 respectively.
Code I'm using to retrieve element:
String URL = "https://www.amazon.com/dp/B07G9RZD14";
driver.navigate().to(URL);
String XPath = ".//*[#id='aplus']/div";
WebElement element = driver.findElement(By.xpath(XPath));
I've repeated this experiment several times and each time I got the same result. Some have suggested that I was changing the size of the browser however this is not the case. I always performed my test in maximized mode from start to finish.
I did experiment further and it turn out that if I inspect the element with Chrome Inspector immediately after the page loads (without scrolling down to element so it is put into view) the dimensions returned matches the dimensions returned by Selenium (1461). It is only after I scroll element into view that the element height "grows" to 1961.
When I inspect the HTML in the above URL I see a script executing an "expander" function.
I have three question.
1) How does this function work? (Looks like it's using Javascript)
2) Is it possible to get the real dimensions of the said element (1961) without scrolling element into view? Or it would be required to scroll into view element with this kind of function attached?
3) If it is required to scroll such elements into view, is it possible for us to know which elements have this function and need to be scrolled into view or I would have to scroll all elements into view as a precaution?
Thanks

Amazon product pages are quite complex, and include a lot of lazy-loaded images and other elements. It's likely that your element is growing in size because new content is being rendered lazily as you scroll down the page.
To answer your question, you will certainly need to scroll down the entire page and allow all elements to finish rendering if you want completely accurate dimensions.

Related

How check that there was scrolling action to element into view?

Is there a way to check that after some manipulations on page, browser scroll into view an Element? And returns true or false after it. Maybe
with JavaScriptExecutor we can do this
And words, I want to check the fact of scrolling
Follow this steps to scroll as you wanted:
Make screenshot in current state
Scroll page by js to Up position
Make screenshot again in Up state
Diff two screenshots
If you want to now is element visible on page (in browser after some scroll) you can:
Get element position on page (in pxls): x, y, height_x, weight_y
Get page screenshot
Get element screenshot
Cut page screenshot to rectangle image (by element coordinates, step1)
Diff element screenshot and rectangle image
In both ways steps 1-3 is simple selenium web-driver actions(I can illustrated on java only). For diff images recommend to use imageMagic
Use the Displayed property
element.Displayed;
Will return true or false.

how to detect visible (in view) element using javascript

I have a div (#diagram) larger than the actual visible area in my browser. #diagram contains up to 1500 "boxes" (other div elements) and I would like to know which of these 1500 boxes are actually really visible to the user so that I can populate them using ajax when they come into view. I actually do have some working code but that goes through all elements triggered by the onscroll() event. This works so so in Chrome but of course my client HAS to use the evil browser IE8 where the looping of all elements upon scrolling completely forces my application on its knees.
Is there some sort of event that is fired when an element comes into view or any other option to detect "true" visibility?
Environment: jQuery/jQueryUI (latest), Internet Explorer 8
Thanks in advance :-)
./cj
What if you go through all your boxes just once when they have been rendered and group them into "pages" - collections of references to DOM divs that are visible between [y1, y2] vertical coordinates of your parent div. You'll have <total height of parent div> / <visible height of parent div> pages.
You preload content of the 1st page, and then on each scroll event you'd check if content for the next page of boxes should be loaded.
Refer -
Element ‘in view’ Event Plugin
When the window is scrolled, the event checks the position of the elements against the viewport height and the scrollTop position.
And
Lazy Load Plugin
Lazy Load is a jQuery plugin written in JavaScript. It delays loading of images in long web pages. Images outside of viewport (visible part of web page) wont be loaded before user scrolls to them

Why sometime scrollTop/scrollLeft not writable?

I'm using dhtmlx Gantt Chart UI component which have task list and graphical chart. Task list and graphical chart are contained in two separate div element which synchronized for parallel scrolling. By scrolling the chart area, task list is automatically scrolled resulting the task row position matches the Gantt line position.
Inspecting the component source code, I found the sync is implemented by the following code :
this.oData.onscroll = function() {
self.panelTime.scrollLeft = this.scrollLeft;
self.panelNames.scrollTop = this.scrollTop;
};
All HTML markup in the UI control are generated dynamically by JavaScript. All is working well except it takes too long time to render 800-ish task list.
To improve rendering time, I decide to built my own server side rendering module to generate the HTML markup identical with that originally generated client side. This markup is fetched from client side using ordinary jquery $.get() and injected to page using $(el).html(). Then I put the necessary event handler as the original client side version.
The problem now is parallel scrolling doesn't work. I could capture the scroll event on the chart area, but I couldn't set the scrollTop property of the task list area. I test in firebug to manually force the scrollTop property, but the value didn't change. It seems that scrollTop property is read-only.
Is there any explanation for this ?
You can't scroll down below the bottom (or past the right) of the element's contents. If the element has overflow: visible (the default), or is at least as large as its contents, then both scroll properties will be stuck at 0. Similarly, even if there is something hidden to scroll into view, then you won't be able to scroll past the end; if you set the scrollTop or scrollLeft to a larger value than makes sense, it will decrease to the largest value that makes sense.
My guess is in your case you're trying to scroll the div before its content is loaded, and it's refusing to scroll because there isn't anything to scroll into view.

How do I get the visual size of visible DOM elements on a web page

I am trying to write an algorithm that tries to segment a webpage into its components such as footer, header, main content area based on the spacial organization of the page.
What I plan on doing is to:
First render the page using a web browser (say Firefox).
Then inspect the DOM model produced by the browser
From the DOM model I'd like to get the following:
a. Size of the element (height, width) (I'd like the actual size - not just what is in the style says)
b. Placement of the element on the web page
c. Z-index of the element.
For the purposes of this question -- I'd appreciate help with: 3.a and 3.b
Thanks.
offsetWidth\offsetHeight is what you want for getting element dimensions:
https://developer.mozilla.org/en/DOM/element.offsetWidth
offsetTop\offsetRight is likely what you want to find location of objects:
http://www.quirksmode.org/js/findpos.html
It depends on the browser. This table shows the methods across browsers:
http://www.csscripting.com/css-multi-column/dom-width-height.php
But if you're just using Firefox than you use Firefox handling code / Javascript. You could also look into the source code of Firebug and see how it calculates width / height / z-index.
I think what you want is: offsetWidth, offsetHeight, offsetTop, and offsetLeft.

innerHTML manipulation in JavaScript

I am developing a web page code, which fetches dynamically the content from the server and then places this content to container nodes using something like
container.innerHTML = content;
Sometimes I have to overwrite some previous content in this node. This works fine, until it happens that previous content occupied more vertical space then a new one would occupy AND a user scrolled the page down -- scrolled more than new content would allow, provided its height.
In this case the page redraws incorrectly -- some artifacts of the old content remain. It works fine, and it is even possible to get rid of artifacts, by minimizing and restoring the browser (or force the window to be redrawn in an other way), however this does not seem very convenient.
I am testing this only under Safari (this is a iPhone-optimized website).
Does anybody have the idea how to deal with this?
The easiest solution that I have found would be to place an anchor tag <a> at the top of the div you are editing:
<a name="ajax-div"></a>
Then when you change the content of the div, you can do this to have the browser jump to your anchor tag:
location.hash = 'ajax-div';
Use this to make sure the user isn't scrolled down too far when you update the content and you shouldn't get the issue in the first place.
(tested in the latest FF beta and latest safari)
It sounds like the webkit rendering engine of Safari is not at first recognizing the content change, at least not fully enough to remove the previous html content. Minimizing and then restoring the windows initiates a redraw event in the browser's rendering engine.
I think I would explore 2 avenues: first could I use an iframe instead of the current 'content' node? Browsers expect IFrames to change, however as you're seeing they're not always so good at changing content of DIV or other elements.
Secondly, perhaps by modifying the scroll position as suggested earlier. You could simply move the scroll back to 0 as suggested or if that is to obtrusive you could try to restore the scroll after the content change. Subtract the height of the old content node from the current scroll position (reseting the browser's scroll to the content node's 0), change the node content, then add the new node's height to the scroll position.
Palehorse is right though (I can't vote his answer up at the moment - no points) an abstraction library like jQuery, Dojo, or even Prototype can often help with these matters. Especially if you see your page / site moving beyond simple DOM manipulation you'll find the tools and enhancements provided by libraries to be a huge help.
It sounds like you are having a problem with the browser itself. Does this problem only occur in one browser?
One thing you might try is using a lightweight library like jQuery. It handles browser differences fairly nicely. To set the inner HTML for a div with the ID of container you would simply write this:
$('#container').html( content );
That will work in most browsers. I do not know if it will fix your problem specifically or not but it may be worth a try.
Would it work to set the scroll position back to the top (element.scrollTop = 0; element.scrollLeft = 0; by heart) before replacing the content?
Set the element's CSS height to 'auto' every time you update innerHTML.
I would try doing container.innerHTML = ''; container.innerHTML = content;

Categories