Re: Form. On Success CallBack not firing on Iphone

Anthony_Zhu
Level 1

Form. On Success CallBack not firing on Iphone

Hello,

Sanford Whiteman

Here is a link to a sign up form. We have our marketo form hidden that submits on a click event on the front end facing form the user sees.

https://www.uschamber.com/co/register?entryId=45127

I'm scratching my head as to why only on mobile specifically iOS devices the on success doesn't fire which (this site is built on craft cms) which instead of redirecing the user to a thank you page drops them off on the homepage. Works fine on every thing else except iphone specifically.  Below is also a snippet of the code.

<script src="//app-ab13.marketo.com/js/forms2/js/forms2.min.js"></script>

<form id="mktoForm_2050" style="display:none"></form>
MktoForms2.loadForm("//app-ab13.marketo.com", "462-UWH-935", 2050, function(form){
form.onSuccess(function(values, followUpUrl) {
console.log('AZ: On Success Event');
let $form = $('#gated-registry-form');

let $articleUrl = $form.find('#articleUrl');

//TODO:Make this redirect work for local dev//
let thankYouPageUrl = '/accounts/thanks?gatedArticle=' + $articleUrl.val();

location.href = thankYouPageUrl;

// Return false to prevent the submission handler from taking the lead to the follow up url
// return false;
});

});
MktoForms2.whenReady(function(mktoForm) {
var $mktoForm = $(mktoForm.getFormElem());
var $form = $('#gated-registry-form');

$form.find('#email').on('keypress', function (event) {
if (event.keyCode == 13) {
event.preventDefault();
}
});



$('#submit-btn, #submitCompanyButton').on('click', function(e) {
console.log('AZ: Front End Form Clicked');
let $email = $form.find('#email');
if ($email.length == 1) {
$mktoForm.find('#Email').val($email.val());
}

let $firstName = $form.find('#firstName');
if ($firstName.length == 1) {
$mktoForm.find('#FirstName').val($firstName.val());
}
let $lastName = $form.find('#lastName');
if ($lastName.length == 1) {
$mktoForm.find('#LastName').val($lastName.val());
}

let $zipCode = $form.find('#zipCode');
if($zipCode.length == 1){
$mktoForm.find('#zipCode').val($zipCode.val());
}

let $companyName = $form.find('#companyName');

if($companyName.length == 1){
$mktoForm.find('#Company').val($companyName.val());
}

let $jobTitle = $form.find('#jobTitle');
if ($jobTitle.length == 1) {
$mktoForm.find('#LeadRole').val($jobTitle.text());
$mktoForm.find('#Title').val($jobTitle.text());
}

let $industry = $form.find('#industry');
if($industry.length == 1){
$mktoForm.find('#Industry').val($industry.text());
}

let $partnerName = $form.find('#partnerName');
if($partnerName.length == 1){
$mktoForm.find('#partnerName').val($partnerName.val());
}

let $articleUrl = $form.find('#articleUrl');
if($articleUrl.length == 1){
$mktoForm.find('#articleSlug').val($articleUrl.val());
}

$('#mktoForm_2050 #coUserRegistered').prop('checked', true);

$mktoForm.find('#coUserSubToCo').prop('checked', $form.find('#subscribeToCo').prop('checked'));
$mktoForm.find('#coUserSubToMo').prop('checked', $form.find('#subscribeToMo').prop('checked'));

const requiredCheckbox = $('.optInToCo.js-required');
const requiredEmail = $mktoForm.find('#Email').val();
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

if ((requiredCheckbox.length && !requiredCheckbox[0].checked) && (requiredEmail.length === 0 || !re.test(String(requiredEmail).toLowerCase()))) {
$('.response-message').text('Please enter a valid e-mail and indicate that you have read and agree to the Terms and Conditions and Privacy Policy');
return;
} else if (requiredCheckbox.length && !requiredCheckbox[0].checked) {
$('.response-message').text('Please indicate that you have read and agree to the Terms and Conditions and Privacy Policy');
return;
} else if (requiredEmail.length === 0 || !re.test(String(requiredEmail).toLowerCase())) {
$('.response-message').text('Please enter a valid e-mail');
return;
} else {
$('.response-message').text('');
}

mktoForm.submit();
});
});
Tags (1)
4 REPLIES 4
SanfordWhiteman
Level 10 - Community Moderator

Re: Form. On Success CallBack not firing on Iphone

Wouldn't say it works "fine" really... 

It has an explicit race condition since you aren't returning false from the onSuccess stack. And you shouldn't be using direct DOM methods on form fields as this will break with several data types. And let and const are broken or nonexistent on browsers still in the wild.

Other than those, maybe!

Jay_Jiang
Level 10

Re: Form. On Success CallBack not firing on Iphone

Looking at the excerpt, there are definitely things I would do differently like using data attributes to map the front-end form fields to marketo fields and making use of loops to make mapping field values dynamic.

