Ran into an interesting problem today - let’s say we have a form that does more than one thing. Give it a setup something like this:

<form action="/" method="post">
  <input type="hidden" name="option_value" value="1" />
  <input name="search_options" type="text" />
  <input type="submit" name="commit" value="Search Options" />
  <br />

  <input type="hidden" name="choice_value" value="1" />
  <input name="search_choices" type="text" />
  <input type="submit" name="commit" value="Search Choices" />
  <br />

  <input name="some_text" type="text" />
  <input type="submit" name="commit" value="Submit Form" />
</form>

This is a pretty decent setup if you want to use those text boxes to search for valid choices for changing option_value or choice_value. Often, if you’re dealing with related records, you’ll have too many choices to throw a dropdown or select box at it, and you’ll want to have some kind of graceful degradation so you don’t have to rely completely on AJAX auto-completes.

The key point is, you want the form to do different things based on whether the user clicked ‘Search Options,’ ‘Search Choices,’ or ‘Submit Form.’ In my case, I wanted to keep (but not persist) the other values on the form, but display a set of options for the user to choose from if they searched for Options or Choices.

But what happens if they’re typing in search_options or search_choices and they hit enter? That’s an interesting problem.

In Chrome, here’s what happens: it gets the first type=”submit” input on the form, and submits with that value. So in this case, it will send commit=”Search Options.” Even if they were typing in search_choices. Not really ideal, is it?

My solution was to implement a hidden field to see if they hit enter instead of clicking a real submit button. I initially tried with this markup:

<form action="/" method="post"> <input type="submit" name="commit" value="Enter" style="display: none" />

Of course, you’d want to hide that in your stylesheets, not inline css, but this is an example. Unfortunately, it doesn’t work. Turns out Chrome ignores submit tags set to display:none. So, I tried it with visibility:hidden, and that works. Using visibility:hidden means the element still takes up the same amount of space in the display model, it just isn’t accessible to the user. So you have to find somewhere clever to hide it. My final markup looked more like this:

<form action="/" method="post">
  <input name="some_text" type="text" />
  <input type="submit" name="commit" value="Enter" style="display: none" /><br />

  <input type="hidden" name="option_value" value="1" />
  <input name="search_options" type="text" />
  <input type="submit" name="commit" value="Search Options" />
  <br />

  <input type="hidden" name="choice_value" value="1" />
  <input name="search_choices" type="text" />
  <input type="submit" name="commit" value="Search Choices" />
  <br />
  <br />

  <input type="submit" name="commit" value="Submit Form" />
</form>

This way, you can check if commit=”Enter”, and if it does, you can check which of the search fields has content, and conduct an appropriate search based on that. There is a case where it isn’t really possible to tell what the user intended; if they type something into both search_options and search_choices and then hit enter, you can’t be sure which one they meant to search, and there’s no indication of where the cursor was when the user hit enter. In that case, I defaulted to the search_options behavior - without javascript I can’t think of anything better to do.

I wonder if there’s a better solution for browsers? Maybe set a variable like _submitted_from with the name of the text field the user hit ‘enter’ on as the value? I guess there isn’t a variable they can create that isn’t used by some form somewhere on the internet, but it certainly seems worth knowing when you’re trying to divine user intention from stateless form submissions.