Right now I have divs that show when you scroll past a certain mark but realized that this gets broken when the browser is resized. Is there any way I can make this responsive? I'm not sure if adding $(window).resize(checkY); would work either.
EDIT:
The end goal is to show the title when the associated content comes into view
HTML
<div class="title" data-position="400,1150">Yama</div>
<div class="title" data-position="1150,1800">Modurra</div>
<div class="title" data-position="1800,2600">Computer</div>
<div class="title" data-position="2600,3300">Maru</div>
<div class="title" data-position="3300,3900">Sushi</div>
<div class="title" data-position="3900,4700">Summit</div>
<div class="title" data-position="4700,10000">Lights Out</div>
JS
<script>
//Note you do not need to make an anonymous
//function just to do the call for checkY
//just pass the function
$(window).scroll(checkY);
function checkY() {
//save this value so we dont have to call the function everytime
var top = $(window).scrollTop();
console.log(top);
$(".title").each(function () {
var positionData = $(this).data("position").split(",");
if (top > positionData[0] && top <= positionData[1]) {
console.log("Show");
$(this).show();
} else {
console.log("Hide");
$(this).hide();
}
});
}
checkY();
</script>
EDIT
.title {
position:fixed;
top:0px;
left:45%;
display:none;
padding:10px;
background:rgba(255,255,255,0);
color:#000;}
#Yama {
position:absolute;
display:block;
height:900px;
font-family: Arial, Helvetica, sans-serif;
font-size:70pt;
letter-spacing:0px;
font-weight:100;
-webkit-font-smoothing: antialiased;
text-align:center;}
This is the wrapper holding everything.
#mini {width:100%; height:100%;
padding-top:140px;}
What you want to do is find the target content and determine if the element is within the viewport. If it is then you show the title.
With this you won't need to use data-* attributes. You can just put the title in the main content's element, and then use jQuery's .closest method to get the closest parent (the content element). And from there do the tests.
HTML
<div id="Yama" class="content">
<div class="title">Yama</div>
</div>
<div id="Modurra" class="content">
<div class="title">Modurra</div>
</div>
<div id="Computer" class="content">
<div class="title">Computer</div>
</div>
<div id="Maru" class="content">
<div class="title">Maru</div>
</div>
<div id="Sushi" class="content">
<div class="title">Sushi</div>
</div>
<div id="Summit" class="content">
<div class="title">Sushi</div>
</div>
<div id="LightsOut" class="content">
<div class="title">Lights Out</div>
</div>
JS
$(window).scroll(checkY);
function checkY(){
var top = $(window).scrollTop();
$(".title").each(function(){
var target = $(this).closest(".content");
//The start range value is just offset().top
var tTop = target.offset().top;
//The end range value is the start range value plus
//the content elements height
var tBottom = tTop+target.outerHeight();
if(top >= tTop && top <= tBottom){
console.log("Show");
$(this).show();
} else {
console.log("Hide");
$(this).hide();
}
});
}
checkY();
JSFiddle Demo
Related
i want to hover over one div and use jquery to find the nearest div by the name and to show that div.
<div class="entry">
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="somethingelse"></div>
<div class="footer"></div>
</div>
all the .footer classes will be hidden but i want to make it so that when i over over the .body class, only the nearest .footer class shows. [ meaning : if i hover over the first .body class, only the first .footer will be shown. ]
my current code isn't working and i'm starting to wonder if it's something wrong with it.
current jquery code :
$('.footer').hide();
$('.body').hover(function(){
$(this).closest('.footer').find('.footer').show();
});
While the problem is the same as this question, the reason is slightly different.
When you use .closest(".class") it's the equivalent of .parents().filter(".class").first() (or .last(), I don't recall exactly which way parents() works as that's what closest is for).
ie it goes up the tree
So $(".body").closest(".entry") would give you an element for your HTML.
In this case, you want siblings, but more specifically the next one. There's a jquery method .next() which looks like it's correct, but as detailed in the link above, this only gives the very next one (in your HTML this would be the date div) even if a filter is applied - so $(this).next(".footer") would give an empty set (as it's not .date).
The work around is:
$(this).nextAll(".footer").first()
Once you get this working, your will find that your hover does not work as expected as the footers are not hiding again - as you're using .hover rather than mouseenter mouseout, you just need to move the .hide() call inside the second event handler, giving:
// startup
$(".footer").hide();
// event
$(".body").hover(function() {
$(this).nextAll(".footer").first().show();
}, function() {
$(".footer").hide();
});
div > div { width: 100px; height: 10px }
.body { border: 1px solid red; }
.date { border: 1px solid blue; }
.footer { border: 1px solid green; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="somethingelse"></div>
<div class="footer"></div>
</div>
$(this).closest('.footer')
You should start to use console.log() sometimes to check elements you would like to get. This does not find anything so nothing further to search and to show.
If you possibly can separate bodies and footers into containers you can do smth like
this.
Try to make use of nextUntil(".footer").next(); as below
$('.body').hover(function() {
$(this).nextUntil(".footer").next().show();
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
IF your html is gonna keep those triads layout, you don't need jQuery for it.
Just use CSS to select the second div after the .body on hover
div{width:100px; height:100px; background-color:lime; margin:10px; float:left}
.body{background:yellow; clear:left;}
.footer{display:none;}
.body:hover + div + div{
display:block;
background:red;
}
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="date"></div>
<div class="footer"></div>
<div class="body"></div>
<div class="somethingelse"></div>
<div class="footer"></div>
The answer by freedomn-m offered a good explanation and good solution in case you want the nearest NEXT .footer, which seems to be the case from your example HTML.
However, if you want your request strictly, so you want exact NEAREST .footer, then his solution will not work for you. And I don't think there is a jQuery built-in functionality that can give you that, so you'll have to do it manually. Get the list of the children of the parent (don't use the siblings as they don't include the current element) and go through the list to calculate the distance from your current element using the indexes and then select the .footer that is really the nearest.
$('.body').hover(function() {
var children = $(this).parent().children();
var index = children.index(this);
var closest = children.length;
var footer = -1;
children.each(function(i, child) {
if (i !== index && $(child).hasClass("footer")) {
var distance = Math.abs(index - i);
if (distance < closest) {
closest = distance;
footer = i;
}
}
});
if (footer > -1)
children.eq(footer).show();
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
If you don't care much about the performance, you can shorten the code a bit by selecting the list of .footer instead of the children of the parent, and then let jQuery give you the index of each of them. Not very efficient, but shorter code:
$('.body').hover(function() {
var index = $(this).index();
var closest = 9999;
var footer;
$(this).siblings(".footer").each(function(i, sibling) {
var distance = Math.abs(index - $(sibling).index());
if (distance < closest) {
closest = distance;
footer = sibling;
}
});
if (footer !== undefined)
$(footer).show();
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
Inspired by freedomn-m's comment, we can also use the .prevAll() and .nextAll() methods to get the previous and next .footer siblings. These two methords return the siblings ordered by the closest, so we simply pick the first one of each list, subtract their indexes from our element's index (to find the distance), compare them together, and return the closest. This solution is also less efficient than the first one, but you may find the code easier to read:
$('.body').hover(function() {
var me = $(this);
var prev = me.prevAll(".footer").first();
var next = me.nextAll(".footer").first();
if (prev.length == 0)
next.show();
else if (next.length == 0)
prev.show();
else {
index = me.index();
if (Math.abs(prev.index() - index) < Math.abs(next.index() - index))
prev.show();
else
next.show();
}
}, function() {
$(".footer").hide();
});
body {
font: 13px Verdana;
}
.footer {
display: none;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry">
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="date">date</div>
<div class="footer">footer</div>
<div class="body">body</div>
<div class="somethingelse">somethingelse</div>
<div class="footer">footer</div>
</div>
I have 10 div elements, and all of them are 500px width and height;
<div class="cont_1">a lots of content here..</div>
<div class="cont_2">a lots of content here..</div>
<div class="cont_3">a lots of content here..</div>
<div class="cont_4">a lots of content here..</div>
<div class="cont_5">a lots of content here..</div>
<div class="cont_6">a lots of content here..</div>
<div class="cont_7">a lots of content here..</div>
<div class="cont_8">a lots of content here..</div>
<div class="cont_9">a lots of content here..</div>
<div class="cont_10">a lots of content here..</div>
and my css
div{
width:500px;
height:500px;
background:#f0f0f0;
border:1px solid #ccc;
margin:10px;
padding:10px;
}
And my seventh div is hidden with display:none. Once the user scrolls to this element how can I display it?
You'll have to attach a scroll event to your page that checks the position of each element after scrolling:
function CheckIfVisible(elem){
var ElemPos = elem.getBoundingClientRect().top;
elem.style.display = (ElemPos > 0 && ElemPos < document.body.parentNode.offsetHeight)?"block":"none";
}
window.addEventListener("onscroll", function(){
var elem = document.getElementsByClassName("cont_1")[0];
CheckIfVisible(elem);
});
window.addEventListener("onscroll", function(){
var elem = document.getElementsByClassName("cont_2")[0];
CheckIfVisible(elem);
});
window.addEventListener("onscroll", function(){
var elem = document.getElementsByClassName("cont_3")[0];
CheckIfVisible(elem);
});
and so on...
I have a one page, scrolling site with 5 main sections that have title bars that span across the top of each respective section. I want each title bar to stick at the top (well, relative top-underneath the top sticky header) as you scroll down the section. I can get one to stick, but I am having trouble making it so that one sticks and then it goes away once the next section's title bar gets to the sticky point.
I can't figure out another way to bind the HTML or CSS with the jQuery if else statement to make this work. I was thinking I could try to make it work within each sections' id but I don't think there's like a "withinId" jQuery selector.
I'm posting the latest jQuery I attempted (with just 2 out of the 5 variables I will need to make work here). I know it's wrong but I'm seriously stuck. Any ideas here? Thanks a million.
(abbreviated) HTML:
<div id="welcome">
<div class="title-bar">
<p>WELCOME</p>
</div>
</div>
<div id="global">
<div class="title-bar">
<p>GLOBAL ENGAGEMENT</p>
</div>
</div>
<div id="community">
<div class="title-bar">
<p>COMMUNITY</p>
</div>
</div>
<div id="resources">
<div class="title-bar">
<p>RESOURCES</p>
</div>
</div>
<div id="horizon">
<div class="title-bar">
<p>ON THE HORIZON</p>
</div>
</div>
CSS:
.title-bar {
padding: 5px;
position: relative;
}
.title-bar.sticky {
position: fixed;
top: 111px;
width: 100%;
z-index: 1040;
}
jQuery:
$(document).ready(function() {
var welcomeTitle = $('#welcome .title-bar');
var globalTitle = $('#global .title-bar');
var communityTitle = $('#community .title-bar');
var resourcesTitle = $('#resources .title-bar');
var horizonTitle = $('#horizon .title-bar');
var stickyOffset = $('#header').offset().top;
if ($w.scrollTop() > stickyOffset + 225) {
welcomeTitle.addClass('sticky');
globalTitle.addClass('sticky');
} else {
welcomeTitle.removeClass('sticky');
globalTitle.addClass('sticky');
}
if (welcomeTitle.hasClass('sticky') && globalTitle.hasClass('sticky')) {
welcomeTitle.removeClass('sticky');
} else {
//
}
});
jsBin demo
Give your "pages" a class="page" and listen for their positions using JS's Element.getBoundingClientRect on: DOM Ready, window Load, window Scroll
$(function() { // DOM ready
var $win = $(window),
$page = $(".page").each(function(){
// Memorize their titles elements (performance boost)
this._bar = $(this).find(".title-bar");
});
function fixpos() {
$page.each(function(){
var br = this.getBoundingClientRect();
$(this._bar).toggleClass("sticky", br.top<0 && br.bottom>0);
});
}
fixpos(); // on DOM ready
$win.on("load scroll", fixpos); // and load + scroll
});
*{box-sizing: border-box;}
html, body{height:100%;}
body{margin:0;font:16px/1 sans-serif; color:#777;}
.page{
position:relative;
min-height:100vh;
}
.title-bar {
position: absolute;
top:0;
width: 100%;
background:#fff;
box-shadow: 0 3px 4px rgba(0,0,0,0.3);
}
.title-bar.sticky {
position: fixed;
}
#welcome {background:#5fc;}
#global {background:#f5c;}
#community{background:#cf5;}
#resources{background:#fc5;}
#horizon {background:#5cf;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="welcome" class="page">
<div class="title-bar">
<h2>WELCOME</h2>
</div>
</div>
<div id="global" class="page">
<div class="title-bar">
<h2>GLOBAL ENGAGEMENT</h2>
</div>
</div>
<div id="community" class="page">
<div class="title-bar">
<h2>COMMUNITY</h2>
</div>
</div>
<div id="resources" class="page">
<div class="title-bar">
<h2>RESOURCES</h2>
</div>
</div>
<div id="horizon" class="page">
<div class="title-bar">
<h2>ON THE HORIZON</h2>
</div>
</div>
Design-wise > add a padding-top to the first container element (inside your .page) to prevent content going underneath the title element (since it toggles from absolute/fixed positions).
Have a look at the Waypoints plugin.
You can probably make it a little easier on yourself by assigning each section a class and then add and remove the class from each section with jquery each function.
Try something like the following:
$(window).on( "scroll", function() {
$( ".section" ).each(function() {
if ( $(window).scrollTop() >= $(this).offset().top - 50 ) {
$( this ).addClass("sticky");
}else{
$( this ).removeClass("sticky");
}
});
});
Then your css
.section{
height: 200px;
background: #333;
border:1px solid #222;
position:relative;
}
.section .title-bar{
position:absolute;
top:0;
left:0;
width:100%;
height:50px;
}
.section.sticky .title-bar {
position:fixed;
}
And html
<div class="section">
<div class="title-bar"></div>
</div>
<div class="section">
<div class="title-bar"></div>
</div>
<div class="section">
<div class="title-bar"></div>
</div>
I'm very new to javascript and jQuery and has now got completely stuck despite trying various options. I'm trying to create a expand/collapse section with multiple divs. I would like each div to open and close seperately, with an arrow at the side pointing up or down, depending whether the content is expanded or collapsed.
From the code I have written below, only the first div works correctly. The only thing which happen When you click on the two other divs, is that the arrow in the first div change.
Any help will be greatly appreciated.
Following is the CSS:
#header_background {
background-image: url(header-background.png);
width:748px;
height:43px;
margin-left: -17px;}
#expand_arrow {
display: inline-block;
width: 17px;
height: 18px;
float:left;
margin-left:20px;
padding-left:0px;
padding-top:11px;
background-repeat:no-repeat; }
.sub_header {
color:#204187;
font-weight:bold;
font-size:16px;
vertical-align:middle;
padding-left:4px;
padding-top:12px;
float:left;
text-decoration:none;
}
Here's the attempted javascript and jQuery:
function chngimg() {
var img = document.getElementById('expand_arrow').src;
if (img.indexOf('expand-arrow.png')!=-1) {
document.getElementById('expand_arrow').src = 'images/collapse-arrow.png';
}
else {
document.getElementById('expand_arrow').src = 'images/expand-arrow.png';
}
}
$(document).ready(function(){
$("#header_background").click(function(){
$("#section").slideToggle("slow");
});
});
And here's the HTML
<div id="header_background" >
<img id="expand_arrow" alt="" src="images/collapse-arrow.png" onclick="chngimg()">
<div class="sub_header" onclick="chngimg()">header 1</div>
</div>
<div id="section" style="display:none">
text 1
</div>
<div id="header_background" >
<img id="expand_arrow" alt="" src="images/collapse-arrow.png" onclick="chngimg()">
<div class="sub_header" onclick="chngimg()">header 2</div>
</div>
<div id="section" style="display:none">
text 2
</div>
<div id="header_background" >
<img id="expand_arrow" alt="" src="images/collapse-arrow.png" onclick="chngimg()">
<div class="sub_header" onclick="chngimg()">header 3</div>
</div>
<div id="section" style="display:none">
text 3
</div>
It's only working for the first set of elements because you're using IDs, and IDs have to be unique within the document (page). You could change to using classes and perform some simple DOM traversal to get the corresponding section based on the header that was clicked. Something like this:
$(document).ready(function() {
$('.header_background').click(function(e) {
$(this).next('.section').slideToggle('slow');
var img = $(this).find('img.expand_arrow')[0]; // the actual DOM element for the image
if (img.src.indexOf('expand-arrow.png') != -1) {
img.src = 'images/collapse-arrow.png';
}
else {
img.src = 'images/expand-arrow.png';
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="header_background" >
<img class="expand_arrow" alt="" src="images/collapse-arrow.png">
<div class="sub_header">header 1</div>
</div>
<div class="section" style="display:none">
text 1
</div>
<div class="header_background" >
<img class="expand_arrow" alt="" src="images/collapse-arrow.png">
<div class="sub_header">header 2</div>
</div>
<div class="section" style="display:none">
text 2
</div>
<div class="header_background" >
<img class="expand_arrow" alt="" src="images/collapse-arrow.png">
<div class="sub_header">header 3</div>
</div>
<div class="section" style="display:none">
text 3
</div>
Look for your next section of the header clicked like so. And change your id for class because ID need to be unique
$(".header_background").click(function(){
$(this).nextAll(".section:first").slideToggle("slow");
});
This a continued question from this post:
Add style to random loaded divs I have now tried to simplify this question as much as possible.
Here goes:
Using this code I am trying to add style to randomly loaded items depending in what order they are loaded.
<script>
$(document).ready(function(){
var divs = $("div.item").get().sort(function(){
return Math.round(Math.random())-0.5;
}).slice(0,6)
$(divs).each(function( index ) {
if(index==1 || index==3)
$(this).css("margin-left", "0%");
else
$(this).css("margin-left", "2%"); //or whatever left value you need
});
$(divs).show();
});
</script>
I need the .item bars to line up as in this picture
So far this only ocurs by chance every so many times you refresh the browser.
I think if you try it yourself you'll see what the problem
Here is the whole shebang for a quick copy/paste
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.2.js"></script>
<style>
.container {width:750px; background-color:#CCC; height:200px; padding-top:70px; margin: 0 auto; margin-top:5%}
.item {display:none; text-align:center; width:32%; float:left}
</style>
<script>
$(document).ready(function(){
var divs = $("div.item").get().sort(function(){
return Math.round(Math.random())-0.5;
}).slice(0,6)
$(divs).each(function( index ) {
if(index==1 || index==3)
$(this).css("margin-left", "0%");
else
$(this).css("margin-left", "2%"); //or whatever left value you need
});
$(divs).show();
});
</script>
</head>
<body>
<div class="container">
<div class="item" style="background-color:#F00">1</div>
<div class="item" style="background-color:#9F0">2</div>
<div class="item" style="background-color:#FF0">3</div>
<div class="item" style="background-color:#939">4</div>
<div class="item" style="background-color:#3CF">5</div>
<div class="item" style="background-color:#CF3">6</div>
<div class="item" style="background-color:#6C9">7</div>
<div class="item" style="background-color:#999">8</div>
<div class="item" style="background-color:#90F">9</div>
<div class="item" style="background-color:#FF9">10</div>
<div class="item" style="background-color:#099">11</div>
<div class="item" style="background-color:#666">12</div>
</div>
</body>
</html>
Because you are not randomizing the DOM order, only what divs to include in the divs array. The order is still numerical.
So when looping the divs using $.each(divs), you are looping the random order you created, but the DOM order is still untouched (if that makes sense). You could say that divs and $('div.items') are out of sync.
You can try this instead: (DEMO: http://jsbin.com/aSejiWA/3)
$(document).ready(function(){
var divs = $("div.item").get().sort(function(){
return Math.round(Math.random())-0.5;
}).slice(0,6);
$(divs).addClass('show'); // to re-select the visual items
$('.item.show').each(function( index ) {
$(this).css('margin-left', index%3 ? '2%' : 0);
}).show();
});
It is because the divs you are looping over won't always match the order of your divs in markup, which means you'll be applying the wrong margins. Try the code below:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.2.js"></script>
<style>
.container {width:750px; background-color:#CCC; height:200px; padding-top:70px; margin: 0 auto; margin-top:5%}
.item {display:none; text-align:center; width:32%; float:left}
</style>
<script>
$(document).ready(function(){
var $container = $('div.container'),
divs = $("div.item").get().sort(function(){
return Math.round(Math.random())-0.5;
}).slice(0,6),
<!-- Make a clone, leaving original pot untouched -->
$clonedDivs = $(divs).clone();
<!-- Clear container -->
$container.html('');
<!-- Append new divs to container -->
$clonedDivs.each(function( index ) {
$container.append(this);
if (index % 3 == 0) {
$(this).css("margin-left", "0%");
} else {
$(this).css("margin-left", "2%"); //or whatever left value you need
}
});
$clonedDivs.show();
});
</script>
</head>
<body>
<div class="pot">
<div class="item" style="background-color:#F00">1</div>
<div class="item" style="background-color:#9F0">2</div>
<div class="item" style="background-color:#FF0">3</div>
<div class="item" style="background-color:#939">4</div>
<div class="item" style="background-color:#3CF">5</div>
<div class="item" style="background-color:#CF3">6</div>
<div class="item" style="background-color:#6C9">7</div>
<div class="item" style="background-color:#999">8</div>
<div class="item" style="background-color:#90F">9</div>
<div class="item" style="background-color:#FF9">10</div>
<div class="item" style="background-color:#099">11</div>
<div class="item" style="background-color:#666">12</div>
</div>
<div class="container">
</div>
</body>
</html>