Probleem met nieuwe velden toevoegen via javascript (php en mysql)

Status
Niet open voor verdere reacties.

brecht27

Gebruiker
Lid geworden
26 nov 2011
Berichten
17
Hopelijk kan iemand mij hier helpen.

Ik had mijn vraag eerder gepost in de php sectie. Maar denk dat dit eerder een javascript probleem is. Daarom post ik hier een nieuwe vraag.
De bedoeling is dat er nieuwe velden kunnen aangemaakt worden door op de knop Add Fields te drukken. Als er een waarde is ingevuld in het zoekveld en deze waarde is teruggevonden in de database zal er bovenaan een veld verschijnen met het resultaat van de zoekactie (= productnaam) naast het veld van het productnummer. Tot nu toe werkt dit perfect (enkel de layout nog een beetje aanpassen, maar dit is maar afwerking). Het probleem is dat ik de knop 'add fields' niet kan laten werken. Het is ook de bedoeling dat de eerdere resultaten wel blijven staan, maar dat daaronder een nieuwe lijn zal worden toegevoegd.
Hopelijk verstaan jullie een beetje wat ik bedoel.

Je kan dit testen via onderstaande link (de zoekwaarden 100 en 200 zitten in de database als test, dus daarop kunnen jullie zoeken):

http://91.199.236.119/~jobysan/testen/input/index2b.php


Hieronder de code:

PHP:
<html>
<head>
<title>test</title>
</head>
<body>

<?php



  if(isset($_GET['submit'])) 
  { 
//echo '<td id="addbox2"><input type="text" name="prodnaam[]" value="" /></td>';
$zoek = $_GET["prodnummer"];


?>
<table width="75%"border="0">
  <tr>
    <td>Productnummer</td>
    <td>Productnaam</td>
  </tr>
  <tr>
    <td><input type="text" value="<?php echo $zoek; ?>" /></td>


<?php    
	require ('config.php');
	
         $conn = mysql_connect($host,$user,$pass) or die (mysql_error());
         mysql_select_db("jobysan_werkbonnen") or die (mysql_error());
       
		 $sql = 'SELECT * FROM werkbonnen WHERE productnummer = "' . $zoek .'"';
		 $res = mysql_query($sql) or die (mysql_error());



while($row = mysql_fetch_assoc($res))
     		{ 
?>    
    
    <td><input type="text" value="<?php echo $row['productnaam']; ?>" /></td>
    
      <?php } ?>
            
  </tr>
</table>


<?php

}
else
{

}

?>


<form method="get" >
<table width="75%"border="0">
  <tr>
    <td>&nbsp;</td>
  </tr>
  <tr>
    <td><hr></td>
  </tr>
    <td>Productnummer</td>
  </tr>
  <tr>
    <td><input type="text" name="prodnummer" />&nbsp;&nbsp;&nbsp;<input name="submit" type="submit" value="Zoek" /></td>
</form>

  </tr>
  <tr>
    <td>&nbsp;</td>
  </tr>
</table>
<input type="button" onClick="addInput()" name="add" value="Add fields" />
</body>
</html>



Nu is het wel zo dat ik de javascript terug heb verwijderd van deze pagina aangezien hij niet werkte.
Hieronder heb ik wel een script gevonden die mij kan helpen maar nu zouden deze 2 moeten samengevoegd worden.
Het is ook wel zo dat er later met deze resultaten moet kunnen gewerkt worden of dat deze zouden moeten opgeslaan kunnen worden in een veld in de mysql database. Hoe dit in elkaar zit weet ik ook niet, maar dit is voor fase 2. Eerst zien dat de eerder gestelde vraag werkt!

Hieronder een link met een voorbeeld van wat de javascript zou moeten doen:

http://91.199.236.119/~jobysan/testen/input/index2.php


En de code daarvoor:

PHP:
<html>
<head>
<title>test</title>
<script language="javascript">
function addInput() {
document.getElementById('addbox1').innerHTML += '<br /><input type="text" name="prodnummer[]" />';
document.getElementById('addbox2').innerHTML += '<br /><input type="text" name="prodnaam[]" />';
}
</script>
</head>
<body>

