Reputation: 229
I have a problem that I want to detect if an element is covered by another one in one page.
eg:
DOM elements
<div class="ele ele1"><p>A</p></div>
<div class="ele ele2"><p>B</p></div>
<div class="ele ele3"><p>C</p></div>
<div class="cover"><p>D</p></div>
CSS style
.ele{
display: inline-block;
width: 100px;
height: 100px;
position: relative;
}
p{
width: 100%;
text-align: center;
}
.ele1{
background-color: red;
}
.ele2{
background-color: blue;
}
.ele3{
background-color: green;
}
.cover{
position: absolute;
width: 100px;
height: 100px;
left: 300px;
top: 10px;
background: grey;
}
http://jsfiddle.net/veraWei/6v89b1fy/
How to detect element A is not been covered but element C is covered by ele D? One more thing: the number of "D" is uncertain. Maybe there are E/F/G... in the page. I appreciate all the thoughts or existing examples/jQuery plugins/CSS/etc.
Thanks all your guys' detailed answers. But I need more shortly explanation maybe one attribute that indicate that A is not covered by any elements and C is covered by rendering. Is there any plugin or attribute existing?
Upvotes: 22
Views: 23933
Reputation: 8181
Here is a quick example of how you may go about doing it. This would check for both vertical and horizontal overlapping. This is kind of generic and not-so-generic as well since this is based off the HTML in your question. Adjust the top/left values of the .cover
to see it work for all possible cases.
var $cover = $(".cover"),
cWidth = $cover.width(),
cHeight = $cover.height(),
cLeft = $cover.offset().left,
cRight = $(window).width() - (cLeft + cWidth),
cTop = $cover.offset().top,
cBtm = $(window).height() - (cTop + cHeight);
$("div:not(.cover)").each(function() {
var $this = $(this),
eleWidth = $this.width(),
eleHeight = $this.height(),
eleLeft = $this.offset().left,
eleTop = $this.offset().top,
eleRight = $(window).width() - (eleLeft + eleWidth),
eleBtm = $(window).height() - (eleTop + eleHeight);
if (
cLeft < (eleLeft + eleWidth) &&
cRight < (eleRight + eleWidth) &&
cTop < (eleTop + eleHeight) &&
cBtm < (eleBtm + eleHeight)
) {
alert($this.text() + " is covered by " + $cover.text());
}
});
.ele {
display: inline-block;
width: 100px;
height: 100px;
position: relative;
margin-top: 40px;
}
p {
width: 100%;
text-align: center;
}
.ele1 {
background-color: red;
}
.ele2 {
background-color: blue;
}
.ele3 {
background-color: green;
}
.cover {
position: absolute;
width: 100px;
height: 100px;
left: 60px;
top: 110px;
background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ele ele1">
<p>A</p>
</div>
<div class="ele ele2">
<p>B</p>
</div>
<div class="ele ele3">
<p>C</p>
</div>
<div class="ele ele3">
<p>D</p>
</div>
<div class="ele ele3">
<p>E</p>
</div>
<div class="ele ele3">
<p>F</p>
</div>
<div class="ele ele3">
<p>G</p>
</div>
<div class="cover">
<p>COVER</p>
</div>
Upvotes: 3
Reputation: 323
Why not try the following :
1) Find the element position relative to the viewport:
rect=elt.getBoundingClientRect();
x=rect.left;
y=rect.top;
(or may be consider the midpoints coordinates)
2) Find the top element at position x, y:
topElt=document.elementFromPoint(x,y);
3) Check if the top element is the same than the original element :
if(elt.isSameNode(topElt)) console.log('no overlapping');
Upvotes: 30
Reputation: 2031
OK. I've gone through all cases of overlapping and have created this fiddle. I've used getBoundintClientRect()
and have used it to get top
, left
, bottom
, right
values of two div
s on which overlapping is to be checked and then I've compared the offsets using various conditional statements and conditions too which you'll find below. In the fiddle all your four elements are having position: absolute
, adjust their top
and left
values to make them overlap one another and to check whether two elements are overlapping or not? pass the two elements in the function -
checkElements(elA, elB); // pass two elements to check
which is in the very last.
You will see the long if
else
conditions in the fiddle, they are just for testing all possibilities of overlapping. Here is that all possible conditions used to check overlapping -
if((eleB.top >= eleA.top && eleB.top <= eleA.bottom) || (eleB.bottom >= eleA.top && eleB.bottom <= eleA.bottom)) {
if((eleB.left >= eleA.left && eleB.left <= eleA.right) || (eleB.right >= eleA.left && eleB.right <= eleA.right)) {
el1.innerHTML = '<p>covered</p>';
}
else {
el1.innerHTML = '<p>not covered</p>';
}
}
else {
el1.innerHTML = '<p>not covered</p>';
}
You will also see if B overlaps A then it will write A is covered because I've compared using x and y coordinates of A and B. In this case, I think an additional condition checking z-index
will be used. I've not created for that.
Check the fiddle, and adjust top
and left
values of different elements and then pass two elements in the function checkElements()
and see the result is correct or not.
You can also do all the checking simultaneously as -
checkElements(elA, elB); // check if A is overlapped by B
checkElements(elB, elC); // check if B is overlapped by C
checkElements(elC, elD); // check if C is overlapped by D
See this fiddle using the multiple checking.
EDIT: If looping is the problem, then you can combine all the loops of if
else
into a single if
else
like this -
if(((eleB.top >= eleA.top && eleB.top <= eleA.bottom) || (eleB.bottom >= eleA.top && eleB.bottom <= eleA.bottom)) && ((eleB.left >= eleA.left && eleB.left <= eleA.right) || (eleB.right >= eleA.left && eleB.right <= eleA.right))) {
el1.innerHTML = '<p>covered</p>'; // or your code of adding true to the attribute that tells about overlapping
}
else {
el1.innerHTML = '<p>not covered</p>';
}
Upvotes: 0
Reputation: 11502
Are you looking for something like this?
http://jsfiddle.net/6v89b1fy/4/
var coverElem = $(".cover");
var elemArray = [];
elemArray.push($(".ele1"), $(".ele2"), $(".ele3"));
for(i=0; i< elemArray.length; i++)
{
var currElemOffset = elemArray[i].offset();
var currElemWidth = elemArray[i].width();
var currElemStPoint = currElemOffset.left ;
var currElemEndPoint = currElemStPoint + currElemWidth;
if(currElemStPoint <= coverElem.offset().left && coverElem.offset().left <= currElemEndPoint)
{
elemArray[i].append("<span>Covered</span>");
}
else
{
elemArray[i].append("<span>Not covered</span>");
}
}
Upvotes: 3