On ipad pro I am trying to disable scroll if popup open and enable the scroll back if popup gets close.
I have found a solution which works perfectly but it blocks inner element scroll too.
function preventDefault(e){
e.preventDefault();
}
function disableScroll() {
document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll() {
document.body.removeEventListener('touchmove', preventDefault);
}
Here, I have an element inside popup which is scrollable and has class name window-content. The above solution blocks the scroll for the entire page means it also blocks the scroll for the inner content of popup.
I have tried below code to allow scrolling inside pop but it did not worked.
function disableScroll() {
document.body.addEventListener('touchmove', preventDefault, { passive: false });
document.getElementsByClassName('window')[0].getElementsByClassName('window-content')[0].removeEventListener('touchmove', preventDefault);
}
I want to allow scroll inside popup and it should only disable for body. Thank you.
I have changed the preventDefault function to avoid the particular element.
preventDefault: function(e) {
if($(e.target).closest(".k-window").length == 0) {
e.preventDefault();
}
},
It is fixed now.
Related
I have a menu that needs to obey the following behavior:
Open with an external button press
Close when there is a click outside it's boundaries
The problem is, that the button to open is also outside the boundaries of the menu and so currently, the button press is opening the editor menu, and then the click listener is immediately closing it again. I've tried using variables and element data so that the click listener only activates if the menu is already open, but the event listener is slower than the button click and so the menu has already been expanded (as far as the listener knows) by the time it is activated. I know I can solve this using timeout so the data isn't changed to "expanded = true" until after the click listener has activated, but this seems kind of clunky and I'm wondering if there is a better option.
Here is a code snippet to demonstrate the problem.
And the js code that accompanies it:
document.addEventListener("click", (event) => {
if (!document.getElementById("menu").contains(event.target) && document.getElementById("menu").dataset.open) {
closeMenu();
}
});
//Expand menu
function openMenu() {
document.getElementById("menu").dataset.open = true;
document.getElementById("menu").style.height = "80vh";
console.log("open");
}
//Collapse menu
function closeMenu() {
document.getElementById("menu").dataset.open = false;
document.getElementById("menu").style.height = "0";
console.log("close");
}
Thanks for your help!
You can have the button prevent its parent element from registering the click by taking the event parameter in openMenu, and calling the stopPropogation method on it.
function openMenu(e) {
e.stopPropogation()
document.getElementById("menu").dataset.open = true;
document.getElementById("menu").style.height = "80vh";
console.log("open");
}
How do I prevent a parent's onclick event from firing when a child anchor is clicked?
Thanks for the answers! Here's my solution based on #Addison Schmidt's answer that fixes a couple of errors:
function openMenu(e) {
if (!event) var e = window.event
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
document.getElementById("menu").dataset.open = true;
document.getElementById("menu").style.height = "80vh";
console.log("open");
}
Source: Event.stopPropagation Not Working
Here's my situation:
I have a custom menu on right mouse click for my project. Here, I have document.addEventListener on click, that makes this menu invisible, like this:
var i = document.getElementById("menu").style;
document.addEventListener('click', function(e) {
i.opacity = "0";
setTimeout(function() {
i.visibility = "hidden";
}, 100);
}, false);
And it's great, works well, but I'm implementing a dropdown submenu that should be opened when you click on a certain element, like so:
$('#change_color').click(function(){
if($('#back_color').hasClass('back_color')){
$('#back_color').removeClass('back_color')
}else{
$('#back_color').addClass('back_color')
}
})
The thing is that when I click on that #change_color then addEventListener is firing, which is obvious.
The question is – how can I prevent that listener function to execute when I click on #change_color?
You can prevent further propagation of the current event in the capturing and bubbling phases using event.stopPropagation() and for simplicity in your code use jQuery.toggleClass().
Code example:
$('#change_color').click(function (e) {
$('#back_color').toggleClass('back_color');
e.preventDefault();
e.stopPropagation();
});
I have a function that when a user clicks outside of the mobile navigation close the mobile menu. I don't think I've got the code just right as when I click the mobile menu it opens and closes straight away.
What I want to happen is when the user clicks outside of the nav slideToggle the menu back.
Current code is:
// Responsive menu
$('.mobile-menu').click(function(e) {
e.preventDefault();
$('nav').slideToggle('slow');
});
// Close out the menu on click outside
window.addEventListener('mouseup', function(event) {
var box = document.getElementById('nav');
if(event.target != box && event.target.parentNode != box) {
$('nav').slideToggle('slow');
}
});
I think it's somewhere to do with mouseup however I don't see a mouseclick in the available parameters.
Thanks
I can give you a cleaner approach to this.
The window's listener should only be bound after the menu is expanded. When it's collapsed, the listener should be removed. This will prevent a lot of hassle and possible bug due to asynchronous execution of 2 event listeners.
With that in mind:
// First we define a callback function to be called after the nav complete showing, which will close the nav when a user tap outside.
var bindEventListener = function(event) {
var box = document.getElementById('nav');
if(event.target != box && event.target.parentNode != box) {
$('nav').slideUp('slow', function(){
// remove the window's event listener after the nav is closed
window.removeEventListener('mouseup', bindEventListener);
});
}
});
// Now we set the button's onclick event and bind the above defined callback for mouseup event.
$('.mobile-menu').click(function(e) {
e.preventDefault();
$('nav').slideDown('slow', function(){
window.addEventListener('mouseup', bindEventListener);
});
});
The target of the click event is not necessarily the nav or it's first level child, so if there is a click event on the nav you will slide it open and then slide it close.
You need to check if the nav contains the target element or equals to it, so inside the event listener, change your condition to this:
if(!(event.target == box || $.contains(box, event.target))) {
...
The problem is that when you mousedown on .mobile-menu it shows the nav, then when you mouseup on anything outside the nav, including .mobile-menu, it hides the nav again. You should check that the click event's target also isn't .mobile-menu. Try the following code:
// Responsive menu
$('.mobile-menu').click(function(e) {
e.preventDefault();
$('nav').slideToggle('slow');
});
// Close out the menu on click outside
$(window).on('mouseup', function(event) {
if(!$(event.target).is("nav") && $.contains(event.target, $("nav")) && !$(event.target).is('.mobile-menu')) {
$('nav').slideToggle('slow');
}
});
I have a modal window that allows users to submit a form as one of the call-to-actions. However, clicking 'Submit' closes the modal window but I do not want it to. Here is the page: infowest.com/residential-internet.
To activate the modal window, the user clicks the yellow-orange "Get started" button on any of the "cards" of Internet options. Then to fill out and submit a form, the user clicks the "Request a callback" button. Actually, come to find, clicking ANYWHERE accept the "Request a callback" button closes the modal window, not just clicking the 'Submit' button.
I tried using this code:
if ( $(event.target).is('.modal-window-content') ) {
return false;
}
if ( $(event.target).is('input') ) {
return false;
}
to keep the modal from closing, which worked but didn't allow the form to submit or even try to submit. The form uses Ajax. It is the WP Contact Form 7 plugin.
I am using jQuery that I'm just making up as I go but I've never really been taught jQuery so I'm assuming I'm making errors in the js code. Here is my code:
var pagePosition;
$('.js--activate-cta-modal').click(function() {
if ( (!$(this).hasClass('.active')) && (!$('body').hasClass('modal-active')) ) {
pagePosition = $(window).scrollTop();
$('.cta-modal-window').css( "margin-top", pagePosition );
$(this).addClass("active");
$('body').addClass("modal-active");
$('body').css( "top", -pagePosition );
return false;
}
if($(this).hasClass('active')) {
$(this).removeClass('active');
$('body').removeClass('modal-active')
$('body').css( "top", "0" );
$('body').scrollTop(pagePosition);
}
});
$('.js--activate-cta-modal').click(function (e) {
e.stopPropagation();
});
$('.modal-overlay').click(function() {
$('body').removeClass('modal-active');
$('.js--activate-cta-modal').removeClass('active');
$('body').css( "top", "0" );
$('body').scrollTop(pagePosition);
});
$('.cta-modal-window').click(function() {
// if ( $(event.target).is('.modal-window-content') ) {
// return false;
// }
// if ( $(event.target).is('input') ) {
// return false;
// }
$('body').removeClass('modal-active');
$('.js--activate-cta-modal').removeClass('active');
$('body').css( "top", "0" );
$('body').scrollTop(pagePosition);
});
$('.close-modal-window').click(function() {
$('body').removeClass('modal-active');
$('.js--activate-cta-modal').removeClass('active');
$('body').css( "top", "0" );
$('body').scrollTop(pagePosition);
});
I greatly appreciate any and all help! Thank you!
It's important not to confuse Event.stopPropagation() and Event.preventDefault(), and to understand exactly what they do.
Event.stopPropagation() will prevent events from bubbling up through the DOM. Normally if you click on an element its event will attempt to fire, and then the parent element will attempt to fire its version of the event, and so on up the tree. This is used to contain events to a certain level on the DOM.
Event.preventDefault() stops the default action that elements might have from triggering. The most common one is using this on a form to stop it from submitting. This is used to cancel out the default behavior of elements with certain events.
Here is an example of a common modal staging technique. http://codepen.io/Oka/pen/xGKJVJ
(If you're new to CodePen, click the eyeballs to view any compiled code. I've used Jade and SCSS here. The page is also running Normalize.css)
With this technique we only need one Event.stopPropagation() to stop similar events from bubbling up from the modal to its container. Clicking anywhere on the modal's container will close the modal, and so will the small close button. You can expand this to suit your needs, the key is the modal should never bubble to its container.
JS
var open = $('.modal-open'),
close = $('.modal-close'),
modal = $('.modal'),
container = $('.modal-container');
function openModal (e) {
container.addClass('active');
}
function closeModal (e) {
container.removeClass('active');
}
open.on('mouseup', openModal);
close.on('mouseup', closeModal);
container.on('mouseup', closeModal);
modal.on('mouseup', function (e) {
e.stopPropagation();
});
(Keep in mind some of this stuff is IE9+. Make sure to check browser compatibility if you have legacy needs.)
I now understand a little more of what
$('element').click(function (e) {
e.stopPropagation();
});
is for. This is used to not perform the click function of the targeted element. I'll need to do some more reading on this but I solved the issue by using this code to target the div.modal-window-content.
Since on mobile device browser such as safari , when user drag the screen, the whole website will move along with the finger. So the common solution is :
addEventListener('touchmove', function(e) { e.preventDefault(); }, true);
This will prevent any touchmove event . However, since the browser on mobile device has no scroll bar , when user want to scroll the dialog box of jquery ui , the touchmove event need to be permit. This statement will block that event.
addEventListener('touchmove', function(e) {
if (e.target.id != 'dialog' )
e.preventDefault();
return false;
}, true);
Then I add this statement to allow the dialog box to scroll. However, this solution has flaw because the background will be draggable and move along with user finger again. How to fix this problem? Thanks.
Been dealing with this all day and found this solution. When you want it to scroll the dialog on safari mobile on ipad/iphone/ipod, you need to use this:
if (/iPhone|iPod|iPad/.test(navigator.userAgent)) {
$('iframe').wrap(function () {
var $this = $(this);
return $('<div />').css({
width: $this.attr('width'),
height: $this.attr('height'),
overflow: 'auto',
'-webkit-overflow-scrolling': 'touch'
});
});
}