Form-submit valkuilen

Sunday 09 January 2005, 21:37:00 | web dev

Het maken van een juiste Form is niet zo simpel als het lijkt. Er zijn een aantal zaken waar je goed op moet letten:

  1. Als je een of meer file upload fields (input type="file") in het form hebt staan, dan moet je de er een post method van maken en enctype van het Form op "multipart/form-data" zetten.
  2. Image buttons: 2 soorten, een input type="image" (gewoon plaatje waar je op kunt klikken) en een plaatje in een <button>. Deze doen verschillende dingen. Tevens doet Internet Explorer raar met een <button>!
  3. Character encodings: dit is vrij slecht geregeld in html4 forms. Er zijn slechts een paar configuraties helemaal juist voor het foutloos verwerken van niet-ASCII tekens.

In dit artikel heb ik deze zaken uitgeplozen.

1. Multipart forms

In geval van file uploads (1 of meer inputs met type="file") moet je een ander enctype instellen op het Form: enctype="multipart/form-data" (en de submit method moet post zijn). Dit heeft trouwens niets te maken met character encoding, het geeft de manier aan waarop de web browser de gegevens naar de web server stuurt. Aangezien het niet meer een 'gewone' POST is, maar een Mime-Multipart bericht, moet de server het request ook op een andere manier verwerken. De default enctype is trouwens application/x-www-form-urlencoded.

2. Image buttons. En <button>: IE doet raar!

Als je een image button maakt met <input type="image" name="button" src=...> dan krijg je op de server twee form fields door, namelijk button.x en button.y (met x/y de locatie waar je op het plaatje klikte). Dit doen alle browsers wel goed.

Maar als je de image button ook nog voorziet van een value dan begint het gedoe. <input type="image" name="button" value="value" src=...> Een normale submit button gebruikt value voor de tekst die op de knop getoond wordt, en voor de waarde die bij de button name naar de server gestuurd wordt als je er op klikt. Bij een image button werkt dit iets anders: het plaatje is wat er getoond wordt, en als je er op klikt worden dus de x en y positie doorgestuurd, maar Mozilla/Firefox stuurt ook button=value (wat een 'normale' button zou doen) mee. Andere browsers doen dit niet, dus je kunt er niet op vertrouwen.

Een <button> werkt weer anders. Je kunt daar HTML in de button plaatsen, inclusief eventuele images, die dan allemaal op je knop verschijnen. Er is alleen een probleem met Internet Explorer. Deze wijkt op twee manieren af van het standaard gedrag (zoals Firefox of Konqueror dat bijvoorbeeld hanteren):

  1. IE stuurt altijd alle <buttons> terug, ook al klik je een andere knop. Je weet dus nooit welke knop aangeklikt is.
  2. IE stuurt niet de waarde van het value attribuut terug, maar de HTML die in de button staat!

Grr! Met IE is een <button> dus bijna onbruikbaar? Inderdaad, behalve als je een beetje gaat goochelen met javascript (eerste opzet gevonden op deze site, maar die werkte alleen in IE):

So, what's a cross-browser way to fix it? If you're using <button> tags at all, you're aiming at farily recent browsers to start with, so I'll assume you can use a little JavaScript. (This whole problem doesn't happen with <input type='submit'>, only with <button>.) Here's what worked for me:

// deze code is dus iets aangepast om ook in andere browsers te werken
<script language="javascript" type="text/javascript">
function submitAction(value)
{
    document.forms["myForm"].action.value = value;
    document.forms["myForm"].submit();
}
</script>

<form id="myForm" method="post" action="targetpage.sn">
    <input type="hidden" name="action" value="">
    <button type="button" accesskey="N" onclick="submitAction('new')"><u>N</u>ew</button>
    <button type="button" accesskey="E" onclick="submitAction('edit')"><u>E</u>dit</button>
    <button type="button" accesskey="D" onclick="submitAction('delete')"><u>D</u>elete</button>
</form>

Note that the button type has changed from 'submit' to 'button'. This code will result in a single action=value pair in the GET URL or the POST data that will contain "new", "edit", or "delete" as expected, and will work in pretty much all modern browsers.

3. Character encoding: hoe vreemde tekens correct verwerken

Als je mensen wilt toestaan om 'vreemde' tekens in te voeren (zoals €, ë, en ÷, maar ook α β γ, of zelfs ش غ ي), en deze in alle gevallen foutloos wilt kunnen verwerken, dan moet je nogal oppassen. Er zijn maar een paar instellingen helemaal juist in alle gevallen. Niet alle browsers reageren namelijk op dezelfde manier, je moet op de server ook nogal oppassen met het verwerken van de binnenkomende request data. Verder maakt het niet zo heel veel uit of je maar een paar niet-ASCII tekens (zoals alleen letters met accenten: ë, à, enz) wilt kunnen verwerken, of alleen het €-teken, of de hele Unicode zwik inclusief alle Chinese en Arabische tekentjes. Als je toch dingen moet aanpassen, waarom dan niet gelijk goed?

Op Sun Developer Network staat een helder artikel met voorbeelden dat het encoding probleem (inclusief database verwerking!) duidelijk uitlegt.

Je moet zowel in de HTML pagina die het FORM bevat iets regelen, alsmede op de server (die de form submit ontvangt en verwerkt). Wat moet je doen: