div “flickers” and Moves on fadeOut/fadeIn - javascript

I have the same problem that is described here: same problem (fiddle: original fiddle) but I dont understand JS yet, I am learning as I code, so when my html code is little bit different as it is now, I dont know, how to apply the solution onto it. Could You help me please with that? When I see, how it should look, I can learn it then.
My code:
<div style="position: absolute; left: 50%;">
<div style="position: relative; left: -50%;">
<div id="101" style="display:none;"><!-- Content here --></div>
<div id="102" style="display:none;"><!-- Content here --></div>
<div id="103" style="display:none;"><!-- Content here --></div>
<div id="104" style="display:none;"><!-- Content here --></div>
<div id="105" style="display:none;"><!-- Content here --></div>
<div id="106" style="display:none;"><!-- Content here --></div>
<div id="107" style="display:none;"><!-- Content here --></div>
<div id="108" style="display:none;"><!-- Content here --></div>
<div id="109" style="display:none;"><!-- Content here --></div>
<div id="110" style="display:none;"><!-- Content here --></div>
<div id="111" style="display:none;"><!-- Content here --></div>
<div id="112" style="display:none;"><!-- Content here --></div>
<div id="113" style="display:none;"><!-- Content here --></div>
</div>
</div>
<script type="text/javascript">
$("#1").on('click', function() {
$("#101").fadeToggle();
$("#102,#103,#104,#105,#106,#107,#108,#109,#110,#111,#112,#113").fadeOut();
});
$("#2").on('click', function() {
$("#102").fadeToggle();
$("#101,#103,#104,#105,#106,#107,#108,#109,#110,#111,#112,#113").fadeOut();
});
// and so on, until #13
</script>
Solution:
$('#indexNav').click(function() {
$('#aboutContent').fadeOut('fast',function(){
$('#indexContent').fadeIn('fast');
});
return false;
});
$('#aboutNav').click(function() {
$('#indexContent').fadeOut('fast',function(){
$('#aboutContent').fadeIn('fast');
});
return false;
});

Wow, thats a lot of code to review. I'm not positive this is going to solve your problem. You don't have any hover events on this, so I assume flicker may be CSS related.
// better selector - you don't have markup for #1, #2, #3, etc.
// can you rework this to be $('.container div') or something based on real markup
$('div').on('click', function() {
// get this element's id
var id = $(this).attr('id');
// find the corresponding div ID, which seems to be 100 greater than original ID
$('#1'+id).fadeToggle()
// find all siblings and hide them
.siblings().fadeOut();
});
I've added a snippet so you can test it.
$(function() { // equivalent to onDomReady
$('button').on('click', function() {
// get this element's id
var id = $(this).attr('id');
// find the corresponding div ID, which seems to be 100 greater than original ID
$('#1' + id).fadeToggle()
// find all siblings and hide them
.siblings().fadeOut();
});
});
div div div {
border: 1px solid black;
margin: 3px;
background: red;
}
<button id="01">01</button>
<button id="02">02</button>
<button id="03">03</button>
<button id="04">04</button>
<button id="05">05</button>
<button id="06">06</button>
<button id="07">07</button>
<button id="08">08</button>
<button id="09">09</button>
<button id="10">10</button>
<button id="11">11</button>
<button id="12">12</button>
<button id="13">13</button>
<div style="position: absolute; left: 50%;">
<div style="position: relative; left: -50%;">
<div id="101" style="display: none;">101</div>
<div id="102" style="display: none;">102</div>
<div id="103" style="display: none;">103</div>
<div id="104" style="display: none;">104</div>
<div id="105" style="display: none;">105</div>
<div id="106" style="display: none;">106</div>
<div id="107" style="display: none;">107</div>
<div id="108" style="display: none;">108</div>
<div id="109" style="display: none;">109</div>
<div id="110" style="display: none;">110</div>
<div id="111" style="display: none;">111</div>
<div id="112" style="display: none;">112</div>
<div id="113" style="display: none;">113</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Update
What you're suffering from is the moment of time when both divs (one fading out, and one fading in) are being toggled. You'll need to position those divs absolutely to get around this. Then they're overlapping each other and you don't need to worry about the flicker. That can have big impacts on layout. Then you get into calculating heights of those child divs and all sorts of stuff:
https://jsfiddle.net/SbKQ3/29/

