26

Set-up

I'm using Python 3.x and Selenium to fill out a query field and subsequently click the search button,

# element containing the product search bar and buttons
search_area = el_id('Products').find_element_by_class_name('searchArea')

# insert name of file to be duplicated
name_field = search_area.find_element_by_xpath("//input[@type='text']")
name_field.clear()
name_field.send_keys('to_be_duplicated')  

# click search button
search_area.find_element_by_xpath('span/a[1]').click()

where el_id(x) = browser.find_element_by_id(x).


Problem

Executing the code above gives the following error,

ElementClickInterceptedException: Element <a class="button button-fleft searchButton" href="#"> is not clickable at point (577.6166763305664,225.06666564941406) because another element <div class="blockUI blockOverlay"> obscures it

I can solve this error by inserting a hard wait before grabbing and clicking the button, like so,

# click search button
time.sleep(1)
search_area.find_element_by_xpath('span/a[1]').click()

But I rather solve it differently, so I followed this answer and did the following,

# click search button
search_button = search_area.find_element_by_xpath('span/a[1]')
WebDriverWait(driver, 10).until_not(EC.visibility_of_element_located((By.XPATH, 
"//*[@id="Products"]/tbody/tr[1]/td/div/input")))
search_button.click()

But I got exactly the same error.

I also tried this answer, but same error.

How do I solve this?

LucSpan
  • 1,831
  • 6
  • 31
  • 66
  • Please provide a [mcve] – Pitto Apr 19 '18 at 12:31
  • Possible duplicate of [Element MyElement is not clickable at point (x, y)... Other element would receive the click](https://stackoverflow.com/questions/44724185/element-myelement-is-not-clickable-at-point-x-y-other-element-would-receiv) – undetected Selenium Apr 19 '18 at 12:35
  • 1
    Thanks DebanjanB! In the end nr.5 did it! `wait.until(EC.invisibility_of_element_located((By.XPATH, "//div[@class='blockUI blockOverlay']")))` and then `el_xp("//input[@value='Save']").click()`. – LucSpan Apr 20 '18 at 10:37

4 Answers4

10

There are several ways to do this, one of the ways is by Javascript executor.

You could say:

element = driver.find_element_by_xpath("//div[@class='blockUI blockOverlay']")

driver.execute_script("arguments[0].style.visibility='hidden'", element)

This way, you can block the div with class = 'blockUI blockOverlay' and your element can be clicked if I'm correct.

Anand
  • 1,899
  • 1
  • 13
  • 23
9

Following nr.5 of DebanjanB's answer, I solved it by implying the code to wait for the temporary overlay to dissapear before trying to click,

wait.until(EC.invisibility_of_element_located((By.XPATH,
              "//div[@class='blockUI blockOverlay']")))
el_xp("//input[@value='Save']").click()
LucSpan
  • 1,831
  • 6
  • 31
  • 66
  • 2
    How can you detect the xpath of the temporary overlay? I tried to detect it on Chrome Dev Tool, but since it disappears quickly I could not know the xpath. – Blaszard May 24 '19 at 20:44
  • 1
    I tried that. Waiting for it to disappear. It finished saying it had disappeared, but I still got the error afterwards when trying to click. – Tony Jul 29 '19 at 18:43
  • In my case, the overlay is an ad and its not temporary, it never disappears. – fragg May 06 '22 at 14:00
  • Tried this, but did not work. The overlay slides out for about two seconds. – George Smith Aug 02 '23 at 18:40
5

Also, you can try to click the element by JavaScript like this:


# element containing the product search bar and buttons
search_area = el_id('Products').find_element_by_class_name('searchArea')

# click element by executing javascript
driver.execute_script("arguments[0].click();", search_area)

Thai Boy
  • 141
  • 2
  • 5
  • It working in my case, I think because of call click() in element will do some thing like "virtual click" with (x,y) position, but with call click() use execute_script will some how call directly to this element's script – dellos Dec 13 '20 at 11:23
4

The accepted answer expects that you know, which element will be used as an overlay. If this expectation is not true (as mentioned by @Blaszard in comment under accepted answer), then you can use this generic function to get any element which is displayed above another element:

def getOverlappingElement(driver: WebDriver, element: WebElement) -> Optional[WebElement]:
  rect = element.rect
  result = driver.execute_script("return document.elementFromPoint(arguments[0], arguments[1]);",
                                 rect['x'] + rect['width'] // 2, rect['y'] + rect['height'] // 2)
  if result == element:
    result = None
  return result

When you call the function like getOverlappingElement(driver, button) then it will return the element which is displayed above button or it returns None, when the button is not overlapped.

This method does not cover cases when the element is partially overlapped. For most cases, when whole page is overlapped by loading animation or by advertisement, it works.

eNca
  • 1,043
  • 11
  • 21