Hide/show elements depending on view when scrolled - javascript

Sounds like a simple waypoint.js and animate.js issue, but its a bit different. I am using 'isScrolledIntoView' elements, but the problem is that multiple elements are viewable at once on the page. Ideally I would like the first element to show until the next element is entirely viewable so that only one element is present at a time. Right now I am having the issue of more than one element showing at the same time, which makes for a not so nice presentation. Here is what I have tried, and here is the website I have tried it on.
The floating ball shows different elements dependent on the scroll position. I'm sure you will be able to see the issue in this example.
http://www.omnihustle.com
<script>
$(document).ready(function() {
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
var myelement = $('#home-screen'); // the element to act on if viewable
$(window).scroll(function() {
if(isScrolledIntoView(myelement)) {
$(".coupontooltip").show("slow");
} else {
$(".coupontooltip").hide("slow");
}
});
});
</script>
<script>
$(document).ready(function() {
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
var myelement = $('#services'); // the element to act on if viewable
$(window).scroll(function() {
if(isScrolledIntoView(myelement)) {
$(".coupontooltip2").show("slow");
} else {
$(".coupontooltip2").hide("slow");
}
});
});
</script>
<script>
$(document).ready(function() {
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
var myelement = $('#agents'); // the element to act on if viewable
$(window).scroll(function() {
if(isScrolledIntoView(myelement)) {
$(".coupontooltip3").show("slow");
} else {
$(".coupontooltip3").hide("slow");
}
});
});
</script>
<script>
$(document).ready(function() {
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
var myelement = $('#portal'); // the element to act on if viewable
$(window).scroll(function() {
if(isScrolledIntoView(myelement)) {
$(".coupontooltip4").show("slow");
} else {
$(".coupontooltip4").hide("slow");
}
});
});
</script>
<script>
$(document).ready(function() {
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
var myelement = $('#webdesign'); // the element to act on if viewable
$(window).scroll(function() {
if(isScrolledIntoView(myelement)) {
$(".coupontooltip5").show("slow");
} else {
$(".coupontooltip5").hide("slow");
}
});
});
</script>
<script>
$(document).ready(function() {
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
var myelement = $('#social'); // the element to act on if viewable
$(window).scroll(function() {
if(isScrolledIntoView(myelement)) {
$(".coupontooltip6").show("slow");
} else {
$(".coupontooltip6").hide("slow");
}
});
});
</script>
<script>
$(document).ready(function() {
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
var myelement = $('#pvf'); // the element to act on if viewable
$(window).scroll(function() {
if(isScrolledIntoView(myelement)) {
$(".coupontooltip7").show("slow");
} else {
$(".coupontooltip7").hide("slow");
}
});
});
</script>
<script>
$(document).ready(function() {
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
var myelement = $('#pricing'); // the element to act on if viewable
$(window).scroll(function() {
if(isScrolledIntoView(myelement)) {
$(".coupontooltip8").show("slow");
} else {
$(".coupontooltip8").hide("slow");
}
});
});
</script>

Related

.addClass on initially loaded element