How about that? I used promises to fadeToggle only when all elements were hidden, which prevented the flickering effect.
$(function() { // equivalent to onDomReady
$('button').on('click', function() {
// get this element's id
var id = $(this).attr('id');
// find the corresponding div ID, which seems to be 100 greater than original ID
$.when($('#1' + id).siblings().fadeOut()).done(function() {
$('#1' + id).fadeToggle();
});
});
});
div div div {
border: 1px solid black;
margin: 3px;
background: red;
}
<button id="01">01</button>
<button id="02">02</button>
<button id="03">03</button>
<button id="04">04</button>
<button id="05">05</button>
<button id="06">06</button>
<button id="07">07</button>
<button id="08">08</button>
<button id="09">09</button>
<button id="10">10</button>
<button id="11">11</button>
<button id="12">12</button>
<button id="13">13</button>
<div style="position: absolute; left: 50%;">
<div style="position: relative; left: -50%;">
<div id="101" style="display: none;">101</div>
<div id="102" style="display: none;">102</div>
<div id="103" style="display: none;">103</div>
<div id="104" style="display: none;">104</div>
<div id="105" style="display: none;">105</div>
<div id="106" style="display: none;">106</div>
<div id="107" style="display: none;">107</div>
<div id="108" style="display: none;">108</div>
<div id="109" style="display: none;">109</div>
<div id="110" style="display: none;">110</div>
<div id="111" style="display: none;">111</div>
<div id="112" style="display: none;">112</div>
<div id="113" style="display: none;">113</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

How associate slideToggle with an animated and automatic scroll to a reach the matching DIV?

