Detecting if onsubmit was cancelled by another event handler? - javascript

I would like a way of detecting/triggering a function when the form onsubmit is cancelled by any onsubmit handler. What's the most reliable method for doing this?

Wrap it up...
// This code should execute last (after onsubmit was already assigned)
var oldsub = document.forms[0].onsubmit;
document.forms[0].onsubmit = function() {
if(!oldsub)
alert("Onsubmit did not exist!");
else if(oldsub())
alert("Onsubmit passed!");
else
alert("Onsubmit failed!");
}

you could override all the forms' onsubmit handlers with your own:
var f = document.getElementById('myForm'); // or whatever
if (f.onsubmit) {
var oldSubmit = f.onsubmit;
f.onsubmit = function () {
var result = oldSubmit.call(this);
if (result === false) {
alert("Cancelled.");
}
return result;
};
}

I'm probably wrong, but would returning false on one handler cancel the stack? Failing that, you could attach a check call on each event to check whether another one in the stack canceled.

Related

JS : How to use return type of callback function for returning the main callee function

I found few good links (How to return value from an asynchronous callback function? and Returning a value from callback function in Node.js etc) of SO but they are not not able to provide solution to my problem.
My Problem: able to get result of asynchronous call, but how I can use this result for returning of my function?
onsubmit = "return checkForm(function(callBackResponse) { alert(callBackResponse) });"
Here getting value of callBackResponse either as true or false, and want to use this value as :
onsubmit = "return responseFromCallBack;"
EDITED : Here is my async stuff
function checkForm(callback) {return firstCallBack(function secondCallBack(response) {
if (some conditions) {
response = false;
callback(response);
}
else {
response = true;
callback(response);
}
}
);
}
If i get ur issue correctly:
you want to "validate" (checkForm()) before submitting?!
in this case set an event listener to the form submit-event...
prevent (event.preventDefault()) the default behavior (submit) call your function (checkForm()) if everything is fine, trigger the submit manually ;)
e.g. document.getElementById('myFormId').submit()
Cheerio :)
If you want to use nested function call approach and want to check function result than you should use of function and form submit event as follow.
$(document).ready(function() {
$("#FormId").submit(function(){
alert(checkForm());
return checkForm();
});
});
function checkForm()
{
//another core logic
return anotherfunction();
}
function anotherfunction()
{
//another core logic than return as per condition true or false.
return false;
}
JSFiddle Example

How to handle return values in the function?