Annotated example code below

As a side note, you've got some IDs appearing twice, once in your front-end form and once in your marketo form, #zipCode and #partnerName.

<form id="contactForm">
<label>First Name</label><br/>
<input type="text" name="FN" id="FirstName" data-mktoName="FirstName" placeholder="First Name"><br/><br/>
<label>Last Name</label><br/>
<input type="text" name="LN" id="LastName" data-mktoName="LastName" placeholder="Last Name"><br/><br/>
<label>Email</label><br/>
<input type="email" name="EM" id="Email" data-mktoName="Email" placeholder="Email Address"><br/><br/>
<label>Company</label><br/>
<input type="text" name="CO" id="Company" data-mktoName="Company" placeholder="Company"><br/><br/>
<input type="checkbox" name="optional1" id="optional1" data-mktoName="optional1"> <label for="optional1">Optional 1</label><br/>
<input type="checkbox" name="optional2" id="optional2" data-mktoName="optional2"> <label for="agree1">Optional 2</label><br/>
<input type="checkbox" name="agree1" id="agree1" data-mktoName="agree1"> <label for="agree2">Agree 1</label><br/><br/>
<input id="submit-btn" type="submit" value="Submit" class="btn btn-blue my-2">
</form>
<script>
// function to loop through front-end form fields to create an object so you don't have to maintain matching fields in your javascript
function getMktoFormData($form){
var mktoFields = $('[data-mktoName]:input'),
mktoCheckboxFields = mktoFields.filter('[type="checkbox"]'),
formDataObject= {};
$.each(mktoFields,function(i){
formDataObject[$(this).attr('data-mktoName')] = $(this).val();
});
// booleans need special care
$.each(mktoCheckboxFields,function(i){
if($(this).prop("checked")){
formDataObject[$(this).attr('data-mktoName')] = 'yes';
} else {
formDataObject[$(this).attr('data-mktoName')] = 0;
}
});
return formDataObject;
}
var $form = $("#contactForm"),
articleUrl = $form.find('#articleUrl').val(),
mktoBaseUrl = "https://cname.domain.com",
mktoMunchkinId = "123-ABC-456",
mktoFormId = 1234; // you can create a widget in Craft to dynamically set these
$('body').append("<form id='mktoForm_"+mktoFormId+"' style='display:none;visibility:hidden;opacity:0;'></form>");
MktoForms2.loadForm(mktoBaseUrl,mktoMunchkinId,mktoFormId,function(form){
form.onSuccess(function(values, followUpUrl) {
location.href = '/accounts/thanks?gatedArticle='+articleUrl;
return false;
});
});
$('#contactForm').submit(
function(e){
e.preventDefault();
var payload = getMktoFormData($form),
alerts = [],
re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
// do you validation 1 by 1 and on the front-end form
if(!re.test(String(payload.Email).toLowerCase())){
console.log('email invalid');
alerts.push(alerts.length+1 + ") The email address you entered is invalid");
}
if (!payload.checkbox) {
console.log('checkbox not checked');
alerts.push(alerts.length+1 + ") You must check the checkbox");
}
// make validation logic easier to manage by joining them at the end, if no alerts, submit
if (alerts.length) {
alert("Please note:\n" + alerts.join("\n") );
} else {
console.log('submit');
$form.find(':input').prop('readonly','readonly');
$('#submit-btn').hide();
$form.append('<p><img src="loading.gif"/> Just a moment</p>');
var mktoForm = MktoForms2.getForm(mktoFormId);
mktoForm.addHiddenFields(payload); // create marketo form fields on the fly using the object you generated. You can use .vals() but you'd have to keep your marketo form fields in sync with your front-end form
mktoForm.submit();
}
}
);‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
</script>
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
SanfordWhiteman
Level 10 - Community Moderator

Re: Form. On Success CallBack not firing on Iphone

If you're gonna overhaul it, might as well fix the badly broken regex.

At any rate... the original problem appears to be the race condition (which has since been changed). I submitted the form and got to the overridden Thank You.

Anthony_Zhu
Level 1

Re: Form. On Success CallBack not firing on Iphone

Thanks I'll do some quick fixes. Think all our marketo forms need an overhaul.  I did add back in the return false and it works everywhere but I've tried on my iphone specifically and it doesn't work there which is the main issue. Did you do it on an iphone by any chance? Also are there any flags or handlers when a form doesn't submit successfully. Could be helpful for debugging something like this. If I add a console log in the on success i never actually see it in my dev console on mobile even with the race condition error not sure what's causing the handler to not even fire.

EDIT: so seems like i needed to add a prevent default on the front end form button click event. The default cms registration system was submitting and before the on success handler could trigger which was why it went through to marketo but craft by default already took the user back to the homepage. Weird that this issue only surfaced on an iphone. ON that note though you guys had some good suggestions. Want to take some time to do some tech debt cleanup on all this that I inherited. 

Cheers