How to check if two div HTML elements intersect/overlap/touch each other?
The two divs are fixed at the X axis so they can only move up and down
I got both top and bottom positions for both div elements
If you already have both top and bottom, then it's just a conditional:
if ((top1 <= top2 && bottom1 >= top2) || (top2 <= top1 && bottom2 >= top1)) {
// intersect/overlap/touch
}
I believe you have to consider the element height, as well as their offsets.
Then it's just a matter of checking:
Which one is is closer to the top (top1>top2)? Realize that if you have the offset of the divs, you will have to check which one is closer to 0.
Check if the value from TOPMOST_TOP_VALUE+TOPMOST_DIV_HEIGHT > top2.
If condition 2 is true, you have intersecting divs.
Hope I could help.
I suggest you assign them some size (width, height and border). Also you can use UI debugger (by using F12 key) to see actually where those are located.
Related
What's the fastest way of checking whether an element has scroll bars?
One thing of course is checking whether element is larger than its viewport, which can easily be done by checking these two values:
el.scrollHeight > el.offsetHeight || el.scrollWidth > el.offsetWidth
but that doesn't mean that it has scrollbars as well (so it can actually be scrolled by humans).
Question
How do I check for scrollbars in a 1 cross browser and 2 javascript only (as in no jQuery) way?
Javascript only, because I need as small overhead as possible, because I'd like to write a very fast jQuery selector filter
// check for specific scrollbars
$(":scrollable(x/y/both)")
// check for ANY scrollbar
$(":scrollable")
I suppose I'd have to check for overflow style settings but how do I do that in a cross browser way?
Additional edit
Not only overflow style settings. Checking whether an element has a scrollbar isn't as trivial as it seems. The first formula I've written above works fine when element doesn't have a border, but when it does (especially when border is of considerable width), offset dimension can be larger than scroll dimension but the element can still be scrollable. We actually have to subtract borders from offset dimension to get the actual scrollable viewport of the element and compare that to scroll dimension.
For future reference
:scrollable jQuery selector filter is included in my .scrollintoview() jQuery plugin. Complete code can be found in my blog post if anybody needs it. Even though it didn't provide the actual solution Soumya's code considerably helped me solve the problem. It pointed me in the right direction.
I found this somewhere a couple of weeks ago. It worked for me.
var div = document.getElementById('container_div_id');
var hasHorizontalScrollbar = div.scrollWidth > div.clientWidth;
var hasVerticalScrollbar = div.scrollHeight > div.clientHeight;
/* you'll get true/false */
Try:
For vertical scroll bar
el.scrollHeight > el.clientHeight
For horizontal scrollbar
el.scrollWidth > el.clientWidth
I know this works for IE8 and Firefox 3.6+ at least.
This may seem (or be) a little hackish, but you could test the scrollTop and scrollLeft properties.
If they're greater than 0, you know there are scrollbars. If they're 0, then set them to 1, and test them again to see if you get a result of 1. Then set them back to 0.
Example: http://jsfiddle.net/MxpR6/1/
function hasScroll(el, direction) {
direction = (direction === 'vertical') ? 'scrollTop' : 'scrollLeft';
var result = !! el[direction];
if (!result) {
el[direction] = 1;
result = !!el[direction];
el[direction] = 0;
}
return result;
}
alert('vertical? ' + hasScroll(document.body, 'vertical'));
alert('horizontal? ' + hasScroll(document.body, 'horizontal'));
I believe there's a different property for IE, so I'll update in a minute with that.
EDIT: Appears as though IE may support this property. (I can't test IE right now.)
http://msdn.microsoft.com/en-us/library/ms534618(VS.85).aspx
Here is yet another solution:
As a few people pointed out, simply comparing offsetHeight and scrollHeight is not enough since they differ on elements with overflow hidden, etc., that still don't have scrollbars. So here I'm also checking if overflow is scroll or auto on the computed styles for the element:
var isScrollable = function(node) {
var overflowY = window.getComputedStyle(node)['overflow-y'];
var overflowX = window.getComputedStyle(node)['overflow-x'];
return {
vertical: (overflowY === 'scroll' || overflowY === 'auto') && node.scrollHeight > node.clientHeight,
horizontal: (overflowX === 'scroll' || overflowX === 'auto') && node.scrollWidth > node.clientWidth,
};
}
I maybe a little late to the party, but...
I believe you can detect for scrollbars with e.offsetWidth vs. e.clientWidth. Offset width includes borders and scrollbars, padding and width. Client width includes padding and width. Please see:
https://developer.mozilla.org/en/DOM/element.offsetWidth (second image)
https://developer.mozilla.org/en/DOM/element.clientWidth (second image)
You need to check:
Whether or not the element has overflow set to auto/scroll (including overflowX/Y) using the computed/cascaded/current style.
If the element does have overflow set to auto/scroll. Establish the offsetWidth and clientWidth.
If the clientWidth is less than the offsetWidth - right border (found again through the computed/cascaded/current style), then you know you have a scrollbar.
Do the same for the vertical (offset/clientHeight).
IE7 reports a clientHeight of 0 for some elements (I haven't checked why), therefore you always need the first overflow check.
Hope this helps!
There are several problems in case of checking the existence of scrollbars one of which is that in mac you don't have any visible scrollbar so both all the solutions above wouldn't give you an accurate answer.
So because the browser's rendering isn't very frequent you can check the having scroll with changing scroll and then setting it back:
const hasScrollBar = (element) => {
const {scrollTop} = element;
if(scrollTop > 0) {
return true;
}
element.scrollTop += 10;
if(scrollTop === element.scrollTop) {
return false;
}
// undoing the change
element.scrollTop = scrollTop;
return true;
};
For IE11 (Internet Explorer 11) I had to change the logic to:
// Subtract 3 (a small arbitrary number) to allow for IE reporting a difference of 1 when no scrollbar is present
var hasVerticalScrollbar = div.scrollHeight - 3 > div.clientHeight;
This is because IE reports scrollHeight as 1 larger than clientHeight when no scrollbar is present but approx 9 larger when a scrollbar is present
If you need to know if theres a scrollbar present for the whole webpage and with full browser support you can use this:
const hasScrollbar = document.body.scrollHeight > window.innerHeight
It's important to use window.innerHeight instead of document.body.clientHeight because in some mobile browsers clientHeight will not get the size of the address bar but scrollHeight will, so you get wrong calculations.
Is isn't for horizontal scrollbar it will be of height based calculation something like
element.offsetHeight - element.clientHeight
?
To conclude, for horizontal scrollbars, do height based calculation and for vertical scrollbars vice versa.
Just messing around here as none of the above solutions worked out for me (so far).
I have found some success with comparing a Div's scrollheight against its offsetHeight
var oh = $('#wrapDiv').get(0).offsetHeight;
var sh = $('#wrapDiv').get(0).scrollHeight;
It seems to give me an acurate comparison...so far. Does someone know if this is legitimate?
none of this answers are correct. you have to use this :
var div = document.getElementById('container_div_id');
var hasHorizontalScrollbar = (div.offsetWidth > div.clientWidth);
var hasVerticalScrollbar = (div.offsetHeight > div.clientHeight);
I'm trying to fadein the <div>s with class .cms and .seo when entering the section with id "services" and fadeout when passing that section or before.
I also want it to animate in relation to the scrolling position if its possible.
I give you the link so you can check the site for your self.
For the animations am using animate.css
The javascript code is inside js/agency.js
Site
This is the code that I've been trying with..
$(window).scroll(function() {
var y=$(window).scrollTop();
if (y < 1092){
$('.cms,.seo').addClass('animated fadeOutRight');
}
if (y > 1092 && y < 1300) {
$('.cms,.seo').addClass('animated fadeInRight');
}
if (y > 1300){
$('.cms,.seo').addClass('animated fadeOutRight');
}
});
I also want to know if it will work on different window sizes or will I have to change the code ?
Thanks!!
It fades out because if (y < 1092) will be true as soon as you scroll.
You probably only want to fadeOutRight only if fadeInRight actually exists on the element, that way it won't hide right away, so:
if (y < 1092 && $('.cms,.seo').hasClass('fadeInRight'))
Furthermore, since your class animated only specifies how the element is animated, apply this right away to the element instead of appending it with javascript.
See working example on this fiddle: https://jsfiddle.net/pjh6gy7e/
It should work on most window sizes unless you change the height of elements responsively.
I'm having a beyond frustrating problem which I have no idea how to tackle.
My question: How do I determine how many elements exist between two positions in a viewport (a scrollable div in this occasion)?
Say I have a scrollable <div> that has a height of 150 px, but has a viewport at 450px with the majority of it being hidden. The div has children that are 30px high, 15 of them.
Question 2: How could I find out how many first children exist between n1 and n2, it seems pretty easy but it's proving not to be.
I've created a jsFiddle where I have partly solved the solution, it works if the top value is set to 0, but it doesn't work if it's anything else. For example, with this solution I am able to determine that there are 7 visible divs between 0 and 200px. But if I change it to determine how many are between 30px and 230px it tells me 0, when again it should be 7.
Help please!
Try this instead:
var $this = $(this),
topOffset = $this.offset().top;
if (topOffset >= top && topOffset <= bottom) {
elements++;
}
This checks to see if the current element's (in the each()) top offset is greater than the top variable's value and increases the elements only then. This way, you don't need to be constantly updating the height variable.
And this works, as you can see here.
Change it so that the 'height' starts equal to the top value.
Your javascript should be:
var container = $('div#container'),
top = 30,
bottom = 230,
height = top,
elements = 0;
container.find('div').each(function(n)
{
if (top <= height && height < bottom)
{
height = height + $(this).height();
elements++;
console.log(top, bottom, height, elements);
}
});
$('span.top').text(top);
$('span.btm').text(bottom);
$('span.num').text(elements);
That worked for me, Good luck!
I have div with images inside it and need to scroll it left and right. I,ve managed to get the scrolling to work, but now I need it to stay in the displayable area.
I need to use jQuery
$('#next').click(function() {
$('#slides').animate({left: '-=80',}, 2000, function() {});
});
$('#prev').click(function() {
$('#slides').animate({left: '+=80',}, 2000, function() {});
});
The two "buttons" is used to scroll.
How do I get the slides' position.left to stay between 0 and -1120 ?
This will be the bottom of my slideshow. The large images will be at the top.
How do I change the z-index of a div ?
You change the z-index using css:
div.class {
z-index: 60;
}
You should get the width of your displayable area then by making use of the width() method.
If you have the maximum width you can use you can easily implement a check before your animation. So if the new width (current - 80) is bigger than 0, fine ... animate it. If not, don't.
Same for scrolling to the right. If it's bigger than your displayable area's width, then don't scroll.
EDIT
You changed your question slightly, so to get the current left value you can check it with:
$('#element').offset().left
This returns the current integer value of your left attribute. Thus again you can verify its current value and compare it with the one that it'd be like after you animated it. If it's too big or too small, don't scroll.
You can check the css left value is in the interval:
if(parseInt($('#slides').css('left')) > -1120 && parseInt($('#slides').css('left')) < 0){
....//animate here
}
I have created a small game, in which some blocks are move around a main div. The mouse which also holding a div (I had assigned the position of cursor to that div).
I just want to trace out, whether the cursor div is moving over the blocks(those are also div). If it comes like that then the game will be over.
How can I detect whether the block or cursor div moves over each other?
If you're using jQuery, you can find the left, top, width and height of a div by using these:
$(myDiv).offset().left
$(myDiv).offset().top
myDiv.offsetWidth
myDiv.offsetHeight
Use those to work out the left, right, top and bottom of each div. Then two divs overlap each other if:
left1 < right2 && left2 < right1 && top1 < bottom2 && top2 < bottom1
This is not a straightforward task using plain javascript, because you have to trace the div's ancestry and sum the relative positions until you find an absolutely positioned div.
On the other hand, this task is quite trivial with a javascript library such as jQuery or Prototype. In jQuery, for example, $(myDiv).offset() returns the div's position relative to the document.
If you also include jQuery UI, and make your main div a "Draggable", and all other divs "Droppable", all you need is hook up on the Droppable's over event to get notified when the main div is dragged over the other one.
The concept you're talking about is called collision detection.
Very simply, you need to get the bounds of your div and then loop through all the blocks to see if they overlap.
getBoundingClientRect()
John Resig has a great article here: getBoundingClientRect is Awesome
If you don't want to use jQuery you can copy/paste from here (LGPL code); http://code.google.com/p/ra-ajax/source/browse/trunk/Ra/Js/Ra.js
The place to look for is the "absolutize" function at line no. 220 which recursively calculates the size of "ancestor nodes" in the while loop.
Pasted in here for references;
var valueT = this.offsetTop || 0;
var valueL = this.offsetLeft || 0;
var el = this.offsetParent;
while (el) {
Ra.extend(el, Ra.Element.prototype);
if( el.tagName == 'BODY' ) {
break;
}
var pos = el.getStyle('position');
if( pos == 'relative' || pos == 'absolute') {
break;
}
valueT += el.offsetTop || 0;
valueL += el.offsetLeft || 0;
el = el.offsetParent;
}
"this" here is a DOM element...
However I suspect that what you have is absolutely positioned divs inside another div with position:relative in which case you can just use;
var y = parseInt(myElement.style.top, 10);
var x = parseInt(myElement.style.left, 10);
which will be orders of magnitudes faster then doing the "offset loops"...