<?php

  if(isset($_POST['submit'])) 
  { 
//echo '<td id="addbox2"><input type="text" name="prodnaam[]" value="" /></td>';
echo "test";
  }
else
{
	echo "&nbsp;";
	}

?>

<table width="75%"border="0">
  <tr>
    <td>Productnummer</td>
    <td>&nbsp;</td>
    <td>Productnaam</td>
  </tr>
  <tr>
    <td id="addbox1"><input type="text" name="prodnummer[]" /></td>
<form id="pricecheckform" name="pricecheckform" method="post" >
    <td><input type="hidden" value="" /><input name="submit" type="submit" value="Zoek" /></td>
</form>
  
  </tr>
  <tr>
    <td></td>
  </tr>
</table>
<input type="button" onClick="addInput()" name="add" value="Add fields" />

</body>
</html>
 
Laatst bewerkt:
Hoihoi :) Ik heb even je PHP-topic gelezen.

Even checken of ik goed begrijp wat je nog hebben wil:
- Een knop 'Add field' die een extra zoekveld toevoegd
- Een knop 'Zoek' die voor alle ingevulde productnummers de resultaten in een tabel zet.
Is dat correct?

Ik denk dat de Barry's suggestie AJAX te gebruiken niet slecht is ;) Niet alleen omdat je dan de pagina niet hoeft te herladen. Je programma wordt vaak duidelijker door een scheiding tussen functionaliteit en weergave. Ik zou PHP gebruiken om alléén de data op te halen en weg te schrijven, en JavaScript voor het weergeven van de resultaten.

Je begeeft je dan wel op geheel ander gebied. Je krijgt dan dus meer met JavaScript te maken, en AJAX is niet het simpelste onderwerp voor beginners. Ik heb wel een standaardscriptje voor je waar je zo jouw zoekfunctie in kan gieten, maar je moet je er dus wel even in willen verdiepen ;)
 
Robin S,

Dat is correct. Alleen heb ik inderdaad geen verstand van AJAX, maar wil mij er wel in verdiepen. Kan je jouw standaardscriptje even doorsturen? Misschien wel met een beetje uitleg erbij zodat ik snel kan zien hoe het in elkaar zit?
 
:) Sorry dat mijn reactie zo lang op zich liet wachten.

Oké, hier is een voorzetje met wat uitleg:
index.html bevat natuurlijk de html voor het zoekveld en de resultaten. Zoals je ziet zijn er 2 buttons die met hun onClick naar de functies zoek en addInput wijzen.
- De functie addInput voegt een rij in de zoektabel toe met een nieuw <input>-element, en verplaatst ook de zoekbutton naar die laatste rij.
- De functie zoek gaat het document af en zet de waarden van alle textvelden in een array (de zoektermen). Die array wordt verstuurd naar contentManager.php. Zodra contentManager.php klaar is met verwerken wordt de functie onReady aangeroepen.
- In onReady kun je met behulp van JavaScript de resultaten aan de resultaattabel toevoegen.

contentManager.php verwerkt de requests die je opstuurt via een JHR-object. Op regel 41-43 en 48-59 heb ik vast iets voor je neergezet (bekijk zelf even of je zo al de gewenste resultaten krijgt). Wanneer je vanaf index.html andere 'actions' begint te maken, kun je gewoon nieuwe cases in de switch toevoegen. De resultaten van zo'n query zet je steeds in $_RESPONSE["data"].

JHR.js en EventManager.js zou je eigenlijk gewoon kunnen beschouwen als 'black boxes'. Als je er meer over wil weten beantwoord ik graag vragen, maar je kan ook gewoon het gebruik afkijken uit index.html ;)

