Prevent Background Scroll on Modal Box - javascript

I am using a plugin which has a modal pop up box for login (CM Registration Pro). I would like the background (body of my website) to not be able to scroll when the modal pop up is open.
I have tried the following code but am unable to get it to work
jQuery(document).ready(function ($) {
if($('.cmreg-overlay').length){
$('html').css('overflow', 'hidden');
}
});
If you would like to see the problem live my website is Redec

A Quick example that should work is:-
var element = document.querySelector('body');
element.addEventListener('click',function(){
if(element.classList.contains('.cmreg-overlay-visible')){
document.documentElement.style.overflow = 'hidden';
}
else{
document.documentElement.style.overflow = 'visible';
}
});

As it stands, your body has no background. If you mean you don't want your body to scroll when the modal box is open, then you can check whether .cmreg-overlay is shown, and if so then set overflow:hidden to the body.
I will assume that only #menu-item-16137, #menu-item-16194 and #menu-item-16195 are Here is how to do it:
// Prevent the body from scrolling when the modal opens
var x = document.querySelectorAll("#menu-item-16137, #menu-item-16194, #menu-item-16195");
for(var i = 0; i < x.length; i++) {
x[i].addEventListener("click", function() {
if($(".cmreg-overlay").style.display != none) {
document.body.style.overflow = hidden;
}
});
}
// Return the body back to scrolling when closing the modal
document.querySelector(".cmreg-overlay").addEventListener("click", function() {
document.body.style.overflow = "auto";
}

Related

I have a javascript that stops working when a button is not showed. How can I fix it?

I've got 4 buttons and each button opens a section and closes the other. There is a possibility that one or the buttons are stay hidden because of a switch in the backend which you can toggle to make it visible (or to hide).
Now, if one or more buttons are not visible the script stops working. If I toggle all the buttons on, the buttons display and the script is working.
I have this code and it works fine (as long as all the buttons are visible):
<style>
.elementor-editor-active .hidden {
display:block;
}
.hidden{
display:none;
}
.shown{
display: block !important;
}
.btn_active_state{
background-color: #FFCC00 !important;
}
.btn_active_state a{
font-weight: bold !important;
}
</style>
<script>
var divs
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var btn3 = document.getElementById("btn3");
var btn4 = document.getElementById("btn4");
btn1.onclick = function(event){
event.preventDefault();
toggleDivs("sect1",this);
};
btn2.onclick = function(event){
event.preventDefault();
toggleDivs("sect2",this);
};
btn3.onclick = function(event){
event.preventDefault();
toggleDivs("sect3",this);
};
btn4.onclick = function(event){
event.preventDefault();
toggleDivs("sect4",this);
};
function toggleDivs(s,btn){
if(btn.classList.contains("btn_active_state")){
document.getElementById(s).classList.remove("shown");
btn.classList.remove("btn_active_state");
document.getElementById(s).classList.remove("shown");
return;
}else{
btn1.classList.remove("btn_active_state");
btn2.classList.remove("btn_active_state");
btn3.classList.remove("btn_active_state");
btn4.classList.remove("btn_active_state");
btn.classList.add("btn_active_state");
document.getElementById("sect1").classList.remove("shown");
document.getElementById("sect2").classList.remove("shown");
document.getElementById("sect3").classList.remove("shown");
document.getElementById("sect4").classList.remove("shown");
document.getElementById(s).classList.add("shown","fade");
}
}
//force button1 state initialise, if required
//btn1.focus();
//btn1.click();
</script>
The script stops working when I toggle one or more buttons to OFF (so they don't display on the front-end). I saw solutions with a Try Catch method, but I don't know (if this is the right way to fix it), where to implement it...
I am using Elementor in Wordpress to accomplish this. (HTML widget where I pasted this code and named the sections and buttons to the names named in the code).
Side note: I'm not an expert in Javascript.
Thanks advance!
While I had 4 Elementor widgets (I used this as buttons) with every widget a unique ID (#btn1, #btn2, #btn3 & #btn4). I had also 4 different Elementor sections with their own ID (#sect1, #sect2, #sect3 & #sect4). If you clicked one of the button, the respective section would display (btn1 shows sect1, btn2 shows sect2 etc..).
The standard script (posted in first place) worked fined when all the buttons (btn1, btn2 etc.) where visible (not rendered, not in the code) on the page. This is because I used the Dynamic Visibility options in the 'Advanced' tab in Elementor (Crocoblock JetEngine/Elementor Pro).
The problem arose when 1 or more buttons were missing because of the Dynamic Visibility (If a switch in the CPT turned off, it will not show the widget). The script stopped working and none of the buttons worked again.
Now, I used this code in a HTML widget and placed the HTML widget under the sections (above the sections are the widgets acting like buttons). The first part of the script gives an 'active' state to the button you click on. Assure that you set the class of the button you want to have an active state as default, to 'active':
<style>
.elementor-editor-active .hidden {
display:block;
}
.hidden{
display:none;
}
.shown{
display: block !important;
}
#btn1, #btn2, #btn3, #btn4 {
cursor: pointer;
}
.active h2 {
font-weight: bold !important;
}
</style>
<script>
var activeButton = document.getElementById("btn1");
function toggleActive(btn) {
if (activeButton && activeButton != btn) {
activeButton.classList.remove("active");
}
activeButton = btn;
btn.classList.add("active");
}
var sect1 = document.getElementById("sect1");
var sect2 = document.getElementById("sect2");
var sect3 = document.getElementById("sect3");
var sect4 = document.getElementById("sect4");
try {
var btn1 = document.getElementById("btn1");
btn1.onclick = function(event){
toggleActive(btn1);
document.getElementById("sect1").classList.add("shown");
document.getElementById("sect2").classList.remove("shown");
document.getElementById("sect3").classList.remove("shown");
document.getElementById("sect4").classList.remove("shown");
};
} catch (error) {
console.log("btn1 not found on the page. Error: " + error);
}
try {
var btn2 = document.getElementById("btn2");
btn2.onclick = function(event){
toggleActive(btn2);
document.getElementById("sect1").classList.remove("shown");
document.getElementById("sect2").classList.add("shown");
document.getElementById("sect3").classList.remove("shown");
document.getElementById("sect4").classList.remove("shown");
};
} catch (error) {
console.log("btn1 not found on the page. Error: " + error);
}
try {
var btn3 = document.getElementById("btn3");
btn3.onclick = function(event){
toggleActive(btn3);
document.getElementById("sect1").classList.remove("shown");
document.getElementById("sect2").classList.remove("shown");
document.getElementById("sect3").classList.add("shown");
document.getElementById("sect4").classList.remove("shown");
};
} catch (error) {
console.log("btn1 not found on the page. Error: " + error);
}
try {
var btn4 = document.getElementById("btn4");
btn4.onclick = function(event){
toggleActive(btn4);
document.getElementById("sect1").classList.remove("shown");
document.getElementById("sect2").classList.remove("shown");
document.getElementById("sect3").classList.remove("shown");
document.getElementById("sect4").classList.add("shown");
};
} catch (error) {
console.log("btn1 not found on the page. Error: " + error);
}
</script>
OK. I have finished this up. you can extend it easily by adding to the buttons list ( at the top of the document ). This is a system to create the buttons, action and sections. It allows you to toggle between them, essentially like tabs. It is likely not the best implementation, but it is a working system, something to get started with. It separates the views from the buttons, two functions to control the state of each. one is controlling the buttons, the other the views. this should be your approach moving forward... Keep It Stupid Simple. Avoid complexity, embrace readability. if you want code to be ultra compact and "efficient", use webpack :D
//define buttons
const buttons = [
{ id:'btn1',
section:'sect1',
label:'Button 1'},
{ id:'btn2',
section:'sect2',
label:'Button 2'},
{ id:'btn3',
section:'sect3',
label:'Button 3'},
{ id:'btn4',
section:'sect4',
label:'Button 4'}
];
//console.table(buttons);
const views = [];
// create buttons and assign click, create sections
for ( const button of buttons){
let nB = document.createElement('button');
nB.id=button.id;
nB.innerText=button.label;
nB.onclick=(e)=>{
e.preventDefault();
toggleView( button.section, views );
toggleButton( button.id, buttons );
}
document.getElementById('menu').appendChild(nB);
// create the span / divs
let nD = document.createElement('div');
nD.id=button.section;
// put something in here for testing
nD.innerText=button.section;
nD.classList.add('hidden');
views.push(button.section);
document.getElementById('viewer').appendChild(nD);
}
// function to change sections
function toggleView( view, viewList ){
//console.log( view );
//console.log( viewList );
// hide all
for ( const v of viewList ){
// not actually the elements, but just reference
document.getElementById( v ).classList.remove('shown');
// unhide 'view' by id
if ( v == view ) {
//console.log(`view ${v} found`);
document.getElementById( v ).classList.add('shown');
}
}
}
function toggleButton( button, buttonList ){
// console.log(button);
// console.log(buttonList);
// enable all
// disable this button id
// iterate through managed list
for ( const b of buttonList ){
// console.log(b);
document.getElementById(b.id).classList.add('btn_active_state');
if ( b.id == button ) document.getElementById(b.id).classList.remove('btn_active_state');
}
}
toggleButton( buttons[0], buttons );
.elementor-editor-active .hidden {
display:block;
}
.hidden{
display:none;
}
.shown{
display: block !important;
}
.btn_active_state{
background-color: #FFCC00 !important;
}
.btn_active_state a{
font-weight: bold !important;
}
<html>
<body>
<div id='menu'></div>
<div id='viewer'></div>
</body>
</html>
Does this help? I've replaced 'this' with the btn var itself when calling toggleDivs(). So rather than toggleDivs("sect1", this) use toggleDivs("sect1", btn1)
btn1.onclick = function(event){
event.preventDefault();
toggleDivs("sect1",btn1);
};
btn2.onclick = function(event){
event.preventDefault();
toggleDivs("sect2",btn2);
};
btn3.onclick = function(event){
event.preventDefault();
toggleDivs("sect3",btn3);
};
btn4.onclick = function(event){
event.preventDefault();
toggleDivs("sect4",btn4);
};
// try to assign the var btn1 to the element
var btn1 = document.getElementById('btn1');
// check to see if it is valid / not null
if ( btn1 ){
// if it gets here, then the button is valid
btn1.onclick = (e) =>{
// show / hide sections
}
}
//otherwise, if btn1==null it will continue to the next

Store div status on page reload

I have multiple divs in one html page under common wrapper class.
I am using hide and show method on clicking next and previous option.
What I am trying to achieve: On page reload/refresh, the div which is showing currently should show after page reload.
So in short if you reload/refresh from pink screen, it should show same pink screen after page reload.
What I tried: I am storing the display properties (none or block) is local storage and on page reload trying to give same properties to divs again. Most of the responses and solution I checked in Stack overflow is regarding opening the same tab when refresh. but my case is what in same tab I have multiple div and I want to open from the same state which it was earlier.
Logic I used:
$(window).on('load', function(){
var disp = localStorage.getItem("disp");
var ustatus = JSON.parse(disp);
$(".chk").text(ustatus);
for (var x=ustatus; x<ustatus.length; x++){
$(".pg"+x).css("display", ustatus[x]);
}
});
This is fiddle link I tried:
Page reload demo JS Fiddle link
Your HTML and CSS code is perfect but you need to make corrections in your JavaScript code.
Observation 1 : You "for" loop to assign display style has problem with variable x. You need to assign integer value to x.
Observation 2 : You need to remove that "display" style from "div" elements when you click on "next" and "previous" links.
Hear is new Js fiddle link with updated code.
$(window).on('load', function () {
//localStorage.removeItem("disp");
var disp = localStorage.getItem("disp");
var ustatus = JSON.parse(disp);
$(".chk").text(ustatus);
for (var x = 1; x <= ustatus.length; x++) {
$(".pg" + x).css("display", ustatus[x-1]);
}
});
$(".next").on("click", function () {
$(this).parent().addClass("off").removeClass("on").removeAttr("style");
$(this).parent().next().addClass("on").removeClass("off").removeAttr("style");
});
$(".prev").on("click", function () {
$(this).parent().addClass("off").removeClass("on").removeAttr("style");
$(this).parent().prev().addClass("on").removeClass("off").removeAttr("style");
});
$(window).on('beforeunload', function () {
var display = $(".clr").map(function () {
return $(this).css("display");
}).get();
localStorage.setItem("disp", JSON.stringify(display));
});
You can also download this file. Please run index.html to see the output.
You don't really need the on class:
$(window).on('load', function(){
var disp = localStorage.getItem("disp");
var ustatus = JSON.parse(disp);
$(".chk").text(ustatus);
for (var x=0; x<ustatus.length; x++){
$(".pg"+(x+1)).toggleClass("off", ustatus[x]);
}
});
$(".next").on("click", function(){
$(this).parent().addClass("off");
$(this).parent().next().removeClass("off");
});
$(".prev").on("click", function(){
$(this).parent().addClass("off");
$(this).parent().prev().removeClass("off");
});
$(window).on('beforeunload', function(){
var display = $(".clr").map(function(){
return $(this).hasClass("off");
}).get();
localStorage.setItem("disp", JSON.stringify(display));
});
Fiddle
note: you can't use $(window).on('load', ...) in a fiddle - the JS in the editor is run on load
EDIT: you might also want to validate ustatus before applying it, something like
if (Array.isArray(ustatus) && ustatus.filter(x => x === true).length === 1) {
for (var x=0; x<ustatus.length; x++){
$(".pg"+(x+1)).toggleClass("off", ustatus[x]);
}
}
You can do it without using display, you can use on and off classes, i think that's why they are created for
$(window).on('load', function(){
var disp = localStorage.getItem("disp");
var ustatus = JSON.parse(disp);
if(ustatus!=undefined){
$(".chk").text(ustatus);
for (var x=1; x<=ustatus.length; x++){
if(ustatus[x-1]=='on'){
$(".pg"+x).addClass("on").removeClass("off");
}
else{
$(".pg"+x).addClass("off").removeClass("on");
}
}
}
$(".next").on("click", function(){
$(this).parent().addClass("off").removeClass("on");
$(this).parent().next().addClass("on").removeClass("off");
});
$(".prev").on("click", function(){
$(this).parent().addClass("off").removeClass("on");
$(this).parent().prev().addClass("on").removeClass("off");
});
$(window).on('beforeunload', function(){
var display = $(".clr").map(function(){
if($(this).hasClass('on'))
return 'on';
else
return 'off';
}).get();
localStorage.setItem("disp", JSON.stringify(display));
});
});

Using JS to apply CSS when clicking buttons

I am using a modal that when clicked it should popup full screen.
Everything is good, modal pops full screen but the header ( logo + menu ) still shows up.
I'm trying to use JS, so when the modal is clicked i want to apply a z-index to the header and when the close button is clicked i will apply another z-index to fix the header.
the link to be clicked is this:
<a class="vPlay vPlay-btn clickformodal" href="#modal-our-work-1" data-toggle="modal" data-video="241737557"><img src="/wp-content/uploads/2018/04/play1.png" /></a>
Now the JS code is this:
let open = document.selectElementByClassName("clickformodal");
let header = document.selectElementByClassName("mk-header");
let close = document.selectElementByClassName("close");
open.addEventListener('click', function () {
header.classList.add("headerbefore");
});
close.addEventListener('click', function () {
header.classList.remove("headerafter");
});
And this is the css that will be applied:
.headerbefore {
z-index: 1;
}
.headerafter {
z-index: 301;
}
The issue here appart that it's not doing what it is supposed too, google chrome shows an error in console saying that let open = document.selectElementByClassName("clickformodal"); is not a function.
What am i doing wrong here?
Help me out please, it's been 2 days that i'm trying to fix this and nothing till now :/
Thanks!!!
There are 2 things going wrong here:
it should be getElementsByClassName, not selectElementByClassName
as getElementsByClassName returns an element collection, you need to add [0] at its end, e.g. document.getElementsByClassName("clickformodal")[0]
let open = document.getElementsByClassName("clickformodal")[0];
let header = document.getElementsByClassName("mk-header")[0];
let close = document.getElementsByClassName("close")[0];
open.addEventListener('click', function () {
header.classList.add("headerbefore");
});
close.addEventListener('click', function () {
header.classList.remove("headerafter");
});
An option could be to use querySelector() instead
let open = document.querySelector(".clickformodal");
let header = document.querySelector(".mk-header");
let close = document.querySelector(".close");
open.addEventListener('click', function () {
header.classList.add("headerbefore");
});
close.addEventListener('click', function () {
header.classList.remove("headerafter");
});
If to add to more than 1, use querySelectorAll() (this sample assume there is as many open as close but only 1 header)
let open = document.querySelectorAll(".clickformodal");
let header = document.querySelector(".mk-header");
let close = document.querySelectorAll(".close");
for (var i = 0; i < open.length; i++) {
open[i].addEventListener('click', function () {
header.classList.add("headerbefore");
});
}
for (var j=0; j < close.length; j++) {
close[j].addEventListener('click', function () {
header.classList.remove("headerbefore");
});
}

jQuery hover function to display an overlay but closes when hover displayed content

I am a little new to JS / jQuery and have done a hover function so when hover a link it shows a hidden DIV area but when I go to then hover over the div area shown of course it closes. I would like that if I then go into the content area won't close but stay open but then if leave that area would close?
JS:
$('.mini-cart').hover(
function () {
cartOpen();
},
function () {
cartClose();
}
);
var overlay = $("#cart_slide");
var cartContainer = $("#cart_over");
function cartOpen() {
cartContainer.fadeIn("slow");
overlay.addClass("overlay");
}
function cartClose() {
cartContainer.fadeOut("medium");
overlay.removeClass("overlay");
}
HTML:
<a class="mini-cart">hover link</a>
<div id="cart_over" style="display:none;">testing</div>
You could introduce the usage of a flag (isCartOpen) variable which is going to control the whether the DIV should be displayed or not.
See this working JSFiddle example and find below the related code:
var isCartOpen = false;
$('.mini-cart, #cart_over').hover(
function() {
isCartOpen = true;
cartOpen();
},
function() {
isCartOpen = false;
setTimeout(cartClose, 1000); // after 1 sec
}
);
var overlay = $("#cart_slide");
var cartContainer = $("#cart_over");
function cartOpen() {
cartContainer.fadeIn("slow");
overlay.addClass("overlay");
}
function cartClose() {
if (isCartOpen)
return;
cartContainer.fadeOut("medium");
overlay.removeClass("overlay");
}
Looks like you'll need to separate your open/close functions . Look at the following:
$('.mini-cart').hover(
cartOpen();
);
// You'll need to create a close button.. ex. <div class="close-button"></div>
$(".close-button").click(function(){
cartClose();
});

jQuery Cookie Toggle Issues

So because my function uses toggle() to hide and show a panel, Its really hard to actually tell when I should set a cookie and how I would integrate it.
Code:
/ Collapse ibox function
$('.collapse-link:not(.binded)').addClass("binded").click( function() {
var ibox = $(this).closest('div.ibox');
var button = $(this).find('i');
var content = ibox.find('div.ibox-content');
if($.cookie("chat") !== 'show'){
content.slideUp(200);
$.cookie("chat", "hide");
}
button.toggleClass('fa-chevron-up').toggleClass('fa-chevron-down');
ibox.toggleClass('').toggleClass('border-bottom');
setTimeout(function () {
ibox.resize();
ibox.find('[id^=map-]').resize();
}, 50);
});
I have no idea how to implement the $.cookie("chat") section.

Categories