Bootstrap5 modal must toggle visibility of divs - javascript

What specific changes need to be made in the Bootstrap 5 example below in order for the following two things to occur:
the "afterAcceptingTerms" div should be hidden until the user has clicked on the Accept Terms modal button, so that only the "beforeAcceptingTerms" div should be visible until the user has clicked on the Accept Terms modal button.**
the "afterAcceptingTerms" should become visible once the user clicks on the Accept Terms modal button, and the "beforeAcceptingTerms" div should be hidden once the user clicks on the Accept Terms modal button.
Here is the Bootstrap 5 code we are currently starting with, but you can see that the code example below fails to toggle the
div classes as stated in the requirements above.
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>Modal Popup Page</title>
<link href="/assets/css/bootstrap.min.css" rel="stylesheet">
<script src="/assets/js/popper.min.js"></script>
<script src="/assets/js/bootstrap.min.js" ></script>
</head>
<body>
<div class="wrapper" id="beforeAcceptingTerms">
<section class="content-section">
<p>You must click on the "I agree to the terms button" in order to see the content on this page.</p>
</section>
</div>
<div class="wrapper" id="afterAcceptingTerms">
<section class="content-section">
<p>The page content goes here. But this is only visible because you clicked on the Accept button on the modal in order to get the modal to go away.</p>
</section>
</div>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
<div class="modal-dialog" style="position: fixed;bottom: 0;left: 0;right: 0;">
<div class="modal-content">
<div class="modal-body">
By using this site, you certify that you agree to our Terms of Use.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" onclick="localStorage.setItem('acceptTerms',1)">I agree to the Terms.</button>
</div>
</div>
</div>
</div>
<script>
let acceptTerms = localStorage.getItem('acceptTerms');
if(acceptTerms != 1){
var myModal = new bootstrap.Modal(document.getElementById('myModal'), {})
myModal.show()
}
</script>
</body>
</html>

You forgot to add CDNs instead your local files.
(I added a button to clear local storage data for testing purpose).
What did I change?
// Window onload event to display your content if users has accepted terms
// calling checkTerms() function
window.onload = (event) => {
checkTerms();
};
const afterAcceptingTerms = document.getElementById('afterAcceptingTerms');
const acceptTermsButton = document.getElementById('acceptTermsButton');
// Added a listener to your accept terms button
// removing inline onclick element attribute
acceptTermsButton.addEventListener('click', function() {
termsAccepted();
});
// Here we manage what to do when user click in the accept terms button
// in this case with try/catch to prevent critical errors its good to send
// errors like that (in a catch block) to a server for you stay on what errors users can experience
function termsAccepted() {
try {
localStorage.setItem('acceptTerms',1);
} catch (error) {
alert('CRITICAL ERROR !!!! USER WILL NOT SEE THE CONTENT');
}
afterAcceptingTerms.classList.remove('none');
}
// Function called when window load !! To check if user has accept the terms !
// I'm using try/catch because this is critical, if the localStorage can't be accessed
// your content won't be shown
function checkTerms() {
let val = '';
try {
val = localStorage.getItem('acceptTerms');
} catch (error) {
alert('CRITICAL ERROR !!!! USER WILL NOT SEE THE CONTENT');
}
if (val === '1') {
afterAcceptingTerms.classList.remove('none');
} else {
var myModal = new bootstrap.Modal(document.getElementById('myModal'), {})
myModal.show()
}
}
Also added a .none class with (display:none) to your #afterAcceptingTerms element, it was essential this element starts with display:none. We are going to remove that class programmatically:
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>Modal Popup Page</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<style>
.none {
display: none;
}
</style>
</head>
<body>
<div class="wrapper" id="beforeAcceptingTerms">
<section class="content-section">
<p>You must click on the "I agree to the terms button" in order to see the content on this page.</p>
</section>
<button id="clearData">Clear storage data</button>
</div>
<div class="wrapper none" id="afterAcceptingTerms">
<section class="content-section">
<p>The page content goes here. But this is only visible because you clicked on the Accept button on the modal in order to get the modal to go away.</p>
</section>
</div>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
<div class="modal-dialog" style="position: fixed;bottom: 0;left: 0;right: 0;">
<div class="modal-content">
<div class="modal-body">
By using this site, you certify that you agree to our Terms of Use.
</div>
<div class="modal-footer">
<button type="button" id="acceptTermsButton" class="btn btn-secondary" data-bs-dismiss="modal">I agree to the Terms.</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script>
var clearData = document.getElementById('clearData');
clearData.addEventListener('click', function() {
localStorage.clear();
});
window.onload = (event) => {
checkTerms();
};
const afterAcceptingTerms = document.getElementById('afterAcceptingTerms');
const acceptTermsButton = document.getElementById('acceptTermsButton');
acceptTermsButton.addEventListener('click', function() {
termsAccepted();
});
function termsAccepted() {
try {
localStorage.setItem('acceptTerms',1);
afterAcceptingTerms.classList.remove('none');
} catch (error) {
alert('CRITICAL ERROR !!!! USER WILL NOT SEE THE CONTENT');
}
}
function checkTerms() {
let val = '';
try {
val = localStorage.getItem('acceptTerms');
if (val === '1') {
afterAcceptingTerms.classList.remove('none');
} else {
var myModal = new bootstrap.Modal(document.getElementById('myModal'), {})
myModal.show()
}
} catch (error) {
alert('CRITICAL ERROR !!!! USER WILL NOT SEE THE CONTENT');
}
}
</script>
</body>
</html>

