How to get this form to submit only when it should - javascript

Probably an idiotic question but I find this really tricky:
I am trying to make a form submit only when it specifically should.
The script below executes every time I submit any other form in my page.
How can I make it not execute, unless it is called for?
$('#nurturing_pop_up_form').validate({
rules: {
emailaddress: {
required: true,
email: true
},
board_meeting: {
required: {
depends: function () {
return $('input[name=in_12_months]').is(':checked')==false && $('input[name=in_6_months]').is(':checked')==false
}
}
}
},
submitHandler: function(form) {
var url_remind = 'http://example.com';
var data_remind = $('#nurturing_pop_up_form').serializeArray();
$.ajax({
type: "POST",
url: url_remind,
data: data_remind,
success: function(){
$('.nurturing_pop_up').fadeOut();
}
});
}
});
Should I add something like this?
$('#nurturing_pop_up_form').submit(function(e){
e.preventDefault();
$('#nurturing_pop_up_form').validate({
rules: {
//the rest like above
Help is very very appreciated!

I am trying to make a form submit only when it specifically should.
This process is handled automatically by jQuery Validate. You should not be doing anything special to force this.
The script below executes every time I submit any other form in my page.
The script "below", .validate({...}), is simply the plugin's initialization routine. Within the code you've shown, you are only initializing ONE form with id="nurturing_pop_up_form". Other forms on the page would be completely unaffected. Perhaps you have invalid HTML, additional instances of .validate(), other submit handlers, or some erroneous code you have not shown us.
How can I make it not execute, unless it is called for?
I think your question is based on an erroneous assumption of what's happening. .validate() is only supposed to be called ONCE on page load (DOM ready handler) to initialize the plugin on your form. The plugin then automatically captures the click, validates the data, and handles the submit.
Should I add something like this?
$('#nurturing_pop_up_form').submit(function(e){
e.preventDefault();
$('#nurturing_pop_up_form').validate({...
Absolutely not. You should never put .validate() within a .submit() handler for the same form. It's completely unnecessary, delays the plugin's initialization, and interferes with the built-in submit handler.
Nothing you've shown can explain how/why other forms would be affected.

Related

SuccessCallback firing immediately in Xrm.Page.data.save

I am writing javascript code to change the form of a entity in Dynamics CRM based on the value of a field on each form.
To change the form, the user has to change the value of the field.
Then during the onChange event, my js comes in, triggers saving, has to wait for the result and then change the form. (If you save and change at the same time, there is still a window shown asking the user to confirm leaving unsaved changes)
Now there should be a way to do that:
Xrm.Page.data.save(saveOptions).then(successCallback, errorCallback)
as it is described on msdn:
Saves the record asynchronously with the option to set callback functions to be executed after the save operation is completed.
I am using it as such:
var campaignType = Xrm.Page.getAttribute('typecode').getValue();
if (xxx.Forms.hasOwnProperty(campaignType)) {
Xrm.Page.data.save().then(function () { xxx.redirectToForm(xxx.Forms[campaignType]); }, null);
But the form change is still triggered immediately during the save.
What am I doing wrong?
I faced a similar problem while trying to update the process bar.
Xrm.Page.data.save().then
(function () {
window.location.reload(true);
},
function () {
windows.alert("broken");
}
);
I strongly suggest you to try to apply the logic on a vanilla CRM, for me what was breaking the logic was a third party component called N52 Rules, their code was interfering with the callback forcing the refresh of the page before the save event. Your code seems correct.
Hey the Save and Refresh Calls are Asynchronous! that is why it hits the success handler immediately.
What you can try is using SDK.REST.js file for CRM
function updateFunction(entityId) {
var campaignType = Xrm.Page.getAttribute('typecode').getValue();
if (xxx.Forms.hasOwnProperty(campaignType)) {
var entity= {};
entity.typecode= campaignType;
SDK.REST.updateRecord(
entityId,
entity,
entityName, //"Account"
function () {
writeMessage("The record changes were saved");
xxx.redirectToForm(xxx.Forms[campaignType]);
},
null
);
}
}
https://msdn.microsoft.com/en-us/library/gg334427(v=crm.7).aspx
Here you can call updateFunction given above onChange and in the onSuccess handler you can try calling the form you want to call. I haven't tried it the way you want, but let me know if it works.
check this link out as well
https://msdn.microsoft.com/en-us/library/gg334720.aspx#BKMK_entityOnSave

Control flow not reaching a line of code

I have a simple function to submit a POST request to an ASP.NET MVC url.
The control does not even reach the last line of code where the form is submitted. Please help. Here's the function I invoke at the click of a hyperlink.
function submitNewAccountInfo() {
debugger;
var newAccountInfo =
{
FullName: $("#NewUserAccountInfo_FullName").val(),
Email: $("#NewUserAccountInfo_Email").val(),
PasswordHash: md5($("#NewUserAccountInfo_Password").val())
};
debugger;
// The control does not even come here. What am I doing wrong?
$("#frmCreateNewAccount").submit(newAccountInfo);
}
Create my account
I fixed my problem. There were a couple of issues with my code:
I wasn't using jQuery to bind/wire up event handlers with events. As a result, the short-cut onclick that I took was attaching an event handler and not an event listener.
This meant that I had to handle all browser incompatibilities and also get hold of the event object to prevent its default behavior, none of which I was doing and all of which jQuery makes it very easy to do.
I changed my code to bind/wire up an event listener using jQuery and my code is now working. Here's the working code.
$(document).ready(function () {
$("#lnkCreateMyAccount").click(submitNewAccountInfo);
});
function submitNewAccountInfo(event) {
event.preventDefault();
var newAccountInfo =
{
FullName: $("#NewUserAccountInfo_FullName").val(),
Email: $("#NewUserAccountInfo_Email").val(),
PasswordHash: $("#NewUserAccountInfo_Password").val()
};
$("#frmCreateNewAccount").submit(newAccountInfo);
}

How can I check the value returned by a validation function to pass along the metrics to Google Analytics?

I use a system that captures visitors information via a form. I can't edit the code of the form validation scripts. I am trying to see if I can check upon clicking on the submit button, before the form submit sends the person to the response URL if the validation was passed.
The "submit" calls the function "formSubmit()", if validation is passed myFormIsValid() is returned. If not, then return false to the form.
Like this:
function formSubmit(elt) {
if (!myFormIsValid()) {
return false;
}
I want to know if validation was passed before allowing the form to move forward and do something like setting a variable value so I can tell Google Analytics that the form was successfully submitted. Is there a way to setup a "listener" to the results of the formSubmit function before it is called? I can put the code on the header or footer and I can use jQuery.
You can handle the submit before it reaches it's destination with an event handler.
jQuery.submit()
$(function () {
$("#MyForm").submit(function (e) {
if (!$(this).valid()) {
e.preventDefault(); // prevents the form from submitting.
return;
}
// you can do things here or just let it continue submitting.
});
});

jquery, binding order/wait for callback

I wrote a jquery plugin for validating forms. It bounds itself to the $('element').Submit event to trigger the validation (the bind is inside the plugin). Somehow like this:
// pseudocode
jquery.rdy {
$('form').validate(); //binding the plugin
}
Inside of the validate plug I bind the validation to the submit
//pseudocode
[...]
$().submit(function () {
validating... //returning true/false
if (false) {
return false //prevent submit form
}
}
[...]
So and now my question is how can I bind (in other js scripts for example) other stuff to the submit but just if a validation is done.
so like this
$('form').submit(function () {
if (validate plugin was executed) {
//do stuff like check if validation was returning a true and now do something else
}
}
Hopefully I descriped it right ...my english is not the best but I tryed to be as concrete s possible (and i hope, pseudocode is a right approach as well)
// EDIT: make the problem more concrete:
I'm trying to figure out a way to solve the following problem: (its very out of the context but the problem is exactly there..)
I have a submit event which is doing something depending on some code triggered in a another decleration.
$('element').submit(function () {
if ($(this).hasClass('foo')) {
// do something
}
});
$('element').submit(function () {
$(this).addClass('foo');
});
And now the first function is doing nothing cause it has been triggered before the second one. Is there a clean way to solve this. Maybe I need a timeout event (even I hate them)?
If you are using jQuery.Validate (which it looks like you are with the .validate() syntax), you can just call the isValid() method:
if (validate plugin was executed) {
can then be
if ($('form').isValid()) {
You can bind more functions to the form element with custom names.
$('form').bind('after_validation',function(){ console.log('hello'); });
And trigger them in your submit form function when you need it:
$('form').trigger('after_validation');
http://api.jquery.com/trigger/
Update:
You cannot change the order of your bound submit events without removing them .unbind('submit') and re-applying in the correct order. What you can do is use custom binds (see above) and trigger them exactly when you need it - like.. inside the submit function.
$('form').submit(function () {
//run validation
$('form').trigger('validation');
//did it pass validation?
if($(this).data('invalid')){
console.log('did not pass validation');
return false;
}
//passed validation - submit the form
return true;
});
//add validation to the "form"
$('form').bind('validation',function () {
//do validation on form...
if(false){
$(this).data('invalid',true);
}
});
//add another validator to the form, etc.
$('form').bind('validation',func...
Im using .data() to store variables to the 'form' element so you can access them down the chain.
This is the basis of what you need and can be applied to a custom jquery plugin to form custom named functions. eg. $().validator().
http://docs.jquery.com/Plugins/Authoring

How dangerous is e.preventDefault();, and can it be replaced by keydown/mousedown tracking?

I'm working on a tracking script for a fairly sophisticated CRM for tracking form actions in Google Analytics. I'm trying to balance the desire to track form actions accurately with the need to never prevent a form from not working.
Now, I know that doing something like this doesn't work.
$('form').submit(function(){
_gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
});
The DOM unloads before this has a chance to process.
So, a lot of sample code recommends something like this:
$('form').submit(function(e){
e.preventDefault();
var form = this;
_gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
//...do some other tracking stuff...
setTimeout(function(){
form.submit();
}, 400);
});
This is reliable in most cases, but it makes me nervous. What if something happens between e.preventDefault();and when I get around to triggering the DOM based submit? I've totally broken the form.
I've been poking around some other analytics implementations, and I've noticed something like this:
$('form').mousedown(function(){
_gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
});
$('form').keydown(function(e){
if(e.which===13) //if the keydown is the enter key
_gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
});
Basically, instead of interrupting the form submit, preempting it by assuming that if someone is mousing down or keying down on Enter, than that form is submitted. Obviously, this will result in a certain amount of false positives, but it completely eliminates use of e.preventDefault();, which in my mind eliminates the risk that I might ever prevent a form from successfully submitting.
So, my question:
Is it possible to take the standard
form tracking snippet and prevent it
from ever fully preventing the form
from submitting?
Is the
mousedown/keydown alternative viable?
Are there any submission cases it may miss? Specifically, are there other ways to end up submitting besides the mouse and the keyboard enter? And will the browser always have time to process javascript before beginning to unload the page?
Them fellers over at that there Googleplex are awful bright and they figgered some day somethin' like this was bound to happen and now, sure enough, it has. Why don't you give this a good try:
$('form').submit(function(e){
e.preventDefault();
var form = this;
_gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
//...do some other tracking stuff...
_gaq.push(function(){
form.submit();
});
});
That _gaq.push thigamajigger executes its elements sequentially, so you should be jest fine.
And no, I don't know why I suddenly started talking like this.
I use a different approach, and generate the event tracking script in the page resulting from the submit. You could call it deferred event tracking.
I wrote a blog post with all details about my approach to event tracking in backend actions. It is biased towards Java-Struts, but you can get the general idea.
The rationale is that I want to track some things after they happened at the server side. In this kind of case, after the form was submitted and processed by the server.
What I do (very summarized):
Store events in an object tied to the session (a list/queue)
Flush these events upon the next page render (generate the javascript and empty the queue)
If you must have forms always work but tracking can be sacrificed if absolutely necessary, you could just try/catch it.
$('form').submit(function(e){
try{
e.preventDefault();
var form = this;
_gaq.push('_trackEvent', 'Form', 'Submit', $(this).attr('action'));
//...do some other tracking stuff...
setTimeout(function(){
form.submit();
}, 400);
} catch (e) {
form.submit();
}
});
e.preventDefault() doesn't have to be right at the beginning of the function call. Why not just have an if statement to verify if everything is working correctly, and only call e.preventDefault() if it does. If any function in the chain doesn't return the expected result, set a submitted variable to false, and don't prevent the default.
This might be a little more difficult to handle when it comes to anything asynchronous (such as your setTimeout, but there will be ways to make fairly sure, depending on what your code looks like. So you can check if methods exist with if (_gaq.push) (for example). You can't make 100% sure without testing every single combination in every browser, but I reckon you can get a pretty satisfactory result with this.
Another approach:
var pageTracker;
_gaq.push(function() {
pageTracker = _gat._getTrackerByName();
});
$('form').submit(function(e){
pageTracker._trackEvent('Form', 'Submit', $(this).attr('action'));
};
I would guess this way _trackEvent would be synchronous but I haven't tested it.
Is there a reason why you can't just issue the call to Google Analytics from the server side based on the POST that it receives?
I don't know what your system is built in, but for instance, this PHP project would issue a call to GA, thus removing the problem of the DOM unloading, the need to break the form, and so on.
http://code.google.com/p/serversidegoogleanalytics/
I realise that you might need to capture a cookie - you might write the value into a hidden field in the form before it is submitted?
To expand on #Malvolio's answer:
Once gaq sends the event the next item in the queue will process. This means that the event HTTP request may abort on the client side, but GA will receive the request. Don't worry about blocking script execution until the response finishes. It is a fire and forget scenario.

Categories