I have a list which serves as a menu. Every time user clicks on one of the elements in the list, I want a more detailed div to slide in from left to right.
So if the user was to click menu item A first, A slides from left to right. If the user then clicks B, A slides out from right to left (disappears off screen) and B slides in.
I searched for this problem and found this post. I incorporated the code from the jsfiddle, but it didn't work. No errors are being shown in the js log in Chrome debugging tool. Nothing happens when I click any item from the menu. What am I doing wrong?
<div class="project">
<ul id="project_menu" class="project_menu">
<li id="menu-php-mysql" data-projectID="php-project">PHP/MySQL</li>
<li id="menu-nodejs" data-projectID="node-project">NodeJS</li>
<!-- more code -->
</ul>
<div class="project-detail">
<div id="php-project">
<i class="ion-ios-close-empty close-icon js-close-icon"></i>
<div classs="project-text">
<!-- data about project -->
</div>
</div>
<div id="node-project">
<i class="ion-ios-close-empty close-icon js-close-icon"></i>
<div classs="project-text">
<!-- data about project -->
</div>
</div>
<!-- and so on.. -->
#php-project {
background-color: #9b59b6;
margin: 30px;
display: none;
}
$(document).ready(function() {
itemsToRender = [];
$('ul#project_menu li').click(function(e) {
menuItemId = (e.currentTarget.id);
$('.common').hide();
$(getProjectId(menuItemId)).css('display', 'inline');
var value = $(getProjectId(menuItemId)).css('right') === '100px' ? '-100px' : '100px';
$(getProjectId(menuItemId)).animate({
right: value
}, 800);
});
});
function getProjectId(menuItemId) {
if (menuItemId.indexOf('php') > 0) {
return '#php-project';
} else if (menuItemId.indexOf('node') > 0) {
return '#node-project';
} else if (menuItemId.indexOf('angular') > 0) {
return '#angular-project';
} else if (menuItemId.indexOf('mean') > 0) {
return '#mean-project';
}
}
Update1: #user5325596 pointed out that my display property for the detail div was set to none, so I fixed that by adding the following:
$(getProjectId(menuItemId)).css('display', 'inline-block');
right after $('.common').hide().
Now, I can see the detail div when I click on the menu item, but it does not animate.
Update2: I have uploaded a jsFiddle, it includes the jquery animation that I am successfully using (fadeIn, which is commented out), as well as the code suggested by elchininet.
Not sure if this is what you need or not
JS Fiddle - updated 2
// initializing
var prevID = '',
divs = $('.sliding-divs');
$("li").on("click", function() {
var theID, theDiv, theDivW, theCenter;
// get the id letter from the li, then pick the corresponding sliding
// div depending on its value.
theID = $(this).attr('id');
theID = theID.replace('li-', '');
theDiv = $('#div-' + theID);
// get the divs width to slide it into the center of the view
theDivW = theDiv.width();
theCenter = $(window).width()/2 - theDivW/2;
// if the user didn't click the link which its slide already
// in the view, this to avoid sliding out and in same div.
if(theID != prevID){
if (prevID == '') {
// if we don't have a previously slided in div, we just slide
// the just click link's div into the view
theDiv.animate({'left': theCenter}, 1000);
} else {
// animated the previous div to the right out of the view, then
// move all divs to their original position out from the left
// this is because if we don't do this, an already slided div
// will later be slided in from right instead in from left
// because we have already changed its position.
// slide the just clicked link's div into the view from left
$('#div-' + prevID).animate({'left': '110%'}, 800);
divs.css({'left':-(theDivW + 100)});
theDiv.animate({'left': theCenter}, 1000);
}
}
// change the value of the id representing previously slided in div
prevID = theID;
});
body {
overflow-x: hidden;
}
ul {
list-style: none;
padding: 0;
}
li {
width: 100px;
height: 25px;
margin: 2px 0;
color: white;
padding: 3px;
text-align: center;
background-color: green;
cursor:pointer;
}
.sliding-divs {
position: absolute;
width: 500px;
line-height: 250px;
background-color: orange;
font-size: 30px;
border: 2px gold solid;
text-align: center;
display: inline-block;
top: 150px;
left: -510px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul>
<li id="li-A">item 1</li>
<li id="li-B">item 2</li>
<li id="li-C">item 3</li>
<li id="li-D">item 4</li>
</ul>
<div class="sliding-divs" id="div-A">
DIV A
</div>
<div class="sliding-divs" id="div-B">
DIV B
</div>
<div class="sliding-divs" id="div-C">
DIV C
</div>
<div class="sliding-divs" id="div-D">
DIV D
</div>
Try with CSS transitions, will save a lot of code. Maybe this is not exactly that you want but I'm sure it'll helps you with your task.
HTML Code
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
</ul>
CSS Code
li{
-webkit-transition: all 1s;
-moz-transition: all 1s;
transition: all 1s;
}
li.open{
-webkit-transform: translateX(100px);
-moz-transform: translateX(100px);
transform: translateX(100px);
}
jQuery Code
$("li").on("click", function(){
$("li.open").removeClass("open");
$(this).addClass("open");
});
jsfiddle
Here you have a jsfiddle with your code modified and the div animations in css.
jsfiddle with part of your code.
There are some minor mistakes i found on fiddle like , comma between class name. : class="project-container,common"
You are hiding all div with class .common, but not show it after. so its style property get display:none even if you add class open to that div.
Here is my Updated and running code:
$(document).ready(function() {
itemsToRender = [];
$('ul#project_menu li').click(function(e) {
$('.common').hide();
menuItemId = (e.currentTarget.id);
var projectId = getProjectId(menuItemId);
console.log(projectId);
$('.project-container.open').removeClass('open');
$(projectId).addClass('open');
$(projectId).show();
/* $(projectId).fadeIn('slow'); <--- THIS WORKS! But I want the slide effect instead */
});
function getProjectId(menuItemId) {
if (menuItemId.indexOf('php') > 0) {
return '#php-project';
} else if (menuItemId.indexOf('node') > 0) {
return '#node-project';
} else if (menuItemId.indexOf('angular') > 0) {
return '#angular-project';
} else if (menuItemId.indexOf('mean') > 0) {
return '#mean-project';
} else if (menuItemId.indexOf('html5-css3-js') > 0) {
return '#html-css-js-project';
}
}
});
.project-detail {
float: right;
max-width: 50%;
margin-right: 75px;
color: #fff;
}
#php-project {
background-color:#9b59b6;
margin: 30px;
display:none;
}
#node-project {
background-color:#27ae60;
margin: 30px;
display:none;
}
.project-container{
transition: all 1s;
-webkit-transition: all 1s;
-moz-transition: all 1s;
}
.project-container.open{
transform: translateX(-200px);
-webkit-transform: translateX(-200px);
-moz-transform: translateX(-200px);
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="project">
<ul id="project_menu" class="project_menu">
<li id="menu-php-mysql" data-projectID="php-project">PHP/MySQL</li>
<li id="menu-nodejs" data-projectID="node-project">NodeJS</li>
</ul>
<div class="project-detail">
<div id="php-project" class="project-container common">
<i class="ion-ios-close-empty close-icon js-close-icon"></i>
<div classs="project-text">
<h2 class="project-label">Project title: <span class="project-name"> php project</span></h2>
</div>
</div> <!-- end of php-project -->
<div id="node-project" class="project-container common">
<i class="ion-ios-close-empty close-icon js-close-icon"></i>
<div classs="project-text">
<h2 class="project-label">Project title: <span class="project-name"> node project</span></h2>
</div>
</div> <!-- end of node-project -->
</div> <!-- end of project-detail -->
</div> <!-- end of project -->
I think you want this to work like in this fiddle
HTML Code
<div class="project">
<ul id="project_menu" class="project_menu">
<li id="menu-php-mysql" data-projectID="php-project">PHP/MySQL</li>
<li id="menu-nodejs" data-projectID="node-project">NodeJS</li>
<!-- more code -->
</ul>
<div class="project-detail">
<div id="php-project">
<i class="ion-ios-close-empty close-icon js-close-icon"></i>
<div classs="project-text">
PHP project text
<!-- data about project -->
</div>
</div>
<div id="node-project">
<i class="ion-ios-close-empty close-icon js-close-icon"></i>
<div classs="project-text">
Node Project Text
<!-- data about project -->
</div>
<!-- and so on.. -->
</div>
</div>
</div>
CSS Code
.project_menu > li{
cursor: pointer;
}
.project-detail{
width: 300px;
height: 100px;
background-color: #dedede;
overflow: hidden;
position: relative;
}
JQuery
$(document).ready(function() {
$('.project-detail > div:first-child').css("right","0px");
itemsToRender = [];
$('#project_menu li').click(function(e) {
menuItemId = (e.currentTarget.id);
$('.common').hide();
$(getProjectId(menuItemId)).css('display', 'inline');
var value = '0px';
$(getProjectId(menuItemId)).animate({
right: '0px'
}, 800);
var req = '.project-detail > div';
$('.project-detail > div').not($(getProjectId(menuItemId))).animate({
right: '300px'
}, 800);
});
});
function getProjectId(menuItemId) {
if (menuItemId.indexOf('php') > 0) {
return '#php-project';
} else if (menuItemId.indexOf('node') > 0) {
return '#node-project';
} else if (menuItemId.indexOf('angular') > 0) {
return '#angular-project';
} else if (menuItemId.indexOf('mean') > 0) {
return '#mean-project';
}
}
Related
I have a list of div items which I am filtering/sorting via JS.
Each item animates in to place - in this case, scales up to its final size.
When I filter the items via buttons, anything already on screen DOES NOT play this animation again.
How can I RESET the filter every time a new button is selected, so EVERY item ALWAYS animates in to place no matter what is being filtered and whether or not it is currently on screen?
WORKING CODEPEN HERE
<div class="filter-list">
<button class="active btn" id="all">All</button>
<button class="btn" id="oranges">Oranges</button>
<button class="btn" id="apples">Apples</button>
<button class="btn" id="bananas">Bananas</button>
</div>
<div class="grid">
<div class="artist-img item oranges">oranges</div>
<div class="artist-img item apples">apples</div>
<div class="artist-img item bananas">oranges</div>
</div>
JS
var $items = $(".item");
var $btns = $(".btn").click(function () {
if (this.id == "all") {
$items.show();
} else {
var $el = $("." + this.id).show();
$items.not($el).hide();
}
$btns.removeClass("active");
$(this).addClass("active");
});
CSS
#keyframes entrance {
0% {
transform: scale(0.5);
}
100% {
transform: scale(1);
}
}
.grid > div {
padding: 1rem;
position: relative;
animation-duration: 0.5s;
animation-name: entrance;
}
To reset the elements you have to get them back to the 0% on the animation. The easiest way to do that is to hide them all first. So instead of hiding all the ones that are not currently selected, hide everything first, then show what you want to show after that. Now immediately hiding and showing does not give the time needed for the first element to get back to 0%, so set a timeout for 1 ms to give it time. Here is the modified code:
var $items = $(".item");
var $btns = $(".btn").click(function() {
$items.hide();
setTimeout(() => {
if (this.id == "all") {
$items.show();
} else {
$("." + this.id).show();
}
}, 1);
$btns.removeClass("active");
$(this).addClass("active");
});
button {
padding: 1rem;
}
.filter-list {
margin: 1rem;
}
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 1rem;
row-gap;
1rem;
}
.grid>div {
background: #000;
padding: 3rem;
animation-duration: 0.5s;
animation-name: entrance;
color: #fff;
}
#keyframes entrance {
0% {
transform: scale(0.5);
}
100% {
transform: scale(1);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filter-list">
<button class="active btn" id="all">All</button>
<button class="btn" id="oranges">Oranges</button>
<button class="btn" id="apples">Apples</button>
<button class="btn" id="bananas">Bananas</button>
</div>
<div class="grid">
<div class="artist-img item oranges">
oranges
</div>
<div class="artist-img item apples">
apples
</div>
<div class="artist-img item oranges">
oranges
</div>
<div class="artist-img item oranges">
oranges
</div>
<div class="artist-img item apples">
apples
</div>
<div class="artist-img item bananas">
bananas
</div>
<div class="artist-img item apples">
apples
</div>
<div class="artist-img item bananas">
bananas
</div>
</div>
Does this JS achieve what you want?
var $items = $(".item");
var $btns = $(".btn").click(function () {
if (this.id == "all") {
$items.show();
} else {
$items.hide();
var $el = $("." + this.id).show();
// $items.not($el).hide();
}
$btns.removeClass("active");
$(this).addClass("active");
});
I'm using owl carousel on a menu.
when I scroll to the div the owl carousel auto slide to the right slides.
now when I arrived in the specific div I add class to the slide (active) but for some reason, I can't remove the active class from the other slides (his siblings).
I think it will be best to check the jsfiddle to understand the problem...
<div class="body">
<div class="menu">
<ul class="owl-carousel owl-theme">
Review
a
b
c
d
e
f
</ul>
</div>
JS file
$('.owl-carousel').owlCarousel({
nav: false,
dots: false,
singleItem: true,
})
var owl = $('.owl-carousel');
owl.owlCarousel();
$( window ).scroll(function() {
let scrollbarLocation = $(this).scrollTop();
let scrollLinks = $('.item');
scrollLinks.each(function(){
let sectionOffset = $(this.hash).offset().top;
if (sectionOffset <= scrollbarLocation){
$(this).siblings().removeClass('active-link');
$(this).addClass('active-link');
let goToSlide = $(this).attr('data-num')
owl.trigger('to.owl.carousel', goToSlide);
}
})
if( scrollbarLocation === 0){
scrollLinks.removeClass('active-link');
owl.trigger('to.owl.carousel', 0);
}
});
check https://jsfiddle.net/jt31h4pr/132/
The problem is that you remove/add active-link class on the same element ( this ). You need to removeClass only on the the element that already has class active-link.
The class active is controlled by the plugin and all the elements that are visible have the active class
See below
$('.owl-carousel').owlCarousel({
nav: false,
dots: false,
singleItem: true,
})
var owl = $('.owl-carousel');
owl.owlCarousel();
$( window ).scroll(function() {
let scrollbarLocation = $(this).scrollTop();
let scrollLinks = $('.item');
scrollLinks.each(function(){
let sectionOffset = $(this.hash).offset().top;
if (sectionOffset <= scrollbarLocation){
$('.active-link').removeClass('active-link'); // added
$(this).addClass('active-link');
let goToSlide = $(this).attr('data-num')
owl.trigger('to.owl.carousel', goToSlide);
}
})
if( scrollbarLocation === 0){
scrollLinks.removeClass('active-link');
owl.trigger('to.owl.carousel', 0);
}
});
.body {
height: 5000px;
}
ul {
padding: 0;
margin: 0;
list-style-type: none;
}
.item {
width: 200px;
height: 70px;
background: red;
margin: 0 15px;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
border-bottom: 4px solid transparent;
}
.active-link {
border-bottom: 4px solid #000;
}
.menu {
position: fixed;
top: 0;
}
section {
width: 100%;
height: 600px;
background: #f8f9fb;
}
#a {
background: lightblue;
margin-top: 200px;
}
#b {
background: lightgreen;
}
#c {
background: tomato;
}
#d {
background: lightpink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/owl.carousel.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.carousel.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.theme.default.css">
<div class="body">
<div class="menu">
<ul class="owl-carousel owl-theme">
Review
a
b
c
d
e
f
</ul>
</div>
<section id="a"></section>
<section id="b"></section>
<section id="c"></section>
<section id="d"></section>
</div>
Look into this fiddle
https://jsfiddle.net/09sLpuwd/1/
What are you doing wrong is trying to remove active class from this and then add active class to the same this, which actualy do nothing.
Insted what I propose is to remove active class from all '.item' emelements and than add it to active one.
As alternative aproach you can store previous item and remove class from it, but I think first way is better.
Hi the problem is with below line
$(this).siblings().removeClass('active-link');
replace it with
$("div.active a").removeClass('active-link');
This was removing and adding class on same time on all so what i did is once i am removing the class from all i am adding it on present elemnt
I'm trying to create a slideshow type effect on the homepage of my app, but I am fairly new to JS and am having trouble with some of the intricacies. I have a working slideshow with delays and setTimeouts that looks like this:
<script>
setTimeout(function() {
$("#hero-image-index").fadeOut().empty();
}, 6000);
setTimeout(function() {
$("#slide-1").fadeOut(500);
}, 6000);
$('#slide-2').delay(6000).fadeIn(3000);
setTimeout(function() {
$("#slide-2").fadeOut(500);
}, 12000);
$('#slide-3').delay(12000).fadeIn(3000);
setTimeout(function() {
$("#slide-3").fadeOut(500);
}, 18000);
$('#slide-4').delay(18000).fadeIn(3000);
setTimeout(function() {
$("#slide-4").fadeOut(500);
}, 25000);
$('#slide-5').delay(25000).fadeIn(3000);
setTimeout(function() {
$("#slide-5").fadeOut(500);
}, 32000);
$('#slide-6').delay(32000).fadeIn(3000);
setTimeout(function() {
$("#slide-6").fadeOut(500);
}, 39000);
$('#slide-7').delay(39000).fadeIn(3000);
$('#hero-image-index-2').delay(39000).fadeIn(3000);
</script>
However, now the client wants a navigation so the user can go from slide to slide at will, which I have set up using ionicons on each "slide". Here's a sample "slide":
<div class="slide text-center" id="slide-1">
<h1 style="margin: 75px 0 40px 0; font-size: 52px; color: white; font-weight: bolder">Genetic Golf</h1>
<h2 style="color: white">We don't guess, we test to find what works best for you!</h2>
<div class="index-icon-box" style="color: white">
<i class="icon go-to-7 ion-chevron-left"></i>
<i class="icon go-to-1 ion-android-radio-button-on"></i>
<i class="icon go-to-2 ion-android-radio-button-off"></i>
<i class="icon go-to-3 ion-android-radio-button-off"></i>
<i class="icon go-to-4 ion-android-radio-button-off"></i>
<i class="icon go-to-5 ion-android-radio-button-off"></i>
<i class="icon go-to-6 ion-android-radio-button-off"></i>
<i class="icon go-to-7 ion-android-radio-button-off"></i>
<i class="icon go-to-2 ion-chevron-right"></i>
</div> <!-- index icon box -->
</div> <!-- slide 1 -->
I was hoping to do something with the JS like "if user doesn't click inside .index-icon-box then run the js as I already have it, but if they click on an .icon then do something like this:
<script>
$(document).ready(function() {
$(".go-to-1").click(function(){
$("#slide-1").show();
$("#slide-2").hide();
$("#slide-3").hide();
$("#slide-4").hide();
$("#slide-5").hide();
$("#slide-6").hide();
$("#slide-7").hide();
});
$(".go-to-2").click(function(){
$("#slide-1").hide();
$("#slide-2").show();
$("#slide-3").hide();
$("#slide-4").hide();
$("#slide-5").hide();
$("#slide-6").hide();
$("#slide-7").hide();
});
};
</script>
However, any way I attempt this just ends up breaking the part I do have working. Can any js-wizards straighten me out?
If your intent on doing this yourself without using a library, you might want to try the following.
First consider putting your slides together in a container, and overlaying
the icons to select the slide over them. Then keep track of the images using the indexes of both the slides and the containers. This provides for an easily edited slideshow setup.
A simple example is shown below, this should be in the neighborhood of what you are looking for.
jQuery(document).ready(function($) {
// Hides all images except for one, the one is given by an
// index. Also updates the controller.
function showSlide(index) {
$('.slides .slide').each(function(i) {
if (i == index) {
$(this).fadeIn(500);
} else {
$(this).fadeOut(500);
}
});
var spans = $('.controller span').removeClass('active');
spans.eq(index).addClass('active');
}
// Show only the first element and set an interval to
// continue to cycle through elements.
var index = 0;
showSlide(index);
var intervalFunc = function() {
index = index >= $('.slides .slide').length ? 0 : index + 1;
showSlide(index);
};
var interval = setInterval(intervalFunc, 6000);
// Handle clicks which will reset the interval to each time.
$('.controller span').click(function() {
// Set the current picture.
index = $(this).index();
showSlide(index);
// Reset the interval
clearInterval(interval);
interval = setInterval(intervalFunc, 6000);
});
});
.slideshow-contianer {
position: relative;
/* For Deomnstation purposes*/
width: 400px;
height: 200px;
margin: 2em;
}
.slides img {
width: 100%;
height: auto;
position: absolute;
left: 0;
top: 0;
}
.controller {
position: absolute;
bottom: 10px;
left: 0;
width: 100%;
-webkit-display: flex;
display: flex;
-webkit-justify-content: center;
justify-content: center;
}
.controller span {
width: 4px;
height: 4px;
border-radius: 50%;
border: 2px solid #ccc;
cursor: pointer;
margin: 10px;
/* Transition is a personal asthetic. */
-webkit-transition: all 0.3s;
transition: all 0.3s;
}
.controller span.active,
.controller span:hover {
-webkit-transform: scale(1.5);
transform: scale(1.5);
background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<div class="slideshow-contianer">
<div class="slides">
<img class="slide" src="https://unsplash.it/400/200?random" />
<img class="slide" src="https://unsplash.it/400/200?random" />
<img class="slide" src="https://unsplash.it/400/200?random" />
<img class="slide" src="https://unsplash.it/400/200?random" />
<img class="slide" src="https://unsplash.it/400/200?random" />
</div>
<div class="controller">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Given a parent div that can scroll vertically and has possibly nested elements within it, how can I get the (innermost) element that currently occupies the top end of the parent div?
For example, suppose I have the parent div as the light blue area in the diagram below, and it has objects in it, that are colored blue or red, some parts of them being outside of the parent div (which should actually be hidden). I want to get the object colored in red.
I can probably do this by comparing the offsetTop of the child elements with that of the parent element, and recursively go inside.
Run the code snippet below to see one solution. Scroll the window to move the divs relative to the window, then click the button to see the id of the innermost div that is at the top of the window. This solution assumes all divs are "normally" nested, i.e. there is no re-arrangement of div vertical placement by fancy css work, no fixed positions, etc.
There are two versions below: the first uses jQuery, the second does not.
$("button#check").click(function() {
var topElem = $("body")[0]; // start at the outermost, i.e. the body
var checkChildDivs = function() { // define the recursive checking function
var children = $(topElem).children("div").not("div#info"); // get all child divs
if (children.length > 0) { // if there are any child divs
$(children).each(function(index, elem) { // check each of them
var posns = getPosns($(elem)); // get their top and bottom posns
// relative to the top of the screen
if ((posns.top <= 0) && (posns.bottom >= 0)) { // if the div overlaps the screen top
topElem = elem; // make this the new innermost div
checkChildDivs(); // check any deeper child divs
return false; // no need to check any lower sibling divs
}
});
}
};
checkChildDivs(); // initiate the checking recursion
$("div#info").text($(topElem).attr("id") || "none, i.e. body"); // report the innermost top div id
});
function getPosns($elem) {
var top = $elem.offset().top; // get the top of the div relative to the document
var hgt = $elem.outerHeight(); // get the height of the element
var wst = $(window).scrollTop(); // get the height of window hidden above the top of the screen
return { // return the top and bottom distances of the element
top: (top - wst), // relative to the top of the screen
bottom: (top - wst + hgt)
};
}
body {
background-color: blue;
}
div {
border: solid black 2px;
padding: 1em;
margin: 1em;
background-color: magenta;
}
div > div {
background-color: red;
}
div > div > div {
background-color: orange;
}
div >div > div > div {
background-color: yellow;
}
button#check {
position: fixed;
height: 2em;
}
div#info {
position: fixed;
background-color: white;
border-width: 1px;
opacity: 0.7;
top: 3em;
left: -0.2em;
height: 1.5em;
width: 15em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="check">Determine Id of Innermost Div at Screen Top</button>
<div id="info"></div>
<div id="a">a
<div id="aa">aa
<div id="aaa">aaa</div>
<div id="aab">aab
<div id="aaba">aaba</div>
<div id="aabb">aabb</div>
<div id="aabc">aabc</div>
</div>
<div id="aac">aac</div>
</div>
<div id="ab">ab
<div id="aba">aba</div>
<div id="abb">abb</div>
<div id="abc">abc</div>
</div>
<div id="ac">ac
<div id="aca">aca</div>
<div id="acb">acb</div>
<div id="acc">acc</div>
</div>
</div>
<div id="b">b
<div id="ba">ba
<div id="baa">baa</div>
<div id="bab">bab</div>
<div id="bac">bac</div>
</div>
<div id="bb">bb
<div id="bba">bba</div>
<div id="bbb">bbb</div>
<div id="bbc">bbc</div>
</div>
<div id="bc">bc
<div id="bca">bca</div>
<div id="bcb">bcb</div>
<div id="bcc">bcc</div>
</div>
</div>
<div id="c">c
<div id="ca">ca
<div id="caa">caa</div>
<div id="cab">cab</div>
<div id="cac">cac</div>
</div>
<div id="cb">cb
<div id="cba">cba</div>
<div id="cbb">cbb</div>
<div id="cbc">cbc</div>
</div>
<div id="cc">cc
<div id="cca">cca</div>
<div id="ccb">ccb</div>
<div id="ccc">ccc</div>
</div>
</div>
And here is a non-jQuery version of the same thing:
var doc = document;
doc.getElementById("check").onclick = function() {
var topElem = doc.getElementsByTagName("body")[0]; // start at the outermost, i.e. the body
var checkChildDivs = function() { // define the recursive checking function
var children = topElem.childNodes; // get all child nodes
if (children.length > 0) { // if there are any child nodes
[].forEach.call(children, function(elem, index, arr) { // check each of them
if (elem.toString() === "[object HTMLDivElement]" && elem.id !== "info") {
// only use divs that do not have id "info"
var posns = getPosns(elem); // get their top and bottom posns
// relative to the top of the screen
if ((posns.top <= 0) && (posns.bottom >= 0)) { // if the div overlaps the screen top
topElem = elem; // make this the new innermost div
checkChildDivs(); // check any deeper child divs
return false; // no need to check any lower sibling divs
}
}
});
}
};
checkChildDivs(); // initiate the checking recursion
doc.getElementById("info").innerHTML = (topElem.id || "none, i.e. body");
// report the innermost top div id
};
function getPosns(elem) {
var top = elem.getBoundingClientRect().top + window.pageYOffset - doc.documentElement.clientTop;
// get the top of the div relative to the document
var hgt = elem.offsetHeight; // get the height of the element
var wst = window.scrollY; // get the height of window hidden above the top of the screen
return { // return the top and bottom distances of the element
top: (top - wst), // relative to the top of the screen
bottom: (top - wst + hgt)
};
}
body {
background-color: blue;
}
div {
border: solid black 2px;
padding: 1em;
margin: 1em;
background-color: magenta;
}
div > div {
background-color: red;
}
div > div > div {
background-color: orange;
}
div >div > div > div {
background-color: yellow;
}
button#check {
position: fixed;
height: 2em;
}
div#info {
position: fixed;
background-color: white;
border-width: 1px;
opacity: 0.7;
top: 3em;
left: -0.2em;
height: 1.5em;
width: 15em;
}
<button id="check">Determine Id of Innermost Div at Screen Top</button>
<div id="info"></div>
<div id="a">a
<div id="aa">aa
<div id="aaa">aaa</div>
<div id="aab">aab
<div id="aaba">aaba</div>
<div id="aabb">aabb</div>
<div id="aabc">aabc</div>
</div>
<div id="aac">aac</div>
</div>
<div id="ab">ab
<div id="aba">aba</div>
<div id="abb">abb</div>
<div id="abc">abc</div>
</div>
<div id="ac">ac
<div id="aca">aca</div>
<div id="acb">acb</div>
<div id="acc">acc</div>
</div>
</div>
<div id="b">b
<div id="ba">ba
<div id="baa">baa</div>
<div id="bab">bab</div>
<div id="bac">bac</div>
</div>
<div id="bb">bb
<div id="bba">bba</div>
<div id="bbb">bbb</div>
<div id="bbc">bbc</div>
</div>
<div id="bc">bc
<div id="bca">bca</div>
<div id="bcb">bcb</div>
<div id="bcc">bcc</div>
</div>
</div>
<div id="c">c
<div id="ca">ca
<div id="caa">caa</div>
<div id="cab">cab</div>
<div id="cac">cac</div>
</div>
<div id="cb">cb
<div id="cba">cba</div>
<div id="cbb">cbb</div>
<div id="cbc">cbc</div>
</div>
<div id="cc">cc
<div id="cca">cca</div>
<div id="ccb">ccb</div>
<div id="ccc">ccc</div>
</div>
</div>
You can use this library : https://github.com/customd/jquery-visible .
Check my snippet for demo
$(function() {
$(window).on('scroll', function() {
$visible = null;
$('section > div').each(function() {
if (!$visible && $(this).visible(true)) {
$visible = $(this);
$(this).addClass('active');
} else {
$(this).removeClass('active');
}
});
$('#answer').html('' + $visible.text());
});
});
#main1,
#main2,
#main3,
#main4 {
display: block;
padding: 10px;
}
body {
background: blue;
}
section > div {
display: block;
width: 100%;
background: lightblue;
margin-bottom: 10px;
}
section > div.active {
background: red;
}
#answer {
display: block;
position: fixed;
bottom: 0;
height: 30px;
width: 300px;
background: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://opensource.teamdf.com/visible/jquery.visible.js"></script>
<section id="main1">
<div style="height:100px;">child 1</div>
</section>
<section id="main2">
<div style="height:100px;">child 2</div>
</section>
<section id="main3">
<div style="height:100px;">child 3</div>
</section>
<section id="main4">
<div style="height:300px;">child 4</div>
<div style="height:400px;">child 5</div>
</section>
<div id="answer"></div>
I am working on creating a website and I am stuck on a certain function I am trying to build. I am trying to slide back a div to its original place if anyplace outside the div is clicked. I've looked everywhere on stack but to no avail. What happens to me is that the background clicks remain active at all times, I only need it to be active when the div has slid to become sort of a popup.
Here is my jsfiddle: https://jsfiddle.net/DTcHh/10567/
Here is the jquery for one of the divs (the rest are similar)
var text = 1;
$('.login1').click(function(e){
e.preventDefault();
$('.loginform_hidden').toggleClass('loginform_visible');
$(".animateSlide").toggle(300, function(){
$(this).focus();
});
if(text == 1){
$(".div1").toggleClass("animateSlide col-xs-12");
$('.login1').html('Go Back');
$('.imageOne').toggleClass('animateSlideTop');
// If an event gets to the body
$('.div2, .div3, .patientAccess').toggle("fast");
document.addEventListener('mouseup', function(event){
var box = document.getElementsByClassName('animateSlide');
if (event.target != box && event.target.parentNode != box){
$('.div2, .div3, .patientAccess').toggle("fast");
$(".div1").toggleClass("animateSlide ");
text=0;
}
});
text = 0;
} else {
$(".div1").toggleClass("animateSlide");
$('.login1').html('Start Animation');
$('.imageOne').toggleClass('animateSlideTop');
$('.div2, .div3, .patientAccess').toggle("fast");
text = 1;
}
});
$(".div1").on('blur', function() {
$(this).fadeOut(300);
});
EDIT: The jsfiddle now incorporates what I have been trying to utilize.
As a demonstration, I built a simplified version of what I think you're aiming to achieve.
I'm using the "event.target" method described in this answer.
Since you are using CSS transitions, I'm using jQuery to detect the end of those transitions using a method found here.
I've given all boxes a class of "animbox" so that they can all be referenced as a group. I've also given each box its own ID so it can be styled individually with CSS.
I've commented the code in an attempt to explain what's going on.
// define all box elements
var $allBoxes = jQuery('.animbox');
// FUNCTION TO SHOW A SELECTED BOX
function showBox($thisBox) {
$allBoxes.hide(); // hide all boxes
$thisBox.show().addClass('animateSlide'); // show and animate selected box
$('div.login', $thisBox).text("Go Back"); // change the selected box's link text
}
// FUNCTION TO RETURN BOXES TO THE DEFAULT STATE
function restoreDefaultState() {
var $thisBox = jQuery('div.animbox.animateSlide'); // identify an open box
if ($thisBox.length) { // if a box is open...
$thisBox.removeClass('animateSlide'); // close this box
$thisBox.one('webkitTransitionEnd'+
' otransitionend'+
' oTransitionEnd'+
' msTransitionEnd'+
' transitionend', function(e) { // when the box is closed...
$allBoxes.show(); // show all boxes
$('div.login', $thisBox).text("Start Animation"); // change the link text
});
}
}
// CLICK HANDLER FOR ALL "login" TRIGGERS
$('div.login').click(function(e) {
var $thisBox = $(this).closest('div.animbox'); // identify clicked box
if (!$thisBox.hasClass('animateSlide')) { // if the box is not open...
showBox($thisBox); // open it
} else { // otherwise...
restoreDefaultState(); // restore the default state
}
});
// CLICK HANDLER TO RESTORE DEFAULT STATE WHEN CLICK HAPPENS OUTSIDE A BOX
$('body').click(function(evt) {
if ($(evt.target).hasClass('animbox') || // if a box is clicked...
$(evt.target).closest('div.animbox').length > 0) { // or a child of a box...
return; // cancel
}
restoreDefaultState(); // restore the default state
});
div.container-fluid {
background-color: #464646;
}
.v-center {
display: table;
height: 100vh;
}
.content {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.patientAccess {
transition: all .5s;
background: white;
height: 200px;
width: 90%;
position: absolute;
opacity: 0.7;
margin-top: -100px;
}
.patientAccess p {
font-size: 1.5em;
font-weight: bold;
}
div.animbox {
transition: all .5s;
position: absolute;
cursor: pointer;
width: 90%;
height: 100px;
opacity: 0.7;
}
div#animbox1 {
background: #e76700;
}
div#animbox2 {
background: #74b8fe;
}
div#animbox3 {
background: #848484;
}
div.login {
color: white;
font-size: 1em;
cursor: pointer;
}
div#animbox1.animateSlide {
width: 200px;
height: 300px;
margin-left: 100px;
opacity: 1;
}
div#animbox2.animateSlide {
width: 250px;
height: 450px;
margin-left: -25px;
margin-top: -150px;
}
div#animbox3.animateSlide {
width: 150px;
height: 150px;
opacity: .5;
margin-left: -100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<div class="container-fluid">
<div class="row-fluid">
<div class="col-xs-12 v-center">
<div class="content text-center">
<div class="col-xs-2 animated slideInRight "></div>
<div class="col-xs-2 animated slideInRight ">
<div class="patientAccess">
<p>Patient Resource Access</p>
</div>
</div>
<div class="col-xs-2 animated slideInRight">
<div class="animbox" id="animbox1">
<div class="login">Start Animation</div>
<div class="loginform_hidden "></div>
</div>
</div>
<div class="col-xs-2 animated slideInRight">
<div class="animbox" id="animbox2">
<div class="login">Start Animation</div>
<div class="registrationform_hidden"></div>
</div>
</div>
<div class="col-xs-2 animated slideInRight">
<div class="animbox" id="animbox3">
<div class="login">Start Animation</div>
</div>
</div>
</div>
</div>
</div>
</div>
You can namespace an event handler using this syntax:
$("#myElement").on("click.myEventHandlerName", function() { ... });
At any point, you can remove the event handler again by calling
$("#myElement").off("click.myEventHandlerName", "#myElement");