Clicking 'Submit' on form closes modal window - javascript

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.

Related

Event listener and button click conflict

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

Bypassing javascript event using another javascript event

I have a button which when click will trigger to open up a popup.
<button id="thisId">OPEN POPUP</button>
The event for it will be something as follow
$(document).on('click', '#thisId', function(){
// DO SOMETHING TO OPEN THE POPUP HERE
});
This button should work as expected if the browser allows popup to be opened on it. Problem is when the popup blocker is enabled. I have quite an amount of buttons like this, probably like nearly 100 buttons with similar thing in the project that i currently working on, and i dont want to do the checking on each of the event handler for each respective buttons. I wanna make a common event handler for all the buttons, which will trigger on click of the button.
So i added another attribute to the same button
<button data-openpopup id="thisId">OPEN POPUP</button>
For this i attach an event specific to this attribute. When the button is clicked, in case if popup blocker is set on for that browser, it will do a checking to check whether popup blocker is on, and if it is, it will throw an alert to the user using jconfirm's alert box. The event for it will be something as follow
$(document).on('click', '[data-openpopup]', function(){
var $this = $(this);
var pop = window.open("about:blank", "new_window_123", "height=150,width=150");
if (!pop || pop.closed || pop.closed == "undefined" || pop == "undefined" || parseInt(pop.innerWidth) == 0 || pop.document.documentElement.clientWidth != 150 || pop.document.documentElement.clientHeight != 150){
pop && pop.close();
// Call jconfirm alert if popup is disabled
$.alert({
title: 'Popup blocked alert!',
content: 'Your popup blocker is currently enabled.',
closeIcon: true,
buttons: {
close: {
text: 'Close',
btnClass: 'btn-blue'
}
}
});
} else {
pop && pop.close();
}
});
Now the issue here is, i want it so that, when click on the button, it will override the original click method which is to open a popup, preventing it from running, and do the popup checking first. If checking is false, then only proceed with the event to open the popup.
So how can i do this?
You could use .stopImmediatePropagation() to prevent the other handler from executing.
But you have to put that in a handler that must be registered before the other(s) since the callbacks are executed in the order the listeners were registered.
If several listeners are attached to the same element for the same event type, they are called in order in which they have been added. If during one such call, event.stopImmediatePropagation() is called, no remaining listeners will be called.
Below, I "simulated" your popup blocker test with an additionnal button... Since it does not seem to be working, at least with AdBlocker Plus (Chrome extention). From what I saw, your condition is always true, AdBlocker active or not.
// To simulate a working blocker detection
var blocker=true;
$("#blockerToggle").on("click",function(){
blocker=!blocker;
$(this).find("span").text(blocker.toString().toUpperCase()).css({"color":(blocker)?"green":"red"});
}).trigger("click");
// Assuming a good popup blocker detection
// This handler can stop the others... Registered AFTER this one.
$(document).on('click', '[data-openpopup]', function(e){
if(blocker){
console.log("Blocker ON! Prevent the other listener(s) from executing.");
e.stopImmediatePropagation();
} else {
console.log("Okay, let the other listener(s) execute.");
}
});
// Other handler
$(document).on('click', '#thisId', function(){
console.log("Other handler executed.");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button data-openpopup id="thisId">OPEN POPUP</button> <button id="blockerToggle">Popup blocker active => <span></span></button>

Stop onclick method running with jQuery

I have a button similar to below
<button id="uniqueId" onclick="runMethod(this)">Submit</button>
What I'm trying to do is stop the runMethod from running, until after I've done a check of my own. I've tried using the stopImmediatePropagation function, but this doesn't seem to have worked. Here's my jQuery:
$j(document).on('click', '#uniqueId', function(event) {
event.stopImmediatePropagation();
if(condition == true) {
// continue...
} else {
return false;
}
return false;
});
Note: runMethod basically validates the form, then triggers a submit.
What you want to do, especially in the way that you want to do it, requires a some sort of workaround that will always be a bit fiddly. It is a better idea to change the way the button behaves (e.g. handle the whole of the click event on the inside of the jQuery click() function or something along those lines). However I have found sort of a solution for your problem, based on the assumption that your user will first hover over the button. I am sure you can extend that functionality to the keyboard's Tab event, but maybe it will not work perfectly for mobile devices' touch input. So, bear in mind the following solution is a semi-complete workaround for your problem:
$(document).ready(function(){
var methodToRun = "runMethod(this)"; // Store the value of the onclick attribute of your button.
var condition = false; // Suppose it is enabled at first.
$('#uniqueId').attr('onclick',null);
$('#uniqueId').hover(function(){
// Check your stuff here
condition = !condition; // This will change to both true and false as your hover in and out of the button.
console.log(condition); // Log the condition's value.
if(condition == true){
$('#uniqueId').attr('onclick',methodToRun); // Enable the button's event before the click.
}
},
function(){
console.log('inactive'); // When you stop hovering over the button, it will log this.
$('#uniqueId').attr('onclick',null); // Disable the on click event.
});
});
What this does is it uses the hover event to trigger your checking logic and when the user finally clicks on the button, the button is enabled if the logic was correct, otherwise it does not do anything. Try it live on this fiddle.
P.S.: Convert $ to $j as necessary to adapt this.
P.S.2: Use the Javascript console to check how the fiddle works as it will not change anything on the page by itself.
Your problem is the submit event, just make :
$('form').on('submit', function(e) {
e.preventDefault();
});
and it works. Don't bind the button click, only the submit form. By this way, you prevent to submit the form and the button needs to be type button:
<button type="button" .....>Submit</button>
Assuming there's a form that is submitted when button is clicked.
Try adding
event.cancelBubble();
Hence your code becomes:
$j(document).on('click', '#uniqueId', function(event) {
// Don't propogate the event to the document
if (event.stopPropagation) {
event.stopPropagation(); // W3C model
} else {
event.cancelBubble = true; // IE model
}
if(condition == true) {
// continue...
} else {
return false;
}
return false;
});
Your code is mostly correct but you need to remove J:
$(document).on('click', '#uniqueId', function(event) {...
You also need to remove the onClick event from the inline code - there's no need to have it there when you're assigning it via jQuery.
<button id="uniqueId">Submit</button>

jQuery preventDefault() doesn't work like I expect - is this a jQuery Bug?

This is simplified code to exactly reproduce a problem I'm having with jQuery.
I would expect it to cancel the original click, then trigger the click event again which in turn would cause the browser to load the href of the url.
<script type="text/javascript">
$( function()
{
var confirmed = false;
$('a').click( function( event )
{
if ( confirmed == false )
{
event.preventDefault();
confirmed = true;
$(event.target).trigger( 'click' );
}
});
});
</script>
Original Question Here
I do not want to change window.location. I want to trigger so that any event handlers that have been bound to the click event will fire too. It just so happens that I also want the browser to follow the link.
.trigger('click') won’t trigger the browser’s default action — it will just trigger jQuery event handlers bound to that event on that element.
Take a look at this answer — you need to create and fire a click event yourself. Here’s the code from that answer:
function fireEvent(obj,evt){
var fireOnThis = obj;
if( document.createEvent ) {
var evObj = document.createEvent('MouseEvents');
evObj.initEvent( evt, true, false );
fireOnThis.dispatchEvent( evObj );
} else if( document.createEventObject ) {
var evObj = document.createEventObject();
fireOnThis.fireEvent( 'on' + evt, evObj );
}
}
Your event handler will always be run when you trigger a "click" event, and before the default behavior happens. So no, it's not a bug.
edit — If you want the default action to happen when the element is clicked and your various conditions are satisfied, just return from your handler.
$('a').click( function( event )
{
if ( confirmed == false )
{
event.preventDefault();
confirmed = true;
}
else
return;
});
When your handler returns, the browser will carry on with the default behavior.
edit again — and of course if you want to simply carry out programmatically the default action of an <a> tag with an "href" attribute, it's just:
window.location = $(element).attr('href');
No need for a "click" event at all.
preventDefault() doesn't cancel the jquery bound click action; it cancels the 'default' click action that is inherent to an anchor tag. unbind() is the proper function for canceling any action/function that is bound to an object.
It looks like you have one state where you want to inhibit the default action (and update a flag), and another state where you simply want the default action to apply. Wouldn't removing the else case entirely do the trick? With no preventDefault() the default click action will still run.
Edit: Pointy's answer now shows your code updated similarly.
Edit: I'm still not entirely sure what you're going for, but if for some reason you must trigger manually, one way to prevent a stack overflow due to recursion would be to assign a custom event (i.e., not click), and then always suppress the default action. Then in your conditional, either do or don't fire the custom event.
So, something like this (untested):
$('a')
.bind('fancyclick', function () { // Your special click logic
changeStatusOf( confirmed );
doCrazyStuff();
location.replace( $(this).attr('href') ); // or whatever
})
.click( function (e) {
e.preventDefault(); // Always suppress natural click
if ( confirmed ){
$(this).trigger('fancyclick'); // Fire the special click
}
});
I'll simply write while I analyse, hoping it'll be easy to follow and easy to compare to your code. Kick me when I can optimize/enhance my replies in any way.
checking - part 1
Move the "preventDefault" outside of the "if" statement! If you don't move it outside of the "if", the code will skip the "preventDefault" if confirmed == true.
<script type="text/javascript">
$( function()
{
var confirmed = false;
$('a').click( function( event )
{
event.preventDefault();
if ( confirmed == false )
{
confirmed = true;
$(event.target).trigger( 'click' );
}
});
});
</script>
checking - part 2
Besides that, I'm wondering about the existence of "var confirmed" in general. The code would also work flawless without it since you're not using the confirmed variable in the function anywhere else...
<script type="text/javascript">
$( function()
{
$('a').click( function( event )
{
event.preventDefault();
$(event.target).trigger( 'click' );
});
});
</script>
checking - part 3
Knowing you can replace the trigger with a simple click, did you try that?
<script type="text/javascript">
$( function()
{
$('a').click( function( event )
{
event.preventDefault();
$(event.target).click();
});
});
</script>
checking - part 4
If the click still fails on the target element, it's definitely time to inspect (using "FireBug on Firefox" or alike) if "event.target" holds an object at all. You never know...
checking - part 5
One more thing: I don't see any Document Ready checking, so I hope you've put that script at the end of your file, right before the "</body>" tag. If you load it in the "<head>" without checking Document Ready, it might happen that javascript tries to bind the event to an element that is yet to be loaded into the dom... which would be like throwing feathers against a 9 Inch steel plate... nothing will happen. ;)
that's all
That's all that comes to mind as an answer to your question. One of them could fix the issue you're having. At least, that's what I hope. These little snippets here at stackoverflow leave massive probabilities related to what we don't see. It's hard to be sure what might be missing when you don't have the "complete view". ;)
How about doing something like creating a link offscreen that would handle the final click? That way, you can prevent the click of the original link, handle the code, then proceed to trigger the click of the hidden copy.

Detecting mouse click on div with Javascript without side-effects

I want to detect whenever someone clicks in a div (essentially I want to know when a user is interacting with a section of text on my site, be that by selecting some text or clicking on a link), but I don't want to interfere with what the user is doing.
If I put a onmousedown or onclick event on the div it ends up breaking selection, links, etc. Is there any way to catch these events without causing any interference ?
Onmousedown or onclick shouldn't interfere with anything as long as it doesn't return false;.
You can do this:
document.getElementById("spy-on-me").onmousedown = function () {
console.log("User moused down");
return true; // Not needed, as long as you don't return false
};
If you have other scripts that are attaching behaviour via this method on the page, then to prevent overriding them you can do:
var spyElement = document.getElementById("spy-on-me");
var oldMousedown = spyElement.onmousedown;
spyElement.onmousedown = function () {
console.log("User moused down");
if(oldMousedown) oldMousedown();
};
Yes, I suspect you are currently returning false at the end of the event binding, just don't do that or any of the things in this binding:
$('a').click(function(e) {
e.stopPropagation();
e.preventDefault();
return false;
});
If you do not do any of these three things, jQuery will not stop the event from bubbling up to the browser.
Edit: Sorry didn't realise it was a plain JavaScript question.
you can use do it by adding a event listener as well
var myNode= document.querySelector('.imagegrid');
myNode.addEventListener("click",function(e){
alert(e.target+" clicked");
});
A similar example is demonstrated here
Can't you simply add a click event to the div?
<div id="secretDiv" (click)="secretDivClick()">
then on your component:
secretDivClick() {
console.log('clicked');
}

Categories