在JavaScript中,您如何检查元素是否实际可见?
我的意思不仅仅是检查visibility
和display
属性。我的意思是,检查元素是不是
visibility: hidden
或display: none
由于技术原因,我不能包含任何脚本。但是我可以在页面上使用Prototype。
答案 0 :(得分:93)
第2点。
我发现没有人建议使用document.elementFromPoint(x,y)
,对我来说,这是测试一个元素是否被另一个元素嵌套或隐藏的最快方法。您可以将目标元素的偏移量传递给函数。
这是elementFromPoint上的PPK测试页面。
答案 1 :(得分:38)
我不知道在旧的或不那么现代的浏览器中支持多少,但我使用的是这样的东西(没有任何库的neeed):
function visible(element) {
if (element.offsetWidth === 0 || element.offsetHeight === 0) return false;
var height = document.documentElement.clientHeight,
rects = element.getClientRects(),
on_top = function(r) {
var x = (r.left + r.right)/2, y = (r.top + r.bottom)/2;
return document.elementFromPoint(x, y) === element;
};
for (var i = 0, l = rects.length; i < l; i++) {
var r = rects[i],
in_viewport = r.top > 0 ? r.top <= height : (r.bottom > 0 && r.bottom <= height);
if (in_viewport && on_top(r)) return true;
}
return false;
}
它检查元素是否具有区域&gt; 0然后它检查元素的任何部分是否在视口内并且它没有隐藏在“另一个元素”下面(实际上我只检查元素中心的单个点,所以它不是100%保证 - 但你可以修改脚本来迭代元素的所有点,如果你真的需要......)。
更新
修改了检查每个像素的on_top函数:
on_top = function(r) {
for (var x = Math.floor(r.left), x_max = Math.ceil(r.right); x <= x_max; x++)
for (var y = Math.floor(r.top), y_max = Math.ceil(r.bottom); y <= y_max; y++) {
if (document.elementFromPoint(x, y) === element) return true;
}
return false;
};
不了解表现:)
答案 2 :(得分:8)
正如jkl指出的那样,检查元素的可见性或显示是不够的。你必须检查它的祖先。 Selenium在验证元素的可见性时执行此操作。
查看selenium-api.js文件中的Selenium.prototype.isVisible方法。
http://svn.openqa.org/svn/selenium-on-rails/selenium-on-rails/selenium-core/scripts/selenium-api.js
答案 3 :(得分:4)
这是我到目前为止所拥有的。它涵盖了1和3.我仍然在努力2,因为我不熟悉Prototype(我更像是jQuery类型的人)。
function isVisible( elem ) {
var $elem = $(elem);
// First check if elem is hidden through css as this is not very costly:
if ($elem.getStyle('display') == 'none' || $elem.getStyle('visibility') == 'hidden' ) {
//elem is set through CSS stylesheet or inline to invisible
return false;
}
//Now check for the elem being outside of the viewport
var $elemOffset = $elem.viewportOffset();
if ($elemOffset.left < 0 || $elemOffset.top < 0) {
//elem is left of or above viewport
return false;
}
var vp = document.viewport.getDimensions();
if ($elemOffset.left > vp.width || $elemOffset.top > vp.height) {
//elem is below or right of vp
return false;
}
//Now check for elements positioned on top:
//TODO: Build check for this using Prototype...
//Neither of these was true, so the elem was visible:
return true;
}
答案 4 :(得分:4)
有趣的问题。
这将是我的方法。
希望它有所帮助。
答案 5 :(得分:3)
Prototype的Element library是方法方面最强大的查询库之一。我建议你查看API。
一些提示:
检查可见性可能很麻烦,但您可以将Element.getStyle()
方法和Element.visible()
方法结合到自定义函数中。使用getStyle()
,您可以检查实际的计算样式。
我不知道你的意思是什么“下面”:)如果你的意思是它有一个特定的祖先,例如一个包装div,你可以使用Element.up(cssRule)
:
var child = $("myparagraph");
if(!child.up("mywrapper")){
// I lost my mom!
}
else {
// I found my mom!
}
如果你想检查子元素的兄弟元素,你也可以这样做:
var child = $("myparagraph");
if(!child.previous("mywrapper")){
// I lost my bro!
}
else {
// I found my bro!
}
同样,如果我理解正确你的意思,Element lib可以帮助你:)你可以检查实际的dimensions of the viewport和offset of your element,这样你就可以计算你的元素是否“屏幕外” ”
我在http://gist.github.com/117125粘贴了prototypejs的测试用例。在您的情况下,我们根本无法信任getStyle()
。为了最大化isMyElementReallyVisible函数的可靠性,您应该结合以下内容:
答案 6 :(得分:2)
一种方法是:
isVisible(elm) {
while(elm.tagName != 'BODY') {
if(!$(elm).visible()) return false;
elm = elm.parentNode;
}
return true;
}
致谢:https://github.com/atetlaw/Really-Easy-Field-Validation/blob/master/validation.js#L178
答案 7 :(得分:1)
捕获鼠标拖动和视口事件(onmouseup,onresize,onscroll)。
当拖动结束时,将拖动的项目边界与所有“感兴趣的元素”(即具有“dont_hide”类或“数组”的元素)进行比较。使用window.onscroll和window.onresize执行相同的操作。标记用特殊属性或类名隐藏的任何元素,或者只是执行您想要的任何操作。
隐藏的测试非常简单。对于“完全隐藏”,您想要知道所有角落是在拖动项目边界内还是在视口外部。对于部分隐藏,您正在寻找匹配相同测试的单个角落。
答案 8 :(得分:1)
我讨厌将你重定向到jQuery(就像经常做的那样),but this discussion关于元素何时真正可见是非常有见地的。
答案 9 :(得分:1)
即使您使用currentStyle / getComputedStyle,我也不认为检查元素自身的可见性和显示属性对于需求#1是否足够好。你还必须检查元素的祖先。如果隐藏了一个祖先,那么该元素也是如此。
答案 10 :(得分:0)
检查元素的offsetHeight属性。如果它大于0,则可见。注意:此方法不包括可见性:隐藏样式设置的情况。但这种风格无论如何都是奇怪的。
答案 11 :(得分:0)
这是一个示例脚本和测试用例。包含定位元素,可见性:隐藏,显示:无。不要测试z-index,假设它有效。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<style type="text/css">
div {
width: 200px;
border: 1px solid red;
}
p {
border: 2px solid green;
}
.r {
border: 1px solid #BB3333;
background: #EE9999;
position: relative;
top: -50px;
height: 2em;
}
.of {
overflow: hidden;
height: 2em;
word-wrap: none;
}
.of p {
width: 100%;
}
.of pre {
display: inline;
}
.iv {
visibility: hidden;
}
.dn {
display: none;
}
</style>
<script src="http://www.prototypejs.org/assets/2008/9/29/prototype-1.6.0.3.js"></script>
<script>
function isVisible(elem){
if (Element.getStyle(elem, 'visibility') == 'hidden' || Element.getStyle(elem, 'display') == 'none') {
return false;
}
var topx, topy, botx, boty;
var offset = Element.positionedOffset(elem);
topx = offset.left;
topy = offset.top;
botx = Element.getWidth(elem) + topx;
boty = Element.getHeight(elem) + topy;
var v = false;
for (var x = topx; x <= botx; x++) {
for(var y = topy; y <= boty; y++) {
if (document.elementFromPoint(x,y) == elem) {
// item is visible
v = true;
break;
}
}
if (v == true) {
break;
}
}
return v;
}
window.onload=function() {
var es = Element.descendants('body');
for (var i = 0; i < es.length; i++ ) {
if (!isVisible(es[i])) {
alert(es[i].tagName);
}
}
}
</script>
</head>
<body id='body'>
<div class="s"><p>This is text</p><p>More text</p></div>
<div class="r">This is relative</div>
<div class="of"><p>This is too wide...</p><pre>hidden</pre>
<div class="iv">This is invisible</div>
<div class="dn">This is display none</div>
</body>
</html>
答案 12 :(得分:0)
/**
* Checks display and visibility of elements and it's parents
* @param DomElement el
* @param boolean isDeep Watch parents? Default is true
* @return {Boolean}
*
* @author Oleksandr Knyga <oleksandrknyga@gmail.com>
*/
function isVisible(el, isDeep) {
var elIsVisible = true;
if("undefined" === typeof isDeep) {
isDeep = true;
}
elIsVisible = elIsVisible && el.offsetWidth > 0 && el.offsetHeight > 0;
if(isDeep && elIsVisible) {
while('BODY' != el.tagName && elIsVisible) {
elIsVisible = elIsVisible && 'hidden' != window.getComputedStyle(el).visibility;
el = el.parentElement;
}
}
return elIsVisible;
}
答案 13 :(得分:0)
您可以使用clientHeight或clientWidth属性
function isViewable(element){
return (element.clientHeight > 0);
}
答案 14 :(得分:0)
试试element.getBoundingClientRect()
。
它将返回一个具有属性
检查元素BoundingClientRect
的宽度和高度是否为零,这是隐藏或不可见元素的值。如果值大于零,则元素应在主体中可见。然后检查bottom
属性是否小于screen.height
,这意味着元素正在使用视口。 (从技术上讲,您还必须考虑浏览器窗口的顶部,包括搜索栏,按钮等。)
答案 15 :(得分:-1)
如果你仍然可以使用原型(prototypejs),第一点的答案很简单:
$('HtmlElementID').visible(); returns: true|false
答案 16 :(得分:-2)
以下是响应的一部分,它告诉您元素是否在视口中。 您可能需要使用elementFromPoint检查其上是否有任何内容,但它的时间会更长。
function isInViewport(element) {
var rect = element.getBoundingClientRect();
var windowHeight = window.innerHeight || document.documentElement.clientHeight;
var windowWidth = window.innerWidth || document.documentElement.clientWidth;
return rect.bottom > 0 && rect.top < windowHeight && rect.right > 0 && rect.left < windowWidth;
}