I'm building a website and right now I'm having an issue trying to get an if statement to read a change of state variable.
I'm trying to close my navbar menu when I click anywhere in the body, other than the navbar. However, my if statement that contains the event listener for the body will not execute because (I think) that the change of state variable that is being used for the condition (true when menu is open, false when menu is closed) is just not being read.
When I open the nav menu, the change of state variable changes to true, as it is intended to. When I close the menu using the button on the nav bar, the change of state variable changes to false, as it is intended to.
Here's my code:
"use strict";
const btnNav = document.querySelector(".nav-btn--container");
const linkContainer = document.querySelector(".link-container");
const header = document.querySelector(".header");
const sidebar = document.querySelector(".sidebar");
const bodyChildren = header.parentElement.children;
const navBtn = document.querySelector(".nav-btn");
const menu = document.querySelector(".sidebar__menu");
const body = document.querySelector(".container");
/**** change of state variables ****/
let menuIsOpen = false;
/**** functions ****/
const closeMenu = function () {
addRemoveBlur("remove");
navBtn.classList.remove("nav-btn--opened");
sidebar.classList.remove("blur");
navBtn.classList.add("nav-btn--closed");
menu.style.visibility = "hidden";
menu.style.transform = "translateX(-150%)";
menuIsOpen = false;
};
const openMenu = function () {
addRemoveBlur("add");
navBtn.classList.remove("nav-btn--closed");
navBtn.classList.add("nav-btn--opened");
menu.style.visibility = "visible";
menu.style.transform = "translateX(0%)";
menuIsOpen = true;
};
const closeMenuByBody = function (e) {
const click = e.target;
closeMenu();
};
const openCloseMenu = function () {
if (!menuIsOpen) {
openMenu();
return;
}
if (menuIsOpen) {
closeMenu();
return;
}
};
/**** this is the problem ****/
if (menuIsOpen) {
body.addEventListener("click", function (e) {
closeMenuByBody(e);
});
}
The problem is that the event listener is never initialized, as your menuIsOpen variable is always declared false.
You should switch your if statement to be contained within the click event handler, like so:
body.addEventListener("click", function (e) {
if (menuIsOpen) {
closeMenuByBody(e);
}
});
You should also consider the following changes to your openCloseMenu method (here renamed to toggleMenu):
const toggleMenu = function () {
if (menuIsOpen) {
closeMenu();
} else {
openMenu();
}
};
As you are evaluating a boolean value, there is no need to test it in two different if expressions: you check if it's true and do something if it is, or else you do something knowing that it's false.
You could also remove your closeMenuByBody method, and just call the closeMenu method from your event listener, as you aren't doing anything in it appart from that:
body.addEventListener("click", function (e) {
if (menuIsOpen) {
e.preventDefault();
closeMenu();
}
});
Related
I was able to get an idea on how to close a modal window when clicking outside, but I am having issues to have it working when trying to have links inside the modal window.
I created a small code in Codepen to illustrate my point:
https://codepen.io/neotriz/pen/MRwLem
window.addEventListener('load', setup);
const get = document.getElementById.bind(document);
const query = document.querySelector.bind(document);
function setup() {
let modalRoot = get('modal-root');
let button = get('modal-opener');
let modal = query('.modal');
modalRoot.addEventListener('click', rootClick);
button.addEventListener('click', openModal);
modal.addEventListener('click', modalClick);
function rootClick() {
modalRoot.classList.remove('visible');
}
function openModal() {
modalRoot.classList.add('visible');
}
function modalClick(e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
return false;
}
}
remove e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();from modalClick . Thats the reason you are not able to click on inside links.
and modify the function rootClick
function rootClick(event) {
if (!(modal == event.target || modal.contains(event.target))) {
modalRoot.classList.remove('visible');
}
}
Codepen : https://codepen.io/anon/pen/ZZGwRr
I am currently working on a javascript module which open and close boxes, tooltip or similar, the function works great the only problem is when I call it twice on a page where the 'boxes' classes are different the window mouseup event will be overwritten and only one of the two module instances of boxes can now be closed after opening them.
var boxRevealer = (function () {
var buttons;
var boxes;
var element;
var drp_active = false;
var boxConstruct = function (btns, bxs) {
buttons = document.querySelectorAll(btns);
boxes = document.querySelectorAll(bxs);
boxEvents();
};
var boxEvents = function () {
buttons.forEach(function (e) {
e.addEventListener("click", function (ee) {
element = document.getElementById(e.getAttribute("data-drp"));
element.classList.toggle("displayn");
drp_active = true;
});
});
window.addEventListener("mouseup", function (e) {
if (drp_active === true) {
if (!e.target.classList.contains("filt_holy")) {
boxes.forEach(function (e) {
console.log("ELEMENT");
console.log(e);
e.classList.add("displayn");
});
}
}
}, false);
};
return {
boxConstruct: boxConstruct,
boxEvents: boxEvents
};
})();
Here is how i call the module
window.addEventListener("load", function(e){
boxRevealer.boxConstruct(".head_drp_btn", ".head_drp");
boxRevealer.boxConstruct(".mkt_drp_btn", ".mkt_drp");
});
So my question is, should I always name the boxes the same, or is there a work around?
Just remove the event before adding it, I think the same event is getting called twice.
So updated code will be as follows:
// Attach an event handler to <div>
e.addEventListener("mousemove", myFunction);
// Remove the event handler from <div>
e.removeEventListener("mousemove", myFunction);
And remove the window event as well before adding it.
I am trying to make a simple button to turn on and off my audio file.
Once I click play I can't turn it off.
I'm using an image as my button and div.onclick to spark the function.
The html audio tag has id audioPlay.
I use the global boolean playSound, initially set to false.
My script looks like this:
var playSound = false;
if (playSound != true) {
audioButton.src = '../../testStuff/audioPlay.png';
audio.onclick = function () {
document.getElementById('audioPlay').play();
playSound = true;
console.log(playSound);
}
}
if (playSound == true) {
audioButton.src = '../../testStuff/audioStop.png';
audio.onclick = function () {
document.getElementById('audioPlay').pause();
playSound = false;
}
}
When I click on it the first time it works fine. It sets playSound to true.
However, when I go to click it a second time, nothing happens. Something is setting playSound back to false and I don't know why.
I've tried switching the ==true if statement above the false one, as well as rolling both if statements into a single onclick function but it still operates this way.
Any ideas?
I think the issue is that you're adding two separate click handlers that are both being executed on each click. This results in playSound always being set to true, but then immediately being set back to false.
Instead, write a function called togglePlay that does something like the following, and set that as your click handler, but only once.
function togglePlay () {
if (playSound) {
audioButton.src = '../../testStuff/audioStop.png';
document.getElementById('audioPlay').pause();
playSound = false;
} else {
audioButton.src = '../../testStuff/audioPlay.png';
document.getElementById('audioPlay').play();
playSound = true;
}
}
//play is the name of the botton that u click to play the music and psuse
const isplay;
play.addEventListener('click',()=>{
const playmusic = ()=>{
isplay = true;
console.log('play music');
music.play();
};
const pausemusic = ()=>{
isplay = false;
music.pause();
};
if(isplay){
pausemusic();
}else{
playmusic();
};
)};
Im working with some JS code, since Im not front developer im having some issues to figuring out how to trigger an event on JS that normally fires when a link is clicked.
This is the link:
Demo
And the JS function that intercept the click on that link is:
(function (global) {
'use strict';
// Storage variable
var modal = {};
// Store for currently active element
modal.lastActive = undefined;
modal.activeElement = undefined;
// Polyfill addEventListener for IE8 (only very basic)
modal._addEventListener = function (element, event, callback) {
if (element.addEventListener) {
element.addEventListener(event, callback, false);
} else {
element.attachEvent('on' + event, callback);
}
};
// Hide overlay when ESC is pressed
modal._addEventListener(document, 'keyup', function (event) {
var hash = window.location.hash.replace('#', '');
// If hash is not set
if (hash === '' || hash === '!') {
return;
}
// If key ESC is pressed
if (event.keyCode === 27) {
window.location.hash = '!';
if (modal.lastActive) {
return false;
}
// Unfocus
modal.removeFocus();
}
}, false);
// Convenience function to trigger event
modal._dispatchEvent = function (event, modal) {
var eventTigger;
if (!document.createEvent) {
return;
}
eventTigger = document.createEvent('Event');
eventTigger.initEvent(event, true, true);
eventTigger.customData = { 'modal': modal };
document.dispatchEvent(eventTigger);
};
// When showing overlay, prevent background from scrolling
modal.mainHandler = function () {
var hash = window.location.hash.replace('#', '');
var modalElement = document.getElementById(hash);
var htmlClasses = document.documentElement.className;
var modalChild;
// If the hash element exists
if (modalElement) {
// Get first element in selected element
modalChild = modalElement.children[0];
// When we deal with a modal and body-class `has-overlay` is not set
if (modalChild && modalChild.className.match(/modal-inner/) &&
!htmlClasses.match(/has-overlay/)) {
// Set an html class to prevent scrolling
//document.documentElement.className += ' has-overlay';
// Mark modal as active
modalElement.className += ' is-active';
modal.activeElement = modalElement;
// Set the focus to the modal
modal.setFocus(hash);
// Fire an event
modal._dispatchEvent('cssmodal:show', modal.activeElement);
}
} else {
document.documentElement.className =
htmlClasses.replace(' has-overlay', '');
// If activeElement is already defined, delete it
if (modal.activeElement) {
modal.activeElement.className =
modal.activeElement.className.replace(' is-active', '');
// Fire an event
modal._dispatchEvent('cssmodal:hide', modal.activeElement);
// Reset active element
modal.activeElement = null;
// Unfocus
modal.removeFocus();
}
}
};
modal._addEventListener(window, 'hashchange', modal.mainHandler);
modal._addEventListener(window, 'load', modal.mainHandler);
/*
* Accessibility
*/
// Focus modal
modal.setFocus = function () {
if (modal.activeElement) {
// Set element with last focus
modal.lastActive = document.activeElement;
// New focussing
modal.activeElement.focus();
}
};
// Unfocus
modal.removeFocus = function () {
if (modal.lastActive) {
modal.lastActive.focus();
}
};
// Export CSSModal into global space
global.CSSModal = modal;
}(window));
How can i call the function that gets called when the user clicks the link but manually on my page, something like <script>firelightbox(parameters);</script>
Using jQuery will solve this easily
$('.selector').click();
but plain old JavaScript may also have a solution for you
Let's just give your anchor element an Id (to keep things simple)
<a id="anchorToBeClicked" href="#modal-text" class="call-modal" title="Clicking this link shows the modal">Demo</a>
Let's create a function that simulates the click
function simulateClick() {
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
var cb = document.getElementById("anchorToBeClicked");
cb.dispatchEvent(evt);
}
Now call this function on window.onload
window.onload = function() {
simulateClick();
};
EDIT:
Actually, the code you are using is not working on actual click event of the anchor tag, instead it relies on hash change of Url in your browser window. You can simply invoke that functionality by using
window.onload = function() {
location.hash = '#modal-text'
};
If you are using jQuery, you can trigger the clicking of a link on page load using this code:
$(document).ready(function(){
$('.call-modal').click();
});
The tutorial at http://www.asp.net/web-forms/tutorials/ajax-control-toolkit/getting-started/creating-a-custom-ajax-control-toolkit-control-extender-vb gives a nice example of a custom extender based on a textbox and a button. Basically the button remains disabled until at least one character is typed into the textbox. If the text is removed from the textbox the button is disabled again.
I am trying to modify this so that the extender is based on a textbox and panel. Again I want the panel to become visible when text is present in a textbox.
This is how I amended code...
Type.registerNamespace('CustomExtenders');
CustomExtenders.ShowHidePanelBehavior = function (element) {
CustomExtenders.ShowHidePanelBehavior.initializeBase(this, [element]);
this._targetPanelIDValue = null;
}
CustomExtenders.ShowHidePanelBehavior.prototype = {
initialize: function () {
CustomExtenders.ShowHidePanelBehavior.callBaseMethod(this, 'initialize');
// Initalization code
$addHandler(this.get_element(), 'keyup',
Function.createDelegate(this, this._onkeyup));
this._onkeyup();
},
dispose: function () {
// Cleanup code
CustomExtenders.ShowHidePanelBehavior.callBaseMethod(this, 'dispose');
},
// Property accessors
//
get_TargetPanelID: function () {
return this._targetPanelIDValue;
},
set_TargetPanelID: function (value) {
this._targetPanelIDValue = value;
},
_onkeyup: function () {
var e = $get(this._targetPanelIDValue);
if (e) {
var visibility = ("" == this.get_element().style.value);
e.visibility = 'visible';
}
}
}
CustomExtenders.ShowHidePanelBehavior.registerClass('CustomExtenders.ShowHidePanelBehavior', Sys.Extended.UI.BehaviorBase);
When run the panel will not appear. No errors are produced.
Where have I gone wrong...
Try this code:
_onkeyup: function () {
var panel = $get(this.get_TargetPanelID());
if (panel) {
var visibilityValue = ("" == this.get_element().value) ? "hidden" : "visible";
panel.style.visibility = visibilityValue;
}
}