You could acquire the element's position and size as well as the window's current X/Y offsets (position) and size to determine whether or not the element is completely in view.
With this information, you can conclude that, in order for the element to be completely within the window, the following must be true:
- The window's left bound must be less than or equal to the element's left bound
- The window's right bound must be greater than or equal to the element's right bound
- The window's top bound must be less than or equal to the element's top bound.
- The window's bottom bound must greater than or equal to the element's bottom bound.
First, get the element's location and size. The location
property will give you the coordinates of the top-left corner of the element in the canvas. The size
property will give you the width and height of the element.
elem = driver.find_element_by_id('square100x100')
elem_left_bound = elem.location.get('x')
elem_top_bound = elem.location.get('y')
elem_width = elem.size.get('width')
elem_height = elem.size.get('height')
You can determine if the current window view meets this criteria by getting the X/Y offsets (position) and the size of the window.
You can get the offsets by executing some javascript. The following should work for all compliant browsers. I personally tested in Chrome, Firefox, and Safari. I know IE will probably need a little massaging.
win_upper_bound = driver.execute_script('return window.pageYOffset')
win_left_bound = driver.execute_script('return window.pageXOffset')
win_width = driver.execute_script('return document.documentElement.clientWidth')
win_height = driver.execute_script('return document.documentElement.clientHeight')
With the above, we've determined the size and position of the element as well as the size and position of the viewing window. From this data, we can now do some calculations to tell if the element is in view.
def element_completely_viewable(driver, elem):
elem_left_bound = elem.location.get('x')
elem_top_bound = elem.location.get('y')
elem_width = elem.size.get('width')
elem_height = elem.size.get('height')
elem_right_bound = elem_left_bound + elem_width
elem_lower_bound = elem_top_bound + elem_height
win_upper_bound = driver.execute_script('return window.pageYOffset')
win_left_bound = driver.execute_script('return window.pageXOffset')
win_width = driver.execute_script('return document.documentElement.clientWidth')
win_height = driver.execute_script('return document.documentElement.clientHeight')
win_right_bound = win_left_bound + win_width
win_lower_bound = win_upper_bound + win_height
return all((win_left_bound <= elem_left_bound,
win_right_bound >= elem_right_bound,
win_upper_bound <= elem_top_bound,
win_lower_bound >= elem_lower_bound)
)
This will also include padding and borders on an element, but not margins. If you want margins to be factored in, you'll want to get the value of the relevant CSS properties.
Additionally, you may want to check other things like opacity, whether it's displayed, z-index, etc.