identifying when items are in view and out of view on website - javascript

I am building some code to try and have something happen when an image is within view, then reset the counter when the image isnt in view and have that same thing happen again if the image returns to view.
I have the code working to recognize when the image comes into view and do something, but then when I add the code to reset the counter when the image is out of view the whole thing stops working.
html:
<div style="height: 2000px">
<img height="320px" width= "240px" id="pbr" src="http://i47.tinypic.com/33bztj8.jpg" alt="image 1">
<img height="320px" width= "240px" id="pbrglow" src="http://i48.tinypic.com/2ykduvl.jpg" alt="image 2">
<button id="button">click to reset</button>
</div>
css:
#pbr {
position: absolute;
top: 500px;
z-index: 0;
}
#pbrglow {
position: absolute;
display: none;
top: 500px;
z-index: 1;
}
#button {
position: absolute;
top: 850px;
z-index: 3;
}
javascript:
var y = $("#pbr").offset().top;
var eventsFired = 0;
$(window).scroll(function() {
var y = $("#pbr").offset().top;
var scrollY = $(window).scrollTop();
if (scrollY + 100 > y && eventsFired == 0) {
eventsFired++;
alert(eventsFired);
}
});
$("#button").on("click", function() {
var scrollYY = $(window).offsetTop();
if (eventsFired == 1) {
alert("happened");
eventsFired = 0;
}
}
Here is the jsfiddle with the code
Once I remove the code starting in $("#button")... the code works, but with this in the code doesnt.
P.S. this is a website I need to work on iOS.

That's because your #button click handler is throwing an error:
Uncaught TypeError: Object [object Object] has no method 'offsetTop'
You can see it on the jsFiddle page if you have a console open (you can enable the console for mobile Safari via Settings->Safari->Developer).
That problem is that $(window) doesn't have an offsetTop() method. If you get rid of that line (and you don't need it anyway, since you're never using scrollYY), everything works.

Related

scrollTo() function does nothing

I wanted to scroll to the bottom of the page using vanilla JS, but I encountered a problem. The code below is supposed to scroll to the bottom of the page:
window.scrollTo(0,document.body.scrollHeight);
Whereas all it does is logs "undefined" in the console. Inputting
document.body.scrollHeight
returns an integer 736. Other than that, it doesn't matter what I input into the function's parameters, nothing happens. What more, it only happens on one website. What may matter (not sure) is that the website hides its vertical scrolling bar, even thought it has a really long list of content.
The problem might be that the actuall scroll that you have on the website is not the scroll of the body but a scroll of another element inside that body.
Here is an example:
$('#btn1').click(function() {
window.scrollTo(0,document.body.scrollHeight);
});
$('#btn2').click(function() {
el = $('.a')[0];
el.scrollTop = el.scrollHeight;
});
body {
overflow: hidden;
margin: 0;
padding: 0;
}
div.a {
height: 100vh;
overflow: auto;
}
div.b {
height: 1500px;
position: relative;
}
div.c {
position: absolute;
bottom: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="a">
<div class="b">
<button id="btn1">Scroll body - doesn't work</button><br />
<button id="btn2">Scroll element - will work</button>
<div class="c">This is at bottom of page</div>
</div>
</div>
Note - the usage of jquery is only to make the example shorter.
Put some content in your page o style the body heigth = 1500px for example, then try to execute same code.
Solved. This is what had to be done:
document.getElementsByTagName('body')[0].style.display = "block";
For whatever reason, changing the display to "block" enabled the scrolling using the given code:
window.scrollTo(0,document.body.scrollHeight);
If you will try to type in browser's console like a var a = 5 you also will get undefined. It happens that your example and my did not return anything.

jQuery .width() on previously created Element returns 0

I am rendering a series of images on the fly into a container. At the end I want a single image centered and the other images to the left and right of it.
My problem is with centering the image. I made a full fiddle with my entire code which is ironically working as I expect it to be. However when testing it I find that
centered.width()
Returns 0 instead of returning the width of the image that should be centered.
Here centered is an image-tag I previously created on the fly.
What confuses me most is how it works in the fiddle but not when I test it opening the website locally, having exactly the same code in there as in the fiddle.
Here goes the entire page I currently have.
var ashe = JSON.parse('{"id":22,"key":"Ashe","name":"Ashe","title":"the Frost Archer","skins":[{"id":22000,"name":"default","num":0},{"id":22001,"name":"Freljord Ashe","num":1},{"id":22002,"name":"Sherwood Forest Ashe","num":2},{"id":22003,"name":"Woad Ashe","num":3},{"id":22004,"name":"Queen Ashe","num":4},{"id":22005,"name":"Amethyst Ashe","num":5},{"id":22006,"name":"Heartseeker Ashe","num":6},{"id":22007,"name":"Marauder Ashe","num":7}]}');
var currentCha = ashe;
function displaySkins(cha) {
//Clear the display.
var $skinDisplay = $('#skinDisplay');
var $skinSpinner = $('#skinSpinner');
$skinDisplay.html('');
$skinSpinner.html('');
currentCha = cha;
//Add small perviews to spinner
cha.skins.forEach(function(skin) {
var img = $('<img class="small-preview" src="http://ddragon.leagueoflegends.com/cdn/img/champion/loading/' + cha.key + '_' + skin.num + '.jpg">');
$skinSpinner.append(img);
skin.img = img;
})
spinTo(0);
}
function spinTo(index) {
centered = currentCha.skins[index].img;
var left = $('#skinSpinner').width() / 2 - centered.width();
console.log(centered.width());
centered.css('left', left);
}
displaySkins(ashe);
#skinDisplay {
width: 100%;
height: 100%;
}
#skinSpinner {
width: 500px;
height: 200px;
border: 1px solid black;
perspective: 500px;
}
#skinSpinner .small-preview {
position: absolute;
display: block;
height: 100%;
width: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="overlay">
<div id="skinDisplay">
</div>
<div id="skinSpinner">
</div>
</div>
bind a load checker to spinTo function:
function spinTo(index) {
centered = currentCha.skins[index].img;
$(centered).bind('load', function(){
var left = $('#skinSpinner').width() / 2 - centered.width();
console.log(centered.width());
centered.css('left', left);
});
}
Seems like you are accessing your DOM before loading it.
$( document ).ready(function(){ displaySkins(ashe); });
This will defer execution of your script until the DOM is loaded.
It works in the fiddle as they put include the script in the end of the DOM. So DOM is loaded first and the script is included and finally executed. You do it the other way round (which is also fine) which obviously does not work

