I'm trying to delay the load of a pop-up on a grid of images but want to prevent the ability to click on other images when this happens. Howver if I turn off onclick 'item.onclick = false', I don't seem to be able to turn it back on when the pop-up is turned back on? see line 'item.onclick = true'. Have also tried disabled = true/false but to no avail. Any suggestions?
var caseStudies = document.querySelectorAll('.posterImage');
var caseHover = document.querySelectorAll('.caseHover');
var modal = document.querySelectorAll('.modal');
caseStudies.forEach((button, index) => {
if ((isMobile == true) || (isTablet == true)) {
button.onclick = function(event) {
caseStudies.forEach((item) => {
item.onclick = false;
console.log(item);
});
caseHover.forEach((item) => {
item.classList.add('eventsNone');
console.log(item);
});
setTimeout(function(){
console.log("loading");
modal[index].style.display = "block";
// When the user clicks anywhere outside of the modal, close it (needs to live inside the button.onclick)
window.onclick = function(event) {
if (event.target == modal[index]) {
modal.forEach((item) => {
item.style.display = "none";
});
caseStudies.forEach((item) => {
item.onclick = true;
});
}
}
}, 500);
}
}
else
{
button.onclick = function(event) {
console.log("route2");
modal[index].style.display = "block";
caseStudies.forEach((item) => {
item.classList.add('eventsNone')
});
// When the user clicks anywhere outside of the modal, close it (needs to live inside the button.onclick)
window.onclick = function(event) {
if (event.target == modal[index]) {
modal.forEach((item) => {
item.style.display = "none";
});
caseStudies.forEach((item) => {
item.classList.remove('eventsNone')
});
};
};
};
};
});
Use an inline onclick = "function()" to set your onclick.
When disabling your onlick do it with element.onclick = null.
And enable it again with element.onclick = "function()"
Sorry for getting it wrong before I miss read it and thought you were doing it with buttons.
Also here is a duplicate question how to disable or enable all onClick for images on a page
Related
I have this big class Search, which controls my search bar on my website. Now, when a input is focused, i dont want my s key (which pops out the search bar) to execute when a input is focused. I tried with document.activeElement, but then, the search bar wont even open, whilst the input not being focused. You can see it, under keydown event listener, under Events comment
class Search {
// Describe and create object
constructor() {
this.openButton = document.querySelectorAll('.js-search-trigger');
this.closeButton = document.querySelector('#close-button');
this.searchOverlay = document.querySelector('.search-overlay');
this.searchField = document.getElementById('search-term');
this.typingTimer;
this.events();
this.isSpinnerVisible = false;
this.resultsDiv = document.getElementById('search-overlay__results');
this.previousValue;
console.log(this.openButton);
}
// Events
events() {
this.openButton.forEach(e => {
e.addEventListener('click', () => {
this.openOverlay();
document.body.classList.add('body-no-scroll');
});
})
this.closeButton.addEventListener('click', () => {
this.closeOverlay();
document.body.classList.remove('body-no-scroll');
})
document.addEventListener('keydown', (e) => {
if(e.key === 's' && !(this === document.activeElement)){
this.openOverlay();
document.body.classList.add('body-no-scroll');
console.log("s pressed")
}
if(e.key === 'Escape' && this.isOverlayOpen){
this.closeOverlay();
document.body.classList.remove('body-no-scroll');
console.log("esc pressed");
}
});
this.searchField.addEventListener('keyup', () => {
this.typingLogic();
})
}
// Methods
openOverlay(){
this.searchOverlay.classList.add('search-overlay--active');
this.isOverlayOpen = true;
}
closeOverlay(){
this.searchOverlay.classList.remove('search-overlay--active');
}
typingLogic(){
if(this.searchField.value != this.previousValue){
clearTimeout(this.typingTimer);
if(this.searchField.value){
if(!this.isSpinnerVisible){
this.resultsDiv.innerHTML = '<div class="spinner-loader"></div>';
this.isSpinnerVisible = true;
}
this.typingTimer = setTimeout(this.getResults(),2000);
}else{
this.resultsDiv.innerHTML = '';
this.isSpinnerVisible = false;
}
}
this.previousValue = this.searchField.value;
}
getResults(){
this.typingTimer = setTimeout(()=> {
this.resultsDiv.innerHTML = 'Some here';
this.isSpinnerVisible =false;
},2000)
}
}
export default Search
You can check tagName property of activeElement. And if it is not input then proceed with your code. Update your condition like below.
if(e.key === 's' && document.activeElement.tagName.toLowerCase() != 'input')
This is an on-click function for the identifier button. This function will trigger a popup design function when the user clicks on some feature on the map. I want this click functionality on that feature to be suppressed when the user clicks the identifier button a second time. This means the identifier button should act like a start-stop switch.
This function is inside useEffect() and the #IdentifierClick is the id for the button which is in return{} part which will trigger the click event.
const IdentifierClick = () => {
console.log("working");
// clicktimes = clicktimes+1;
// console.log("Button click times ",clicktimes)
if((enableIdentify == false))
{
initialMap.on('singleclick', function (evt)
{
console.log(evt, "printevt");
var myLayerChecked;
console.log(layerlist, "printlayerlist");
for (let i = 0; i <= 4; i++)
{
layerlist[1].values_.layers.array_[i].values_.layers.array_.forEach(arrayItem => {
myLayerChecked = arrayItem.state_.visible;
console.log("myLayerChecked", myLayerChecked);
// console.log(layerlists,"printlayerlist");
if (myLayerChecked == true) {
document.getElementById('popup-content').innerHTML = '<p class="identifier_p"><b>Identifier Details</b></p>';
console.log("My Array Data", arrayItem.values_.source)
designHtml(evt, arrayItem.values_.source, arrayItem.values_.title);
enableIdentify = true;
}
else
{
console.log("No Layer is checked");
}
});
}
})
}
else {
}
});
The intialMap.on('singleclick',function()) should be enabled and disabled by IdentifierClick function when we click to trigger the function. Please help me achieve this task.
I'm trying to hide the "modal" box when the user press Esc key.
So, I first check where the box contains class - 'hidden', which
technically hide the box in UI.
Then if it's not hidden (the box does not contain class - 'hidden') and
appearing on screen, the function will wait for the Esc key for the
box to be disappeared.
Showing and hiding the box parts working just fine, but document.addEventListener part is not working.
const btnopenModal = document.querySelectorAll('.show-modal');
const btnCloseModal = document.querySelector('.close');
const overlay = document.querySelector('.overlay');
const modal =document.querySelector('.modal');
const showModal = function() {
modal.classList.remove('hidden');
overlay.classList.remove('hidden');
};
const hideModal = function() {
modal.classList.add('hidden');
overlay.classList.add('hidden');
}
for(let i = 0; i < btnopenModal.length; i++)
btnopenModal[i].addEventListener('click', showModal);
btnCloseModal.addEventListener('click', hideModal);
overlay.addEventListener('click', hideModal);
if(!overlay.classList.contains('hidden')) {
document.addEventListener('keypress', function(e) {
console.log(e.key);
if(e.key === 'Escape') {
hideModal();
}
})
};
Any other way around for this to work?
I would think that your if statement is evaluated when the webpage first runs, and my guess is that the if statement evaluates to false as it probably does contain the class "hidden" at first. I don't understand why you put it the key handler inside of an if statement, if it is for safety you should put it inside your function like so:
document.addEventListener('keypress', function(e) {
if(!overlay.classList.contains('hidden')) {
console.log(e.key);
if(e.key === 'Escape') {
hideModal();
}
};
})
Move if condition into callback. You want to always add keypress listener, just do not execute hideModal() if !overlay.classList.contains('hidden')
const btnopenModal = document.querySelectorAll('.show-modal');
const btnCloseModal = document.querySelector('.close');
const overlay = document.querySelector('.overlay');
const modal =document.querySelector('.modal');
const showModal = function() {
modal.classList.remove('hidden');
overlay.classList.remove('hidden');
};
const hideModal = function() {
modal.classList.add('hidden');
overlay.classList.add('hidden');
}
for(let i = 0; i < btnopenModal.length; i++)
btnopenModal[i].addEventListener('click', showModal);
btnCloseModal.addEventListener('click', hideModal);
overlay.addEventListener('click', hideModal);
document.addEventListener('keypress', function(e) {
console.log(e.key);
if(e.key === 'Escape' && !overlay.classList.contains('hidden')) {
hideModal();
}
});
I want to make a "popup" box activated by a button that reduces the opacity of all other elements. When the user clicks out of the box, it should disappear and the opacity should go back to normal. However, these two functions are conflicting with each other. It requires me to click the button TWICE in order for showBox() to be called. And clicking out of the box does nothing unless I reinvoke hideOnClickOutside(document.querySelector('div')); in the browser's console.
Why do I have to click "New Audio" twice and why does hideOnClickOutside() not work unless reinvoked?
function showBox() {
document.body.style.opacity = "0.5";
document.querySelector('div').style.display = "block";
}
document.querySelector('button').addEventListener('click', showBox);
const isVisible = elem => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js
function hideOnClickOutside(element) {
const outsideClickListener = event => {
if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
element.style.display = 'none';
removeClickListener()
document.body.style.opacity = "1";
}
}
const removeClickListener = () => {
document.removeEventListener('click', outsideClickListener)
}
document.addEventListener('click', outsideClickListener)
}
hideOnClickOutside(document.querySelector('div'));
<button>New Audio</button>
<div style="display: none">
<button>Record Directly</button>
</div>
hideOnClickOutside() function was taken from another StackOverflow answer
Edit
I figured out that it requires two clicks because on the first click, showBox() is called, but immediately after, so is outsideClickListener, and at this point the element is NOW visible AND the user has clicked "outside" the element. This reverts the style changes of showBox().
The easiest fix is to store the reference to the "New Audio" button and check to see if that is the target of the click on document. If so, then return from the function without updating DOM.
const button = document.querySelector('button')
button.addEventListener('click', showBox);
// ..
function hideOnClickOutside(element) {
const outsideClickListener = event => {
if (event.target === button) return
// ..
Keep in mind, with the current code you have, the hideOnClickOutside function only gets until the first time isVisible is true and the target is not button, since you remove the event listener on that condition.
function showBox(e) {
document.body.style.opacity = "0.5";
document.querySelector('div').style.display = "block";
}
const button = document.querySelector('button')
button.addEventListener('click', showBox);
const isVisible = elem => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js
function hideOnClickOutside(element) {
const outsideClickListener = event => {
if (event.target === button) return
if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
element.style.display = 'none';
removeClickListener()
document.body.style.opacity = "1";
}
}
const removeClickListener = () => {
document.removeEventListener('click', outsideClickListener)
}
document.addEventListener('click', outsideClickListener)
}
hideOnClickOutside(document.querySelector('div'));
<button>New Audio</button>
<div style="display: none">
<button>Record Directly</button>
</div>
The other problem is that once the showBox function is called, you actually probably want the button to be considered outside. Let's refactor your code to store references to the showButton and box, add a flag to disable the showButton and only add the event listener to the document if the showButton is clicked and remove the event listener only when the box is displayed.
You can later refactor this to fit your particular use case. The idea is to think of the various states this application can be in and create functions to manage that state.
const box = document.querySelector('#box');
const showButton = document.querySelector('#show-button');
showButton.addEventListener('click', showBox);
let isDisabled = false;
const isVisible = elem => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js
function toggleDisabled(bool) {
showButton.attributes.disabled = bool;
isDisabled = bool;
}
function toggleDisplay(display, opacity) {
document.body.style.opacity = opacity;
box.style.display = display;
}
function showBox(event) {
if (!isDisabled) {
event.preventDefault();
event.stopPropagation();
toggleDisplay("block", 0.5);
toggleDisabled(true);
document.addEventListener('click', outsideClickListener);
}
}
function outsideClickListener(event) {
if (!box.contains(event.target) && isVisible(box)) { // or use: event.target.closest(selector) === null
toggleDisplay("none", 1);
toggleDisabled(false);
document.removeEventListener('click', outsideClickListener)
}
}
<button id="show-button">New Audio</button>
<div id="box" style="display: none">
<button>Record Directly</button>
</div>
Now I am not a star really with Javascript, but i seem to encounter the all known problem with mobile devices and the onclick function. Onclick requires a mouse action where off course on the phone that doesnt apply. Now in Jquery, you can use "on" .. but how does this work with regular javascript?
// Get the modal
var modal = document.getElementById('reserveer-modal');
// Get the button that opens the modal
var btn = document.getElementById("reserveer-knop");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
var x = window.innerWidth;
if (x > 768) {
//event.preventDefault();
modal.style.display = "block";
} else {
//event.preventDefault();
}
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
Try to change onclick to addEventListener and see if that helps you..
// When the user clicks the button, open the modal
btn.addEventListener('click', function () {
var x = window.innerWidth;
if (x > 768) {
//event.preventDefault();
modal.style.display = "block";
} else {
//event.preventDefault();
}
});
You can also pass named function to addEventListener
Binding the click event listener to the element should fix the problem you've been having.
btn.addEventListener("click", function() {
var x = window.innerWidth;
if (x > 768) {
//event.preventDefault();
modal.style.display = "block";
} else {
//event.preventDefault();
}
});
Alternatively, you could try using the touchstart event, which works just like the "mousedown" event, just for mobile.
elem.addEventListener("touchstart", handler);
Your code would look like this:
btn.addEventListener("touchstart", function() {
var x = window.innerWidth;
if (x > 768) {
//event.preventDefault();
modal.style.display = "block";
} else {
//event.preventDefault();
}
});
Had the same issue, after setting z-index to 100 it worked.
Seems like in my case there was a z-index issue.
Make sure you don't have any async/await functions in your code or any arrow functions () => {}. Mobile browsers seem to use older versions of JavaScript before async/await or arrow function were introduced.