I have several hidden DIVs and I want to animate the slideToggle. All buttons get links to scroll to the matching DIV.
The problem is when I click on the button the scroll is stopped before reaching the DIV. So how can I do to complete and animate the scroll (i.e slow scroll) with .slideToggle?
$(document).ready(function() {
$(".menu").hide();
$(".tog").click(function() {
$(".menu:visible").toggle();
if (!$("." + $(this).data('id')).is(':visible')) {
$("." + $(this).data('id')).slideToggle();
}
});
});
.edsContenu {
padding: 5px;
text-align: center;
background-color: #00011f;
display: none;
height:200px;
}
.bridgeContenu{
padding: 5px;
text-align: center;
background-color: #00011f;
display: none;
height:200px;
}
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<div id="discovered">
<div id="file" class="container">
<a href="#edsContenu" class="tog" data-id="edsContenu" id='showEDS'> <input id="eds" type="image" src="IMAGES/PNG/eds.png" alt="EDS system" height="250px" width="250px" /></a>
</div>
<div id="file" class="container">
<a href="#bridgeContenu" class="tog" data-id="bridgeContenu" id='showBridge'><input id="bridge" type="image" src="IMAGES/PNG/pont.png" alt="pont photonique" height="250px" width="250px" /></a>
</div>
<div id="edsContenu" class="menu edsContenu">
<section id="content">
<div id="text">
</div>
</section>
</div>
<div id="bridgeContenu" class="menu bridgeContenu">
<section id="content">
<div id="text">
</div>
</section>
</div>
Made some changes to the code, read the comment
$(document).ready(function() {
$(".menu").hide();
$(".tog").click(function() {
var id = "#" + $(this).data('id')
// hide all menu except the current one, otherwise using
// $(".menu:visible").hide() and using $(id).is(':hidden') after is really pointless
$(".menu:visible:not('"+id+"')").toggle();
if ($(id).is(':hidden')) {
$(id).toggle("fast", function(){
// after toggle is finished then animate scrollto
$("html, body").animate({ scrollTop: $(id).offset().top }, 1000);
});
}
});
});
.menu{
background:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="discovered">
<div id="file" class="container">
<a href="#research" class="tog" data-id="edsContenu" id='showEDS'> <input id="eds" type="image" src="IMAGES/PNG/eds.png" alt="EDS system" height="250px" width="250px" /></a>
</div>
<div id="file" class="container">
<a href="#research" class="tog" data-id="bridgeContenu" id='showBridge'><input id="bridge" type="image" src="IMAGES/PNG/pont.png" alt="pont photonique" height="250px" width="250px" /></a>
</div>
<div id="edsContenu" class="menu edsContenu">
<section id="content">
<div id="text">
test edsContenu
</div>
</section>
</div>
<div id="bridgeContenu" class="menu bridgeContenu">
<section id="content">
<div id="text">
test bridgeContenu
</div>
</section>
</div>

prevAll() not working in more complicated DOM

I'm trying to select a single sibling further up in the DOM after clicking a button. I only want to find the closest sibling upwards (in production there's a lot more HTML between the buttons, so it's more necessary to split it up this way). I'm using a prevAll(selector:first) to do this, and when I use a very simple version (here), it seems to work ok. But when I do it in a way that's more similar to my actual environment, prevAll() can't seem to find the sibling element div.googleMapsContainer:
Here is my HTML:
<div style="display: none;" class="googleMapsContainer" id="gm1">
<div class="gmap" style="max-width: 80%;
max-height: 400px;
background-color: grey;" class="map">
</div>
This Text Should be visible after click
</div>
<div class="tableProcessingToolBarContainer">
<div class="container-fluid tableProcessingTools" >
<div class="row-fluid">
<div class="appSliderContent tptSliderContent container-fluid ">
<button class="gmapInit glassyButton">View data in Google Maps</button>
</div>
</div>
</div>
</div>
<div style="display: none;" class="googleMapsContainer" id="gm2">
<div class="gmap" style="max-width: 80%;
max-height: 400px;
background-color: grey;" class="map">
</div>
This Text Should be visible after click
</div>
<br>
<div class="tableProcessingToolBarContainer">
<div class="container-fluid tableProcessingTools" >
<div class="row-fluid">
<div class="appSliderContent tptSliderContent container-fluid ">
<button class="gmapInit glassyButton">View data in Google Maps</button>
</div>
</div>
</div>
</div>
And here is my JavaScript:
$(document).on('click', '.gmapInit', function() {
console.log("here is this: ");
console.log($(this));
var closeThing = $(this).prevAll("div.googleMapsContainer:first");
console.log("here is the closest: ");
console.log(closeThing);
closeThing.attr("style", "");
});
The console shows that the closeThing is nothing, as the prevAll was not successful. Here's a JsFiddle for demonstration: https://jsfiddle.net/NateH06/twk9mtjg/
This one is working for me, I just modified your Fiddle.
I selected the parent div that was in the same scope and then used your prevAll() call to precise my selection. What happens when you try this in your actual Project?
Have a look:
$(document).on('click', '.gmapInit', function() {
var closeThing = $(this).parents("div.tableProcessingToolBarContainer").prevAll("div.googleMapsContainer:first");
closeThing.attr("style", "");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="display: none;" class="googleMapsContainer" id="gm1">
<div class="gmap" style="max-width: 80%;
max-height: 400px;
background-color: grey;" class="map">
</div>
This Text Should be visible after click
</div>
<div class="tableProcessingToolBarContainer">
<div class="container-fluid tableProcessingTools" >
<div class="row-fluid">
<div class="appSliderContent tptSliderContent container-fluid ">
<button class="gmapInit glassyButton">View data in Google Maps</button>
</div>
</div>
</div>
</div>
<div style="display: none;" class="googleMapsContainer" id="gm2">
<div class="gmap" style="max-width: 80%;
max-height: 400px;
background-color: grey;" class="map">
</div>
This Text Should be visible after click
</div>
<br>
<div class="tableProcessingToolBarContainer">
<div class="container-fluid tableProcessingTools" >
<div class="row-fluid">
<div class="appSliderContent tptSliderContent container-fluid ">
<button class="gmapInit glassyButton">View data in Google Maps</button>
</div>
</div>
</div>
</div>

click on div 1, open new content. click on div 2 open content of div1

I have a lots of boxes with different content.
If you click on the first box, you can see a popup-box with more details.
If you click on the second, third, etc. boxes you have to see the details of the boxes.
My problem: If I click on box no. 2 I see the details of box no. 1.
HTML:
<div id="fade" class="black_overlay"></div>
<div id="openDiv" class="openDiv case1 col-xs-12">
<div class="col-xs-12">
<img src="https://placehold.it/100x50/ffffff/000000" alt="#" />
</div>
<div class="col-xs-12 content">
<p>Some Stuff here</p>
</div>
<div id="light" class="white_content">
<p>Case 1! More Stuff. Say Hello!</p>
Close
</div>
q</div>
<div id="openDiv" class="openDiv case2 col-xs-12">
<div class="col-xs-12">
<img src="https://placehold.it/100x50" alt="#" />
</div>
<div class="col-xs-12 content">
<p>Some Stuff here</p>
</div>
<div id="light" class="white_content">
<p>Case 2! More Stuff. Say Hello!</p>
Close
</div>
</div>
Jquery:
function clickCase() {
$(".openDiv").click(function() {
$("#light").toggle();
$("#fade").toggle();
});
$("#closeDiv").click(function() {
$("#light").toggle();
$("#fade").toggle();
});
}
Here is the whole code: http://jsfiddle.net/jvynbq1u/
Just update function
function clickCase() {
$(".openDiv").click(function() {
$(this).find("#light").toggle();
$("#fade").toggle();
});
$(".closeDiv").click(function() {
$(this).find("#light").toggle();
$("#fade").toggle();
}); }
and change classes in HTML to close
<div id="openDiv" class="openDiv case1 col-xs-12">
<div class="col-xs-12">
<img src="https://placehold.it/100x50/ffffff/000000" alt="#" />
</div>
<div class="col-xs-12 content">
<p>Some Stuff here</p>
</div>
<div id="light" class="white_content">
<p>Case 1! More Stuff. Say Hello!</p>
Close
</div>
</div>
<div id="openDiv" class="openDiv case2 col-xs-12">
<div class="col-xs-12">
<img src="https://placehold.it/100x50" alt="#" />
</div>
<div class="col-xs-12 content">
<p>Some Stuff here</p>
</div>
<div id="light" class="white_content">
<p>Case 2! More Stuff. Say Hello!</p>
Close
</div>
</div>
and don't forget to add "closeDiv" into class of elements with this ID. It is working for me on JSFiddle. http://jsfiddle.net/jvynbq1u/9/
Please also use classes, when you want to add one function on more elements, not id. One specific ID should be only for one element on page.
You should be use with different id. those id's are same as unique id.
Try this code and check with my demo:
<div id="fade" class="black_overlay"></div>
<div id="openDiv1" class="openDiv case1 col-xs-12">
<div class="col-xs-12">
<img src="https://placehold.it/100x50/ffffff/000000" alt="#" />
</div>
<div class="col-xs-12 content">
<p>Some Stuff here</p>
</div>
<div id="light1" class="white_content">
<p>Case 1! More Stuff. Say Hello!</p>
Close
</div>
</div>
<div id="openDiv2" class="openDiv case2 col-xs-12">
<div class="col-xs-12">
<img src="https://placehold.it/100x50" alt="#" />
</div>
<div class="col-xs-12 content">
<p>Some Stuff here</p>
</div>
<div id="light2" class="white_content">
<p>Case 2! More Stuff. Say Hello!</p>
Close
</div>
</div>
function clickCase() {
$("#openDiv1").click(function() {
$("#light1").toggle();
$("#fade").toggle();
});
$("#openDiv2").click(function() {
$("#light2").toggle();
$("#fade").toggle();
});
}
jQuery(document).ready(function() {
clickCase();
});
Demo jsfiddle
You can use conditional ternary operator.
function clickCase() {
$(".openDiv").click(function() {
($(this).attr('id') == "openDiv") ? $("#light").toggle() : $("#light1").toggle();
$("#fade").toggle();
});
$("#closeDiv, #closeDiv1").click(function() {
($(this).attr('id') == ("openDiv" || "closeDiv")) ? $("#light").toggle() : $("#light1").toggle();
$("#fade").toggle();
});
}
jQuery(document).ready(function() {
clickCase();
});
.openDiv {
width: 200px;
height: 200px;
float: left;
margin: 5px;
padding: 5px;
}
.case1 {
background-color: #00b5b5;
}
.case2 {
background-color: #4c4c4c;
color: white;
}
.black_overlay {
display: none;
position: fixed;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: #000;
z-index: 1001;
opacity: 0.8;
}
.white_content {
color: #292929;
display: none;
position: fixed;
top: 15%;
left: 10%;
width: 80%;
height: 70%;
padding: 5px 10px;
background-color: white;
z-index: 1002;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="fade" class="black_overlay"></div>
<div id="openDiv" class="openDiv case1 col-xs-12">
<div class="col-xs-12">
<img src="https://placehold.it/100x50/ffffff/000000" alt="#" />
</div>
<div class="col-xs-12 content">
<p>Some Stuff here</p>
</div>
<div id="light" class="white_content">
<p>Case 1! More Stuff. Say Hello!</p>
Close
</div>
</div>
<div id="openDiv1" class="openDiv case2 col-xs-12">
<div class="col-xs-12">
<img src="https://placehold.it/100x50" alt="#" />
</div>
<div class="col-xs-12 content">
<p>Some Stuff here</p>
</div>
<div id="light1" class="white_content">
<p>Case 2! More Stuff. Say Hello!</p>
Close
</div>
</div>
In the case of multiple elements you can use ternary chaining
Example:
$(this).attr('id') == "openDiv") ? $("#light").toggle() :
$(this).attr('id') == "openDiv1" ? $("#light1").toggle() :
$(this).attr('id') == "openDiv2" ? $("#light2").toggle() :
$("#light3").toggle();// keep expanding till you reach enough.
It is also a good idea to save $(this).attr('id') in a variable if you need to check multiple elements.
Alternatively you could use a switch case.
Example:
switch($(this).attr('id')){
case "openDiv": $("#light").toggle(); break;
case "openDiv1": $("#light1").toggle(); break;
//go on for how many you would need.
}
Note: I have made the id's unique.

show/hide with same ids

I searched a lot on Stackoverflow, solution for my question, but no one of them helped me. I have a multiple show/hide (toggle) content, with same id's and I want to make, that the only one of them, what I need, opens, not all of them. There's my JSFiddle You can test it.
This is my JavaScript
$("#view").click(function(){
$('.hidden-content').slideToggle(500).toggleClass("active");
});
You cannot have duplicate id attributes within a single document. When you do only the first element with the given id is recognised; hence the issue you've seen.
Instead change the view elements to use a class, then use the this reference within the click event handler to traverse the DOM to find the related .hidden-content element and toggle it. Try this:
$(".view").click(function() {
$(this).closest('.div').find('.hidden-content').slideToggle(500).toggleClass("active");
});
.div {
width: 400px;
}
.content {
padding: 10px;
}
.view {
color: red;
cursor: pointer;
}
.hidden-content {
display: none;
}
.hidden-content .active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
It is a bad practice to use same id for more than one elements.
You can try the following
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
and your jquery will look like the following
$(".view").click(function(){
$(this).parent('.content').next('.hiddencontent').slideToggle(500).toggleClass("active");
});
You should replace the id to class. And for accordion, you can use like below.
HTML,
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
Js,
<script>
$(document).ready(function(){
$(".hidden-content").hide();
$(".view").on('click', function(){
$(this).parents().parents().find(".hidden-content").slideToggle(500).toggleClass("active");
if($(this).parents().parents().siblings().find(".hidden-content").hasClass('active')){
$(this).parents().parents().siblings().find(".hidden-content").removeClass('active');
$(this).parents().parents().siblings().find(".hidden-content").hide();
}
});
});
</script>
You can change your click event as follows to make it work.
$("div[id='view']").click(function() {
$(this).parent().next().slideToggle(500).toggleClass("active");
});
Note: You shouldn't have the same id for multiple elements, id attribute value should be unique why because the id attribute is used to identify an element uniquely in the DOM. You can have the same class name for different elements.
Please refer this answer it provides more information on how things work when multiple elements have the same id attribute value.
$("div[id='view']").click(function() {
$(this).parent().next().slideToggle(500).toggleClass("active");
});
.div {
width: 400px;
}
.content {
padding: 10px;
}
#view {
color: red;
cursor: pointer;
}
.hidden-content {
display: none;
}
.hidden-content .active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div class="div">
<div class="content">
<div id="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div id="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div id="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div id="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
$(".view").click(function() {
$(this).closest('.div').find('.hidden-content').slideToggle(200).toggleClass("active");
});
.div {
width: 400px;
}
.content {
padding: 10px;
}
.view {
color: red;
cursor: pointer;
}
.hidden-content {
display: none;
}
.hidden-content .active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>
<div class="div">
<div class="content">
<div class="view">view/edit</div>
</div>
<div class="hidden-content">
hidden content
</div>
</div>

Traversing down Bootstrap DOM with jQuery

Here is my HTML, first:
<div id="master-template" class="row" style="height: 600px;">
<!-- Left Side -->
<div class="col-lg-6" style="height: 100%;">
<div class="row" style="height: 50%;" >
<div class="region col-lg-12" data-div="1">
</div>
</div>
<div class="row" style="height: 50%;">
<div class="region col-lg-12" data-div="2">
</div>
</div>
</div>
<!-- Right Side -->
<div class="region col-lg-6" style="height: 100%;" data-div="3">
</div>
</div>
And my jQuery:
$("#master-template").find('.region').click(function() {
alert("click");
});
So, I only get the alert when I click on the "Right Side". Because it is a direct descendant. The others do not register; almost as if the .row is blocking it. Is there a way I can (with either one or two) click functions in jQuery register clicks for all div's with .region? children, grandchildren, etc?
This is happening because Right Side is the only .region DIV that has any dimension. (By virtue of height:100%).
The other two .regions are not being clicked because they have no dimension (height is 0)

Categories

Resources