J'essaie de diriger un navigateur vers une autre page. Si je voulais une demande GET, je pourrais dire
document.location.href = 'http://example.com/q=a';
Mais la ressource à laquelle j'essaie d'accéder ne répondra pas correctement à moins d'utiliser une requête POST. Si cela n’était pas généré dynamiquement, je pourrais utiliser le code HTML
<form action="http://example.com/" method="POST">
<input type="hidden" name="q" value="a">
</form>
Ensuite, je voudrais simplement soumettre le formulaire à partir du DOM.
Mais vraiment, je voudrais un code JavaScript qui me permet de dire
post_to_url('http://example.com/', {'q':'a'});
Quelle est la meilleure implémentation multi-navigateurs?
Modifier
Je suis désolé je n'ai pas été clair. J'ai besoin d'une solution qui modifie l'emplacement du navigateur, tout comme pour l'envoi d'un formulaire. Si cela est possible avec XMLHttpRequest , ce n'est pas évident. Et cela ne devrait pas être asynchrone, ni utiliser XML, donc Ajax n'est pas la solution.
/**
* sends a request to the specified url from a form. this will change the window location.
* @param {string} path the path to send the post request to
* @param {object} params the paramiters to add to the url
* @param {string} [method=post] the method to use on the form
*/
function post(path, params, method) {
method = method || "post"; // Set method to post by default if not specified.
// The rest of this code assumes you are not using a library.
// It can be made less wordy if you use one.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var key in params) {
if(params.hasOwnProperty(key)) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
Exemple:
post('/contact/', {name: 'Johnny Bravo'});
EDIT: Comme cela a été tellement voté, j'imagine que les gens vont beaucoup copier-coller. J'ai donc ajouté le contrôle hasOwnProperty
pour corriger les bugs involontaires.
Ce serait une version de la réponse sélectionnée en utilisant jQuery .
// Post to the provided URL with the specified parameters.
function post(path, parameters) {
var form = $('<form></form>');
form.attr("method", "post");
form.attr("action", path);
$.each(parameters, function(key, value) {
var field = $('<input></input>');
field.attr("type", "hidden");
field.attr("name", key);
field.attr("value", value);
form.append(field);
});
// The form needs to be a part of the document in
// order for us to be able to submit it.
$(document.body).append(form);
form.submit();
}
Une implémentation simple et rapide de la réponse @Aaron:
document.body.innerHTML += '<form id="dynForm" action="http://example.com/" method="post"><input type="hidden" name="q" value="a"></form>';
document.getElementById("dynForm").submit();
Bien sûr, vous devriez plutôt utiliser un framework JavaScript tel que Prototype ou jQuery ...
Utilisation de la fonction createElement
fournie dans this answer , nécessaire en raison de la fragmentation de IE avec l'attribut name sur les éléments créés normalement avec document.createElement
:
function postToURL(url, values) {
values = values || {};
var form = createElement("form", {action: url,
method: "POST",
style: "display: none"});
for (var property in values) {
if (values.hasOwnProperty(property)) {
var value = values[property];
if (value instanceof Array) {
for (var i = 0, l = value.length; i < l; i++) {
form.appendChild(createElement("input", {type: "hidden",
name: property,
value: value[i]}));
}
}
else {
form.appendChild(createElement("input", {type: "hidden",
name: property,
value: value}));
}
}
}
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
La réponse de Rakesh Pai est incroyable, mais un problème se produit pour moi (dans Safari ) lorsque j'essaie de publier un formulaire avec un champ appelé submit
. Par exemple, post_to_url("http://google.com/",{ submit: "submit" } );
. J'ai légèrement modifié la fonction pour contourner cette collision spatiale variable.
function post_to_url(path, params, method) {
method = method || "post";
var form = document.createElement("form");
//Move the submit function to another variable
//so that it doesn't get overwritten.
form._submit_function_ = form.submit;
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var key in params) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
document.body.appendChild(form);
form._submit_function_(); //Call the renamed function.
}
post_to_url("http://google.com/", { submit: "submit" } ); //Works!
Non, vous ne pouvez pas avoir la demande de publication JavaScript comme un formulaire à envoyer.
Ce que vous pouvez avoir est un formulaire en HTML, puis soumettez-le avec JavaScript. (comme expliqué à plusieurs reprises sur cette page)
Vous pouvez créer le code HTML vous-même, vous n'avez pas besoin de JavaScript pour écrire le code HTML. Ce serait idiot si les gens le suggéraient.
<form id="ninja" action="http://example.com/" method="POST">
<input id="donaldduck" type="hidden" name="q" value="a">
</form>
Votre fonction configurerait simplement le formulaire comme vous le souhaitez.
function postToURL(a,b,c){
document.getElementById("ninja").action = a;
document.getElementById("donaldduck").name = b;
document.getElementById("donaldduck").value = c;
document.getElementById("ninja").submit();
}
Ensuite, utilisez-le comme.
postToURL("http://example.com/","q","a");
Mais je voudrais juste laisser de côté la fonction et juste faire.
document.getElementById('donaldduck').value = "a";
document.getElementById("ninja").submit();
Enfin, la décision de style va dans le fichier ccs.
.ninja{
display:none;
}
Personnellement, je pense que les formulaires doivent être nommés, mais ce n’est pas important pour le moment.
Si vous avez Prototype installé, vous pouvez resserrer le code pour générer et envoyer le formulaire masqué comme suit:
var form = new Element('form',
{method: 'post', action: 'http://example.com/'});
form.insert(new Element('input',
{name: 'q', value: 'a', type: 'hidden'}));
$(document.body).insert(form);
form.submit();
c'est la réponse de rakesh, mais avec le support des tableaux (ce qui est assez courant dans les formulaires):
javascript simple:
function post_to_url(path, params, method) {
method = method || "post"; // Set method to post by default, if not specified.
// The rest of this code assumes you are not using a library.
// It can be made less wordy if you use one.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
var addField = function( key, value ){
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", value );
form.appendChild(hiddenField);
};
for(var key in params) {
if(params.hasOwnProperty(key)) {
if( params[key] instanceof Array ){
for(var i = 0; i < params[key].length; i++){
addField( key, params[key][i] )
}
}
else{
addField( key, params[key] );
}
}
}
document.body.appendChild(form);
form.submit();
}
oh, et voici la version jquery: (code légèrement différent, mais se résume à la même chose)
function post_to_url(path, params, method) {
method = method || "post"; // Set method to post by default, if not specified.
var form = $(document.createElement( "form" ))
.attr( {"method": method, "action": path} );
$.each( params, function(key,value){
$.each( value instanceof Array? value : [value], function(i,val){
$(document.createElement("input"))
.attr({ "type": "hidden", "name": key, "value": val })
.appendTo( form );
});
} );
form.appendTo( document.body ).submit();
}
Si seulement j'avais lu tous les autres posts, je n'ai donc pas perdu de temps à créer ceci grâce à la réponse de Rakesh Pai. Voici une solution récursive qui fonctionne avec les tableaux et les objets. Aucune dépendance sur jQuery.
Ajout d'un segment pour gérer les cas où l'ensemble du formulaire doit être soumis comme un tableau. (c'est-à-dire s'il n'y a pas d'objet wrapper autour d'une liste d'éléments)
/**
* Posts javascript data to a url using form.submit().
* Note: Handles json and arrays.
* @param {string} path - url where the data should be sent.
* @param {string} data - data as javascript object (JSON).
* @param {object} options -- optional attributes
* {
* {string} method: get/post/put/etc,
* {string} arrayName: name to post arraylike data. Only necessary when root data object is an array.
* }
* @example postToUrl('/UpdateUser', {Order {Id: 1, FirstName: 'Sally'}});
*/
function postToUrl(path, data, options) {
if (options === undefined) {
options = {};
}
var method = options.method || "post"; // Set method to post by default if not specified.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
function constructElements(item, parentString) {
for (var key in item) {
if (item.hasOwnProperty(key) && item[key] != null) {
if (Object.prototype.toString.call(item[key]) === '[object Array]') {
for (var i = 0; i < item[key].length; i++) {
constructElements(item[key][i], parentString + key + "[" + i + "].");
}
} else if (Object.prototype.toString.call(item[key]) === '[object Object]') {
constructElements(item[key], parentString + key + ".");
} else {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", parentString + key);
hiddenField.setAttribute("value", item[key]);
form.appendChild(hiddenField);
}
}
}
}
//if the parent 'data' object is an array we need to treat it a little differently
if (Object.prototype.toString.call(data) === '[object Array]') {
if (options.arrayName === undefined) console.warn("Posting array-type to url will doubtfully work without an arrayName defined in options.");
//loop through each array item at the parent level
for (var i = 0; i < data.length; i++) {
constructElements(data[i], (options.arrayName || "") + "[" + i + "].");
}
} else {
//otherwise treat it normally
constructElements(data, "");
}
document.body.appendChild(form);
form.submit();
};
Une solution consiste à générer le formulaire et à le soumettre. Une mise en œuvre est
function post_to_url(url, params) {
var form = document.createElement('form');
form.action = url;
form.method = 'POST';
for (var i in params) {
if (params.hasOwnProperty(i)) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = i;
input.value = params[i];
form.appendChild(input);
}
}
form.submit();
}
Je peux donc implémenter un bookmarklet de raccourcissement d'URL avec
javascript:post_to_url('http://is.Gd/create.php', {'URL': location.href});
Trois options ici.
Réponse JavaScript standard: Utilisez un cadre! La plupart des frameworks Ajax vous auront résumé un moyen simple de créer un XMLHTTPRequest POST.
Faites la demande XMLHTTPRequest vous-même, en passant post dans la méthode open au lieu de get. (Plus d'informations dans Utilisation de la méthode POST dans XMLHTTPRequest (Ajax).)
Via JavaScript, créez un formulaire de manière dynamique, ajoutez une action, ajoutez vos entrées et soumettez-le.
Voici comment je l'ai écrit en utilisant jQuery. Testé dans Firefox et Internet Explorer.
function postToUrl(url, params, newWindow) {
var form = $('<form>');
form.attr('action', url);
form.attr('method', 'POST');
if(newWindow){ form.attr('target', '_blank');
}
var addParam = function(paramName, paramValue) {
var input = $('<input type="hidden">');
input.attr({ 'id': paramName,
'name': paramName,
'value': paramValue });
form.append(input);
};
// Params is an Array.
if(params instanceof Array){
for(var i=0; i<params.length; i++) {
addParam(i, params[i]);
}
}
// Params is an Associative array or Object.
if(params instanceof Object) {
for(var key in params){
addParam(key, params[key]);
}
}
// Submit the form, then remove it from the page
form.appendTo(document.body);
form.submit();
form.remove();
}
Je suivrais la route de l'Ajax comme d'autres l'avaient suggéré avec quelque chose comme:
var xmlHttpReq = false;
var self = this;
// Mozilla/Safari
if (window.XMLHttpRequest) {
self.xmlHttpReq = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
self.xmlHttpReq.open("POST", "YourPageHere.asp", true);
self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
self.xmlHttpReq.setRequestHeader("Content-length", QueryString.length);
self.xmlHttpReq.send("?YourQueryString=Value");
Le moyen le plus simple consiste à utiliser Ajax Post Request:
$.ajax({
type: "POST",
url: 'http://www.myrestserver.com/api',
data: data,
success: success,
dataType: dataType
});
où:
Ensuite, dans le gestionnaire de succès, redirigez le navigateur avec quelque chose comme window.location.
La bibliothèque Prototype comprend un objet Hashtable, avec une méthode ".toQueryString ()", qui vous permet de transformer facilement un objet/une structure JavaScript en une chaîne de style de chaîne de requête. Étant donné que la publication requiert que le "corps" de la demande soit une chaîne formatée avec une chaîne de requête, cela permet à votre requête Ajax de fonctionner correctement en tant que publication. Voici un exemple utilisant Prototype:
$req = new Ajax.Request("http://foo.com/bar.php",{
method: 'post',
parameters: $H({
name: 'Diodeus',
question: 'JavaScript posts a request like a form request',
...
}).toQueryString();
};
Cela fonctionne parfaitement dans mon cas:
document.getElementById("form1").submit();
Vous pouvez l'utiliser comme:
function formSubmit() {
document.getElementById("frmUserList").submit();
}
En utilisant cela, vous pouvez poster toutes les valeurs des entrées.
Ma solution va coder des objets profondément imbriqués, contrairement à la solution actuellement acceptée par @RakeshPai.
Il utilise la bibliothèque npm 'qs' et sa fonction stringify pour convertir des objets imbriqués en paramètres.
Ce code fonctionne bien avec un back-end Rails, bien que vous devriez pouvoir le modifier pour fonctionner avec tout le back-end dont vous avez besoin en modifiant les options passées à stringify. Rails nécessite que arrayFormat soit défini sur "parenthèses".
import qs from "qs"
function normalPost(url, params) {
var form = document.createElement("form");
form.setAttribute("method", "POST");
form.setAttribute("action", url);
const keyValues = qs
.stringify(params, { arrayFormat: "brackets", encode: false })
.split("&")
.map(field => field.split("="));
keyValues.forEach(field => {
var key = field[0];
var value = field[1];
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", value);
form.appendChild(hiddenField);
});
document.body.appendChild(form);
form.submit();
}
Exemple:
normalPost("/people/new", {
people: [
{
name: "Chris",
address: "My address",
dogs: ["Jordan", "Elephant Man", "Chicken Face"],
information: { age: 10, height: "3 meters" }
},
{
name: "Andrew",
address: "Underworld",
dogs: ["Doug", "Elf", "Orange"]
},
{
name: "Julian",
address: "In a hole",
dogs: ["Please", "Help"]
}
]
});
Produit ces paramètres Rails:
{"authenticity_token"=>"...",
"people"=>
[{"name"=>"Chris", "address"=>"My address", "dogs"=>["Jordan", "Elephant Man", "Chicken Face"], "information"=>{"age"=>"10", "height"=>"3 meters"}},
{"name"=>"Andrew", "address"=>"Underworld", "dogs"=>["Doug", "Elf", "Orange"]},
{"name"=>"Julian", "address"=>"In a hole", "dogs"=>["Please", "Help"]}]}
Encore une autre solution récursive, car certaines d’autres semblent cassées (je ne les ai pas toutes testées). Celui-ci dépend de lodash 3.x et de ES6 (jQuery non requis):
function createHiddenInput(name, value) {
let input = document.createElement('input');
input.setAttribute('type','hidden');
input.setAttribute('name',name);
input.setAttribute('value',value);
return input;
}
function appendInput(form, name, value) {
if(_.isArray(value)) {
_.each(value, (v,i) => {
appendInput(form, `${name}[${i}]`, v);
});
} else if(_.isObject(value)) {
_.forOwn(value, (v,p) => {
appendInput(form, `${name}[${p}]`, v);
});
} else {
form.appendChild(createHiddenInput(name, value));
}
}
function postToUrl(url, data) {
let form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', url);
_.forOwn(data, (value, name) => {
appendInput(form, name, value);
});
form.submit();
}
Vous pouvez ajouter dynamiquement le formulaire à l'aide de DHTML, puis le soumettre.
Vous pouvez utiliser une bibliothèque comme jQuery et sa méthode $ .post .
J'utilise le document.forms Java et le boucle pour obtenir tous les éléments du formulaire, puis l'envoyer via xhttp. Voici donc ma solution pour javascript/ajax submit (avec tout le code HTML inclus à titre d'exemple):
<!DOCTYPE html>
<html>
<body>
<form>
First name: <input type="text" name="fname" value="Donald"><br>
Last name: <input type="text" name="lname" value="Duck"><br>
Addr1: <input type="text" name="add" value="123 Pond Dr"><br>
City: <input type="text" name="city" value="Duckopolis"><br>
</form>
<button onclick="smc()">Submit</button>
<script>
function smc() {
var http = new XMLHttpRequest();
var url = "yourphpfile.php";
var x = document.forms[0];
var xstr = "";
var ta ="";
var tb ="";
var i;
for (i = 0; i < x.length; i++) {
if (i==0){ta = x.elements[i].name+"="+ x.elements[i].value;}else{
tb = tb+"&"+ x.elements[i].name +"=" + x.elements[i].value;
} }
xstr = ta+tb;
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
// do whatever you want to with the html output response here
}
}
http.send(xstr);
}
</script>
</body>
</html>
Ceci est basé sur le code de beauSD utilisant jQuery. Il est amélioré pour fonctionner de manière récursive sur les objets.
function post(url, params, urlEncoded, newWindow) {
var form = $('<form />').hide();
form.attr('action', url)
.attr('method', 'POST')
.attr('enctype', urlEncoded ? 'application/x-www-form-urlencoded' : 'multipart/form-data');
if(newWindow) form.attr('target', '_blank');
function addParam(name, value, parent) {
var fullname = (parent.length > 0 ? (parent + '[' + name + ']') : name);
if(value instanceof Object) {
for(var i in value) {
addParam(i, value[i], fullname);
}
}
else $('<input type="hidden" />').attr({name: fullname, value: value}).appendTo(form);
};
addParam('', params, '');
$('body').append(form);
form.submit();
}
C'est comme l'option 2 d'Alan (ci-dessus). Comment instancier le httpobj est laissé comme un exercice.
httpobj.open("POST", url, true);
httpobj.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
httpobj.onreadystatechange=handler;
httpobj.send(post);
FormObject est une option. Mais FormObject n'est plus supporté par la plupart des navigateurs.
La méthode que j'utilise pour envoyer et diriger automatiquement un utilisateur vers une autre page consiste à écrire un formulaire masqué, puis à le soumettre automatiquement. Soyez assuré que la forme masquée ne prend absolument aucun espace sur la page Web. Le code ressemblerait à ceci:
<form name="form1" method="post" action="somepage.php">
<input name="fielda" type="text" id="fielda" type="hidden">
<textarea name="fieldb" id="fieldb" cols="" rows="" style="display:none"></textarea>
</form>
document.getElementById('fielda').value="some text for field a";
document.getElementById('fieldb').innerHTML="some text for multiline fieldb";
form1.submit();
Application de soumission automatique
Une application de soumission automatique dirigerait les valeurs de formulaire que l'utilisateur inscrirait automatiquement sur l'autre page pour revenir à cette page. Une telle application serait comme ceci:
fieldapost=<?php echo $_post['fielda'];>
if (fieldapost !="") {
document.write("<form name='form1' method='post' action='previouspage.php'>
<input name='fielda' type='text' id='fielda' type='hidden'>
</form>");
document.getElementById('fielda').value=fieldapost;
form1.submit();
}
Voici comment je le fais.
function redirectWithPost(url, data){
var form = document.createElement('form');
form.method = 'POST';
form.action = url;
for(var key in data){
var input = document.createElement('input');
input.name = key;
input.value = data[key];
input.type = 'hidden';
form.appendChild(input)
}
document.body.appendChild(form);
form.submit();
}
plug-in jQuery pour la redirection avec POST ou GET:
https://github.com/mgalante/jquery.redirect/blob/master/jquery.redirect.js
Pour tester, incluez le fichier .js ci-dessus ou copiez/collez la classe dans votre code, puis utilisez le code ici, en remplaçant "args" par vos noms de variable et "valeurs" par les valeurs de ces variables:
$.redirect('demo.php', {'arg1': 'value1', 'arg2': 'value2'});
Vous pouvez utiliser la méthode de déclenchement jQuery pour soumettre le formulaire, comme si vous appuyez sur un bouton,
$('form').trigger('submit')
il soumettra sur le navigateur.