How to Add icons to Input (Submit and Reset) Buttons using jQuery UI

As you may have already noticed, most browsers do not support adding icons to <input type=”submit”> and <input type=”reset”> using jQuery UI. The code below will correct this issue by replacing matched <input> tags with appropriate <button> tags…

$(document).ready(function(){
 $('input:submit, input:reset').each(function(){
  $(this).replaceWith('<button type="' + $(this).attr('type') + '">' + $(this).val() + '</button>');
 });
});

We loop through each submit and reset button and replace it with a button tag using the original input’s value as the new button’s text. Since we are using the original input’s value attribute, it should not be considered optional. Otherwise, you’ll end up with a button that has no text unless you set it explicitly with the .button({label: ‘my button label’}) option unless you intend to show only the icon by calling .button({text: false}) option.

Now we can assign icons to the buttons without updating the html using the following code…

 $('button:submit').button({
  icons: {
   secondary: 'ui-icon-circle-check'
  }
 });
 $('button:reset').button({
  icons: {
   secondary: 'ui-icon-circle-close'
  }
 });

12 thoughts on “How to Add icons to Input (Submit and Reset) Buttons using jQuery UI”

  1. Simply replacing an <input type=”submit”> with <button> will not make the <button> work exactly like the <input type=”submit”>.

    If the <input type=”submit”> had name=”aname” and value=”avalue” attributes, then the form would include aname=avalue as one of its parameters. That leads to modification 1: Include name and value parameters in the <button> too. Then it works in IE8, FF4 and Chrome12 (just tested that). But in IE6, it includes Xname=Xvalue sets for *every* such button that once was a submit input.

    I wish I knew of a way for an <input type=”submit”> can turn into a <button> but still retain *all* its previous behaviour…

  2. Since <button> supports name and value attributes, include the HTML 4.01/XHTML 1.0 Strict/Transitional DTD tag at the beginning of the document. Then let me know if this works with IE6…

    $(document).ready(function(){
    $('input:submit, input:reset').each(function(){
    $(this).replaceWith('<button type="' + $(this).attr('type') + '" name=" + $(this).attr('name') + " value="' + $(this).val() + '">' + $(this).val() + '</button>');
    });
    });

    The above code would convert…

    <input type="submit" name="action" value="Process">

    to…

    <button type="submit" name="action" value="Process">Process</button>

    Which should work if the browser parses the button according to the specs outlined in the DTD specified in line 1 of your (x)html document 😉

    Notes/Personal Opinions:
    I know it’s hard to tell a client this, but I do every time I hear “it needs to work in IE6”. IE6 cannot be supported any longer. Microsoft even ended their own support life cycle for that product back in Jul-2010 (a year ago!). We won’t even press the issue that IE6 was released back in Dec-2001 (10 years ago!).

    If a client expects me to code for a decade-old browser (that MS doesn’t even support anymore), I try to explain this to them. If they don’t understand or insist that it must work the same in IE6, I either charge a considerably higher fee or retract my proposal.

    I have yet to find a client that insists on supporting IE6 after explaining the reasons in laymen’s terms.

  3. Or you could use a “proxy button” approach: Hide the submit button, append a and have the click event of the button invoke the click event on the submit.

    e.g.

    $(‘input:submit’).each(function() {
    var button = ”+$(this).val()+”;
    // hide submit and add button after with click linked to submit
    $(this).hide().after(button).next().button({icons: {primary: “ui-icon-plusthick”}}).click(function() {$(this).prev().click(); return false;});
    });

  4. Hi,

    I think page like this makes it more clear (also found as http://www.morch.com/download/submitButtonsFailInIE6.html):

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd"&gt;
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <title>Buttons</title>
    </head>
    <body>
    <form action="missing.cgi">
    <p>
    <button type="submit" name="action1" value="Process1">Process1</button>
    <button type="submit" name="action2" value="Process2">Process2</button>
    <input type="submit" name="action3" value="Process3">
    </p>
    </form>
    </body>
    </html>

    Hitting the either the Process1 or Process2 buttons tries to load this URL:
    missing.cgi?action1=Process1&action2=Process2

    Hitting Process3 tries to load this URL:
    missing.cgi?action1=Process1&action2=Process2&action3=Process3

    So the params for submit buttons are included whether they are pressed or not, but the params for submit inputs are only included if they are pressed. Hence the input to button conversion won’t work for IE6.

    As for IE6, well, one of our largest customers has an internally developed system that only does IE6 and they can’t afford to re-implement it or upgrade it. We support IE6 or they’ll find something that does. Yeah, it sucks.

  5. I understand the issue. I did not realize that <button> name/value pairs were passed even when not pressed. Andy’s solution seems like a good option to achieve what you’re looking for. Give that a shot and let us know if it works out for your needs 😉

  6. I do not understand the code below
    var button = ”+$(this).val()+”;
    in Andy Chapman’s comments
    Is it a typo or new syntax?

  7. I didn’t notice the broken syntax. Here’s how I would implement his implied method…

    $('input[type="submit"]').each(function() {
    	$(this).hide().after('<button>').next().button({
    		icons: {
    			primary: 'ui-icon-plusthick',
    		},
    		label: $(this).val()			
    	}).click(function(event) {
    		event.preventDefault();
    		$(this).prev().click();
    	});
    });

    Tested and works as I think it should. Try this solution Peter 😉

    —– From jQuery —–
    Because :submit is a jQuery extension and not part of the CSS specification, queries using :submit cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. For better performance in modern browsers, use [type=”submit”] instead.

  8. I found that in the last line of codel I had to change
    $(this).prev().click();
    to
    $(this).prev().submit();

    Otherwise, submits inside Ajax.BeginForm do a full submit and not Ajax Html submit.

  9. For ASP .NET I had to change it a little:

    $('input:submit, input:reset').each(function () {
    $(this).replaceWith('' + $(this).val() + '');
    });

    Great post!

Leave a Reply

Your email address will not be published. Required fields are marked *