Related

Unhandled Promise Rejection: TypeError: null is not an object (evaluating 'editUserUI.innerHTML = interfaceHTML')

I am trying to set the inner html of a div element with the id "admin-edit-user-content" in javascript. But the console gives me the error in the tile, apparently my document.getElementById('#admin-edit-user-content'); is null. However, this element does definitely exist. It is in my body of my index.html:
<html lang="nl">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
</head>
<body class="grey lighten-3">
<!-- There's a lot of other code here that is not relevant right now -->
<div id="modal-admin-edit-user" class="modal">
<div class="modal-content">
<h4>Gebruiker bewerken</h4>
<div id="admin-edit-user-content">
<!-- inner html goes here -->
</div>
</div>
</div>
<!-- Some more code -->
<script src="/scripts/index.js"></scripts>
</body>
</html>
Then in my index.js:
// A lot of code goes before this
// this function is called on a button press
function updateEditUserUI(uid) {
// editUserUI is null and I don't understand why
const editUserUI = document.getElementById("#admin-edit-user-content");
const interfaceHTML = `
<p>Some inner html, I've gotten rid of all the details because they are not relevant for this question</p>
`;
// Right here I get the exception:
editUserUI.innerHTML = interfaceHTML;
}
// more code
Does anyone know why this happens? Because I'm completely out of ideas.
I've tried only executing the code when the cont variable in the example below was true, but this didn't help.
var cont = false;
document.addEventListener('DOMContentLoaded',() => {
cont = true;
});
Thank you in advance,
Jonas
If you are using getElementById, you do not need a # before the ID. Just do
document.getElementById('admin-edit-user-content');
You use a # if you are using querySelector or querySelectorAll.
there are some code missing, hence I can not predict much.
Check this:
document.getElementById("#admin-edit-user-content"); //no # needed
Hope this helps:
<html lang="nl">
<body class="grey lighten-3">
<!-- There's a lot of other code here that is not relevant right now -->
<div id="modal-admin-edit-user" class="modal">
<div class="modal-content">
<h4>Gebruiker bewerken</h4>
<div id="admin-edit-user-content">
<!-- inner html goes here -->
</div>
</div>
</div>
<button onclick="updateEditUserUI()">Your Button</button>
<!-- Some more code -->
<script>
function updateEditUserUI() {
// editUserUI is null and I don't understand why
const editUserUI = document.getElementById("admin-edit-user-content");
const interfaceHTML = "<p>Some inner html</p>";
// Right here I get the exception:
editUserUI.innerHTML = interfaceHTML;
};
</script>
</body>
</html>

more than 2 model in same page

In the examples above, i use a button to close the modal. However, with a little bit of JavaScript, you can also close the modal when clicking outside of the modal box.
the problem is when i use 2 modals just i can close first modal when i click any where , the second one i cannot !!
<!DOCTYPE html>
<html>
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<body>
<button onclick="document.getElementById('id01').style.display='block'" class="w3-button w3-black">Open Modal 1</button>
<button onclick="document.getElementById('id02').style.display='block'" class="w3-button w3-black">Open Modal 2</button>
<div id="id01" class="w3-modal">
<div class="w3-modal-content w3-card-4">
<div class="w3-container">
<p>model 1</p>
</div>
</div>
</div>
<div id="id02" class="w3-modal">
<div class="w3-modal-content w3-card-4">
<div class="w3-container">
<p>model 2</p>
</div>
</div>
</div>
<script>
// Get the modal
var modal = document.getElementById('id01','id02');
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
</body>
</html>
The function document.getElementById, just like the Element in the name indicates, only gets one element, so the second parameter, 'id2', is ignored, and you end up only getting the first modal element. Read more in the document.
You can use document.getElementsByClassName to fix this:
<!DOCTYPE html>
<html>
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<body>
<button onclick="document.getElementById('id01').style.display='block'" class="w3-button w3-black">Open Modal 1</button>
<button onclick="document.getElementById('id02').style.display='block'" class="w3-button w3-black">Open Modal 2</button>
<div id="id01" class="w3-modal">
<div class="w3-modal-content w3-card-4">
<div class="w3-container">
<p>model 1</p>
</div>
</div>
</div>
<div id="id02" class="w3-modal">
<div class="w3-modal-content w3-card-4">
<div class="w3-container">
<p>model 2</p>
</div>
</div>
</div>
<script>
// Get the modal
var modals = document.getElementsByClassName('w3-modal');
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
console.log(event.target, event.target == modals[0], event.target == modals[1]);
if (event.target == modals[0] || event.target == modals[1]) {
modals[0].style.display = "none";
modals[1].style.display = "none";
}
}
</script>
</body>
</html>
Optionally, you can use a relatively new api, document.querySelector, to unify the usages of selecting DOM elements. It uses css selector like string to select elements. But it's a bit new so you may want to check browser compatibility before using it.

