Checking if an element is visible within a scrollable div - javascript

First off, this may be considered a duplicate question - however no answer was provided to the one I found when searching:
jQuery check if element is visible inside scrollable div
I can't seem to find a solution for checking if an element is visible within a parent div that has a scroll bar, there are obviously ways to do this with the offset being from the parent element, but I was looking whether there was an all around solution that would check each of the same selector wrapped up as a plugin so it can be checked constantly.
The current plugin I am using is limited to the actual window viewport and I don't believe it's possible to alter it to work for a scrollable div.
Current code:
;(function($, win) {
$.fn.inViewport = function(cb) {
return this.each(function(i,el){
function visPx(){
var H = $(this).height(),
r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
return cb.call(el, Math.max(0, t>0? H-t : (b<H?b:H)));
} visPx();
$(win).on("resize scroll", visPx);
});
};
}(jQuery, window));

Related

FullCalendar dayClick not triggering

I had issue when dayClick function was't triggering on page with scroll for some cells and it was fine for others. Basically it was fine on page without scroll, but on longer content having page it cause problem.
What I have found out is that there is two functions to define cell position in grid ( fullcalendar 2.5.0 version):
'getHorizontalIndex' and 'getVerticalIndex'
Function 'getVerticalIndex' return 'undefined' because mouse 'topOffset' position was out of 'boundingRect' dimensions, so after digging deeper I found out function 'getScrollParent' (line 297) which is responsible for finding top parent element.
function getScrollParent(el) {
var position = el.css('position');
var scrollParent = el.parents().filter(function() {
var parent = $(this);
return (/(auto|scroll)/).test(
parent.css('overflow') + parent.css('overflow-y') + parent.css('overflow-x')
);
}).eq(0);
return position === 'fixed' || !scrollParent.length ? $(el[0].ownerDocument || document) : scrollParent;
}
and because in my css were no elements with css 'overflow:scroll' or 'overflow:auto' my parent element was 'html' which height was detected as height without scroll.
Solution was simple - specify 'overflow:auto;' in css for calendar element. For example, if you have code like:
<div id="mycalendar"></div>
(function(){
$("#mycalendar").fullCalendar({});
})();
add style 'overflow:auto;' for 'mycalendar' div.
The current fix is to remove overflow-x: hidden from the HTML element. Its a known issue: https://github.com/fullcalendar/fullcalendar/issues/3615

What is the right generic way to find any element on screen?

I wanted to write a code which should find whether an element exists on screen or not.
As per my requirement it should also support for an element which is inside a div that has inner scrolling.
Assumptions are
1.that only one level of inner scrolling should be supported.
2.only visibility in context of vertical scrolling is checked.
The main problem is the following usecase as depicted on this link.
An element A ($("#innerele")) is present inside the DIV ($("#outerdiv")) which is scrollable. First you have to find out whether the DIV itself is present on screen and second then test that whether A is visible. For e.g A may be at a the top position inside DIV and thus visible, but if DIV itself is not visible then it should return false.
I could write the following code which is jquery plugin which takes care of the above requirements. The context is the DIV which has inner scrolling inside it.
$.fn.isonscreen = function(context){
//Subtract the offset of the parent container.
//Will be 0 in case cont is undefined
var tominus=0,
//Add the scrollTop position incase no cont is undefined.
toadd=0;
if(context){
//Find if the div is itself visible
if(!context.isonscreen()){
return false;
};
tominus = context.offset().top;
}else{
context = $(window);
toadd = context.scrollTop();
}
if($(this).offset().top - tominus <= (toadd + context.height())){
return true;
};
return false;
}
For the above link the code to find if A is on screen or not -
$("#innerele").isonscreen($("#outerdiv"))
Will this work everytime or there is some usecase where it will fail?.

Universal javascript resize function

Basically this function is meant to store the height value of the element that calls it and then if that height matches the element it will expand its height by 200px and if it does not match the stored value it restores that value (in essence shrinking the element container). How do I get it to read from the external style sheet to get the var heightVal = parseInt(boxStyle.height);?
function expand(e){
var box = document.getElementById(e);
var boxStyle = box.style;
var heightVal = parseInt(boxStyle.height);
if(boxStyle.height == heightVal){
boxStyle.height = heightVal + 200 +'px';
}
else{
boxStyle.height = heightVal;
}
}
This is my revised answer... This code allows for the function to be used universally to re-size any elements height regardless of whether you want it to start minimized or maximized and/or whether you want it to expand or collapse. I developed this function as an improvement on the answer I had previously written. This is actually a result of another function I have been working on to change the CSS class to allow for animation without using either javascript nor jquery. I now have both functions working and universal!
The parameters are pretty straight forward... box represents the element you want to resize, hNew represents the height you want to resize it to (can be larger or smaller than the current height of the element and the function still works).
function resize_height(box, hNew){
if(box.style.height != hNew || box.style.height == box.old_height){
box.old_height = box.style.height
box.style.height = hNew;
}
else{
box.style.height = box.old_height;
}
}