I have this function:
function kontrola(){
var jmeno = self.document.forms.newPassForm.user.value;
$.get("checkMail.php?mail="+jmeno, function(data){
if(data=='1'){
alert('Tento uživatel v databázi neexistuje!');
return false;
}else return true;
});
}
My problem now is, that alert is not displaying (value for data variable is passed ok). If I add return false; at the end of the function, the alert is displayed, but if condition isnt fullfilled, I can´t send data from the form. Do you have any solution for this?
return does not do the same thing in a jQuery callback as it would in a normal function.
jQuery views return true; as continue (and assumes that you just wanted to skip to the next object in the jQuery object's set) and return false; as break (and assumes you just want to break out of the current iteration). return false when used in some event handlers will also prevent the default event behavior, but it is not the recommended approach to do that.
A better way to accomplish getting the return value would be to "split" your calling function with a callback that you inject into the get call.
function kontrola(callback){
var jmeno = self.document.forms.newPassForm.user.value;
$.get("checkMail.php?mail="+jmeno, function(data){
if(data=='1'){
alert('Tento uživatel v databázi neexistuje!');
callback(false);
}else{ callback(true); }
});
}
function someCaller(){
var someWork = 1 + 2;
//split the rest of this call function to be done inside of the callback
kontrola(function(result){
var boolResult = result;
if( boolResult ){
//do more work
}else{
//handle false case
}
});
}
edit
Since this is attached to a submit button, I would suggest sending the submit element with the event
onsubmit = return "kontrola(this);"
For the reason that you are going to submit at a later time if successful
function kontrola(submitElement){
var jmeno = self.document.forms.newPassForm.user.value;
$.get("checkMail.php?mail="+jmeno, function(data){
if(data=='1'){
alert('Tento uživatel v databázi neexistuje!');
}else{ submitElement.submit(); }
});
return false;
}
If you data variable is an integer, you will want data===1 without those currently present single quotes (which compares to a string, which will always fail when comparing to a number).

Is it possible to get a return type from a keyup function?

My current code is this and what I'm trying to is see if I could get a return value after the key up is done.
$("#confirm").keyup(function(event){
event.preventDefault();
ajax_pass_check();
});
so I would end up with something like this because my ajax_pass_check(); function returns true/false.
$("#confirm").keyup(function(event){
event.preventDefault();
return ajax_pass_check();
});
I would like to see if I could do that, and try something like
var one = $("#confirm").keyup(function(event){
event.preventDefault();
return ajax_pass_check();
});
I'm new to javascript and I've looked on google for awhile and I haven't found what I needed so I thought I'd ask. However when I did try that, I didn't get the expected result I was hoping for. Since var one remained false, when it should have been true after the function ajax_pass_check();
~edit: I took advice one of you guys (thanks for all the replies!) I still can't figure out why my var one variable false even though I set it to true in the keyup function.
$(document).ready(function(){
var one = false;
$("#confirm").keyup(function(event){
event.preventDefault();
one = ajax_pass_check();
//one = true; //even if I do that it doesn't work.
});
if(one == true)
{
$('input[type="submit"]').removeAttr('disabled');
}
else
{
$('input[type="submit"]').attr('disabled','disabled');
}
});
Instead of returning a value, you should consider using global scope for the variable, and set its desired value inside your function:
var wasSuccessful = false;
$("#confirm").keyup(function(event){
event.preventDefault();
your_function();
});
function yourfunction() {
if your awesome code worked { wasSuccessful = true; }
else { wasSuccessful = false; }
}
No, but you could call another function to use the result of ajax_pass_check. For example,
$("#confirm").keyup(function(event){
event.preventDefault();
doSomethingElse(ajax_pass_check());
});
function doSomethingElse(keyUpOk) { // Do something ... }
Assuming (based on your function names) you are using this to do some form of validation this will allow you to display or clear an error message.
The reason you cant do
var one = $("#confirm").keyup(function(event){
event.preventDefault();
return ajax_pass_check();
});
is because the key up function is just binding you function to the event, so this code will have already been executed when the key is released. You will probably want to call a function so that something is done with the result of the keyup event handler after the keyup event is fired, not when you function is bound to the event.
Try this instead
$(document).ready(function(){
var one = false;
$("#confirm").keyup(function(event){
event.preventDefault();
one = ajax_pass_check();
//one = true; //even if I do that it doesn't work.
if(one == true)
{
$('input[type="submit"]').removeAttr('disabled');
}
else
{
$('input[type="submit"]').attr('disabled','disabled');
}
});
});
The Answer is: No
The jQuery Function keyup doesnt return a special value, only the jQuery Object see the API(at the top), since it is used only to bind functions.
Depence on what you want to achieve, one of the solutions, mentioned by the others could solve your issue.

How can I stop a default event when using a named function in addEvent?

Normally, if I wish to stop a default event in mootools I can do this:
$('form').addEvent('submit', function(e) {
e.stop();
//Do stuff here
});
However, I don't like using an anonymous function in events because I often want to reuse the code. Lets say I have a validate function. I could do this:
$('form').addEvent('submit', validate);
which works fine until I want to stop the default event. validate obviously doesn't know what e is so I can't just do e.stop(). Also I've tried passing the event as a variable to validate but whenever I use a named function with parameters, the function gets called automatically on domready, rather than on the event firing. Even worse, an error is thrown when the event is fired.
What am I doing wrong?
UPDATE: Here is the validate function in full, just in case. However, since the error is occurring after the first line, I doubt anything after is being called so it is probably irrelevant.
var validate = function(e) {
e.stop();
if(this.get('tag') === 'form') {
this.getElements('input.text').each(validate);
}
else {
element = this;
div = element.getParent();
input = element.get('value');
filter = JSON.decode(div.get('filter'));
if(!filter.some(function(value, key) {
if(value === 'required') if(!setAndNotEmpty(element, input)) return true;
if(value === 'email') if(!isEmail(element, input)) return true;
if(value === 'date') if(!isDate(element, input)) return true;
if(value === 'time') if(!isTime(element, input)) return true;
if(key === 'chars') if(!charsLessThan(element, input, value)) return true;
if(key === 'words') if(!wordsLessThan(element, input, value)) return true;
return false;
})) setFault('', element);
}
}
you need to declare "validate" as follows:
function validate(e){
}
Then you can use e.stop()
function validate(e){
e.stop();
}
$('form').addEvent('submit', validate);
of note is that in jQuery, you can also return a result from a method to stop propogation. I'm not sure if mootools allows this, but you could possibly do this by:
function validate(e){
return false;
}
$('form').addEvent('submit', validate);
To answer the "what am I doing wrong" part - you're simply misunderstanding what is happening when you pass in an anonymous method. Passing an anonymous method function(e) {} is not causing e to be passed, it is simply defining the name of the first argument to be passed in. The event object will be passed into the method whether or not the method names the argument, hence you will find that the following would also work:
function validate(){
arguments[0].stop();
}
$('form').addEvent('submit', validate);
$('form').addEvent('submit', function(e) {
e.stop();
//Do stuff here
}
I don't know if this is part of your issue, but watch your () in addEvent arguments.
$('form').addEvent('submit', function(e)) {
Your 'e' argument wasn't properly closed off in the first line.
bindWithEvent Changes the scope of this within the target function to refer to the bind parameter. It also makes "space" for an event. This allows the function to be used in conjunction with Element:addEvent and arguments.
preventDefault Cross browser method to prevent the default action of the event.
function validate(e)
{
e.preventDefault();
if(this.get('tag') === 'form') {
this.getElements('input.text').each(validate);
}
else {
element = this;
div = element.getParent();
input = element.get('value');
filter = JSON.decode(div.get('filter'));
if(!filter.some(function(value, key) {
if(value === 'required') if(!setAndNotEmpty(element, input)) return true;
if(value === 'email') if(!isEmail(element, input)) return true;
if(value === 'date') if(!isDate(element, input)) return true;
if(value === 'time') if(!isTime(element, input)) return true;
if(key === 'chars') if(!charsLessThan(element, input, value)) return true;
if(key === 'words') if(!wordsLessThan(element, input, value)) return true;
return false;
})) setFault('', element);
}
$('form').addEvent('submit', validate.bindWithEvent(this));
Pretty self explanitory when you see the words prevent default next to each other. So when you submit a form the page will not go to your action.

How to delay a function from returning until after clicks have occurred

The following confirmDialog function is called midway through another jquery function. When this confirmDialog returns true the other function is supposed to continue... but it doesn't. The reason for this seems to be that the entire confirmDialog function has already executed (returning false) by the time the continue button gets clicked. How can I delay it returning anything until after the buttons have been clicked?
(Or, if I'm completely on the wrong track, what is the problem and how do I fix it?)
function confirmDialog(message) {
....
$('input#continue', conf_dialog).click(function() {
$(this).unbind();
$('p',conf_dialog).fadeOut().text('Are you really sure you want to '+message).fadeIn();
$(this).click(function() {
$(conf_dialog).remove();
return true;
});
});
$('input#cancel', conf_dialog).click(function() {
$(conf_dialog).remove();
return false;
});
}
Im' not sure you can.
AFAIK only built-in function like confirm, alert or prompt can be blocking while asking for an answer.
The general workaround is to refactor your code to use callbacks (or use the built-in functions). So that would mean splitting your caller function in two, and executing the second part when the input is obtained.
In confirmDialog, you're setting up event handlers, that will execute when events are fired, not when confirmDialog is run. Another issue, is that you return true or false inside the event function, so that won't apply to the outer function confirmDialong.
The part that relies on the button presses would need to be re-factored. Perhaps put it in another function, and call it from the click handlers:
var afterConfirm = function(bool) {
if(bool) {
//continue clicked
} else {
//cancel clicked
}
//do for both cases here
}
//inside confirmDialog input#continue
$(this).click(function() {
$(conf_dialog).remove();
afterConfirm(true);
});
You may want to look into using Deferred objects. Here are two links that explain them.
http://www.sitepen.com/blog/2009/03/31/queued-demystifying-deferreds/
http://api.dojotoolkit.org/jsdoc/1.3/dojo.Deferred
Using a Deferred you could take your calling function:
function doSomething () {
// this functions does something before calling confirmDialog
if (confirmDialog) {
// handle ok
} else {
// handle cancel
}
// just to be difficult lets have more code here
}
and refactor it to something like this:
function doSomethingRefactored() {
// this functions does something before calling confirmDialog
var handleCancel = function() { /* handle cancel */};
var handleOk = function() { /* handle ok */};
var doAfter = function() { /* just to be difficult lets have more code here */};
var d = new dojo.deferred();
d.addBoth(handleOk, handleCancel);
d.addCallback(doAfter);
confirmDialog(message, d);
return d;
}
ConfirmDialog would have to be
updated to call d.callback() or
d.errback() instead of returning true
or false
if the function that calls
doSomething needs to wait for
doSomething to finish it can add its
own functions to the callback chain
Hope this helps... it will make a lot more sense after reading the sitepen article.
function callingFunction() {
$('a').click(function() {
confirmDialog('are you sure?', dialogConfirmed);
// the rest of the function is in dialogConfirmed so doesnt
// get run unless the confirm button is pressed
})
}
function dialogConfirmed() {
// put the rest of your function here
}
function confirmDialog(message, callback) {
...
$('input#continue', conf_dialog).click(function() {
callback()
$(conf_dialog).remove();
return false;
}),
$('input#cancel', conf_dialog).click(function() {
$(conf_dialog).remove();
return false;
})
...
}
You could add a timeout before the next function is called
http://www.w3schools.com/htmldom/met_win_settimeout.asp

Categories