A user does something but stays at the same page - javascript

A user is clicking the button with id continueButton. If they stay on the same page upon after clicking the button, then I trigger UK-AwesomeEvent.
My effort so far
Bootstrapper.on('click', '#continueButton', function() {
setTimeout(function() {
//if nothing happens then trigger this event
if (document.title === 'Current address' && doNotGetRedirectedToAnotherPageWhenButtonIsClicked) {
Bootstrapper.ensEvent.trigger("UK-AwesomeEvent");
}
}, 250);
});
Desired outcome
In place of doNotGetRedirectedToAnotherPageWhenButtonIsClicked I want a method that basically states that a user is not redirected to another page. I couldn't find anything online.

In general, you can call the preventDefault() method of the event object…
Bootstrapper.on('click', '#continueButton', function(event) {
event.preventDefault()
to prevent whatever the default behaviour is (and in this context it sounds like that behaviour is "A submit button is triggering the submission of a form").
However, because you have used setTimeout, it is too late. The event handler function has already finished and the form submission started.
The closest you could come would be to always prevent the default behaviour and then restart the form submission if you later change your mind:
Bootstrapper.on('click', '#continueButton', function(event) {
event.preventDefault()
setTimeout(function() {
if (document.title === 'Current address') {
Bootstrapper.ensEvent.trigger("UK-AwesomeEvent");
} else {
event.target.form.submit();
}
}, 250);
});
(Note there is a fair chunk of educated speculation here because you didn't provide a complete, reduced test case)

Related

How to make an event occur for only the first time that a button is pressed?

I have a series of events that I want to execute when a button is pressed. Among those, there is one event, functionA();, that I only want it to happen for the first time that the button is pressed (resets after each refresh). How can I do this? Thanks.
Right now my code looks like this:
document.getElementById("submit").addEventListener("click", function(e) {
e.preventDefault();
functionA();
functionB();
functionC();
}
But I only want functionA(); - functionC(); to happen the first time the button is pressed. The second time onwards, only functionB();and functionC(); will be executed. Is there a way to do this? This count should reset each time the webpage is refreshed too. Thanks
Set a variable to remember if it has already been done.
let didFuncA = false;
document.getElementById("submit").addEventListener("click", function(e) {
e.preventDefault();
if (!didFuncA) {
functionA();
didFuncA = true;
}
functionB();
functionC();
});
function functionA() {
console.log("A");
}
function functionB() {
console.log("B");
}
function functionC() {
console.log("C");
}
<button id="submit">Click</button>
FYI, these are just function calls, they're not events. click is an event.
If the button is an actual submit button and you are submitting a form that loads a page then
rename the button - never call anything submit in a form if you ever want to submit the form using script
use session or localStorage if the page is refreshed
I guess the page is NOT reloaded because I see a preventDefault, but in case you want to survive a page reload, use session or localStorage
If you meant to reset this after a page refresh, then of course do NOT use session/localStorage
document.getElementById("myForm").addEventListener("submit", function(e) {
e.preventDefault();
if (!sessionStorage.getItem("submitted")) {
functionA();
sessionStorage.setItem("submitted","yes")
}
functionB();
functionC();
});

Detecting if beforeunload event was cancelled by an unrelated function

I have a simple function to show a spinner overlay while a new page request is being made.
$(window).on("beforeunload", function() {
$('#nav-spinner').show();
});
This works perfectly.. but, it is used on a complex WordPress site and there are other (third party) components that also use this event to sometimes cancel the navigation (for instance, a confirmation when navigating away from a partially filled form).
Is there any way to determine if another function cancelled the page unload so I can remove my overlay immediately when they are remaining on the page.
I would like to do this when an actual navigation is cancelled - using a timer to remove the overlay will result in either the overlay being hidden prematurely or remaining for longer than it should.
Test Case that shows the problem
So the following code shows what you have currently. I am setting the background red since it is a minimum amount of code.
window.addEventListener("beforeunload", function(event) {
document.body.classList.add("red");
});
// 3rd party code that is showing the "are you sure"
window.addEventListener("beforeunload", function(event) {
event.preventDefault();
event.returnValue = 'I am 3rd party code';
});
.red {
background-color: red;
}
<form>
<button>Click Me then click "Cancel"</button>
</form>
Solving the problem
So now that we have the test case for what is wrong. The background should NOT remain red when the user clicks cancel. So how can we detect it? Well there is NO events that tells you what the user did.
So the only thing you can do would be to add a timer to remove what you added when the user cancels it. So if they click cancel, the timer runs and removes it.
But how do we keep it there if they do not cancel it? We use unload to kill the timeout that hides it. So remove the timeout and it will not fire.
var timer
// update the page as page exits
window.addEventListener("beforeunload", function(event) {
document.body.classList.add("red");
// if this timer runs, it means beforeunload was cancelled
timer = window.setTimeout( function () {
document.body.classList.remove("red");
}, 50);
});
// remove the timer when the pages finally exits so the class is not removed.
window.addEventListener("unload", function(event) {
window.clearTimeout(timer)
})
// 3rd party code that is showing the "are you sure"
window.addEventListener("beforeunload", function(event) {
event.preventDefault();
event.returnValue = 'I am 3rd party code';
});
.red {
background-color: red;
}
<form>
<button>Click Me then click "Cancel"</button>
</form>
You may have to play with the timeout millisecond values. The flash of content for showing could be lessened with a transition, but hopefully the browser does not kill that unload.

Capture all click events and discard unallowed

I develop a web GUI for a special tablet. This tablet is running with Linux and the used browser is Chromium. The application is a web application with PHP, HTML5, JQuery and JavaScript. Now I run into a problem. The screen is a touchscreen and the user is able to navigate through the application by touch the screen. However now we decided to add a feature for saving electricity. This feature will shutdown the background light after three minutes. To turn on the backlight again, the user should touch the screen again. This leads to this problem, because on any touch the buttons are also pressed even if the background light is shutdown. I want to prevent this by discarding all clicks on the touchscreen if a cookie is set. If this cookie is not set the touchscreen and the application should work as desired. How can I solve this problem?
I installed an event listener to register all clicks and to reset the time.
window.addEventListener('mousedown', function(e){
$.get('php/timeupdate.php', function(){});
}, false);
Code used to stop the execution:
$(document).on('click', function(event) {
$.get('php/getwakeup.php', function(e){
if(e==='true'){
//event.preventDefault(); // I tried all three possibilities
//event.stopImmediatePropagation();
event.stopPropagation();
}
});
});
You can try this:
$(document).on('click', function(event) {
// get your cookie
if( cookie is set ) {
event.stopPropagation();
}
});
event.stopPropagation(); stops every event handling from where you called it =)
EDIT:
You have to set your $.get call synchronous or do it completely diffrent. Take a look at the jQuery.Ajax documenation. There is a parameter called "async".
But be careful unless the call is ready nothing else will be executed on you page! So if your script doesn't answer nothing else will work on your site.
The better solution would be setting ja recurring call that will get the information you need. Set it to every two seconds (setInterval is your friend here). If your response is true than set a global variable that you can check in your onDocumentClick event.
window.isBacklightOff = false;
setInterval(function() {
$.get('php/timeupdate.php', function(e) { window.isBacklightOff = !!e; })
}, 2000);
$(document).on('click', function(event) {
// get your cookie
if( window.isBacklightOff === true ) {
event.stopPropagation();
}
});
When the back light goes off you can set some flag handleEvents=false;
So when the flag is on don't handle any events.
Now when the back light is on you can set handleEvents = true.
$(document).on('click', function(event) {
// get your flag say handleEvents
if( !handleEvents ) {
event.stopImmediatePropagation();
return;
} else {
//do your biz logic send ajax..etc
}
});
Reason why your code above is not working:
$(document).on('click', function(event) {
$.get('php/getwakeup.php', function(e){
if(e==='true'){
//event.preventDefault(); // I tried all three possibilities
//event.stopImmediatePropagation();
event.stopPropagation();
}
});
});
The function inside $.get is async and called on success in that you are setting the event to stop propagating...well by that time when the success function is called the event is already complete and has called all the listeners.
So in short you must not do the event stop propagation inside the success function.

Wordpress - insert Ajax-based login form upon link click event

I'm looking to get help with a WordPress staging site located at:
http://sbane39-beta.knowarecms.net.
I'm trying to get an existing Ajax-based login form to display when a non-logged-in user clicks an 'Add To Cart' button in my installation of the Event Espresso event management plugin.
An Ajax-based login form already exists, and functions properly when a user clicks the "Member Log In" button located just below the scrolling slideshow in the header of the page.
However, a copy of the form that is should be called when an "Add To Cart" button (in the main nav bar, click Events, All Events to see a list of available events) is clicked doesn't appear - instead, the default behavior of the link fires, which is a redirection to the Event Espresso shopping cart with the specific event added to it.
In both cases, the click event is being handled by the script at :
http://sbane39-beta.knowarecms.net/wp-content/themes/sbanenew/js/ajax-login-script.js.
In the case of the "Member Log In" button, the handler function is:
$("a[title='memberlogin']").on('click', function(e){...}
For the "Add to Cart" buttons, the handler function is:
$("a[id^='cart_link_']").on('click', function(e){...}
When debugging the later, I can see that the function is being called on the click event, but for some reason preventDefault action isn't working to stop execution.
I added the return false statement to stop propagation, but with no luck.
My JS debugging skills aren't good enough to see why this is happening. Hopefully this forum is the appropriate place to seek help, so TIA for any guidance.
In response to brybott's request, here's the (modified) code with the return false statement moved:
$("a[id^='cart_link_']").on('click', function(e){ //When an Add To Cart button is clicked...
e.preventDefault();//prevent the default action
//$addToCartURL = $(this).attr('href');
//display event login form only to logged out users
jQuery.post(ajax_login_object.ajaxurl, data, function(response) {
if(response == 'yes') {
//alert('You are already logged in');
} else {
$formLoginEvent.fadeIn(1000);//Fade the form in
$('form#login_event a.close').on('click', function(e){
e.preventDefault();
$('form#login_event').fadeOut(1000);
});
return false; //stop propagation
}
});
});
I noticed one thing in your code..
$("a[id^='cart_link_']").on('click', function(e){ //When an Add To Cart button is clicked...
//$addToCartURL = $(this).attr('href');
//display event login form only to logged out users
jQuery.post(ajax_login_object.ajaxurl, data, function(response) {
if(response == 'yes') {
//alert('You are already logged in');
} else {
e.preventDefault();//prevent the default action
return false; //stop propagation
$formLoginEvent.fadeIn(1000);//Fade the form in
$('form#login_event a.close').on('click', function(e){
e.preventDefault();
$('form#login_event').fadeOut(1000);
});
}
});
});
When you return a function, in your case you return false; //stop propagation, no lines that come after the return statement run. So, in your case, fading the form in will never happen. Try dropping the return false; line down to the end of your else statement and see if it works.
So brybott was correct in stating that the return false statement was misplaced. I needed to move it outside the jQuery.post call, to the last line of the click() handler function - doing that causes the form to display, and keeps the redirection from occuring.

Warn user about unsaved changes to a form, when a form is being replaced during an AJAX call?

I'm new to Javascript and JQuery, and I'm implementing a warning to users that displays when they have made unsaved changes to a form's input/select/textarea elements if they navigate away from a page. I currently have the following which works fine when they leave a static form page:
/*
* Warn users when leaving a page with unsaved content, watches elements: (input, textarea, select) unless
* they are tagged with the "noWarning" class
*/
$(document).ready(function() {
$(document).on('change', 'input:not(.noWarning),textarea:not(.noWarning),select:not(.noWarning)', function () {
window.onbeforeunload = function(e) {
return 'You have unsaved changes';
};
});
});
The only page where it does not work, is in our main editing page. This page, unlike the others, has multiple tabs for editing different aspects of an item, which when clicked, trigger an AJAX call which replaces the content div with the appropriate form for editing the different aspect.
No warning dialog is displayed when a user clicks on a tab though, so any unsaved changes to the input are lost.
My intuition is that because the url is not changing, onBeforeUnload() is not executing. So I would have to check for any changes directly in the function which handles the AJAX call for replacing the form when a tab is clicked:
function clickedTabbedMenu() {
// This function replaces the content div with a new div and form
}
So my question is, how do I go about checking if any changes have been made to the elements in the current form before I replace the content div with another??? Can I directly call the "change" event listener for a true/false??? Or perhaps a different approach to handle this page's warning messages?
Any help is appreciated
Attach a change event handler to all the elements of the form. Have a variable outside the handler's scope dirty (or even a data on the form element) be set to false when a form is loaded, and true on every change event. Then, before replacing the form, check if dirty.
This would also be a good strategy for your non-AJAX pages as well - instead of setting the whole onBeforeUnload each time an element changes, just set onBeforeUnload once, and check if dirty inside it. This makes handling your AJAX and non-AJAX pages very similar.
EDIT: Untested because it's late and I need bed, but basically:
$(document).ready(function() {
var dirty = false;
$(document).on('change', 'input:not(.noWarning),textarea:not(.noWarning),select:not(.noWarning)', function () {
dirty = true;
});
function checkDirty() {
if (dirty) {
alert('You have unsaved changes');
return false;
}
return true;
}
// for non-AJAX pages
window.onbeforeunload = function(e) {
return checkDirty();
};
// for AJAX pages
$('.ajax_navigation_tab').on('click', function() {
if (!checkDirty()) {
// do the ajax thing
dirty = false;
}
});
});
I would try checking for and calling window.onbeforeunload() in your ajax script.
If it exists and returns a string, use it as an error message and halt the operation :)

Categories