ugrás a tartalomhoz

AJAX form post

Jazoja · 2012. Jan. 28. (Szo), 22.55
Van egy HTML FORM-om, amit JS/XMLHttpRequest segítségével szeretném POST-olni.
A FORM nagy mennyiségű dinamikusan generált INPUT CHECKBOX elemet tartalmaz, a felhasználó által kiválasztottak értékeit (value/name?) szeretném elküldeni.

A SEND függvény az alábbi hibával leáll: (Firefox9+FireBug)

Component returned failure code: 0x80460001 (NS_ERROR_CANNOT_CONVERT_DATA)
XMLHttpRequestObjectForSavingCategories.send(document.forms["categories_form"]);
A hibával kapcsolatban nem sok infót találtam, de úgy látom függvény STRING-et várna.

Van valami egyszerű módja, hogy a CHECKBOX-ok értékét el tudjam küldeni? (pl. beépített konvertáló függvény)
Vagy jobb ha nekiállok ismerkedni valamely JS keretrendszerrel? (pl. jQuery és társai)
 
1

Ha a kódot mutatnád ami a

Karvaly84 · 2012. Jan. 28. (Szo), 23.18
Ha a kódot mutatnád ami a hibát dobja az többet elárulna, ezek a NS_ERROR meg hasonlók semmit nem árulnak el, csak azt, hogy egy DOM függvényben van a hiba.

Ha a XMLHttpRequestObjectForSavingCategories egy XMLHttpRequest példánya és "POST" kérést akarsz küldeni, akkor nem a form-ot kell neki átadni, mert az egy "object" típus, és a form "submit" eseményéhez kötnék egy eseményfigyelőt, amiben a checkbox-ok értékeit escape-elve név érték párokban tenném a send metódus paraméterébe, és letiltanám a form elküldését.
2

a kód

Jazoja · 2012. Jan. 29. (V), 01.44
Kicsit rövidítettem a nevén. A hibát a .send()-es sorban dobja.

var XHRSaveCats = new XMLHttpRequest();
function saveCategories()
{
	var dataSource = "<?php echo site_url()?>/catUpdate.php";
	if(XHRSaveCats) 
	{
		XHRSaveCats.open("POST", dataSource,true);
		XHRSaveCats.setRequestHeader('Content-Type', 'multipart/form-data');
		XHRSaveCats.send(document.forms["categories_form"]);
		XHRSaveCats.onreadystatechange = function()
		{
			if (XHRSaveCats.readyState == 4)
			{
				if (XHRSaveCats.status == 200) 
				{
					var ret = XHRSaveCats.responseText;
					alert(ret);
				}
				else
				{
					alert("Error code " + XHRSaveCats.status);
				}
			}
		}

		XMLHttpRequestObjectForSaving.send(null);
	}
}
Így néz ki a generált HTML FORM (egy része) az INPUT CHECKBOX-okkal:

<form action="http://localhost/catUpdate.php" method="post" name="categories_form">
 <div id="buttons">
  <button id="SaveCats" title="Kategóriák mentése szerverre" type="button" onclick="saveCategories();">Kategóriák mentése szerverre</button>
  </div>
  <div id="div-0">
   <label>Főkategóriák:</label>
   <input id="cat-5" type="checkbox" name="Ajándék" value="post" onchange="openCloseSubCategory(5);" checked="">Ajándék
   <input id="cat-124" type="checkbox" name="Aktuális" value="post" onchange="openCloseSubCategory(124);">Aktuális
   <input id="cat-1" type="checkbox" name="Egyéb" value="post" onchange="openCloseSubCategory(1);" checked="">Egyéb
   <input id="cat-25" type="checkbox" name="Nincs kategorizálva" value="post" onchange="openCloseSubCategory(25);">Nincs kategorizálva
   <input id="cat-131" type="checkbox" name="Összes" value="post" onchange="openCloseSubCategory(131);">Összes
 </div>
</form>
3

Na hát ez számomra több

Karvaly84 · 2012. Jan. 29. (V), 08.45
Na hát ez számomra több helyen is vérzik!

1. var dataSource = "<?php echo site_url()?>/catUpdate.php";
Ide valami épkézláb URL kell, nem pedig PHP echo mert azt max. a szerver oldalon írja ki a PHP, ez pedig a böngészőben fut.

2. XHRSaveCats.setRequestHeader('Content-Type', 'multipart/form-data');
helyett pl.: XHRSaveCats.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

3. XHRSaveCats.send(document.forms["categories_form"]);
A send() metodust arra használhatod "POST" kérésnél hogy a "query string"-et teszed bele amikor küldöd a kérést. egy ilyesmire gondolok:
ajandek=true&aktualis=false
A form elemek "name" attributumában ne használj ékezetet, és az értékeket pl a encodeURIComponent() függvény segítségével escape-eld.

