Replacing two divs without having bottom content flicker during the replacement - javascript

I have two divs with very similar content.
When the button is clicked, I would like the first div to disappear and the second one to appear in the exact same place.
They do not have a constant height, but they should have the same automatic height because they have very similar content.
I implemented this example to demonstrate the problem.
In this snippet, you can see that once the button is clicked, the divs are replaced with a fade in/out animation.
The problem is that the content below (text text in this example), goes up and down during the fade in / out process, which impacts negatively on user experience.
Assuming there is a lot of content below these divs, it just doesn't look good.
What would be the best way to implement this behavior without having all content below the divs "flicker" during the replacement?
$("#clicker").click(function() {
if ($('.first').is(':visible')) {
$('.first').fadeOut();
$('.second').fadeIn();
} else {
$('.second').fadeOut();
$('.first').fadeIn();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<button id="clicker">Click me</button>
<div style="background-color:yellow;display:none" class="first">first content</div>
<div style="background-color:red" class="second">second content</div>
<div id="more_stuff_here">
text text<br> text text
</div>

This is happening because you have applied fade effect for both display:none and display:block. So it will disturb your layout because at some point of animation both elements are becoming display:block.
So the solution is there is no need of fade effect when you are doing display:none. Just use hide().
So use hide() instead of fadeOut(). fadeIn() will animate your content.
Stack Snippet
$("#clicker").click(function() {
if ($('.first').is(':visible')) {
$('.first').hide();
$('.second').fadeIn();
} else {
$('.second').hide();
$('.first').fadeIn();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<button id="clicker">Click me</button>
<div style="background-color:yellow;display:none" class="first">first content</div>
<div style="background-color:red" class="second">second content</div>
<div id="more_stuff_here">
text text<br> text text
</div>

$("#clicker").click(
function()
{
if ($('.first').is(':visible')) {
$('.first').fadeOut();
$('.second').fadeIn();
}
else {
$('.second').fadeOut();
$('.first').fadeIn();
}
}
);
.first, .second {
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<button id="clicker">Click me</button>
<div style="background-color:yellow;display:none" class="first">
first content
</div>
<div style="background-color:red" class="second">
second content
</div>
<div id="more_stuff_here">
text text<br>
text text
</div>

I prefer you to wrap .first and .second in a div with constant height.
<div class="container"><div class="first">....</div><div class="second">....</div></div>

Related

Background color change on scroll

I wanna change the background color on a scroll, but I think that problem is I'm using Bootstrap. Can you help me? Any solutions? I'm almost sure it doesn't work because of Bootstrap. I can't type in data-color !important or in JavaScript. What can I do to overwrite the Bootstrap class?
const sections = document.querySelectorAll('.bg');
function changeBackground(){
const bottom= window.scrollY + window.innerHeight;
sections.forEach(section => {
sectionMiddle= section.offsetTop + (section.offsetHeight / 2);
if(bottom >sectionMiddle){
document.body.style.backgroundColor = section.dataset.color;
}
});
}
window.addEventListener('scroll', changeBackground);
*{
margin:0;
padding:0;
box-sizing: border-box;
}
body{
background-color: #9bc3f6;
transition: background .8s;
}
.section1, .section2{
height:100vh;
width:100%;
}
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0- alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-CuOF+2SnTUfTwSZjCXf01h7uYhfOBuxIhGKPbfEJ3+FqH/s6cIFN9bGr1HmAg4fQ" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid section1 bg" data-color="yellow">
<h1>Hello World</h1>
</div>
<div class="container-fluid text-center section2 bg" data-color="blue">
<h1>Hello World 2</h1>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-alpha3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-popRpmFF9JQgExhfw5tZT4I9/CI5e2QcuUZPOVXb1m7qUmeR2b50u+YFEYe1wgzy" crossorigin="anonymous"></script>
</body>
</html>
It's not a css best practice to put !important to override css rules, to override bootstrap css rules it's better to add extra tags in your selector :
for example:
``const sections = document.querySelectorAll('body .bg');``
or:
``const sections = document.querySelectorAll('html body .bg');``

How do I loop through HTML elements while executing a function on each element

I am a newbie to Javascript, I wanted to implement a for loop that would go through each div as selected by its class.
The simple idea is to reveal DIVs when I click on a button. But it has to be sequential: I click DIV1 appears, when I click again DIV2 appears and so on. Currently my code only changes the class of one DIV and not the rest. Here are my code samples:
$(document).ready(function(){
// jQuery methods go here...
var count = document.getElementById("page1").childElementCount;
for(var i = 0; i < count; i++){
var myClass = ".panel" + i;
$("button").click(function(){
$(myClass).addClass("showing animated fadeIn")
});
}
});/**document ready **/
.showing{
background-color: red;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>title</title>
<link rel="stylesheet" type="text/css" href="mystyle.css">
<link rel="stylesheet" type="text/css" href="animate.css">
</head>
<body>
<button class="one">Click Me!</button>
<div id="page1">
<div class="panel1">
</div>
<div class="panel2">
</div>
<div class="panel3">
</div>
<div class="panel4">
</div>
</div><!-- page one -->
<div id="trial">
</div>
<script src="jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="jquery.touchSwipe.min.js"></script>
<script type="text/javascript" src="trial.js"></script>
</body>
</html>
Please let me know what I am missing especially in the for loop or if I can do something else to be able to grab a DIV and add a class every time I click on the button.
Firstly, the HTML attribute class is made for multiple elements with the same style/behaviour. You should use id if it is to dissociate one panel for another.
You have to store a count variable to know which panel has to appear next.
And always try to do what you want in Javascript without jQuery if it is possible !
var i = 1;
function clickBtn() {
if (!document.getElementById("panel-" + i))
return;
document.getElementById("panel-" + i).classList.add("visible");
i++;
}
.panel {
width: 50px;
height: 50px;
display: none;
margin: 5px;
background-color: #bbb;
}
.panel.visible {
display: block;
}
<button onclick="clickBtn()">click me</button>
<div>
<div id="panel-1" class="panel"></div>
<div id="panel-2" class="panel"></div>
<div id="panel-3" class="panel"></div>
<div id="panel-4" class="panel"></div>
</div>
You could use counter like clickCount instead of for loop
$(document).ready(function(){
// jQuery methods go here...
var clickCount = 1;
$("button").click(function(){
var myClass = ".panel" + clickCount;
$(myClass).addClass("showing animated fadeIn")
clickCount++;
});
});/**document ready **/
.showing{
background-color: red;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>title</title>
<link rel="stylesheet" type="text/css" href="mystyle.css">
<link rel="stylesheet" type="text/css" href="animate.css">
</head>
<body>
<button class="one">Click Me!</button>
<div id="page1">
<div class="panel1">
</div>
<div class="panel2">
</div>
<div class="panel3">
</div>
<div class="panel4">
</div>
</div><!-- page one -->
<div id="trial">
</div>
<script src="jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="jquery.touchSwipe.min.js"></script>
<script type="text/javascript" src="trial.js"></script>
</body>
</html>
You've got this a little bit backwards; you're trying to attach an event handler to the button for each element. Instead, you should have one event handler for the button, which cycles through the elements.
You could set a variable to keep track of which element is currently highlit, but it's easier to just determine that based on the current state of the DOM:
$(document).ready(function() {
$('button.one').click(function() {
$('.showing') // find the current element
.removeClass('showing') // clear it
.next() // find its next sibling
.addClass('showing'); // show that
if ($('.showing').length === 0) {
// nothing is showing, so show the first one
$('#page1 div:eq(0)').addClass('showing')
}
})
})
#page1 div {height: 10px}
#page1 div.showing {background-color: red}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="one">Click Me!</button>
<div id="page1">
<div class="panel1"></div>
<div class="panel2"></div>
<div class="panel3"></div>
<div class="panel4"> </div>
</div>
There's a small cheat in the above -- if the current element is the last one, then it won't have a next() to highlight. That's why I waited to check for the case where there's nothing visible until after moving the highlight; that way it will work for both the first click, and for when you need the highlight to loop back around to the first element.
If you intended to have the elements reveal themselves in sequence and not hide earlier ones, just get rid of the .removeClass('showing') line:
$(document).ready(function() {
$('button.one').click(function() {
$('.showing') // find the current element
.next() // find its next sibling
.addClass('showing'); // show that
if ($('.showing').length === 0) {
// nothing is showing, so show the first one
$('#page1 div:eq(0)').addClass('showing')
}
})
})
#page1 div {height: 10px}
#page1 div.showing {background-color: red}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="one">Click Me!</button>
<div id="page1">
<div class="panel1"></div>
<div class="panel2"></div>
<div class="panel3"></div>
<div class="panel4"> </div>
</div>
What you can do is count the amount of children that you have, and compare the amount of clicks through a given iterator you have to see what should be shown.
I added an extra functionality that hides the elements again once the max amount of divs has been shown.
Hope this helps.
$(document).ready(function() {
$('#page1').children().each(function () {
$(this).hide();
});
});
var panel="panel";
var pannelNum=0;
var count = $("#page1").children().length;
$(".one").on( "click", function() {
pannelNum=pannelNum+1;
if(pannelNum > count) {
$('#page1').children().each(function () {
$(this).hide();
});
pannelNum=0;
}
else {
clicked=panel+""+pannelNum;
$('.'+clicked).show();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="one">Click Me!</button>
<div id="page1">
<div class="panel1">
this is panel 1!
</div>
<div class="panel2">
this is panel 2!
</div>
<div class="panel3">
this is panel 3!
</div>
<div class="panel4">
this is panel 4!
</div>
</div><!-- page one -->
<div id="trial">
</div>

Slide a hidden bootstrap card from right to left on button click

I have a bootstrap4 `card' which is hidden and I want to display it with slide right to left slow animation on button click. Below is the markup
<div class="card" id="setup" style="display:none;">
<div class="card-header">Settings</div>
<div class="card-body">
Setup
</div>
</div>
</div>
Below is click event
$("#Finalize").click(function () {
$('#setup).show();
$("#setup").animate({ left: '0' }, 'slow');
});
With the above jquery code, I am just able to display the card, its animation effect is not working? What's wrong and how to make it work?
This worked for me:
$(function(){
$("#Finalize").click(function () {
$(".cardcontainer").show();
var left = $('#card').offset().left;
$("#card").css({left:left}).animate({"left":"0px"}, "slow");
});
});
.cardcontainer{
position:relative;
height: 220px;
display:none
}
.card{
position:absolute !important;
width:200px;
right:0px;
}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<div class="cardcontainer">
<div class="card" id="card">
<div class="card-header">Settings</div>
<div class="card-body">
Setup
</div>
</div>
</div>
</div>
<div>
<a id="Finalize" href="#" class="btn btn-primary">Go somewhere</a>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
Ok, here is the html:
<div class="card animatable" id="setup" style="display: none;">
<div class="card-header">Settings</div>
<div class="card-body">
Setup
</div>
</div>
</div>
here is the CSS (we need to define a width for the card. I just put 500px, you can make it however big you want it obviously)
#setup {
width: 500px;
}
And here is the javascript.
$("#Finalize").click(function () {
if ($('#setup').hasClass('animatable')) {
$('#setup').show();
$('#setup').css('margin-left', $(window).width());
$("#setup").animate({ right: "+=" + $(window).width()}, 'slow');
$('#setup').removeClass('animatable');
}
});
Note I know you said you didn't want a margin. According to the HTML code you posted, the card will appear on the left side of the screen with the DOM loads. So if you run the animation, it will fly off the screen because it's going to move to the left when it's already placed at the left. So we need to move it to the right, hence my margin-left. Now if you absolutely cannot have a margin, you can give the card an absolute position, and just left it over to the right side of the screen. Also, we need to give it a width so that the card won't crumple up when we move it to the right side of the screen.
I hope this helps!

foundation sticky does not work and remove markup when initialised from javascript

I am trying to make an element sticky without touching the HTML.
I tried to follow the documentation but i don't know where did i missed something.
I know there have been a similiar bug
but i use the patched (6.3.1) version
var elem = new Foundation.Sticky($('.another'));
.item{
height: 120vh;
}
.another{
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/js/foundation.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet"/>
<div class="item">
item
</div>
<div class="another">
another
</div>
<div class="item">
item
</div>
and a pen

Resizable split screen divs using jquery UI

I have a design in mind that involves a split panel view in html, similar to a winforms split panel. I've been expirimenting with jQuery UI - Resizable and I like the function, I just can't seem to co-ordinate the resizing of the two divs. The problem with the current code is that the two divs resize away from each other, not with one following the other. How can I make the two divs work together?
<html>
<head>
<title>Test</title>
<link rel="stylesheet" type="text/css" href="css/custom.css" />
<link rel="stylesheet" type="text/css" href="css/superfish.css" media="screen">
<link rel="stylesheet" type="text/css" href="css/jquery-ui-1.8.10.custom.css" media="screen">
<script type="text/javascript" src="script/jquery-1.5.1.js"></script>
<script type="text/javascript" src="script/superfish.js"></script>
<script type="text/javascript" src="script/jquery-ui-1.8.10.custom.min.js"></script>
<script type="text/javascript">
// initialise plugins
$(function(){
try {
$('ul.sf-menu').superfish();
//set up divs
$('#Content').resizable({ handles: 'e', alsoResize: $('#Attributes')});
}catch(ex){
alert(ex.message);
}
});
</script>
</head>
<body>
<div id="Header">
<div id="Menu">
<ul class="sf-menu" id="nav">
<!-- Snip menu -->
</ul>
</div>
</div>
<div id="Middle">
<div id="Content" class="ui-widget-content">This is where the view is.<br/>
Imagine an image here ...
<br/>
<br/>
<br/>
</div>
<div id="Attributes" class="ui-widget-content">
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
</div>
</div>
<div id="FootBreak"/>
<div id="Footer">
Help
</div>
</body>
</html>
I have worked out a reasonable hack, using the resize event.
<script type="text/javascript">
var WIDTH_ATTR = 'initWidth';
// initialise plugins
$(function(){
try {
$('#Content').resizable({ handles: 'e', resize: resizeAttr });
$('#Content').attr(WIDTH_ATTR, $('#Content').width());
$('#InfoPanel').attr(WIDTH_ATTR, $('#InfoPanel').width());
}catch(ex){
alert(ex.message);
}
});
function resizeAttr(event, ui){
var change = ui.size.width - $('#Content').attr(WIDTH_ATTR);
$('#InfoPanel').width($('#InfoPanel').attr(WIDTH_ATTR) - change);
};
</script>
I'm still open to cleaner answers from others...
I am not sure if this meets the requirements, but ExtJS handles split panes with ease and works cross-browser. For example, see this RSS feed client in ExtJS. Be aware the ExtJS has commercial licensing restrictions if your intent is to sell your product.
Here is an example with a horizontal split (one top div, one bottom div), maybe slightly more minimalistic:
HTML:
<html>
<head>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<div id="div1">1st</div>
<div id="div2">2nd</div>
</body>
</html>
CSS:
#div1, #div2 {
position: absolute;
left: 0;
right: 0;
outline: solid 1px #ccc; /* just for making the divs visible */
margin: 5px; /* just for making the divs visible */
}
#div1 {
height: 100px;
top: 0;
}
#div2 {
top: 110px;
bottom: 0;
}
JavaScript:
$('#div1').resizable({
handles: 's',
resize: resizeEventHandler
});
function resizeEventHandler(event, ui){
var new_height = ui.size.height;
$('#div2').css('top', new_height + 10);
}
See demo here.

Categories

Resources