Expand side area based on the content of the first one - javascript

I'm trying expand one area based on the height of the other with jQuery. However, the first area has dynamic content, so I can't set a fixed value as I did in JS code (line 6, with 175px of height).
I have an example here: https://codepen.io/anon/pen/VyEZjv.
HTML
<div>
<div class="columns row-8">
<section id="summary" class="area">
<main>
<div id="details">
<div>bla bla</div>
<div>bla bla</div>
<div>bla bla</div>
</div>
<div id="more-details" class="hide">
<div>more bla bla</div>
<div>more bla bla</div>
<div>more bla bla</div>
</div>
</main>
<footer>
<button id="more-details-link">View more details</button>
</footer>
</section>
</div>
<div class="columns row-4">
<section id="activity" class="area">
<main>
<ul>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
</ul>
</main>
<footer>
<a id="full-activity" href="#">See full activity</a>
</footer>
</section>
</div>
</div>
JS:
var minHeight = $('#summary > main').height();
$('#activity > main').height(minHeight);
$('#more-details-link').on('click', function(){
if ($('#more-details').is(':hidden')) {
$('#more-details').slideDown();
// I don't want to set a fixed value, because the first area content may vary
$('#activity > main').animate({height: '115px'});
} else {
$('#more-details').slideUp();
$('#activity > main').animate({height: minHeight});
}
});
So, the first area has two divs: one is always shown and the other one is hidden by default. When I click the expand button, this area will slide down to show the hidden div. I want the second area to expand as well, using the same slide effect, and keep the same height of the first area.
The only way I achieved it was sliding the second area after the first one, not along.
Thanks in advance.
(edit) To be more specific, I want the second area to be the same height as the first one. So, I if the first area is 100px height while collapsed, the second one will have 100px height too. If I expand the first area to 500px, the second one must have the same 500px.
I don't want to set a fixed height to the second area, like I did in the js code. I need to get the first area height and set the same value to the second one. I can't get the height of the first one right after the slideDown() because it's an async function and I'll get the wrong height.
PS: I'm limited to jQuery and CSS to this.

