elementFromPoint() under iOS 5

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
 

The JavaScript call elementFromPoint(x,y) can be used to find the element of a web page at a certain coordinate. If you have used this call in the past on a web page or in a native iOS App which was developed for iOS 4.x or older, you’ll notice that your web page or App might fail when used under iOS 5. Under iOS 5 the elementFromPoint(x,y) call finds different elements or even returns null instead of an element. It looks like the call is now broken. But this is not the case, in fact, under iOS 5 it works correct the first time, it was broken before.

elementFromPoint(x,y) was defined to return the element at the given coordinates within the view port (the visible area) of the web page, or null (if the coordinates are outside of the viewport). The coordinates are measured relative to the origin of the view port. This is how iOS 5 finally works.

Before (iOS 4.x and older), elementFromPoint(x,y) completely ignored the view port. It measured the coordinates relative to the origin of the document. And even elements outside of the visible area could be found. This behavior seems to make much more sense than the new iOS 5 behavior, but according to the official JavaScript specification, it’s not the correct behavior.

The different behavior between iOS 5 and older iOS versions can cause some serious problems. The coordinate systems are no longer compatible, so when the web page or App has to run under old an new iOS versions, it is necessary to find out the correct coordinate system that is used.

In a native iOS App you could simply check the iOS version, and based on its value you can decide which coordinate system you need to use when calling elementFromPoint(x,y). But when writing a web page, this is not so easy: the iOS version is not exposed to the web page (it might be part of the UserAgent information, but because almost all browser do allow to use a fake userAgent information, this information is not reliably at all). Also on the Mac and on other platforms different WebKit releases might be used which do use different coordinate systems for the elementFromPoint(x,y) call as well. Therefore it makes sense to find a way to identify the coordinate system independent of the iOS version, and if necessary correct the coordinates.

At first when we compare the two coordinate systems, we notice that the coordinates are offset by the scroll location. If we scroll the web page so that the top left corner of the page is visible, both coordinate systems are the same. The origin of the view port is identical to the origin of the web page. And the scroll offset is also 0 in both directions. If you scroll down 100 px, the origin (the coordinate (0,0)) of the viewport is located at the coordinate (0,100) of the web page. So the scroll offset is exactly the offset between the two coordinate systems. Therefore, transforming one coordinate system into the other is very easy. We only need to add or subtract the actual scroll offsets.

function documentCoordinateToViewportCoordinate(x,y) {
  var coord = new Object();
  coord.x = x - window.pageXOffset;
  coord.y = y - window.pageYOffset;
  return coord;
}

function viewportCoordinateToDocumentCoordinate(x,y) {
  var coord = new Object();
  coord.x = x + window.pageXOffset;
  coord.y = y + window.pageYOffset;
  return coord;
}

These JavaScript functions take a coordinate of one system and transform them into a coordinate of the other system.

But in order find out if and which of the functions we need to use, we have to find out, in which coordinate system the call elementFromPoint(x,y) expects the coordinates. To do this we use the fact that elementFromPoint() returns null when the coordinates are outside of the view port, when it expects coordinates measured relative to the viewport (as noted above, when the coordinates are relative to the origin of the document, elementFromPoint() will always return an element, even when outside of the visible area, so we can distinguish between the two cases).
Good test coordinates would be (0, window.pageYOffset + window.innerHeight -1) and (window.pageXOffset + window.innerWidth -1, 0), for vertical scrolling and horizontal scrolling. As noted above, when no scrolling is done, both coordinate systems are identical, and we don’t need to take care about anything. But if the page is scrolled, we need to check which system is used. The test coordinates take the actual scroll offset and add the width or height of the visible area (this is the innerWidth and innerHeight of the “window” object) and subtract 1. This makes sure that the coordinate addresses the very last pixel line or column of the visible area measured relative to the document origin. This is always a valid document-based coordinate which lies within the document boundaries (a coordinate outside of the document boundaries would return null even with the elementFromPoint() call for the document-based coordinate system). If the page is scrolled by at least one single pixel, the test coordinates would lie outside of the viewport, when interpreted as relative to the viewport, so elementFromPoint() would return null. When elementFromPoint() would interpret them relative to the document, these coordinates are always valid and would always return an element. And this is how we can easily detect, which coordinate system elementFromPoint() is using.