Can't change div style with JS function

The main goal is to show different divs depending on which button I click, so they all start with the display style at "none" (except a default one called "atualizacoes"). And after I click a button ALL of the divs should be set to
display="none" and after that the one I associated that button with is set to display="block".
However something isn't right because when I click one of the buttons, the default div does disappear however nothing ever appears.
This is how I'm trying to accomplishing it:
In order:
snippet 1 - function I use inside my index.html to change all the
displays
snippet 2 - rule in my stylesheet
snippet 3 - parts of my index.html code (I didn't want to paste
EVERYTHING)
<script type="text/javascript">
function replace(show) {
document.getElementById('default').style.display="none";
document.getElementById('ecra').style.display="none";
document.getElementById(show).syle.display = "block";
}
</script>
.ecra
{
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>University Platform</title>
<!-- Bootstrap core CSS -->
<link href="bootstrap/css/bootstrap.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="dashboard.css" rel="stylesheet">
<!-- jquery -->
<script src="assets/js/jquery.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<!-- these are the buttons that are located on a sidebar -->
<div class="row">
<h3>Options</h3>
<button type="button" class="btn btn-default botao pull-left" onclick="replace('addestudante')">Adicionar Estudante</button>
</div>
<div class="row">
<button type="button" class="btn btn-default botao pull-left" onclick="replace('adduc')">Adicionar UC</button>
</div>
<!-- these are the divs I want to switch around -->
<div class="row" id='default'>
<p> Hello World </p>
</div>
<!-- in CSS I also made a rule that makes all "ecra" divs be invisible from the start-->
<div class="row ecra" id='addestudante'>
<button type="button" class="btn btn-default"> TEST 1</button>
</div>
<div class="row ecra" id='adduc'>
<button type="button" class="btn btn-default"> TEST 2</button>
</div>
</body>
Why is this function not working properly? Is there something wrong with my code?
There are a couple of issues with what you've written.
For one, you don't have any elements with ID "ecra" — what you want to do is affect all the elements that have the class "ecra". You can do this by looping or mapping over document.getElementsByClassName("ecra").
Secondly, you've misspelt style when you try to show the show element.
Try using this adapted function instead:
function replace(show) {
document.getElementById("default").style.display = "none";
Array.from(document.getElementsByClassName("ecra")).map(element => element.style.display = "none");
document.getElementById(show).style.display = "block";
}
By what I thought, you want to get elements by class name. They're ecra, so you can use querySelectorAll and do a loop for its length. I'll not use getElementsByClassName because it will make the line more longer and return an array.
function replace(show){
var q=document.querySelectorAll('.ecra'),
document.getElementById('default').style.display="none";
for(var i=0,l=q.length;i<l;i++){
!function(i){
q[i].style.display="none"
}(i)
}
document.querySelector('#'+show).style.display = "block"
}
I saw jQuery imported in your page. So I suggest to use jQuery.
<script type="text/javascript">
function replace(show) {
jQuery(function($){
$("#default").css({
"display" : "none"
});
$(".ecra").css({
"display" : "none"
});
$("#"+show).css({
"display" : "block"
});
});
}
</script>
Edited, missing characters.
JS corrected : http://jsfiddle.net/csfd8x35/
.ecra
{
display: none;
}
<!-- these are the buttons that are located on a sidebar -->
<div class="row">
<h3>Options</h3>
<button type="button" class="btn btn-default botao pull-left" onclick="replace1('addestudante')">Adicionar Estudante</button>
</div>
<div class="row">
<button type="button" class="btn btn-default botao pull-left" onclick="replace1('adduc')">Adicionar UC</button>
</div>
<!-- these are the divs I want to switch around -->
<div class="row" id='default'>
<p> Hello World </p>
</div>
<!-- in CSS I also made a rule that makes all "ecra" divs be invisible from the start-->
<div class="row ecra" id='addestudante'>
<button type="button" class="btn btn-default"> TEST 1</button>
</div>
<div class="row ecra" id='adduc'>
<button type="button" class="btn btn-default"> TEST 2</button>
</div>
<script>
function replace1(show) {
document.getElementById('default').style.display="none";
var allByClass = document.getElementsByClassName('ecra');
for (var i=0;i< allByClass.length; i++) {
allByClass[i].style.display = "none";
}
document.getElementById(show).style.display = "block";
}
</script>

bootstrap modal button click event not fired on first time

i am new to twitter bootstrap .i am using the bootstrap 3
and this is my html code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Bootstrap Samples</title>
<script src="scripts/jquery1.10.2.min.js"></script>
<script src="bootstrap-3.1.1-dist/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="bootstrap-3.1.1-dist/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="bootstrap-3.1.1-dist/css/bootstrap-theme.min.css" />
<style>
.banner {color:#FF0000;}
</style>
<script>
$(document).ready(function(){
$("#MyModal5").on('hidden.bs.modal',function(){
$("#btnYes").on('click',function(e){
var $myMod = $(this);
var id = $myMod.data('cust-id');
if(id=='y'){
alert("You clicked yes button");
}
});
});
});
</script>
</head>
<body>
<!-- -------------------------------------------------------------------- -->
<div class="modal fade" id="MyModal5">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-title">
<label style="color:#FF6600;">Confirmation</label>
</div>
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<label>This may cause to make an additional hit to server. Are you sure you want to continue ?</label>
</div>
<div class="modal-footer">
<button class="btn btn-success btn-sm" id="btnYes" data-cust-id="y" data-dismiss="modal">Yes</button>
<button class="btn btn-danger btn-sm" id="btnNo" data-cust-id="n" data-dismiss="modal">No</button>
</div>
</div>
</div>
</div>
<!-- -------------------------------------------------------------------- -->
<div class="container">
<div class="row">
<div class="col-sm-12">
<label>If you want to visit google</label>Click here
</div>
</div>
</div>
</body>
</html>
idea is that i have a link, while i click on that link i need to populate the model.its working,now if i click on the 'yes' button on that modal ,i need an alert, but problem is that alert is not showing when i click on yes button for first time ,but if i again click on that button for second time it is showing,another problem is tht if i clicked on third time alert is showing twise,i dont know the exact reason,i suspect this is because of the on event of jquery.
can any one help me to slove this issue
I believe the issue may stem from your click event bindings being nested. Try removing the outer binding and just register the click event in this way:
$(document).ready(function() {
$("#btnYes").on("click",function(e) {
var $myMod = $(this).closest(".modal"); // Select on closest parent modal
// Now run your required code
});
});
});
Hope this works and helps! Good luck.