Situation:
I have written a function that detects whether <section> has entered the viewport via scroll, if so .addClass('fadeInUp') else .removeClass('fadeInUp') causing the .animation-element to fade in on the viewport.
Problem: Because the conditional is binded to the scroll function, the 1st <section> that is initially loaded does not .addClass('fadeInUp') until the user scrolls past then scrolls back to the <section>. View JS Fiddle for example
Question: How can I also detect if the initially loaded <section> is in the viewport, then .addClass('fadeInUp'), etc...
Current JS function:
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
$(window).scroll(function() {
$('.animation-element').each(function() {
if (isScrolledIntoView(this) === true) {
$(this).addClass('fadeInUp')
} else {
$(this).removeClass('fadeInUp')
}
});
});
Here is the JS Fiddle of the prototype.
Simply call the same code you call inside the event hander outside the event handler on the page load.
$(function () {
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
function checkElements(selector) {
$(selector).each(function() {
if (isScrolledIntoView(this) === true) {
$(this).addClass('fadeInUp')
} else {
$(this).removeClass('fadeInUp')
}
});
}
$(window).scroll(function() {
checkElements('.animation-element'); // <-- check on scroll
});
checkElements('.animation-element'); // <-- check on page load
}
I am not sure what you are asking. Is this what you are looking for?
var updateScroll = function() {
$('.animation-element').each(function() {
...
}
}
$(window).scroll(updateScroll);
updateScroll();

Check if element is in viewport inside iframe

I have one page which contains Iframe, iframe has few elements that need to be loaded only if it's in viewport.
But iframe is not scrollable, only master page has scroll. I have written following function but its not working if used with master page.
function isVisible(a) {
var b1 = a.getBoundingClientRect(),
b={},
c = window.innerWidth || doc.documentElement.clientWidth,
d = window.innerHeight || doc.documentElement.clientHeight,
e = function(a, b) {
return document.elementFromPoint(a, b)
};
if(window.frameElement){
var w = window.frameElement.getBoundingClientRect();
// d = window.innerHeight || doc.documentElement.clientHeight;
for( var i in b1){
b[i]=Math.abs(b1[i])+Math.abs(w[i])
}
}else{
b=b1;
}
return !(b.right < 0 || b.bottom < 0 || b.left > c || b.top > d) && (a.contains(e(b.left, b.top)) || a.contains(e(b.right, b.top)) || a.contains(e(b.right, b.bottom)) || a.contains(e(b.left, b.bottom)))
}
Please suggest a way forward, thanks in advance .
This will defer loading of the iframe content until it is scrolled into view.
JSFiddle Example
var $iframe = $("#iframe");
$(window).on("scroll", function() {
// you should probably throttle or debounce this method; I didn't
if (isScrolledIntoView($iframe[0])) {
// assumes same origin for iframe
// if iframe has window object and function "viewportUpdate" call function
var iframeWindow = $iframe[0].contentWindow;
if (iframeWindow && iframeWindow.viewportUpdate)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
iframeWindow.viewportUpdate(docViewTop, docViewBottom);
}
}
});
// from http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
iframe content uses this method to do your magic:
function viewportUpdate(docViewTop, docViewBottom)
{
// do your magic here.. whatever that is
// for example, loop over each "img" element and log to console if in view
$("img").each(function()
{
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
var elementIsInView = (elemBottom <= docViewBottom) && (elemTop >= docViewTop);
if (elementIsInView)
{
console.log("iframe img element is in view");
}
});
}

Return element of collection which is currently in view

I have a few elements and detect if each of them is currently in the viewport. I'm using this answer for that: Answer
function isScrolledIntoView(elem)
{
var $elem = $(elem);
var $window = $(window);
var docViewTop = $window.scrollTop();
var docViewBottom = docViewTop + $window.height();
var elemTop = $elem.offset().top;
var elemBottom = elemTop + $elem.height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
The problem I have is now, as I'm using a collection of elements because there are a couple which have the same class .box, how can I tweak the snippet to actually return the current visible element out of a collection.
Thanks
Edit:
I tried to return
[((elemBottom <= docViewBottom) && (elemTop >= docViewTop)), $(elem, this)]
Is this helping you?
$( ".box" ).each(function( index ) {
// for each element you are getting the boolean if is in viewport
if(isScrolledIntoView(this)) {
// do something
}
});
function isScrolledIntoView(elem)
{
var $elem = $(elem);
var $window = $(window);
var docViewTop = $window.scrollTop();
var docViewBottom = docViewTop + $window.height();
var elemTop = $elem.offset().top;
var elemBottom = elemTop + $elem.height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

Stop function from being executed after run once

I have a this function
function toDiv() {
$(".wrap")))
$('.barfill').each(function(){
var width=$(this).data('width');
$(this).animate({ width: width }, 500);
var $perctext = $('<div>', {'class': 'perctext', text: width});
$perctext.appendTo(this);
$perctext.delay(500).each(function(a) {
$(this).delay(a * 250).animate({
'left': width
}, 1000);
});
});
else {}
}
that runs after the element appears on the pane by using this.
function toView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
I want it to run ONCE and when the element is on the pane again the function won't trigger again.
I applied .one() to the parent function so it runs only once but that didn't do the trick.
You can check the Fiddle Demo to clarify the problem further.
Note: I updated this question for clarity, since it seemed to create some misunderstandings.
Use .unbind() to remove the listener once it's been used:
$(window).scroll(toDiv);
function toView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
function toDiv() {
if (toView(
$(".wrap"))) {
$('.barfill').each(function () {
var width = $(this).data('width');
$(this).animate({
width: width
}, 500);
var $perctext = $('<div>', {
'class': 'perctext',
text: width
});
$perctext.appendTo(this);
$perctext.delay(500).each(function (a) {
$(this).delay(a * 250).animate({
'left': width
}, 1000);
});
});
$(window).unbind('scroll');
}
}
JSFiddle
function highlander(fn) {
return function() [
if (fn) {
fn.apply(this, arguments);
fn = null;
}
}
}
var printHello = highlander(function() {
console.log('Hello');
});
printHello();
printHello();
printHello();
// will print hello only once!
Your solution should be found, simply, in the original counter principle.
// define a counter
var counter = 0;
$(window).scroll(toDiv);
function toView(elem) {
//check the counter value
if (counter > 0) return false;
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
function toDiv() {
if (toView(
$(".wrap")))
$('.barfill').each(function(){
// increase the counter value
counter++;
var width=$(this).data('width');
$(this).animate({ width: width }, 500);
var $perctext = $('<div>', {'class': 'perctext', text: width});
$perctext.appendTo(this);
$perctext.delay(500).each(function(a) {
$(this).delay(a * 250).animate({
'left': width
}, 1000);
});
});
else {
}
}
Checkout the DEMO

Undeclared Javascript Function

I am sure something is wrong with my function declaration
$(window).ready(function(){
if isScrolledIntoView(".my_class"){
$("#some_id").hide();
}
});
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
Why doesn't this work?
You forget to wrap () around if condition also use window.load or document.ready.
$(window).load(function(){
if (isScrolledIntoView(".my_class")){
$("#some_id").hide();
}
});
if (isScrolledIntoView(".my_class")){

Categories