HTML how to tell which elements are visible? - javascript

I have seen several solutions which determine when an element is visible in the viewport whilst scrolling the page, but I haven't seen any which do this for elements that are contained in a scrolling container div as in the example here.
How would I detect the items as they scroll into view via the scrolling div? And by contrast how would I detect them if they fell out of view. In all cases the overflow elements are not hidden at the outset.
HTML
<div id="mainContainer" class="main">
<div id="scrollContainer"class="scroller">
<div id="picturesContainer"class="holder">
<div id="pictureContainer1" class="picture position1">
pictureContainer1</div>
<div id="pictureContainer2" class="picture position2">
pictureContainer2</div>
<div id="pictureContainer3" class="picture position3">
pictureContainer3</div>
<div id="pictureContainer4" class="picture position4">
pictureContainer4</div>
<div id="pictureContainer5" class="picture position5">
pictureContainer5</div>
<div id="pictureContainer6" class="picture position6">
pictureContainer6</div>
<div id="pictureContainer7" class="picture position7">
pictureContainer7</div>
<div id="pictureContainer8" class="picture position8">
pictureContainer8</div>
<div id="pictureContainer9" class="picture position9">
pictureContainer9</div>
</div>
</div>
</div>
CSS
.main{
position:absolute;
top:0px;
left:0px;
height: 200px;
width:200px;
background-color: grey;
border: 1px solid black;
}
.scroller{
position:absolute;
top:0px;
left:0px;
height: 250px;
width:250px;
background-color: lightblue;
border: 1px solid black;
overflow: scroll;
}
.picture{
position:absolute;
height: 200px;
width: 200px;
background-color: lightyellow;
border: 1px solid black;
}
.position1{
top:0px;
left:0px;
}
.position2{
top:0px;
left:200px;
}
.position3{
top:0px;
left:400px;
}
.position4{
top:200px;
left:0px;
}
.position5{
top:200px;
left:200px;
}
.position6{
top:200px;
left:400px;
}
.position7{
top:400px;
left:0px;
}
.position8{
top:400px;
left:200px;
}
.position9{
top:400px;
left:400px;
}
.holder{
position:absolute;
top:0px;
left:0px;
width:600px;
height:600px;
background-color:lightgreen;
}

include jQuery library on page first.
function getObjDims(obj){
if (!obj) return false;
var off = $(obj).offset();
var t = {
top:off.top,
left:off.left,
width:$(obj).width(),
height:$(obj).height()
};
return {x1:t.left, y1:t.top, x2:t.left+t.width,y2:t.top+t.height}
};
function testInside(pic,box){
var d=getObjDims(pic);
return (box.x1<=d.x1 && box.y1<=d.y1 && box.x2>=d.x2 && box.y2>=d.y2)?1:-1;
};
$(document).ready(function(){
var inside={};
var port=$('#scrollContainer');
var box=getObjDims(port);
$(window).resize(function(){
box=getObjDims(port);
});
$(port).scroll(function(){
var str=[];
$('.picture').each(function(i){
var oldState = inside[this.id]!=undefined?inside[this.id]:0;
var newState = testInside(this,box);
inside[this.id]=newState;
if (oldState!=newState)
switch (newState){
case 1:str.push(this.id);break;// go IN
case -1: break;// go OUT
}
});
$('#picStatus').text(str.join(', '));
});
});
Add in HTML for results output:
<div style='margin-top:280px;'>Pictures in window (numbers):</div>
<div id='picStatus'></div>
It is code based on object's coords, witch are recalculated on scroll event. There are some things to know. IE and, seems to be, Opera takes into consideration width and height of scrollbars themselves, that demands curtain code tuning. I just have suggested solution direction and did not spent much time for debugging this.
And yet, maybe will be useful following (from jquery api about offset):
Note: jQuery does not support getting
the offset coordinates of hidden
elements or accounting for borders,
margins, or padding set on the body
element.

http://www.quirksmode.org/mobile/viewports.html discusses the issues around viewports, determining their dimensions, and calculating element bounds relative to a viewport's coordinate frame. Part 2 of that blog post then goes into the implicit viewports in mobile browsers. He doesn't give code that answers your question exactly, but it's definitely relevant and worth a read.

Related

Shift down / up position fixed elements in HTML