function elementFromPointIsUsingViewPortCoordinates() {
  if (window.pageYOffset > 0) {     // page scrolled down
    return (window.document.elementFromPoint(0, window.pageYOffset + window.innerHeight -1) == null);
  } else if (window.pageXOffset > 0) {   // page scrolled to the right
    return (window.document.elementFromPoint(window.pageXOffset + window.innerWidth -1, 0) == null);
  }
  return false; // no scrolling, don't care
}

We can combine this to one custom elementFromPoint() function that is using a document-based coordinate system as input and will internally do all the magic for us:

function elementFromDocumentPoint(x,y) {
  if (elementFromPointIsUsingViewPortCoordinates()) {
    var coord = documentCoordinateToViewportCoordinate(x,y);
    return window.document.elementFromPoint(coord.x,coord.y);
  } else {
    return window.document.elementFromPoint(x,y);
  }
}

And the counterpart for viewport-based coordinates:

function elementFromViewportPoint(x,y) {
  if (elementFromPointIsUsingViewPortCoordinates()) {
    return window.document.elementFromPoint(x,y);
  } else {
    var coord = viewportCoordinateToDocumentCoordinate(x,y);
    return window.document.elementFromPoint(coord.x,coord.y);
  }
}

So instead of using elementFromPoint() directly, you simply use elementFromViewportPoint() or elementFromDocumentPoint() instead, depending of the coordinates you have to deal with. It will then work correct in old and new WebKit releases.

Please note: if you use the code of my older blog post “Customize the contextual menu of UIWebView” in your projects, you need to update this as well, because it also uses the elementFromPoint() call. But this should be really easy to do.

Posted in iPhone & iPod Touch, Programming, Tips & tricks, Web Technology.

Tagged with Development, iOS, JavaScript, UIWebView, WebKit.

elementFromPoint的用法(详解) document.ElementFromPoint:根据坐标获得元素,可用于触屏设备上获取当前点击元素的名称 语法: oElement = document . elementFromPoint ( iX , iY ) 参数: iX :  必选项。整数(Integer)。单位:象素(Pixel)。定位横坐标偏移量。 iY :  必选项。整数(Integer)。单位:象素(Pixel)。定 阅读详情

相关推荐

elementFromPoint