index.html
HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script src="../../lib/beta/EventManager.js" type="text/javascript"></script>
        <script src="JHR.js" type="text/javascript"></script>
        <script type="text/javascript">

            var Settings = {
                PHP: "contentManager.php"
            };

            function alertMessage(e) {
                alert("Message:\n" + e.message + "\n\nFull responseText:\n" + this.responseText);
            }
            function addInput() {
                var btn_zoek = document.getElementById("zoek");
                
                var tr = document.createElement("tr");
                btn_zoek.parentNode.parentNode.parentNode.appendChild(tr);
                
                var td = document.createElement("td");
                tr.appendChild(td);

                var input = document.createElement("input");
                td.appendChild(input);
                td.appendChild(btn_zoek);
            }
            function onReady(e) {
                var data = e.data;
                console.log(data);
            }
            function zoek() {

                var zoektermen = [];
                var inputList = document.getElementsByTagName("input");
                for (var i = 0; i < inputList.length; i++) {
                    if (inputList[i].type == "text") {
                        zoektermen.push(inputList[i].value);
                    }
                }
                console.log(zoektermen);

                var jhr = new JHR();
                jhr.addEventListener("info", alertMessage, false);
                jhr.addEventListener("warning", alertMessage, false);
                jhr.addEventListener("error", alertMessage, false);
                jhr.addEventListener("ready", onReady, false);
                
                jhr.open("POST", Settings.PHP, true);
                jhr.send({
                    action: "ZOEK",
                    data: zoektermen
                });
                
            }

            function main() {
//                var btn_zoek = document.getElementById("zoek");
            }
            window.onload = main;

        </script>
        <title></title>
    </head>
    <body>
        <table id="results">
            <tr>
                <th>Zoekterm</th>
                <th>Resultaat</th>
            </tr>
        </table>
        <table id="search" width="75%" border="0">
            <tr>
                <td>&nbsp;</td>
            </tr>
            <tr>
                <td><hr></td>
            </tr>
            <tr>
                <td>Productnummer</td>
            </tr>
            <tr>
                <td>
                    <input type="text" name="prodnummer" />&nbsp;&nbsp;&nbsp;
                    <input id="zoek" type="button" onClick="zoek()" value="Zoek" />
                </td>
            </tr>
        </table>
        <input type="button" onClick="addInput()" name="add" value="Add fields" />
    </body>
</html>

contentManager.php
PHP:
<?php

class FileNotExistException extends Exception {
    public function __construct($fileName) {
        parent::__construct("File (" . $fileName . ") does not exist");
    }
}
function file_get_json  ($fileName) {
    $content = file_get_contents($fileName);
    if ($content === false && !file_exists($fileName)) {
        throw new FileNotExistException($fileName);
    }
    $json = json_decode($content, true);
    if ($json === null) {
        throw new Exception("No json in (" . $fileName . ")");
    }
    return $json;
}

function info($val) {
    global $_RESPONSE;
    array_push($_RESPONSE["info"], $val);
}
function warn($val) {
    global $_RESPONSE;
    array_push($_RESPONSE["warning"], $val);
}

try {

    $_POST = file_get_json("php://input");
    $_DATA = $_POST["data"];
    $_RESPONSE = array(
        "action" => $_POST["action"],
        "data" => null,
        "error" => null,
        "info" => array(),
        "warning" => array()
    );

    require ('config.php');
    $conn = mysql_connect($host,$user,$pass) or die (mysql_error());
    mysql_select_db("jobysan_werkbonnen") or die (mysql_error());

    switch ($_POST["action"])
    {

        case "ZOEK":
            $_RESPONSE["data"] = array();
            $sql = 'SELECT * FROM werkbonnen WHERE productnummer = "' . $_DATA .'"';
            $res = mysql_query($sql) or die (mysql_error());
            while ($row = mysql_fetch_assoc($res)) {
                array_push($_RESPONSE["data"], $row['productnaam']);
            }
            break;

//        case "...":
//            /* Do something... */
//            break;

        default:
            throw new Exception("No such action (" . $_POST["action"] . ")");
            break;
    }

    mysql_close($conn);

}
catch (Exception $e) {
    $_RESPONSE["error"] = $e->getMessage();
}

echo json_encode($_RESPONSE);

?>

