Reputation: 183
I am trying to only click on elements that would actually be visible to a user, i.e. don't click on elements outside the where I am currently scrolled to on a website.
I manage to detect all the ones that are hidden, but how to get a list of only elements a normal user would be able to see.
Upvotes: 0
Views: 3309
Reputation: 5647
If I right understand you, you are locating a bunch of elements like this:
elements = driver.find_elements_by_xpath("//a")
it will give you a list of elements. Some of this elements are visible, some of them not. To prove it you can use this:
for element in elements:
print(element.is_displayed()) # prints true if displayed, otherwise false
Try this code snippet:
driver = webdriver.Chrome("C:\\path\\to\\chromedriver.exe")
url = "https://stackoverflow.com/"
driver.get(url)
elements = driver.find_elements_by_xpath("//a") # finds all elements by given xPath
for element in elements: # for every element in elements list
print(element.is_displayed()) # print 'true' if displayed, or 'false' if not
print("DONE")
Output:
False
True
False
True
True
True
True
True
True
False
False
False
False
...
DONE
NOTE: it is only an example, normally you have to wait until the page fully loads to locate all elements correctly and also get the correct state of them.
EDIT: I have found a nice solution in this question and the sample code in this case would be like this:
driver = webdriver.Chrome("C:\\path\\to\\chromedriver.exe")
url = "https://stackoverflow.com/"
driver.get(url)
time.sleep(3)
elements = driver.find_elements_by_xpath("//span")
def element_in_viewport(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)
)
for element in elements:
print(element_in_viewport(driver, element))
print("DONE")
Output:
True
True
True
True
True
True
True
True
True
True
True
True
True
False
True
True
True
True
False
False
False
False
False
False
False
...
DONE
In my perspective this code snippet works good.
Upvotes: 2