/* Siesta 5.1.0 Copyright(c) 2009-2018 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ /** @class Siesta.Test.Browser.Role.CanGetElementFromPoint */ Role('Siesta.Test.Browser.Role.CanGetElementFromPoint', { requires : [ '$' ], does : [ Siesta.Util.Role.CanCalculatePageScroll ], has : { }, methods : { /** * This method will return the top-most DOM element at the specified coordinates from the test page. If * the resulting element is an iframe and `shallow` argument is not passed as `true` * it'll query the iframe for its element from the local point inside it. * * @param {Number} x The X coordinate, relative to the viewport area (currently visible part of the page) * @param {Number} y The Y coordinate, relative to the viewport area (currently visible part of the page) * @param {Boolean} [shallow] Pass `true` to _not_ check the nested iframe if element at original coordinates is an iframe. * * @return {HTMLElement} The top-most element at the specified position on the test page */ elementFromPoint : function (viewportX, viewportY, shallow, fallbackEl, fullInfo) { var document = this.global.document; var el = document.elementFromPoint(viewportX, viewportY) // trying 2nd time if 1st attempt failed and returned null // this weird thing seems to be required sometimes for IE8 and may be for IE10 if (!el) el = document.elementFromPoint(viewportX, viewportY) // final fallback to the provided element or to the <body> element el = el || fallbackEl || document.body; var localX = viewportX var localY = viewportY // If we found IFRAME and its not a `shallow` request, try to dig deeper if (el && el.nodeName.toUpperCase() == 'IFRAME' && !shallow) { // if found iframe is loaded from different domain // just accessing its "el.contentWindow.document" property will throw exception try { var iframeDoc = el.contentWindow.document; var offsetsToTop = this.$(el).offset(); localX = viewportX - this.pageXtoViewportX(offsetsToTop.left) localY = viewportY - this.pageYtoViewportY(offsetsToTop.top) var resolvedEl = iframeDoc.elementFromPoint(localX, localY) // again weird 2nd attempt for IE if (!resolvedEl) resolvedEl = iframeDoc.elementFromPoint(localX, localY) resolvedEl = resolvedEl || iframeDoc.body; // Chrome reports 'HTML' in nested document.elementFromPoint calls which makes no sense if (resolvedEl.nodeName.toUpperCase() === 'HTML') resolvedEl = iframeDoc.body; el = resolvedEl; } catch (e) { // digging deeper failed, restore the local coordinates localX = viewportX localY = viewportY } } return fullInfo ? { el : el, // viewport coords in the inner frame localXY : [ localX, localY ], // viewport coords in the top frame (seems not needed, as just the input values are reused) globalXY : [ viewportX, viewportY ] } : el } } });