JHR.js
[JS]function JHR() {

var dataSerializer = JSON.stringify;
var dataUnserializer = JSON.parse;

var d = EventManager.createEventDispatcher(this);
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", onReadyStateChange, false);

this.open = function() {
xhr.open.apply(xhr, arguments);
};
this.send = function(data) {
if (data === undefined || data === null) {
xhr.send(null);
}
else {
xhr.send(dataSerializer(data));
}
};

function onReady() {
try {
var response = dataUnserializer(this.responseText), k;
console.log(response);

for (k in response.info) {
d.dispatchEvent("info", {message: response.info[k]});
}
for (k in response.warning) {
d.dispatchEvent("warning", {message: response.warning[k]});
}

if (response.error) {
throw new Error(response.error);
}
else {
d.dispatchEvent("ready", {
action: response.action,
data: response.data
});
}
}
catch (e) {
d.dispatchEvent("error", {message: e.message});
}
return response;
}
function onReadyStateChange() {
if (this.readyState == 4 && this.status == 200) {
onReady.call(this);
}
}

this.__defineGetter__("responseText", function() {
return xhr.responseText;
});

this.addEventListener("info", function(e) {
console.info(e.message);
});
this.addEventListener("warning", function(e) {
console.warn(e.message);
});
this.addEventListener("error", function(e) {
console.error(new Error(e.message));
});
}[/JS]

EventManager.js
[JS]var EventManager = (function EventManager() {

var eventDispatchers = [];

function CustomEvent(type, target, args) {

var propagate = true;

this.type = type;
this.target = target;

this.propagates = function() {
return propagate;
};
this.stopPropagation = function() {
propagate = false;
};

for (var p in args) {
if (!this.hasOwnProperty(p)) {
this.__defineGetter__(p, (function(p) {
return function() { return args[p]; };
})(p));
}
}

}
function Listener(callback, priority) {
this.callback = callback;
this.priority = priority || 0;
this.suspension = 0;
}
function EventDispatcher(obj, listeners) {

this.dispatchEvent = function (type, args) {

var typeArray = listeners[type];
if (!typeArray) {
return;
}

var e = new CustomEvent(type, obj, args), i = 0;
while(e.propagates() && i < typeArray.length) {
if (typeArray.suspension == 0) {
typeArray.callback.call(obj, e);
}
else {
typeArray.suspension--;
}
i++;
}
};

}

this.createEventDispatcher = function(obj) {

if (this.isEventDispatcher(obj)) throw new Error("Object already is an event dispatcher");

var listeners = {};
var d = new EventDispatcher(obj, listeners);
eventDispatchers.push(obj);

obj.addEventListener = function (type, callback, capture, priority) {

priority = priority || 0;

var typeArray = listeners[type] = listeners[type] || [];

var i = 0;
while (typeArray && typeArray.priority <= priority) {
i++;
}
listeners[type].splice(i, 0, new Listener(callback, priority));

};
obj.removeEventListener = function (type, callback, capture) {
var typeArray = listeners[type];
for (var i = typeArray.length - 1; 0 <= i; i--) {
if (typeArray.callback == callback) {
listeners[type].splice(i, 1);
}
}
};
obj.suspendEventListener = function (type, callback, capture) {
var typeArray = listeners[type];
for (var i = 0, l = typeArray.length; i < l; i++) {
if (typeArray.callback == callback) {
typeArray.suspension++;
}
}
};

return d;
}
this.isEventDispatcher = function(obj) {
return obj in eventDispatchers;
}

return this;

}).call({});[/JS]
 
Robin,

Zou het kunnen dat er ergens iets niet helemaal juist gaat in het script? Ik heb alle bestanden overgenomen maar krijg geen resultaat te zien van mijn zoekterm.

Hieronder de link zodat je even kan kijken:

http://91.199.236.119/~jobysan/testen/input/index.html


Als je 100 invult als zoekterm zou je een resultaat van test100 moeten krijgen en als je 200 als zoekterm invult zou je het resultaat test200 moeten krijgen. Deze waarden zitten in de database momenteel als testwaarden.
 