I'm working on a HTML framework that most of it's pages constructed from two section. first section (TopPanel) is a sliding panel that could slide down or up (with jQuery as well). second section is the Main part of page that could contain any sort of HTML document.
<!doctype html>
<html>
<head>
<!--Meta scripts & more-->
</head>
<body>
<div class="TopPanel">
<!--Panel's Contents-->
</div>
<div class="Main">
<!--Some standard HTML docs here-->
</div>
</body>
</html>
When the TopPanel is sliding down, all elements of the Main section must move down. But it's possible to exist some position:fixed element in the Main section. so it's clear that they won't move unless we gave them some margin-top: [$('.TopPanel').height()] px;. But it's not what I'm looking after!
I'm looking for a way to shift down and shift up all content of the Main section with a smooth effect and without changing of all elements attributes.
Have you thought about using a CSS transform:translateY(20px) on the body tag? If you are using fixed position on the other element, it shouldn't actually affect it although I haven't tested that.
You can then use transitions to get the smooth movement you are after.
body{
padding:10px;
overflow:hidden;
background:#fff;
height:100%;
transition:all .2s;
}
body.active{
transform: translateY(60px);
}
Example:
http://codepen.io/EightArmsHQ/pen/gpwPPo
Lookout for this kind of stuff though : Positions fixed doesn't work when using -webkit-transform
JSFIDDEL version
(UPDATED) Try this:
$('.main').click(function(){
$('.main').toggleClass('toggle');
})
.main{
width:20%;
height: 10%;
background-color: rgba(100,100,100,0.7);
text-align: center;
position: fixed;
top: 12%;
transition:all 1.0s
}
.top{
width: 20%;
height: 10%;
text-align: center;
background-color: rgba(300,50,50,0.7);
position: absolute;
}
.toggle{
transform: translateY(100px);
transition:all 1.0s
}
<div class="content">
<div class="top">
Top
</div>
<div class="main">
Main
</div>
</div>
It would need some tweaking but it still does what you are looking for.
I think you are looking for is maybe this:
I have used JQuery UI 1.9.2 for making the toggle ease effect. For more i have created the Fiddle
JQuery
$("button").click(function(){
$(".topPanel").toggleClass("height", 300);
$(".main").toggleClass("top", 300);
});
CSS
body { margin:0; }
.topPanel
{
width:100%;
height:50px;
background:#333;
}
.main
{
top:50px;
bottom:0px;
width:100%;
position:absolute;
background:#ddd;
}
.height { height:100px; }
.top { top:100px; }
p { font-weight:bold; }
HTML
<div class="topPanel">
</div>
<div class="main">
<center><button>Click Me!</button></center>
<p>Hey look at me, i am moving along when you click button!</p>
</div>

what is the best way to show the pop-up on click of an image?

Here I have a jsFiddle
you can See there are 3 images of Players now What I want is Whenever I click on the image it should show the pop-up below the players.
Player can be In any position it will not be in a grid
so My question is What is the best way perform this.
I have something in my probably the wast it is like..
-- whether onclick of an Image I should change the position of the position of the popup image as well as span tag's text.
-- I should provide a popup to the every Player and just hide and show them
or something else you can suggest.It will help me a lot.
#player-back{
height:250px;
background:#0F0;
}
#p1{
margin-top:50px;
margin-left:80px;
}
#p2{
margin-left:150px;
}
#p3{
margin-left:200px;
}
#player-popup{
background:orange;
height:27px;
width:85px;
border-radius:10px;
text-align:center;
margin-left:50px;
}
<div id='player-back'>
<img src='http://s6.postimg.org/su0e7812l/player1.png' id='p1'/>
<img src='http://s6.postimg.org/afpv38orx/player2.png' id='p2'/>
<img src='http://s6.postimg.org/h7ga63drh/player3.png' id='p3'/>
<div id='player-popup'>
<span>Player1</span>
</div>
</div>
Thank you for spending time for me in advance Thank you.
<div id='player-back'>
<img src='http://s6.postimg.org/su0e7812l/player1.png' data-playerid="1" id='p1'/>
<img src='http://s6.postimg.org/afpv38orx/player2.png' data-playerid="2" id='p2'/>
<img src='http://s6.postimg.org/h7ga63drh/player3.png' data-playerid="3" id='p3'/>
<div id='player-popup' style="display:none">
<span>Player1</span>
</div>
</div>
Script:
$("img").click(function(){
var top = $(this).offset().top + $(this).width() + 2;
var left = $(this).offset().left - $(this).height() / 2;
$("#player-popup span").text("Player "+$(this).data("playerid"));
$("#player-popup").css({ top: top, left: left }).show();
});
css:
#player-back{
height:250px;
background:#0F0;
}
#p1{
margin-top:50px;
margin-left:80px;
}
#p2{
margin-left:150px;
}
#p3{
margin-left:200px;
}
#player-popup{
background:orange;
height:27px;
width:85px;
border-radius:10px;
text-align:center;
position:absolute;
}
Demo: https://jsfiddle.net/astm1o3p/21/
Here make chqnges in the css for popup set
position:absolute;