Change iframe style on second load, doesn't work in Internet Explorer 9

I am trying to change the style of an iframe on the second load. I tried this:
$(function() {
var loadCnt = 0;
$('#iframem').load(function() {
if (loadCnt >0) {
$("#idiv").width(453).height(349);
$("#iframem").css("left", "-656px");
$("#iframem").css("top", "-250px");
}
++loadCnt;
});
});
HTML:
<div style="overflow: hidden; width: 377px; height: 230px; position: relative;" id="idiv">
<iframe id="iframem" src="http://www.example.org" style="border: 0pt none ; left: -1px; top: -8px; position: absolute; width: 1680px; height: 867px;" scrolling="no"></iframe></div>
It works perfectly, but it is not working on Internet Explorer 9. What is the correct approach to do that?
I think there is a logical problem in your approach and am not sure how you have it working at all. As JavaScript only runs after the page loads, this mean that in your code you would never actually get to loadCnt larger than 1 - as every time you load the page it sets it to 0 again.
In order to achieve what you are describing you will need to take a different approach, and there are several ways to go about it:
Use a server-side language and use a session variable where you set
the load count
If your pages are loaded through Ajax and injected to the DOM, then, for example, if your code is on the home page on the first 'real'
load of the page the loadCnt and then moving between pages when
you 'load' the homepage again you actally are not loading the whole
JavaScript script, just re-injecting the HTML to the document and then you can add a listener that uses the loadCnt.
Use JavaScript localStorage - on the first load you will set the
counter to 0 on a local storage object that you will be able to
retrieve on later loads:
if (localStorage.getItem("counter") === null) {
// Check if the item exists; if not set it to 0 as it is the first run
localStorage.setItem('counter', 0);
}
else {
// Get the counter - here you can do your work for when the page is loaded after the first load
localStorage.getItem('counter');
}
Use a Javascript cookie to do the same as in previous logic, but in a cookie (as localStorage could have compatibility issues)
You should always use the onload attribute to set any function. In Internet Explorer you can't set the onload event by code. There is the way to do it, I mentioned in option 2 of my answer.
Option 1
HTML
<div style="overflow: hidden; width: 377px; height: 230px; position: relative;" id="idiv">
<iframe id="iframem" src="http://www.example.com" style="border: 0pt none ; left: -1px; top: -8px; position: absolute; width: 1680px; height: 867px;" scrolling="no" onload="myIframeLoadFunction()">
</iframe>
</div>
JavaScript Code
var loadCnt = 0;
function myIframeLoadFunction(){
if (loadCnt >0) {
$("#idiv").width(453).height(349);
$("#iframem").css("left", "-656px");
$("#iframem").css("top", "-250px");
}
++loadCnt;
}
Option 2
You need to specifically bind onload event after element gets render on HTML.
JavaScript Code
(function (selector) {
var loadCnt = 0, frame = $(selector).get(0);
if (frame) {
frame.onload = function () {
if (loadCnt >0) {
$("#idiv").width(453).height(349);
$("#iframem").css("left", "-656px");
$("#iframem").css("top", "-250px");
}
++loadCnt;
};
}
})('#iframem');