Most megiszom a reggeli kávém, aztán a HTML kódodra mutatok egy szebb megoldást, ha addig nem sikerül.

Ui.: egyébként a XMLHttpRequestObjectForSaving.send(null); mit csinál?

Ui.: Ui.: Az onreadystatchange eseménykezelőt az open() metódus hívása elött állítsd be, a te kódodban nincs jelentősége, de az open() kiváltja az "readystataechange" eseményt.
5

1. var dataSource = "<?php

kuka · 2012. Jan. 29. (V), 16.18
1. var dataSource = "<?php echo site_url()?>/catUpdate.php";
Ide valami épkézláb URL kell, nem pedig PHP echo mert azt max. a szerver oldalon írja ki a PHP, ez pedig a böngészőben fut.
Nincs azzal semmi gond, elvégre a PHP echo is kiírhat épkézláb URL-t. Azaz, ahogy a PHP generálhat HTML-t, úgy generálhat JavaScriptet is. (Persze feltéve, hogy az adott kód át is halad a PHP értelmezőn.)
6

Egy működő kódot módosítottam

Jazoja · 2012. Jan. 29. (V), 16.31
Csak néhány gyors válasz, aztán átnézem a kódod.

1. var dataSource = "<?php echo site_url()?>/catUpdate.php";
Ide valami épkézláb URL kell, nem pedig PHP echo mert azt max. a szerver oldalon írja ki a PHP, ez pedig a böngészőben fut.

Konkrétan itt PHP->JS adatátadás történik, azaz az oldal generálásakor teszi oda az URL-t. Ez WP alatt van, nekem műkszik.

3. XHRSaveCats.send(document.forms["categories_form"]);
A send() metodust arra használhatod "POST" kérésnél hogy a "query string"-et teszed bele amikor küldöd a kérést. egy ilyesmire gondolok:
ajandek=true&aktualis=false

Volt már működő kódom, amivel adatokat kértem le szerverről, hogy mit azt meg url-ben kódoltam. Egy ilyen működőt kezdtem áthegeszteni és valami módot keresni arra, hogy ne kelljen nekem JS-el végigmenni a DOM-on és a FORM elemeit kivadászva átalakítani egy URL kódolt formába.
Sima FORM-ot küldésekor (hagyományos AJAX nélküli módon) a FORM összes elemét automatikusan bekódolja (gondolom a böngésző).

Ui.: egyébként a XMLHttpRequestObjectForSaving.send(null); mit csinál?

Asszem ezzel zárja be a kapcsolatot.
4

Na valami ilyesmit

Karvaly84 · 2012. Jan. 29. (V), 11.04
Na valami ilyesmit kéne:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Post request with XMLHttpRequest</title>
</head>
<body>
	<form action="http://localhost/catUpdate.php" method="post"
		id="categories_form" name="categories_form">
		<div id="buttons">
		<!--
		Feltételezem HTML5-ben írtad a kódot. A button elem nem illik egy form
		űrlap elembe.
		
		Az alábbi type="button" helyett type="submit", az ugyanis kiváltja
		az űrlapon a "submit" eseményt amit elkapunk, ennek hatására dolgozzuk
		fel az űrlapot, így megoldható, hogy kikapcsolt JavaScript esetén is
		működjün az űrlap.
		 
		<button id="SaveCats" title="Kategóriák mentése szerverre" type="button"
				onclick="saveCategories();">Kategóriák mentése szerverre</button>
		-->
		<input id="SaveCats" title="Kategóriák mentése szerverre" type="submit"
			value="Kategóriák mentése szerverre" />
		</div>
		<div id="div-0">
			<!--
			A label elemet egy kijelölt űrlapelemhez szokás használni.
			Pl. minden input elemhez külön-külön.
			
			<label>Főkategóriák:</label>
			-->
			<p>
				Főkategóriák:
				<input class="savedCategorie" type="checkbox" name="Ajandek" value="5" />
				Ajándék
				<input class="savedCategorie" type="checkbox" name="Aktualis" value="124" />
				Aktuális
				<input class="savedCategorie" type="checkbox" name="Egyeb" value="1" />
				Egyéb
				<input class="savedCategorie" type="checkbox" name="NincsKategorizalva" value="25" />
				Nincs kategorizálva
				<input class="savedCategorie" type="checkbox" name="Osszes" value="130" />
				Összes 
			</p>
		</div>
	</form>
	<script type="text/javascript">
	var categories, savedCategories, XHRSaveCats, i;
	
	categories = document.getElementById("categories_form");
	
	savedCategories = categories.getElementsByClassName("savedCategorie");
	
	// Ez a funkció gondolom kinyitja/bezárja az alkategoriákat.
	function openCloseSubCategory() {
		if (this.checked) {
			console.log("Open " + this.value + ". sub categorie!");
		} else {
			console.log("Close " + this.value + ". sub categorie!");
		}
	}
	
	for (i = 0; i < savedCategories.length; i++) {
		savedCategories[i].addEventListener("change", openCloseSubCategory, false);
	}
	
	////////////////////////////////////////////////////////////////////////////
	// Űrlap feldolgozás
	////////////////////////////////////////////////////////////////////////////
	
	// Az XHR objektum "readystatechange" eseményéhez.
	function checkReadyState() {
		var ret;
		if (this.readyState === 4 && this.status === 200) {
			ret = this.responseText;
			console.log("Response: " + ret);
		}
	}
	
	// Az XHR objektum send() metódusához.
	function createQueryString(query) {
		var str = "", k;
		for (k in query) {
			if (query.hasOwnProperty(k)) {
				if (str) {
					str += "&";
				}
				str += k + "=" + encodeURIComponent(query[k]);
			}
		}
		return str;
	}
	
	XHRSaveCats = new XMLHttpRequest();
	
	function saveCategories(event) {
		var param = {}, i;
		event.preventDefault();
		for (i = 0; i < savedCategories.length; i++) {
			if (savedCategories[i].checked) {
				param[savedCategories[i].name] = "true";
			} else {
				param[savedCategories[i].name] = "false";
			}
		}
		console.log("POST request: " + (param = createQueryString(param)));
		XHRSaveCats.onreadystatechange = checkReadyState;
		XHRSaveCats.open("POST", categories.action, true);
		XHRSaveCats.setRequestHeader("Content-Type",
			"application/x-www-form-urlencoded");
		XHRSaveCats.send(param);
	}
	
	categories.addEventListener("submit", saveCategories, false);
	</script>