container width much larger then content

I have a bunch of content that floats left in a container, and I'd like for the container to hug the content, but for some reason it's much wider then the content and I have no idea why. I have it set up in a fiddle here http://jsfiddle.net/vG8NY/6/ the red and blue bordered containers should hug the right edge of the circle.
The code is very simple and is as follows:
HTML:
<div class="hot_spot-container">
<div class="content-spot">
<img class="hotspot-cir" src="http://www.klossal.com/sixred/discovery/images/hotspot-left.png" />
<div class="hotspot-content"></div>
<img class="hotspot-cir" src="http://www.klossal.com/sixred/discovery/images/hotspot-right.png" />
<br class="clear-fix" />
</div>
</div>
CSS:
.hot_spot-container {border:1px solid blue;
position:absolute;
}
.content-spot {
border:1px solid red;
display:inline-block;
}
.hotspot-cir {
float:left;
height:100%;
width:auto;
}
.hotspot-content {
float:left;
background:#ec6e47;
}
.clear-fix {
clear:both;
}
JS
$(".content-spot").css({
height:$(window).height() * ".2"
});
try this:
$(".content-spot").css({
height:$(window).height() * ".2",
width:$(window).height() * ".2"
});
when you change height of content-spot it's width still fixed and need to get resize too.
DEMO
you can use this code too:
$(".hotspot-cir").css({
height:$(window).height() * ".2"
});
DEMO
You must define the width for the element to which you have set the position: absolute; so you should use something like this:
.hot_spot-container {border:1px solid blue;
position:absolute;
/* any width you want or if you don't know the width then define auto.*/
width: 45px;
}
if you make
.hot_spot-container {display:inline-block}
instead of it having position:absolute it does what you want it to. if you want position absolute you need to give it a width
Try this
I removed your javascript and made this changes
.content-spot {
border:1px solid red;
display:inline-block;
width: auto;
}
.hot_spot-container {
border:1px solid blue;
position:absolute;
display: inline-block;
}

How to make resizable, scrollable sidebar like Facebook's "Chat/Event Ticker"?

I am trying to design a collapsible/hide-able sidebar for my web application, in the vain of Facebook's Chat/Event Ticker. It needs to have two separate sections, separated vertically, and both independently scrollable.
I have tried to implement this using jakiestfu's Snap.js plugin.
https://github.com/jakiestfu/Snap.js/
While this works great, it moves the content on my page out of view, and breaks my position: fixed header elements due to CSS transform: tranlate3d().
Since there's no good fix the these CSS issues, I was wondering if anyone knew of a solution to mimic functionality of the Facebook Chat/Event Ticker sidebar.
I've done something similar using CSS3 resizing on the fixed sidebar (mine was on the left) and adjusting the main page's margin-left when the sidebar size changed. You could likely do something similar on the sidebar first, then split the sidebar in two the same way.
var sizeme = 200,
sizeItBro = function () {
if ($("#sidebar").width() != sizeme) {
sizeme = $("#sidebar").width() + 40;
$("#main").css("margin-left", sizeme + "px").text(sizeme + " pixels of margin.");
}
};
window.setInterval(sizeItBro, 150);
* {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
body {
margin:0;
padding:0;
}
#main {
margin-left:200px;
min-height:100%;
padding:20px;
}
#sidebar {
position:fixed;
top:0;
bottom:0;
left:0;
background:#ffa;
width:200px;
min-width:100px;
max-width:500px;
resize:horizontal;
overflow:auto;
border-right:2px ridge #fe9;
padding:20px;
}
#tophalf {
background:#fe9;
height:300px;
min-height:100px;
max-height:500px;
resize:vertical;
overflow:auto;
border-bottom:2px ridge #fe9;
margin:-20px -20px 20px;
padding:20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">Main Content</div>
<div id="sidebar">
<div id="tophalf">Sidebar A</div>
<p>Sidebar B</p>
</div>