How can I check if an element is in overflow area?

i have a div with a with of 300px.
this DIV contains different Icons and if there are too many Icons then they are not visible due to overflow:hidden
How may i programatically check if an icon is visible or is in overflow area?
I couldn't find anything exactly like that so I wrote a quick library function.
Element.addMethods({
isClipped: function(element, recursive){
element = $(element);
var parent = element.up();
if ((element === document.body) || !parent) return true;
var eLeft = element.offsetLeft,
eRight = eLeft+element.getWidth(),
eTop = element.offsetTop,
eBottom = eTop+element.getHeight();
var pWidth = $R(parent.scrollLeft, parent.getWidth()+parent.scrollLeft),
pHeight = $R(parent.scrollTop, parent.getHeight()+parent.scrollTop);
if (!pWidth.include(eLeft) || !pWidth.include(eRight) || !pHeight.include(eTop) || !pHeight.include(eBottom)) {
return true;
}
if (recursive) return parent.isClipped(true);
return false;
}
});
It's not elegant (I did say "quick") but it allows you to use isClipped() on any element. You can see a jsfiddle test here. It tests if any part of an element (excluding borders) is part of the overflow. You could do something similar to test for elements that are entirely outside the containing client area.
http://elvingrodriguez.com/overflowed/
It's a jQuery plugin that tells you if an element is overflowed.
If a node's scrollWidth/Height is higher than it's offsetWidth/Height, then something will be (partially) hidden. It's then a matter of determining which area is hidden through simple math (adding up icon widths, calculating the scroll offset and then eventually checking if an icon is within that visible area).

Scroll to an element using jQuery

I need the page to scroll just so that an element is visible.
Options I've tried:
jQuery's scrollTo: the problem is that the page scrolls so that the element is on top (or at least it tries to do that, much like how this works: <a name="xyz"> / <a href="#xyz">). I want the minimum amount of scrolling, so that the entire element is visible (and, if the element is too tall, work like the anchor there).
scrollIntoView: awful. I want it to scroll smoothly (like $.scrollTo($('#id1'), 'fast');). Also, it doesn't seem to do what I want either.
What you need to do is identify the position within the page of the element, top and bottom (and left/right if you are considering horizontal scrolling). Then identify the current position of the viewport on the window, the scrollTop of the window should then be animated to whatever value will bring the other just in to view.
I just knocked up the following in this editor, so it's untested, but will give you the general idea for a plugin.
Updated - to show version that worked for the OP, as well as a smoother version
jQuery.fn.scrollMinimal = function(smooth) {
var cTop = this.offset().top;
var cHeight = this.outerHeight(true);
var windowTop = $(window).scrollTop();
var visibleHeight = $(window).height();
if (cTop < windowTop) {
if (smooth) {
$('body').animate({'scrollTop': cTop}, 'slow', 'swing');
} else {
$(window).scrollTop(cTop);
}
} else if (cTop + cHeight > windowTop + visibleHeight) {
if (smooth) {
$('body').animate({'scrollTop': cTop - visibleHeight + cHeight}, 'slow', 'swing');
} else {
$(window).scrollTop(cTop - visibleHeight + cHeight);
}
}
};
$('#item').scrollMinimal();
There's a plugin for just what you need
I don't want to copy the code from blog post, because it can get outdated (due to upgrades). But anyway. You can find all details and code about the .scrollintoview() jQuery plugin on blog post.
Usage
Contrary to scrollTo() plugin where you have to provide scrollable element this plugin only requires you to provide the element you'd like to scroll into view. Plugin finds nearest scrollable ancestor (with scrollbars) and scrolls to the element with animation, so user doesn't loose track of their position in the page.
The good thing is also that it won't scroll anything if element is already within visible boundaries of scrollable ancestor.
$("ElementSelector").scrollintoview();
That's it most of the time. But if you need to set some additional settings, there are some you can change and provide custom behaviour:
scrollintoview: function (options) {
/// <summary>Scrolls the first element in the set into view by scrolling its closest scrollable parent.</summary>
/// <param name="options" type="Object">Additional options that can configure scrolling:
/// duration (default: "fast") - jQuery animation speed (can be a duration string or number of milliseconds)
/// direction (default: "both") - select possible scrollings ("vertical" or "y", "horizontal" or "x", "both")
/// complete (default: none) - a function to call when scrolling completes (called in context of the DOM element being scrolled)
/// </param>
/// <return type="jQuery">Returns the same jQuery set that this function was run on.</return>
FYI, jQuery scrolling element into viewport plugins alternative:
intoViewPort plugin
scrollIntoView plugin

Categories

Resources