@drawohara
published on: 2013-06-17

i stood up a little quiz about html forms today.

ref: https://gist.github.com/ahoward/98591ebc9113bea1cf02

  <!--
fork this. do not use the internet. take < 10 minutes to find at least 10
distinct errors on this form. submit your answer in the comments field of
your fork and email me (ara[at]dojo4.com) the url.
-->
  <form method='DELETE' ACTION='./' enctype="multipart/file-upload">
    
    <fieldset>
      <legend> tags </legend>
      <input type='text' name='tags' value='foo'/>
      <input type='text' name='tags' value='bar'/>
    </fieldset>
    <label for='foo'>Foo: </label> <input name='foo'> <input name='foo'>
    <label>
      Bar: <input name='bar'>
    </label>
    <input name='email' readonly/>
    <input name='password' disabled=disabled/>
    <input type='file' name='file' value='.bashrc'/>
    <fieldset>
      <legend>Sex</legend>
        <input type="radio" name="sex">
          <option value='male'>Male</option>
          <option value='female'/>
        </input>
      <fieldset>
        <legend>Transportation</legend>
          <input type="checkbox" name="vehicle" value="Bike">I have a bike<br>
          <input type="checkbox" name="vehicle" value="Car">I have a car 
      </fieldset>
    </fieldset>
    <select name='web-develop-skilz'>
      <option value='A'>
      <option value='B'>
      <option value='C'>
      <option value='D'>
      <option value='F'>
    </select>
    
    <hr>
    <button type='submit'>
  </form>

the goal of having people skim this completely broken html form was just to see people’s line of thinking with this: the backbone of html interfaces

following are some sample answers, grouped roughly by category, and commentary on each of them


fubar doctype


for sure most people missed that many errors depended on the doctype declaration. what style of tags you may use depends entirely on the doctype.


method=delete


although we think about http verbs with client apis, including javascript. for a majority of browsers you get GET and POST. this is important if you’ve been considering an xhtml based api.


enctype=bunk


enctype bugs always waste a day. get it wrong and you’ll waste the day posting the name of your file as a string, instead of the actual encoded file contents. also important to note is that the enctype merely dictates how the form is encoded and is fully orthogonal to the http verb used.


input=foo && input=foo


lot’s of misperceptions on this one. it is totally legit to post the same parameter > 1 times in a form. the spec supports it and even ancient cgi support the notion of posting multiple values under the same key. it is merely convention that many controllers dump these into a hash where ‘last in wins’

you can prove this easily to yourself. post this from a form

  <input name='answer' value='40'>
  <input name='answer' value='2'>
      
  

and you’ll see the following in the browser console

<img style =’max-height:420px;’ src=’http://cl.ly/image/3I2Q2v0D1B1G/Screen%20Shot%202013-06-17%20at%204.09.23%20PM.png’

if you handle the form post like so

  def form
    return if request.get?
    
    parsed = Parser.new(env).parse
    
    render :json => parsed.as_json, :layout => true
  end
# hack the rack parser to show that http DOES post multiple values
# and that, if we want, we could accumulate them
#
  class Parser < Rack::Multipart::Parser
    def setup_parse
      super
    ensure
      @params = KeyList.new
    end
    class KeyList
      def initialize(*args, &block)
        @params = {}
      end
      
      def [](key)
        @params[key]
      end
      
      def []=(key, value)
        (@params[key] ||= []).push(value)
      end
      
      def key?(key)
        @params.key?(key)
      end
      
      def to_params_hash()
        self
      end
    end
  end

then you will get a response that looks like

  {"params":{"answer":["40","2"]}}

TL:DR;

your web stack may drop multiple values on the floor by loading a hash, but ruby’s cgi.rb library, and http generally does not. this applies to inputs, checkboxen, etc - anything with name can pass multiple values.

in particular ruby’s cgi.rb does not limit posting multiple values under a key

while rails does


labels are blargh


labels without a for are totally legit. when you wrap an input with a label the ‘for’ is implied as being the contained input. these are equivalent

<label for='foo'>Foo</label> <input name='foo'>
<label for='foo'>Foo <input name='foo'></label>

with the former being much simpler to deal with in js ( $label.find(‘input’) )

 $label.find('input')
 

vs.

 
  var name = $label.attr('for');
  
  $input = $('name[' + name ']');
 

readonly and disabled are the hardz


readonly and disabled are both boolean attributes and, as such, have both quoted/non-quoted and valued/non-valued permutations

all these are fine

  <input readonly>
  <input readonly=readonly>
  <input readonly="readonly">

although being consistent and using quotes is more widely handled in text editors

refs:


form[action]


relative actions are not only totally legit, but useful. consider a login form used both for general users under /login that’s also used under /admin/login: in this case it may be quite useful for a form to post back relative to it’s controller


file[value=]


file inputs cannot have deafult values, and must be posted via form with the proper enctype


input[type=]


yup, gotta have the correct type on those inputs to mask passwords, pop up email keyboard, all sorts of goodies. html5 introduces many new types. now ‘em!


radio/select/options/checkboxes are teh hardz


checkboxes pass values only if the box is checked and, like other form elements, case easily pass in multiple values under the same name. it’s only because rails’ stuff them into a hash that this appears not to be true.

in general, don’t rely on helpers to generate the correct html for you. learn how radio buttons, checkboxen, and selects work under the hood.


chickens


img