Formulário ajax simples usando javascript no jQuery

Estou trabalhando com um formulário para o qual o mark-up não posso mudar e não posso usar o jQuery. Atualmente, o formulário envia os resultados para uma nova janela. É possível alterar isso para um formulário de ajax para que os resultados sejam exibidos no envio em vez de alterar qualquer marcação? Puxando os resultados (mark-up) da página de resultados de volta para a página de formulário.

Aqui está o mark-up para o formulário.

 
What mobile phone is the best?

Qualquer dicas / tutorial é muito apreciado. 🙂

O seguinte é uma solução muito mais elegante da outra resposta, mais adequada para navegadores modernos.

Meu raciocínio é que, se você precisar de suporte para navegadores mais antigos, provavelmente já usará uma biblioteca como a jQuery e, portanto, tornará esta questão inútil.

 /** * Takes a form node and sends it over AJAX. * @param {HTMLFormElement} form - Form node to send * @param {function} callback - Function to handle onload. * this variable will be bound correctly. */ function ajaxPost (form, callback) { var url = form.action, xhr = new XMLHttpRequest(); //This is a bit tricky, [].fn.call(form.elements, ...) allows us to call .fn //on the form's elements, even though it's not an array. Effectively //Filtering all of the fields on the form var params = [].filter.call(form.elements, function(el) { //Allow only elements that don't have the 'checked' property //Or those who have it, and it's checked for them. return typeof(el.checked) === 'undefined' || el.checked; //Practically, filter out checkboxes/radios which aren't checekd. }) .filter(function(el) { return !!el.name; }) //Nameless elements die. .filter(function(el) { return el.disabled; }) //Disabled elements die. .map(function(el) { //Map each field into a name=value string, make sure to properly escape! return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value); }).join('&'); //Then join all the strings by & xhr.open("POST", url); // Changed from application/x-form-urlencoded to application/x-form-urlencoded xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); //.bind ensures that this inside of the function is the XHR object. xhr.onload = callback.bind(xhr); //All preperations are clear, send the request! xhr.send(params); } 

O acima é suportado em todos os principais navegadores e IE9 e acima.

Aqui está uma function bacana que eu uso para fazer exatamente o que você está tentando fazer:

HTML:

 
...

JS:

 function AJAXPost(myself) { var elem = myself.form.elements; var url = myself.form.action; var params = ""; var value; for (var i = 0; i < elem.length; i++) { if (elem[i].tagName == "SELECT") { value = elem[i].options[elem[i].selectedIndex].value; } else { value = elem[i].value; } params += elem[i].name + "=" + encodeURIComponent(value) + "&"; } if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else { // code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("POST",url,false); xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlhttp.setRequestHeader("Content-length", params.length); xmlhttp.setRequestHeader("Connection", "close"); xmlhttp.send(params); return xmlhttp.responseText; } 

Expandindo a resposta de Madara: Eu tive que fazer algumas mudanças para fazer isso funcionar no Chrome 47.0.2526.80 (não testado em mais nada). Espero que isso possa poupar alguém algum tempo.

Este fragment é uma modificação dessa resposta com as seguintes alterações:

  • filtro !el.disabled ,
  • verifique o tipo de input antes de excluir !checked
  • Tipo de pedido para x-www-form-urlencoded

Com o seguinte resultado:

 function ajaxSubmit(form, callback) { var xhr = new XMLHttpRequest(); var params = [].filter.call(form.elements, function (el) {return !(el.type in ['checkbox', 'radio']) || el.checked;}) .filter(function(el) { return !!el.name; }) //Nameless elements die. .filter(function(el) { return !el.disabled; }) //Disabled elements die. .map(function(el) { return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value); }).join('&'); //Then join all the strings by & xhr.open("POST", form.action); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.onload = callback.bind(xhr); xhr.send(params); }; 

Hoje em dia usando FormData é o método mais fácil. Você constrói com uma referência ao elemento Form e serializa tudo para você.

O MDN tem um exemplo disso aqui – aproximadamente:

 const form = document.querySelector("#debarcode-form"); form.addEventListener("submit", e => { e.preventDefault(); const fd = new FormData(form); const xhr = new XMLHttpRequest(); xhr.addEventListener("load", e => { console.log(e.target.responseText); }); xhr.addEventListener("error", e => { console.log(e); }); xhr.open("POST", form.action); xhr.send(fd); }); 

e se você quiser como um object (JSON):

 const obj = {}; [...fd.entries()].forEach(entry => obj[entry[0]] = entry[1]); 

A estratégia é serializar o formulário e enviar os dados usando XHR e, em seguida, fazer o que quiser com a resposta. Há um bom conjunto de utilitários e ajuda na Ajax Toolbox de Matt Krus e na Javascript Toolbox relacionada.

Se você está apenas serializando o formulário postado, então o seguinte fará o truque. Ele pode ser facilmente estendido para include outros tipos de controle de formulário:

 var serialiseForm = (function() { // Checkboxes that have already been dealt with var cbNames; // Return the value of a checkbox group if any are checked // Otherwise return empty string function getCheckboxValue(cb) { var buttons = cb.form[cb.name]; if (buttons.length) { for (var i=0, iLen=buttons.length; i 
 function ajaxSubmit(form, callback) { var xhr = new XMLHttpRequest(); var params = [].filter.call(form.elements, function (el) {return !(el.type in ['checkbox', 'radio']) || el.checked;}) .filter(function(el) { return !!el.name; }) //Nameless elements die. .filter(function(el) { return !el.disabled; }) //Disabled elements die. .map(function(el) { if (el.type=='checkbox') return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.checked); else return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value); }).join('&'); //Then join all the strings by & xhr.open("POST", form.action); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.onload = callback.bind(xhr); xhr.send(params); 

};

Eu apenas peguei a resposta da Coomie acima e fiz o trabalho para Radio / Checkboxes. Eu não posso acreditar como isso é simples e claro. Com algumas exceções, acabei de usar frameworks.

  var params = ""; var form_elements = form.elements; for (var i = 0; i < form_elements.length; i++) { switch(form_elements[i].type) { case "select-one": { value = form_elements[i].options[form_elements[i].selectedIndex].value; }break; case "checkbox": case "radio": { if (!form_elements[i].checked) { continue; // we don't want unchecked data } value = form_elements[i].value; }break; case "text" : { value = form_elements[i].value; }break; } params += encodeURIComponent(form_elements[i].name) + "=" + encodeURIComponent(value) + "&"; } var xhr = new XMLHttpRequest(); xhr.open('POST', "/api/some_url"); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { console.log("xhr.responseText"); } else { console.log("Error! Status: ", xhr.status, "Text:", xhr.responseText); } } }; console.log(params); xhr.send(params);