Ja, ik ben niet helemaal consistent geweest met de datatypes. Je ziet in de functie zoek dat er een array met zoektermen wordt verzameld. Deze komt in de php-code terecht in de variabele $_DATA. In de php staat echter nog de code alsof deze variabele een enkele zoekterm bevat.
Om 't op te lossen moet je dus even de ZOEK-case in de php herschrijven, nu met de kennis dat $_DATA een array van zoektermen is. De resultaten kun je dan weer in een array verzamelen en in $_RESPONSE["data"] zetten. Succes! ;)
 
Robin,

De zoek-case staat in de file contentManager.php vanaf regel 41 tot 59 ???
Ik moet wel zeggen dat ik minder thuis ben in het werken met arrays. Kan jij dit even voor me aanpassen?
 
De "ZOEK"-case is in contentManager.php van vorig bericht, van regel 48 t/m 55 ;)
Arrays zijn redelijk gemakkelijk om mee te werken. Bekijk eens de PHP array function reference. Hieronder de aangepaste "ZOEK"-case, maar er kunnen nog foutjes in zitten - ik kan 't immers niet testen omdat ik jouw database niet heb ;)
Wat ik graag doe voor mijn eigen scripts: gebruik FireFox i.c.m. FireBug. Zo zie je snel waar er iets fout gaat en haal je alle foutjes uit je code ;)
PHP:
case "ZOEK":
	$_RESPONSE["data"] = array();
	foreach($_DATA as $zoekterm) {
		$_RESPONSE["data"][$zoekterm] = array();
		$sql = 'SELECT * FROM werkbonnen WHERE productnummer = "' . $zoekterm .'"';
		$res = mysql_query($sql) or die (mysql_error());
		while ($row = mysql_fetch_assoc($res)) {
			array_push($_RESPONSE["data"][$zoekterm], $row['productnaam']);
		}
	}
	break;
 
Robin,

Werkt nog steeds niet. Ik zal zelf ook nog eens zoeken, maar kan het op het eerste gezicht niet terugvinden.

Hieronder een link waar je het kan bekijken:
http://91.199.236.119/~jobysan/testen/input/index.html

De waarden 100 en 200 geven respectievelijk test100 en test200 als resultaat uit de database. Alleen krijg ik geen resultaat... :(
 
De query werkt nu hoor, de php geeft de juiste waarden. Nu moet je alleen zelf nog wat code schrijven om ze op je scherm te toveren ;) Dat doe je in index.php in de functie onReady. Als 't niet lukt kan iemand anders je vast wel verder helpen, want ik ga op vakantie ;) Succes!

Edit:
Om te controleren dat je nu de juiste waarden van de PHP krijgt kun je dit aan onReady toevoegen:
[JS]for (var k in data) {
alert("data[" + k + "] = " + data[k]);
}[/JS]
 
Laatst bewerkt:
Thanks Robin tot nu toe en een hele fijne vakantie.


Ondertussen heb ik al vanalles zitten proberen, maar geraak er niet aan uit.
Met de functie die je hebt opgegeven werkt het inderdaad als popup, maar ik krijg het niet op de juiste plaats.
Wat moet ik aan een input veld toevoegen zodat hij mij het resultaat geeft?
Kan ik iets gebruiken in deze zin:

<input id="result" type="text" onClick="onReady(this.form)" />

Of totaal niet?
Wie kan mij helpen?
 
Het toevoegen van HTML-elementen via JavaScript kun je afkijken uit de functie addInput. Je zou dit kunnen proberen toe te voegen aan onReady:
[JS]var results = document.getElementById("results");
for (var k in data) {
//alert("data[" + k + "] = " + data[k]);

var tr = document.createElement("tr");
results.appendChild(tr);

var td = document.createElement("td");
td.innerHTML = k;
tr.appendChild(td);

td = document.createElement("td");
td.innerHTML = data[k].join(", "); //Ik ben er hier vanuit gegaan dat een zoekterm meerdere resultaten kan opleveren
tr.appendChild(td);

}[/JS]