在瀏覽器里,爲了獲取元素我們常常用下面幾個方法:document.getElementById(id) document.getElementsByName(name) document.getElementsByTagName(tagName) document.querySelector()有時,爲了獲取鼠標處的元素,我們得知道另一個方法:document.elementFromPoint(x,

Marshall001的博客 1536

DOM基础学习2

学习内容:密码输入的显示于隐藏练习,元素操作--修改样式属性,排他思想,自定义属性的操作,tab栏切换练习 学习笔记: 密码输入的显示于隐藏练习 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>document</title> <style> .box { position: relative; width:

qq_61718994的博客 932

document.elementFromPoint

先说一下这个方法的参数 elemntFromPoint(x,y);//传入坐标值,返回当前页面上包含该坐标点的顶层元素 注意2点,坐标值和顶层元素 先说坐标,因为不同的人理解是不一样的,也就造就了这个方法在不同的浏览器中表现是不一样的,所以在传入坐标时就分 整体页面坐标 和 可视区域坐标,我们看上篇文章中的图来理解下:中间的方块是可视区域...

weixin_33754913的博客 1545

chrome elementFromPoint 获取屏幕指定位置的元素

原文链接: chrome elementFromPoint 获取屏幕指定位置的元素 ...

阿豪 591

每天记录一点新遇到的浏览器方法和属性

问题1:document的elementFromPoint方法 这个方法可以根据坐标的点来获取元素,不过是获取最上层的元素,而且浏览器兼容也是需要考虑的,因为不同的浏览器传入的参数有可能是clientx,也有可能是pagex。下面的代码就可以实现这个功能。 function init() { document.onclick = getElement; writeroot = docu

高山上的鱼 1012

JavaScript中的坐标

在我们的日常生活中,JavaScript已经成为了一种无处不在的编程语言。它的应用范围从简单的网页动画,到复杂的前端框架,再到后端的Node.js,甚至还包括物联网设备。然而,JavaScript并非一成不变,它一直在发展,一直在添加新的特性和功能。今天,我们将探讨JavaScript中的一个重要的概念:坐标。在这篇文章中,我们将详细介绍坐标,包括它的定义、使用方法,以及如何在不支持坐标的浏览器中进行polyfill。​。

爱蹦跶的全栈大A阿 1671

Js——elementFromPoint方法

src:http://www.aspxuexi.com/html/dhtml/2007-8-30/elementFromPoint.htm 语法: oElement = document . elementFromPoint ( iX , iY ) 参数: iX :  必选项。整数(Integer)。单位:象素(Pixel)。定位横坐标偏移量。 iY :  必选项。整数(Inte...

weixin_30794499的博客 440

js获取点击<li>标签里的内容值的两种方法

第一种方法:使用elementFromPoint获取鼠标点击内容 第二种方法:使用this 例子如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Demo</title> </head> <body> <div class = "pic"> <div class="ul"> <ul id= ..

寒池鹤影 7318

JS_x,y坐标模拟点击

【代码】JS_x,y坐标模拟点击。

小歪博客 858

JavaScript

js 常用内置方法

码刀攻城 333

水印兼容ie7,解决水印覆盖控件问题,解决ie7的pointer-events: none无效问题

解决因pointer-events: none无效从而出现的覆盖问题的方案是:先隐藏忽略水印容器,根据点击事件拿到点击位置,找到相同位置下的元素,并主动触发该元素的点击事件,最后重新显示水印容器。

qq_44883447的博客 747

dom对html增删改操作,【DOM】DOM的操作(增删改查)

操作DOM的核心就是增删改查参考:目录一、节点创建型API1.1 createElement1.2 createTextNode1.3 cloneNode1.4 createDocumentFragment二、页面修改形API(包括删除和添加)(删)(改)2.1 appendChild(追加为子元素)2.2 insertBefore(插入前面)2.3 removeChild(删除子元素)2.4 r...

weixin_30896727的博客 457

根据鼠标坐标取该坐标下的元素,包括touch

根据坐标获取元素的方法: document.elementFromPoint(pageX,pageY); 或者 document.elementFromPoint(clientX,clientY); 如果是pc浏览器监听鼠标事件,可以一直使用event对象获取坐标值 如果是平板,监听的是touchstart, touchmove, touchend三个事件需要注意,不

javakeffer的专栏 478

解决Selenium元素拖拽不生效Bug

如果你是使用Python+Selenium技术栈实现的Web UI自动化,可以直接下载seletools(Selenium Tools,作者:Dmitrii Bormotov)包,并将它导入到需要执行拖放的地方,然后简单地调用它的drag_and_drop()方法即可。方案3:先通过clickAndHold()方法点击并按住元素,然后使用moveByOffset()方法将元素拖拽到目标区域,再使用release()方法将按住的元素释放——无效。方案5:借助Robot类实现拖拽——无效。

主要分享测试的学习资源,帮助快速了解测试行业,帮助想转行、进阶、小白成长为高级测试工程师。 2003

js 获取坐标下元素elementFromPoint

//考虑滚动条 及iframe     function GetDomByPosition(x,y) {     var sx =document.documentElement.scrollLeft;     var sy =document.documentElement.scrollTop;     var  dom =  document.elementFromPoint(x-sx...

2098

javascript技巧参考

事件源对象 捕获释放 event.srcElement.setCapture();  event.srcElement.releaseCapture();  事件按键 event.keyCode event.shiftKey event.altKey event.ctrlKey 事件返回值 event.returnValue 鼠标

johnnyjiang的专栏 625

[J]常用的JavaScript片段整理

事件源对象 event.srcElement.tagName event.srcElement.type 捕获释放 event.srcElement.setCapture();  event.srcElement.releaseCapture();  事件按键 event.keyCode event.shiftKey event.altKey event.ctrlKey 事件返回值 e

DeckCain 874

JavaScript经典

 JavaScript经典Event 事件事件源对象event.srcElement.tagNameevent.srcElement.type捕获释放event.srcElement.setCapture();event.srcElement.releaseCapture();事件按键event.keyCodeevent.shiftKeyevent.

windy317的专栏 326

[ 前端 ] 移动端填坑

1 IOS 表单元素点击自带背景阴影最近一直做移动端前端开发,发现一个神奇的东西,对于IOS下的,input或者label元素, 点击之后,总是会出现一个背景阴影的现象。

杨有梦的博客 636
上一篇: 关于bundle id的一些说法
下一篇: WebKit on the iPhone (Part 1)
xdonx
博客等级 码龄19年 102粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值