Absolute Positioned img inside absolute div doesnt position as expected

I have the following html
<div class="banner_area_internal">
<div class="banner_wrapper_internal" id="overlay_field">
<img src="images/internal_banner_holder.png" />
<img class="internal_banner" src="images/about-banner.jpg" />
<div id="overlay">
<img class="internal_banner_overlay" src="images/about-banner_hover.jpg" />
</div>
</div>
</div>
css
.banner_area_internal {
margin-top:10px;
width:100%;
height:250px;}
.banner_wrapper_internal {
height:250px;
width:1000px;
margin:0 auto}
.banner_wrapper_internal p {
font-size:30px;
color:#ffffff;
font-weight:bold;
margin:0px 300px;
display:block}
.internal_banner {
position:relative;
top:-235px;
left:15px;
z-index:-2;
}
.internal_banner_overlay {
position:absolute;
top:-25px;
left:15px;
z-index:-2;
}
#overlay{
position:absolute;
overflow:hidden;
width:340px;
height:200px;
z-index:-1;
border:2px #aeaeae solid;
}
#overlay_field
{
position: relative;
width:1000px;
height:250px;
overflow:hidden;
}
and the following script as mentioned by #rkw
$(document).ready(function() {
$("#overlay_field").hover(function(){
$("#overlay").show(); //Show tooltip
}, function() {
$("#overlay").hide(); //Hide tooltip
})
$('#overlay_field').mousemove(function(e){
$("#overlay").css({left:e.pageX-360, top:e.pageY-280});
});
});
The Effect I'm trying to achieve here is:
An image appears in as a banner "internal_banner"
When the mouse hovers over this image(or rather "overlay_field") a small div appears which follows the mouse. Now the contents of the div is another image "internal_banner_overlay"
I want this image to be positioned exactly as "internal_banner", i.e stay in the same place so it appears like the mouse let's you see another underlying image. The problem is the image doesn't stay at one place, it positions within the div and moves with the mouse rather than the document even though it's position is set to absolute.
In simple words, when the mouse moves over the banner area, it should appear like the cursor changed to a small box that let's you see through the banner at another image.
Just add the temp banner in the upper div and change its opacity on mouseover and mouseout events.
<div class="banner_area_internal">
<div class="banner_wrapper_internal" id="overlay_field">
<img src="abcd.png" />
<img class="internal_banner permBanner" src="permBanner.png" />
<img alt="" src="tempBanner.jpg" id="temp" style="height: 250px; width: 1000px; opacity: 0; position: absolute">
</div>
</div>
JS:
$(document).ready(function() {
$("#overlay_field").hover(function(){
$("#overlay").show(); //Show tooltip
}, function() {
$("#overlay").hide(); //Hide tooltip
})
$('#overlay_field').mousemove(function(e){
var width = 250;
var height = 250;
var left = parseInt(e.pageX)-parseInt(pageXOffset);
var top = parseInt(e.pageY)-parseInt(pageYOffset);
var a = document.getElementById("temp");
a.style.opacity = 1;
a.style.left = "0px";
a.style.top = "0px";
a.style.clip = "rect("+top+","+(left+100)+","+(top+100)+","+left+")";
});
});
Style
.banner_area_internal {
margin-top:10px;
width:100%;
height:250px;}
.banner_wrapper_internal {
height:250px;
width:1000px;
margin:0 auto}
.banner_wrapper_internal p {
font-size:30px;
color:#ffffff;
font-weight:bold;
margin:0px 300px;
display:block;
}
.internal_banner {
position:relative;
top:-235px;
left:15px;
z-index:-2;
}
.internal_banner_overlay {
position:absolute;
top:-25px;
left:15px;
z-index:-2;
}
#overlay{
position:absolute;
overflow:hidden;
width:250px;
height:250px;
border:2px #0000bb solid;
}
#overlay_field
{
position: absolute;
width:1000px;
height:250px;
overflow:hidden;
}​
#temp{position:absolute;}
Alternate:
Or alternatively you can add and remove the temporary banner on the mouseover and mouseout events.

Categories