This is legacy code.
I'm working on a project where we're using iframes to simulate AJAX.
Basically, we're using the target attribute to submit the <form> in an iframe, resulting in the request not opening a new tab. Also, we echo a <script></script> in the response from the PHP, and the result is executed since it populates the iframe.
Here's an example of such <form> :
<form id="form_to_submit" method="POST" action="ajax/createUser" target="iframe_name">
<input type="text" name="input_to_send">
<button type="button" onclick="$('#form_to_submit').submit()">Submit With Onclick!</button>
</form>
Nowadays, not only this looks evil, but it has one (perhaps others) huge pitfall. If one request is made through this process, and the client goes somewhere, and then goes back in his browser history, it'll send the request again.
To fix this last problem, there are many solutions. I think the one I prefer the most is to use real AJAX instead of iframes. Now, in theory, I could change every single form in the source code to make it use AJAX, but I know I won't have 1 straight week of work just for this purpose.
I'm looking for a "quick" way to intercept these requests before they're sent to the iframe, and send them with AJAX instead.
So far, I tried to target <form> tags which have a target="iframe_name" and listen to the submit event to then send the request again with a same method/URL/data.
$('form[target=iframe_name]').on('submit', function (event) {
event.preventDefault(event);
var url = $(this).attr('action'),
datas = $(this).serialize();
$.post(url, datas).done(function (response) {
eval($(response).text());
});
});
But that only works if they're submitted through a real click on a submit button. I'd say 95% of these cases are submitted through onclick tags which will .submit() the forms, and in these cases, the submit event won't trigger it appears.
I'm stuck, any idea ?
Note : I'm tagging jquery only to let you know it's available to be used, even though the question is still relevant with any lib/framework of JS.
You can actually remove the onclick attributes just by doing a general jQuery action on document ready:
<script>
$(document).ready(function() {
var getButton = $('form').find('button');
getButton.prop('onclick',null);
// put listener script here for new form submit (using ajax)...
});
</script>
This piece of code just does a general lookup on the page for all forms, finds the buttons, then removes the onclick attribute. Once you do this the form should not submit anymore with that inline javascript.
I would suggest this be temporary as you incrementally change the forms over time to natively work using the jQuery listener (like the other 5% of forms you have created with no onclick).
Related
I have HTML two forms, one that submits data upon entry to a database using PHP, the other directs the user to a paypal payment page, my problem is that the user would have to submit both forms which of course I do not want them to have to do. Is there anyway to use one submit button for two forms?
(Javascript is welcome)
You should be able to do this with JavaScript:
<input type="button" value="Click Me!" onclick="submitForms()" />
If your forms have IDs:
submitForms = function(){
document.getElementById("form1").submit();
document.getElementById("form2").submit();
}
If your forms don't have IDs but have names:
submitForms = function(){
document.forms["form1"].submit();
document.forms["form2"].submit();
}
A form submission causes the page to navigate away to the action of the form. So, you cannot submit both forms in the traditional way. If you try to do so with JavaScript by calling form.submit() on each form in succession, each request will be aborted except for the last submission. So, you need to submit the first form asynchronously via JavaScript:
var f = document.forms.updateDB;
var postData = [];
for (var i = 0; i < f.elements.length; i++) {
postData.push(f.elements[i].name + "=" + f.elements[i].value);
}
var xhr = new XMLHttpRequest();
xhr.open("POST", "mypage.php", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(postData.join("&"));
document.forms.payPal.submit();
You can submit the first form using AJAX, otherwise the submission of one will prevent the other from being submitted.
In Chrome and IE9 (and I'm guessing all other browsers too) only the latter will generate a socket connect, the first one will be discarded. (The browser detects this as both requests are sent within one JavaScript "timeslice" in your code above, and discards all but the last request.)
If you instead have some event callback do the second submission (but before the reply is received), the socket of the first request will be cancelled. This is definitely nothing to recommend as the server in that case may well have handled your first request, but you will never know for sure.
I recommend you use/generate a single request which you can transact server-side.
The currently chosen best answer is too fuzzy to be reliable.
This feels to me like a fairly safe way to do it:
(Javascript: using jQuery to write it simpler)
$('#form1').submit(doubleSubmit);
function doubleSubmit(e1) {
e1.preventDefault();
e1.stopPropagation();
var post_form1 = $.post($(this).action, $(this).serialize());
post_form1.done(function(result) {
// would be nice to show some feedback about the first result here
$('#form2').submit();
});
};
Post the first form without changing page, wait for the process to complete. Then post the second form.
The second post will change the page, but you might want to have some similar code also for the second form, getting a second deferred object (post_form2?).
I didn't test the code, though.
If you have a regular submit button, you could add an onclick event to it that does the follow:
document.getElementById('otherForm').submit();
if you want to submit two forms with one button you need to do this:
1- use setTimeout()
2- allow show pop up
<script>
function myFunction() {
setTimeout(function(){ document.getElementById("form1").submit();}, 3000);
setTimeout(function(){ document.getElementById("form2").submit();}, 6000);
}
</script>
<form target="_blank" id="form1">
<input type="text">
<input type="submit">
</form>
<form target="_blank" id="form2">
<input type="text">
<input type="submit">
</form>
javascript doesn't submit two forms at the same time. we submit two forms with one button not at the same time but after secounds.
edit: when we use this code, browser doesn't allow pop up.
if you use this code for your software like me just set browser for show pop up but if you use it in designing site, browser is a barrier and code doesn't run.
Im trying to track when a user hits the submit button on a contact form.
The page's URL doesn't change, its static.
I can't track a differnt URL after submission, the only option would be to track when a user hits the submit button.
Do I need to edit my analytics account?
Where do I add the additional javascript?
UA is installed correctly (analytics.js)
I'm new to GA and javascript so please break it down for me.
Thanks
I can't track a differnt URL after submission, the only option would be to track when a user hits the submit button.
That is a bit of a non sequitur. Even when the Url does not change there is probably some stuff happening - before you send it there is probably some form validation, and there is some action behind the scene to send there form, like e.g an ajax call.
You could attach event tracking to a submit handler:
<form onSubmit="ga('send','event','category','action','label')">
<input type="text" id="text" name="text">
<input type="submit">
</form>
However this would just tell you that somebody hit the submit button, not if they filled in the form correctly or if the form actually has been sent.
Now I enter speculation land, because I do not know how your form actually works - maybe you can show us an url or give more information.
But maybe you have a validation function that is called on the submit action of the form to see if the form is filled in correctly. In that case it would be advisable to do the tracking in the validation function (horribly simplified example, not production code):
<form onSubmit="validate()"><input type="text" id="text" name="text"><input type="submit"></form>
<script>
function validate() {
var test = document.querySelector('#text').value
if(test = "") {
ga('send','event','Form','Submit','Submitted, but not filled in');
return false;
}
ga('send','event','Form','Submit','Submitted with correct values');
return true;
}
</script>
That's a tad better, at least it tracks the difference between correct submissions and invalid submissions.
Even more speculation: If your form is sent without page reloads it uses probably an ajax call, and there is a huge probability that is uses jQuery (I say that because a) it really is probable and b) it's easier to construct an example in jQuery. The same can be achivied with other libraries or in native JS, but the example will produce an error if you do not use jQuery).
jQuery has a thing called "global ajax handlers". "Global" means they are not callbacks for a specific action, they hook into jQuerys ajax "mechanism" whenever a call to an ajax function is made. The following might work if you have only one aja event per page (else you need logic to distinguish the different ajax event e.g, by checking the url they are being send to), and allows you to track if the ajax call has returned successfully, like when your form data has been send to the server and the request return a 2xx status code:
$(document).ajaxSuccess(function() {
ga('send','event','Form','Submit','Yeah, form data sent to the server');
});
However this does not tell you if the data has been processed correctly. For that you need to make the server emit a success message and check the response:
$( document ).ajaxSuccess(function( event, xhr, settings ) {
if ( settings.url == "formprocessor.php" ) {
if(xhr.responseText.indexOf("success") > -1) {
ga('send','event','Form','Response Received','Form data processed ');
} else {
ga('send','event','Form','Response Received','Form data NOT processed ');
}
}
});
The global ajax event handler is attached to the document - you can put that anywhere on your page, it will do nothing unless an ajax event was called.
Again, this is not production code. Do not try to copy and paste.
This was certainly a bit much if you are new to this, but it should at least help you to improve the question and to see what kind of things are possible. If you can share an Url to your form I can possibly improve the answer.
Been searching around on this for a while and can't come up with any documentation to outline what i want to achieve.
I'm using wordpress and the Contact Form 7 plugin, all is working perfectly, what i want to achieve is to run some particular javascript upon form submit, i know we can use "on_sent_ok:" in the additional settings, but this only performs if the form is actually submitted.
What i'd like to do is to do some other javascript when the form doesn't submit ok, which throws the user back to the section which didn't validate.
I can use the following code to run after 1.7s of the form submit being clicked, however it's a bit sloppy as if the user was running with a slow connection, there's potential this could run before the form is submitted properly.
$('.wpcf7-submit').click(function() {
setTimeout(function() {
if ($('.fs1 input,.fs1 textarea').hasClass('wpcf7-not-valid')) {
$('.pop-up-form').removeClass('pustep2').removeClass('pu-closing');
$('.form-step').hide();
$('.fs1').show();
}
if ($('.fs2 *').hasClass('wpcf7-not-valid')) {
alert('error on page 2 - take user back to the area with issues')
}
}, 1700);
});
Is there any particular function or hook i can use to run JS when the form AJAX has completed?
Thanks!
In version 3.3 new jQuery custom event triggers were introduced:
New: Introduce 5 new jQuery custom event triggers
wpcf7:invalid
wpcf7:spam
wpcf7:mailsent
wpcf7:mailfailed
wpcf7:submit
You can use wpcf7:invalid like the example below:
$(".wpcf7").on('wpcf7:invalid', function(event){
// Your code here
});
Given the variety of responses on this topic the plugin developer seems to change their mind about how this should work every 5 minutes. Currently (Q1 2017) this is the working method:
document.addEventListener( 'wpcf7mailsent', function( event ) {
alert( "Fire!" );
}, false );
And the valid events are:
wpcf7invalid — Fires when an Ajax form submission has completed
successfully, but mail hasn’t been sent because there are fields with
invalid input.
wpcf7spam — Fires when an Ajax form submission has
completed successfully, but mail hasn’t been sent because a possible
spam activity has been detected.
wpcf7mailsent — Fires when an Ajax
form submission has completed successfully, and mail has been sent.
wpcf7mailfailed — Fires when an Ajax form submission has completed
successfully, but it has failed in sending mail.
wpcf7submit — Fires
when an Ajax form submission has completed successfully, regardless
of other incidents.
Sauce: https://contactform7.com/dom-events/
Sometimes it may not work, as Martin Klasson pointed out, only 'submit' event works, most probable because it's triggered by a form and bubbles up to the selected object. Also as I can understand, now events have other names, like "invalid.wpcf7", "mailsent.wpcf7", etc. In short, this should work:
jQuery('.wpcf7').on('invalid.wpcf7', function(e) {
// your code here
});
More detailed explanation here: How to add additional settings on error in Contact form 7?
This code works since 5.8.x version:
$('.wpcf7').on('wpcf7invalid wpcf7spam wpcf7mailsent wpcf7mailfailed', function () {
// your code here
});
I had quite a go at this, and I found that when only the Submit event works, it means that there is a js problem / conflict in your theme.
If it's a custom theme you built, make sure jQuery and jQuery migrate are both loaded, in this order, and that the Contact form 7 js is also loaded in the footer.
Make sure you have wp_head, and wp_footer in your php templates.
For DOM events to work, your form must be in Ajax mode. If the page reloads upon submission, forget about DOM events. If you have the form ID showing up in the URL, same thing. My form was initially not in Ajax mode because the Contact Form JS was not loaded, and jQuery Migrate either.
The form must behave exactly like shown on this page for the DOM events to be fired properly. Once you have that, it should be working.
I've tested this with jQuery 3.3.1 and Migrate 3.0.1 and the following event listener worked:
document.addEventListener( 'wpcf7mailsent', function( event ) {
console.log('mail sent OK');
// Stuff
}, false );
To check if your theme is the culprit, test your form using Wordpress' default theme, if it works, you know the issue is on your end and not so much in the dev's doc!
I tried to implement the dom event behavior in wordpress contact form 7 plugin as described here, but after trying numerous methods which are given as fixes in different forums I implemented a method of my own.
I m describing the method here below. The method involves some steps which are listed below:
Creating the contact form
Scripting for the contact form to capture event triggers and form data
Loading the script
1. Creating the contact form
<label> Your name
[text* cform7-name id:cform7-name autocomplete:name] </label>
<label> Your Number
[tel* cform7-contact id:cform7-contact] </label>
<label> Course You are interested (Press Ctrl + Select to select Mutiple)
[select* cform7-courses id:cform7-courses multiple "JAVA" "Python" "C#" "Others"] </label>
<label> Your message (optional)
[textarea cform7-submit id:cform7-message] </label>
[submit id:cform7Submit "Submit"]
Above is a sample script with ids so that we can easily retreive those elements from DOM tree using JS. [You can modify the field ids as your need]
2. Scripting for the contact form to capture event triggers and form data
document.addEventListener('DOMContentLoaded', function() {
var frmButton = document.getElementById('cform7Submit');
frmButton.addEventListener( 'click', function( event ) {
var data = {
name: document.getElementById('cform7-name').value,
contact: document.getElementById('cform7-contact').value,
courses: document.getElementById('cform7-courses').value,
comment: document.getElementById('cform7-message').value
};
event.preventDefault();
console.log('Event Data ', event);
console.log('Data ', data);
}, false );
}, false);
Save the above script in wordpress deployment directoty. In my case I placed the script in the root deployment directory itself(<worpress-root-directory>) and saved the file as cform7.js.
Ex: /var/www/wordpress-site/cform7.js
After finishing this we need to load the script.
3. Loading the script
function cform7_script() {
wp_enqueue_script( 'cform7-js', '/cform7.js');
}
add_action('wp_enqueue_scripts', 'cform7_script');
Place the above code in the <worpress-root-directory>/wp-includes/functions.php file
That's done! On clicking the form submit button(cform7-submit) you must see the data logged in the console.
My intention is to submit data from a form to the server and not have the page reload. It does not even need to display updated data. I am developing using Firefox and I'm looking at two paths to get what I want:
I've discovered that if I place a button inside a form, the form will be submitted with the name of the page containing it as a "GET" request. The form tag in this case has not method attribute and the action tag is empty. I can input the function that I want into the action attribute, and the browser will apply the rest of the form fields to the request. I find the formulation of the form convenient, but the browser goes ahead and replaces the page with whatever the response is from the server, taking me away from the original page.
Taking the button out of the form and wiring it exclusivly to a javascript function allows me to register a function to the onreadystatechange event. This has the effect of running a function rather than reloading the page when the server responds. The down side of this seems to be that it is necessary for the function to formulate the "GET" request on it's own.
It seems to me that there should be a way for the javascript function to tell the form to submit using it's own devices, and then be ready to process the the response. Being new at this I am unfamiliar with what "Best Practice" would be for this requirement.
You can just use a <button> to post your details.
function ajaxPage(postPage, paramList) {
xmlhttp.open("POST",postPage,false);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(paramList);
return xmlhttp.responseText;
}
In this case your postPage is a address to a piece of relevant code and paramList is a list of & delimited name value pairs.
Kind regards,
Westie
You can add an "onsubmit" function to your form.
It is important to return false or call event.preventDefault() in that function in order to prevent the browser from posting the form.
HTML:
<form onsubmit="javascript:myFunction()">
...
</form>
Script:
function myFunction(evt) {
// do your ajax call...
evt.preventDefault();
}
Not really need the "Submit" you can search for autocomplete suggestions implementation with ajax:
Onfocus On..Even you will send all form data to server side, you you want autocomplete with server side response than it a pus and you can explain for the user for that you need.
This link may help you a bit.
This is what I've Ended up with, going forward with pathway number 2 as described in the original question, The button invoking the script is outside the form, so there is no submit event. Data from the form is harvested by the script as described in this answer to a related question:
https://stackoverflow.com/a/589100/747544
From there, the "get" request is formulated by the script
XMLHttpRequest.open("GET", "/myCommand?"+queryString ,true);
XMLHttpRequest.send(null);
The form is in effect "scanned" by the script without ever having been submitted, so there is no need to prevent the default behavior with an onSubmit event returning false. or preventDefault().
Can I pass post variables and reload a page on clicking an hyperlink?
To be clear I have something like this.
Click
If javascript is enabled,
I think I can use "event.preventDefault()" to suppress passing as GET variable.
So now onclick, name should be passed as post variable instead of get.
If javascript is disabled,
Then the above should work.
You could do it, by creating a new form element, pointing it at the href and calling .submit() on it.
<a class="postlink" href="test.php?name=test">Click</a>
<script type="text/javascript">
$('.postlink').click(function() {
var form= document.createElement('form');
form.method= 'post';
form.action= this.protocol+'//'+this.hostname+this.pathname;
$.each(this.search.slice(1).split(/[&;]/g), function() {
var ix= this.indexOf('=');
if (ix===-1) return;
var input= document.createElement('input');
input.type= 'hidden';
input.name= decodeURIComponent(this.slice(0, ix));
input.value= decodeURIComponent(this.slice(ix+1));
form.appendChild(input);
});
document.body.appendChild(form);
form.submit();
return false;
});
</script>
Or you could just do an AJAX request instead and reload() the page afterwards if you prefer.
However, I'm not sure why you'd want to do this. What use is a link that's usually POSTed, except when it's not? (Not just when JS is disabled/unavailable or when it's a search engine, but also when the user middle-clicks the link or tries to right-click-bookmark it or whatever.)
If all you want is something that behaves like a button to submit a POST form, better to actually use a real form and submit button, and then use CSS to restyle it to look like a link if that's what you want it to look like.
Very good hint....
I was first trying to send the form data via an Ajax Post call and reloading the page afterwards, but it was not working properly:
var biq_select_val = jQuery('#biq_search_select').val();
jQuery.post(window.location.href,
{ biq_amazon_item_list_search: biq_select_val},
function() {window.location.reload();}
);
Now I am using just a:
jQuery('#biq_amazon_item_list_search_form').submit();
and it is working fine.
I have some 10 links on a page. When user clicks on those links ajax-reload must take place.
To be clear I have something like this.
one
Two
If javascript is enabled,
Onclick, ajax load must take place.
If javascript is disabled, Then the above should work.
Basically I am using name to limit some values of my search page.