swap to larger image on mouseover

I'm working with Microsoft Web Expression to create a website and I want a smaller image on mouseover/hover to be replaced with a larger one; similar to thumbnail idea, however looking at my code I just can't find how to implement any of the advises I've looked at here.
HTML part:
<div id="layer11" style="position: absolute; width: 150px; height: 20px; z-index: 1; left: 0px; top: 0px; " class="auto-style17">
<img id="img1" alt="" height="20" onmouseout="FP_swapImgRestore()" onmouseover="FP_swapImg(1,1,/*id*/'img1',/*url*/'s2.png')" src="s1.png" width="150" /></div>
And here are the javascript functions:
function FP_swapImg() {//v1.0
var doc=document,args=arguments,elm,n; doc.$imgSwaps=new Array(); for(n=2; n<args.length;
n+=2) { elm=FP_getObjectByID(args[n]); if(elm) { doc.$imgSwaps[doc.$imgSwaps.length]=elm;
elm.$src=elm.src; elm.src=args[n+1]; } }
}
function FP_swapImgRestore() {//v1.0
var doc=document,i; if(doc.$imgSwaps) { for(i=0;i<doc.$imgSwaps.length;i++) {
var elm=doc.$imgSwaps[i]; if(elm) { elm.src=elm.$src; elm.$src=null; } }
doc.$imgSwaps=null; }
}
And I just can't figure out what I should change so that the swapped image is larger rather than compressed on the existing one.
you have to remove the width and height attributes
see http://jsbin.com/nifuvitoqa/1/edit

Calculation Returns Multiple Values

I have a jQuery function that checks the values of the child images heights, then sets the parents height to the value of the smallest image's height, then adds overflow: hidden to avoid overflow.
I execute the function from the document.ready event, however I am getting odd results. I will get HTMLobjectHeight, 0, undefined, or the correct value on a pageload. Why is this varying? is it firing before the images are loaded?
function setContainHeight()
{
var container = $('.com-background');
var imgs = $('.com-background img');
var smallestImg = imgs[0];
$(imgs).each(function()
{
if ($(this).height() < $(smallestImg).height() )
smallestImg = $(this).height();
});
container.height(smallestImg);
container.css("overflow", "hidden");
};
One other issue I am having is, when I add this function to the window.resize event it also fires on pageload, and gives an undefined result.
HTML
<div class="com-background" style="height: 434px; overflow: hidden;">
<h1 class="community_title">Sun Lakes</h1>
<img width="250" height="167" src="http://192.168.33.10.xip.io/wp-content/uploads/2013/04/Ocotillo-lake-e1404789921289.jpg" class="wp-post-image" alt="Ocotillo - lake" style="display: block; z-index: 1;">
<img width="250" height="188" src="http://192.168.33.10.xip.io/wp-content/uploads/2013/04/Resort-e1404789892490.jpg" class="attachment-post-secondary-image-thumbnail active" alt="Resort" style="z-index: 3; opacity: 0.988634061784097;">
<img width="837" height="378" src="http://192.168.33.10.xip.io/wp-content/uploads/2014/05/homestead-error.png" class="attachment-post-tert-image-thumbnail" alt="homestead-error" style="z-index: 2;"> <div class="numeric_search">
</div>
SASS/CSS
.com-background
{
width: 100%;
position: relative;
img
{
z-index: 1;
position: absolute;
top: 0;
left: 0;
width: inherit;
max-width: 100%;
height: auto;
}
}
To make sure the images have been loaded, start with a $(window).load event listener
I'd also use Math.min to get the lowest image height
$(window).on("load resize", function(event) {
// find container
var container = $(".com-background");
// get image heights in an array
var heights = container.find("img").map(function(idx, elem) {
return $(elem).height();
}).get();
// get the minimum height
var minimum = Math.min.apply(null, heights);
// set container height and overflow property
container.height(minimum).css({overflow: "hidden"});
});
If you want get all of height of images , you need to be sure that all images was downloaded and ready to used ... To be sure, you need use $(window).load() instead of $(document).read like that:
$(window).load( function() {
setContainHeight();
$(window).resize( setContainHeight );
});

Categories