Bootstrap Modal blocks select element

When the Modal appears there is a select list that is anchored to the top left of the page. Eventually that list will be used to provide navigation options; however I am unable to select an option in the list. I have tried to set the z-index higher than the modal but nothing seems to work. Hope someone can shed some light on a solution? Thanks!
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Tool</title>
<!-- Bootstrap v2.3.2 -->
<link href="css/bootstrap.css" rel="stylesheet" />
</head>
<body>
<button type="button" class="onl btn btn-success btn_online">Submit</button>
<!-- popup message -->
<div id="popup_message" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="_c1g">Description</h3>
</div>
<div class="well msg" id="msg" style="max-height:400px;overflow:auto;"></div>
<div class="modal-footer">
<button class="btn _c1e" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
<script src="script/jquery-1.8.3.js" type="text/javascript"></script>
<!--Bootstrap v3.0.0-->
<script src="script/bootstrap.min.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
$(document).on('click', '.btn_online', function (e) {
$('#popup_message').modal('show');
$("body").append("<select id='my_redirect' style='top:20px;left:20px;z-index:1051;position:absolute;'><option value='' >Select...</option><option value='Page1' >Page1</option><option value='Page2' >Page2</option></select>")
});
});
</script>
To resolve the issue of a modal blocking all elements beneath it when closed you can also add the following block:
<style>
/*Modal blocking caused issues with selecting objects*/
.modal { display:none; }
</style>
Twitter bootstrap multiple modal error
My assumptions were correct. The modal enforces focus on itself. The above has the solution created by #SmartLove. Basically place the following after the bootstrap scripts..
$.fn.modal.Constructor.prototype.enforceFocus = function () {};
Now the select element works as expected! Woo Hoo!

Categories