</body>
</html>
7

Lépésről-lépésre 1.

Jazoja · 2012. Jan. 29. (V), 17.50
A következő módosításokat csináltam (eddig):

1. átírtam a gombot, és eltávolítottam a "onClick" részt

<button type='button' onClick="saveCategories();">

<input type='submit'>
2. a FORM-ra akasztok egy eseménykezelőt, ami SUBMIT eseménynél meghívja a "saveCategories" függvényt

var categories = document.getElementById("categories_form");
categories.addEventListener("submit", saveCategories, false);
3. ami az eseményt az "event" paraméteren veszi át, és rögtön kikapcsolom az alap eseményt (hogy ne POST-olja és írányítsa át az oldalt)

function saveCategories(event)
{
  event.preventDefault();
  ...
}
folyt. köv.
8

Lépésről-lépésre 2.

Jazoja · 2012. Jan. 30. (H), 22.02
4. Az összes INPUT CHECKBOX közös osztályba kerül (ez nálam "catCB")
5. mentés előtt lekérem az összes ilyen osztályba tartozó elemet

catCBs = categories.getElementsByClassName("catCB");
6. majd egy for ciklussal összeállítok egy stringet

var CatsInURLmessage="";
for (var i=0; i<catCBs.length;i++)
{
  if(catCBs[i].checked==true)
    CatsInURLmessage+=catCBs[i].value+"="+catCBs[i].checked+"&";
}
7. nyitok egy kapcsolatot a FORM "action" tagjában szereplő címhez

XHRSaveCats.open("POST", categories.action,true);
8. és elküldöm az üzenetet

XHRSaveCats.send(CatsInURLmessage);
9. amit szerver oldalon már fel tudok dolgozni

foreach($_POST as $cat=>$state)
{
  if($state == "true")
  {
    $categories[$i]=$cat;
    $i++;
  }
}
Kérdés:
A kiválasztott kategóriák azonosítóit nem lehet elküldeni csak egy sima tömbként?
9

A kiválasztott kategóriák

Karvaly84 · 2012. Jan. 31. (K), 13.08
A kiválasztott kategóriák azonosítóit nem lehet elküldeni csak egy sima tömbként?

Mit értesz "azonosító" alatt?

Hasznos linkek:

XMLHttpRequest.send() - Nem tanulmányoztam mélyen, mert eddig nem volt ilyenekre szükségem, de van lehetőség a send() metódusban object típusú adatot átadni.

FormData()
10

Azonosítók tömbként

Jazoja · 2012. Feb. 1. (Sze), 14.19
Mit értesz "azonosító" alatt?

Az INPUT CHECKBOX "value" mezőjében tárolt értéket (egész szám).
A szervernek igazából csak ezekre a számokra (wordpress post kategória azonosító) van szüksége.

Jelenleg <id>=<value> párokban küldöm az adatokat URL-be kódolva, ami kb így néz ki:
localhost/catUpdate.php?1=true&53=true&12=true&...
Itt a <value> effektíve felesleges, mert csak a "true" (azaz bejelölt CHECKBOX) értékeket küldök, minden <id> mellé.

De nekem ez is elég lenne: 1,53,12,...
vagy valami JS tömb, a kategóriák azonosítóival, amit utána PHP POST már tud kezelni.

A .send() fgv.-t majd este átnézem.