In order to be able to expand both sections simultaneously, you need to know the height the largest one occupies when expanded.
To make this happen, I use below probably the ugliest trick out there:
/* Show and hide '#more-details' instantly to find out the height it reaches. */
var maxHeight;
$('#more-details').show();
maxHeight = $('#summary > main').height();
$('#more-details').hide();
When you get this done, you now only have to substitute '115px' in your event listener with maxHeight:
$('#more-details').slideDown();
$('#activity> main').animate({height: maxHeight});
Check out the following snippet for more.
Snippet:
/* ----- JavaScript ----- */
var
/* Cache summary, activity and more-details. */
summary = $('#summary > main'),
activity = $('#activity > main'),
moreDetails = $('#more-details'),
/* Cache the height of the summary. */
minHeight = summary.height(),
maxHeight;
/* Set the activity to match the summary's height. */
activity.height(minHeight);
/* Show and hide '#more-details' instantly to find out the height it reaches. */
moreDetails.show();
maxHeight = summary.height();
moreDetails.hide();
/* Set the 'click' event of the link. */
$('#more-details-link').on('click', function(){
if (moreDetails.is(':hidden')) {
moreDetails.slideDown();
activity.animate({height: maxHeight});
} else {
moreDetails.slideUp();
activity.animate({height: minHeight});
}
});
/* ----- CSS ----- */
main {padding: 7px}
footer {border-top: 1px solid #000}
.columns {float: left;margin: 10px}
.row-8 {width: 200px}
.row-4 {width: 200px}
.area {background-color: #AAA}
.hide {display: none}
#activity>main {overflow: hidden}
<!----- HTML ----->
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<div>
<div class="columns row-8">
<section id="summary" class="area">
<main>
<div id="details">
<div>bla bla</div>
<div>bla bla</div>
<div>bla bla</div>
</div>
<div id="more-details" class="hide">
<div>more bla bla</div>
<div>more bla bla</div>
<div>more bla bla</div>
</div>
</main>
<footer>
<button id="more-details-link">View more details</button>
</footer>
</section>
</div>
<div class="columns row-4">
<section id="activity" class="area">
<main>
<ul>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
<li>activity</li>
</ul>
</main>
<footer>
<a id="full-activity" href="#">See full activity</a>
</footer>
</section>
</div>
</div>

I'm not sure I understand your question well
If you want to expand the two sections at the same time, what about a multiple selector
$('#full-activity, #activity > main')
in
$('#more-details-link').on('click', function(){
...
$('#full-activity, #activity > main').animate({height: '115px'});
...
$('#full-activity, #activity > main').animate({height: minHeight});

Related

jQuery scroll to specific height then slidedown div

Ok, so I've tried looking at everything on here and many people have suggested adding a width or a height or even using jquery css to hide elements, but nothing is working for me.
I am trying to have 3 elements slideDown when the user scrolls to a specific section of the page. The problem is that the 3 elements flash on the screen for a brief moment then slide down. How do I remove the brief flash?
$('#e1, #e2, #e3').hide();
$(window).scroll(function() {
var height = $(window).scrollTop();
if (height > 400) {
$('#e1').slideDown(1500);
$('#e2').slideDown(2000);
$('#e3').slideDown(2500);
}
});
DIV#customContent DIV.customObj {
float: left;
width: 406px;
}
DIV#customContent DIV.customObj DIV {
display: none;
margin: 15px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="customContent">
<div class="customObj">
<h3>Service</h3>
<div id="e1">
<ul>
<li>business offices</li>
<li>hotels</li>
<li>multi-family dwellings</li>
<li>higher traffic</li>
<li>passenger and freight</li>
<li>elevators</li>
<li>escalators</li>
<li>wheel chair lifts</li>
<li>dumbwaiters</li>
</ul>
</div>
</div>
<div class="customObj">
<h3>Modernization</h3>
<div id="e2">
<ul>
<li>business offices</li>
<li>hotels</li>
<li>multi-family dwellings</li>
<li>higher traffic</li>
<li>passenger and freight</li>
<li>elevators</li>
<li>escalators</li>
<li>wheel chair lifts</li>
<li>dumbwaiters</li>
</ul>
</div>
</div>
<div class="customObj">
<h3>Lift Solutions</h3>
<div id="e3">
<ul>
<li>business offices</li>
<li>hotels</li>
<li>multi-family dwellings</li>
<li>higher traffic</li>
<li>passenger and freight</li>
<li>elevators</li>
<li>escalators</li>
<li>wheel chair lifts</li>
<li>dumbwaiters</li>
</ul>
</div>
</div>
<div class="clear"></div>
</div>

How Do I Stop Static Sidebar at Footer

I have a static sidebar on scroll but when it reaches the footer it overlaps. Is there a way for me to stop this scrolling onto the footer? I understand this may be a simple concept but I have little experience working with the Scroll event in JQuery so any help would be fantastic.
Please find my code and a CodePen below.
<div id="main">
<div class="spacing">CONTENT HERE TO SHOW HOW THE SCROLL WILL WORK. PLEASE SCROLL DOWN</div>
<div class="container">
<div id="sidebar">
<div id="nav-anchor"></div>
<nav>
<ul>
<li>Blue</li>
<li>Green</li>
<li>Red</li>
<li>Yellow</li>
<li>Purple</li>
</ul>
</nav>
</div>
<!-- /sidebar -->
<div id="content">
<section id="blue">
...
</section>
<section id="green">
...
</section>
<section id="red">
...
</section>
<section id="yellow">
...
</section>
<section id="purple">
...
</section>
</div>
<!-- /#content -->
</div>
<!-- /.container -->
<footer>
<p>Footer here</p>
</footer>
</div>
<!-- /#main -->
$(document).ready(function(){
$(window).scroll(function(){
var window_top = $(window).scrollTop() + 12;
var div_top = $('#nav-anchor').offset().top;
if (window_top > div_top) {
$('nav').addClass('stick');
} else {
$('nav').removeClass('stick');
}
});
});
http://codepen.io/harryberry94/pen/MyOezg
If you want to hide the static element when it is overlapping the footer, add one more condition in your if condition after $('nav').addClass('stick'); :
var footer_top = $("footer").offset().top;
var static_div_bottom = $('nav').offset().top + $('nav').height();
$('#abc').text(footer_top +" " + static_div_bottom +" " + window_top);
if(static_div_bottom > footer_top){
$('nav').removeClass('stick');
}
You can use css for that if all you want is for your div not to overlap the footer, no need to use javascript and the scroll event. Just add z-index:-1; for nav.stick. Also if it needs a greater z-index to go over other elements in the page you can give the footer position:absolute; and a greater z-index (to keep content from going under the footer add padding-bottom to the body element).

Targeting all li's instead of just the first

I'm using the Superslides script to create a responsive slideshow for a site. I have created a basic caption box that I want to be hidden and then slide in from the bottom when the slide going with the caption is display.
In the Superslide script the current slide gets a higher z-index (of 2, otherwise it is set to 0) and a display: block (otherwise 'none') change to it when it's coming into view.
I am not very good with Javascript so I am having a bit of trouble targeting my captions to animate in at the right time. I put together a script that is supposed to evaluate all the li tags (each li is a different slide) and if it has a z-index of 2 it changes the bottom margin of the caption div so it slides into view. My problem is that my script only targets the very first li instead of running through all of them. For the first li it works great, I just need it to run though the rest of the li's as well. Any suggestions are appreciated!
Script:
var li = document.querySelector('li[style]'),
inlinezIndex = li.style.zIndex;
console.log(inlinezIndex);
if(inlinezIndex == 2){
document.getElementById('caption').style.bottom = '300px';
$('#caption').css({'transition': '10s'});
}
else{
document.getElementById('caption').style.bottom = '0px';
}
HTML:
<div id="slides">
<ul class="slides-container">
<li class="slide1">
<img src="images/people.jpeg" alt="Cinelli">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work1</p>
</div>
</li>
<li class="slide1">
<img src="images/surly.jpeg" width="1024" height="682" alt="Surly">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work1</p>
</div>
</li>
<li class="slide1">
<img src="images/cinelli-front.jpeg" width="1024" height="683" alt="Cinelli">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work2</p>
</div>
</li>
<li class="slide1">
<img src="images/affinity.jpeg" width="1024" height="685" alt="Affinity">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work3</p>
</div>
</li>
<li class="slide1">
<img src="images/cinelli-front.jpeg" width="1024" height="683" alt="Cinelli">
<div id="caption">
<h1>Hello</h1>
<h2>This is a test</h2>
<p>To see if I can get this to work4</p>
</div>
</li>
</ul>
<nav class="slides-navigation">
<i class="icon-chevron-right"></i>
<i class="icon-chevron-left"></i>
</nav>
</div>
Try using querySelectorAll instead of querySelector.
You could then loop through the li's and apply your styling, etc.
Also I see you are using multiple elements with the same id ("caption") and this is bad practice. Actually, I think it's invalid HTML according to the HTML5 specification as id's are supposed to be unique (look at this stackoverflow thread).
Example
var list = document.querySelectorAll('.slides-container li');
for (var i = 0; i < list.length; i++) {
var li = list[i];
var zIdx = li.style.zIndex;
// Use a class instead of id for captions
var caption = li.querySelector('.caption');
if (zIdx == 2) {
caption.style.bottom = '300px';
} else {
caption.style.bottom = '0px';
}
}
I'd also put css transitions in css (handy-dandy transitions):
.caption {
transition: bottom 10s;
}

Make One NAV link active across multiple sections (using classes???)

I need to have only one nav link in active state when a user goes through multiple sections of my website. How do I make the proper edits to this JS to make that happen?
For instance, if the default nav link id = #dinos_
I want all my sections that use section ids like #dinos_trex, #dinos_raptor, #dinos_triceratops to keep making the nav id that = #dinos_ to stay in the active state in the nav.
After further research, would someone be able to code something with 'classes'?
Lets say a set of divs share a certain class name, in this case "dinos_" how can I set an active state for just one nav item if the user is on 'any' of the related "dinos_" sections????
here is the current jquery Im using:
var sections = $('section'), nav = $('nav'), nav_height = nav.outerHeight();
$(window).on('scroll', function () {
var cur_pos = $(this).scrollTop();
sections.each(function() {
var top = $(this).offset().top - nav_height,
bottom = top + $(this).outerHeight();
if (cur_pos >= top && cur_pos <= bottom) {
nav.find('a').removeClass('active');
sections.removeClass('active');
$(this).addClass('active');
nav.find('a[href="#'+$(this).attr('id')+'"]').addClass('active');
}
});
});
Im guessing this snippet of code in particular is where I need someone to help me redefine?
nav.find('a[href="#'+$(this).attr('id')+'"]').addClass('active');
Here is my HTML
<header id="header">
<!-- Nav -->
<nav id="nav">
<ul>
<li>DINOS</li> /*multiple unique section ids that contain the word dinos_ in their id name should set this to 'active */
<li>ROBOTS</li> /*multiple unique section ids that contain the word robots_ in their id name should set this to 'active */
<li>UNDEAD</li> /*multiple unique section ids that contain the word undead_ in their id name should set this to 'active */
</ul>
</nav>
</header>
<section id="dinos_" class="main style2 right dark fullscreen">
<div class="content box style2">
<header>
<h2>DINOSAURS INTRO</h2>
</header>
<p>
Intro to the dinos</p>
</div>
up
down
</section>
<section id="dinos_trex" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>T-REX</h2>
</header>
<p>
Section for the T-rex</p>
</div>
up
down
</section>
<section id="dinos_raptor" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>THE RAPTOR</h2>
</header>
<p>
Section for the raptor/p>
</div>
up
down
</section>
<section id="robots_" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>ROBOTS INTRO</h2>
</header>
<p>
Section for the Robots Intro</p>
</div>
up
down
</section>
<section id="robots_gunner" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>THE ROBOT GUNNER</h2>
</header>
<p>
Section for the gunner</p>
</div>
up
down
</section>
Using the waypoints plugin:
http://imakewebthings.com/waypoints/
UPDATED
JS:
$('section').waypoint({
handler: function (direction) {
$(".active").removeClass("active");
$("nav a[href=\"#" +this.element.id + "\"").addClass("active");
}
});
HTML with some minor changes:
<header id="header">
<!-- Nav -->
<nav id="nav">
<ul>
<li>DINOS
</li>
<li>ROBOTS
</li>
<li>UNDEAD
</li>
</ul>
</nav>
</header>
<section id="dinosaurs" class="main style2 right dark fullscreen">
<div class="content box style2">
<header>
<h2>DINOSAURS INTRO</h2>
</header>
<p>Intro to the dinos</p>
</div> up
down
</section>
<section id="dinosaurs_trex" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>TREX</h2>
</header>
<p>Section for the Trex</p>
</div> up
down
</section>
<section id="dinosaurs_raptor" class="main style2 left dark fullscreen">
<div class="content box style2">
<header>
<h2>THE RAPTOR</h2>
</header>
<p>Section for the Trex</p>
</div> up
down
</section>
Here's a fiddle:
http://jsfiddle.net/4qwawrgx/
change your this code
nav.find('a[href="#'+$(this).attr('id')+'"]').addClass('active');
to this
function activateNav() {
var hashValue = window.location.hash.substr(1);
$('body').find('a[href="#'+ hashValue +'"]').addClass('active');
}
$( document ).ready(function() {
activateNav();
$('a').on('click', function() {
activateNav();
});
});

Using JQuery hashtags to fade in & fade out content of a certain div

*EDIT: Here's a link to a staging version of the site: http://staging-site.site44.com/ *
I am extremely new to jquery so I apologize if this question is extremely simple. What I'm trying to do on my website is first when the page is loaded have the content in my #topContent div fade in.
But along with this I'd also like my main navigation to use jquery hashtags to switch up the page content displayed in the #topContent div. I've read up a bit on how to do this in jquery and from what I've read I think I need create page sections within my main html doc that are hidden until a certain nav link is selected - then hide the content that is currently showing and show the content associated with the nav link that was just selected, how close am I?
Here's my attempt so far at doing this...
HTML
<nav id="headerNav">
<ul class="navList">
<li class="navItem">Products</li>
<li id="view-about" class="navItem">About</li>
<li class="navItem">Portfolio</li>
<li class="navItem">Contact</li>
</ul>
</nav>
</div>
</div>
<!-- topMain -->
<div id="topContentWrapper">
<div id="topContent">
<div id="#products">
<h2>Test worked! - products </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="#about">
<h2>Test worked! - about </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="#portfolio">
<h2>Test worked! - Portfolio </h2>
<p>this test just worked sooo hard!</p>
</div>
</div>
</div>
JS
// Fade In Effect
$(document).ready(function() {
$("#topContent").css("display", "none");
$("#topContent").fadeIn(2000);
$("a.transition").click(function(event){
event.preventDefault();
linkLocation = this.href;
$("#topContent").fadeOut(1000);
});
function redirectPage() {
window.location = linkLocation;
}
$("#view-about").click(function(event){
$("#products").fadeOut(1000);
$("#portfolio").fadeOut(1000);
$("#about").fadeIn(1000);
});
});
Ok, this code should work:
$(function(){
$last = null;
$(".navList li a").click(function(){
if ($last != null) $last.fadeOut(1000);
$last = $($(this).attr("href"));
$($(this).attr("href")).fadeIn(2000);
});
});
However, you will need to change your topContent to this:
<div id="topContent">
<div id="products" style="display: none;">
<h2>Test worked! - products </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="about" style="display: none;">
<h2>Test worked! - about </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="portfolio" style="display: none;">
<h2>Test worked! - Portfolio </h2>
<p>this test just worked sooo hard!</p>
</div>
</div>
Reasons:
Firstly, you need your ids to be like this: id="about" and not this: id="#about".
The id specified doesn't need a # in front of it. (Same as how class doesn't need a . when setting a tag with it)
The jQuery code I tested locally, so it should work.
Note:
You may want to automatically have some different content automatically displayed, because right now as it loads it is blank until you click one of the links.
Hope this helped!
Edit:
I suggest you change the code to this:
ids = [ "products", "about", "portfolio" ];
links = [ "Products", "About", "Portfolio" ];
$(function(){
$last = null;
$(".navList li a").click(function(){
New = "#" + ids[links.indexOf($(this).text())];
if ($last != null) $last.fadeOut(1000);
$last = $(New);
$(New).fadeIn(2000);
});
});
Because it will keep all the content constantly in the same place. For this to work, you'll need to change two more sections of your code:
<ul class="navList">
<li class="navItem">Products</li>
<li id="view-about" class="navItem">About</li>
<li class="navItem">Portfolio</li>
<li class="navItem">Contact</li>
</ul>
And:
<div id="topContent">
<div id="products" style="display: none; position: absolute">
<h2>Test worked! - products </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="about" style="display: none; position: absolute">
<h2>Test worked! - about </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="portfolio" style="display: none; position: absolute">
<h2>Test worked! - Portfolio </h2>
<p>this test just worked sooo hard!</p>
</div>
</div>
That last part was just my suggestion, but do whatever you need to.
Instead of doing this in your a.transition handler:
$("#topContent").fadeOut(1000);
do:
$("#topContent").children().fadeOut(1000);
The issue is that you're actually fading out the higher level item thus the children are no longer visible even if you fade them in.

Categories

Resources