Wil je een input-element in je tabel hebben, dan kun je er één maken met document.createElement en de waarde zetten met input.value:
[JS]var input = document.createElement("input");
input.value = data[k].join(", ");
td.appendChild(input);[/JS]
 
Thanks Robin. We komen in de buurt.
Bekijk even het resultaat via de onderstaande link:

http://91.199.236.119/~jobysan/testen/input/index.html

Je kan dit testen door de waarde 100 in het zoekveld in te geven onderaan (resultaat is dan test100), of de waarde 200 (resultaat is dan test200).

Nu is er echter nog een probleem. Als je een zoekwoord invult onderaan en dan op de zoekknop drukt geeft hij de waarde bovenaan weer wat perfect is tot nu toe. Maar je kan ook een nieuwe lijn toevoegen onderaan en terug een ander zoekwoord opgeven, druk je dan op zoek dan geeft hij de vorige waarde ook terug mee en dit is niet de bedoeling.
Het is de bedoeling dat er bovenaan een lijst zal gevormd worden met alle zoekwoorden en resultaten onder elkaar maar zonder herhalingen van vorige ingevulde velden. Begrijp je wat ik bedoel?

Dan is er nog een bijkomend punt: de resultatentabel met de zoekwoorden (bovenaan) zouden ook moeten kunnen opgeslagen worden in een mysql database zodat er later terug mee kan gewerkt worden (op bvb een andere pagina). Is dit mogelijk?
 
Laatst bewerkt:
brecht27 zei:
Begrijp je wat ik bedoel?
Bijna :)

Je wil, denk ik, één van de volgende twee dingen:
Als er op de zoek-knop gedrukt word, ...
a) worden éérst de eerdere zoekresultaten gewist. In de plaats daarvan verschijnen dan de nieuwe resultaten.
b) wordt er een nieuwe tabel gemaakt voor de resultaten. De resultaten van eerdere queries staat nog steeds op het scherm, maar in een andere tabel (bv. gescheiden door die strepen, de hr-elementen).

Het opslaan van resultaattabellen is met deze constructie vrij gemakkelijk. Onder de ZOEK-case in contentManager.php maak je een nieuwe case (SAVE, bijvoorbeeld). Daar kun je dan zoekresultaten toevoegen aan een MySQL-tabel.
PHP:
case "SAVE":
    /* Do something... */
    break;

Verder moet je nog een functie hebben die vanuit index.html zo'n resultaattabel naar de php stuurt, maar laten we eerst die resultaten op een goede manier op het scherm zetten ;)
 
Ik denk dat je in de goede richting aan het denken bent ;)

Boven de "hr-lijn" komen onder elkaar alle resultaten (zoekwoord - resultaat) zoals het nu is, maar de eerdere gezochte resultaten mogen niet meer opnieuw toegevoegd worden.
Onder de "hr-lijn" komt een input veld voor het zoekwoord en een zoek-knop zoals het nu is. Indien op de knop zal gedrukt worden komt het resultaat bovenaan erbij.

Laten we inderdaad eerst de resultatentabel perfect maken voor we overgaan tot het opslaan van de gegevens in de MySQL tabel.
 
Laatst bewerkt:
Ik snap 't denk ik - er is dus gewoon één resultaattabel.

Hier heb ik een globale variabele Results waarin alle resultaten bijgehouden worden. Er wordt steeds gecontroleerd of er al op een term gezocht is. Afhankelijk daarvan wordt er een extra rij in de tabel toegevoegd.
[JS]var Results = {};
function onReady(e) {
var data = e.data;
console.log(data);

var results = document.getElementById("results");
for (var k in data) {

var r;
if (k in Results) {
r = Results[k];
r.data = data[k];
}
else {
var tr = document.createElement("tr");
results.appendChild(tr);

var td = document.createElement("td");
td.innerHTML = k;
tr.appendChild(td);

r = Results[k] = {
data: data[k],
td: document.createElement("td")
};
tr.appendChild(r.td);
}

r.td.innerHTML = r.data.join(", ");

}
}[/JS]
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan