HOWTO: Create image submit button

Borek - May 9, 2006 - 17:02

Hello, I wanted to change the search box appearance from an ugly grey button to some custom image and I found this task being far from trivial (I even think that there is a bug in Drupal Forms API but I'm a total newbie so I don't want to make quick conclusions). If you have the same issue, read on.

First, please forget the technique which uses CSS only. You may hear of an image replacement trick which substitutes textual 'input type=submit' by some image. Forget it - you will never achieve cross-browser compatibility, I tried hard but failed (I published some results on my Czech blog - you won't understand much but you might appreciate code samples).

The right approach is to change the page rendering and to emit 'input type=image' instead of 'input type=submit'. Here's step-by-step guide:

  1. Navigate to your theme directory and open the template.php file (create it if it doesn't exist).
  2. Add this function:

    <?php
    function phptemplate_search_theme_form($form) {
     
    $form['submit']['#theme'] = 'button';
     
    $form['submit']['#button_type'] = 'image';
     
    $form['submit']['#attributes'] = array(
       
    'src' => '/path-to-your-theme/img/search-button.png',
       
    'alt' => t(Search)
      );
      return
    form_render($form);
    }
    ?>

    This function changes the search form tree (see the Forms API Quick Start Guide if you don't know what I'm talking about) and then renders the form.

  3. In the perfect world, this would be enough, but currently, you need to hack into the Drupal code because the Forms API doesn't support 'input type=image' directly. So in template.php, create another function with the following content:

    <?php
    function phptemplate_button($element) {
     
    // following lines are copied directly from form.inc core file:

      //Make sure not to overwrite classes
     
    if (isset($element['#attributes']['class'])) {
       
    $element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
      }
      else {
       
    $element['#attributes']['class'] = 'form-'. $element['#button_type'];
      }

     
    // here the novelty begins: check if #button_type is normal submit button or image button
     
    $return_string = '<input ';
      if (
    $element['#button_type'] == 'image') {
       
    $return_string .= 'type="image" ';
      }
      else {
       
    $return_string .= 'type="submit" ';
      }
     
    $return_string .= (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ') .'value="'. check_plain($element['#value']) .'" '. drupal_attributes($element['#attributes']) ." />\n";;
      return
    $return_string;
    }
    ?>

  4. Now, you should be ready to go!

My opinion is that Forms API should be image-input-type aware by default. Note that I'm a total newcomer so I might overlook some simpler way to do this but searching for "image" inside form.inc gives me some self-confidence :)

Hope this helped.

HOWTO: Create image submit button

bermin - May 11, 2006 - 19:07

I was having some troubles with this solution but found that you can change a submit button by using INPUT type=image name="search" src="graphics/searchgo.gif" border="0" instead of "type=submit".

Sorry, I don't get it. My

Borek - May 13, 2006 - 08:21

Sorry, I don't get it. My solution is exactly about changing type=submit to type=image. BTW, I filled in the feature request so in future versions, this task should be much easier.

Borek, http://borber.com/

Very useful. I was about to

tag - May 17, 2006 - 21:57

Very useful. I was about to dig in and do the same but you saved me some time, thanks!

One note -- if you're trying to replace the 'search' button in the side block as I was, you want to implement function phptemplate_search_block_form($form) rather than the function you have in the first block of code above.

In Drupal 4.7 this causes drupal to fail to be able to post

jeffreydalton.info - May 24, 2006 - 21:07

Implimented this solution and had a custom search button image which seemd like all was well but then found I could no longer post any data for new pages or edit existing pages. When page is submitted nothing happens but the search does work . :-(

Any ideas???

Better to use a module

Mojah - May 31, 2007 - 02:41

Better to use a module according to this post...

http://drupal.org/node/140387.

It may be related to the problem you're having and it also may be related to this entire post which goes in the direction of editing the form button via a function at the theming level. The user mooffie states that theming functions are run after forms are processed.

Good luck!

Exactly what I needed. Thanks.

skelly - January 13, 2007 - 21:46

Exactly what I wanted to achieve and I was half-way there in a similar fashion till I came across your much neater #button_type work-around.

I agree that this is the "right" way to work around what feels like and oversight in core. Much better than CSS hacks.

Thanks for posting.

Extra submit button

HallSL - January 29, 2007 - 01:23

Thanks for this. I've almost got it working, but I'm getting two buttons in the code, the new graphic one and the old grey one. FWIW they both work. What am I missing?

I'm doing this to a webform if that makes a difference.

Use the right element name

kingandy - March 26, 2007 - 16:31

If the form you're altering uses a different name than "submit" for its submit button, then declaring "$form['submit'][...]" will add an element instead of altering the details of the existing one.

Just change 'submit' to whatever your submit button is called. If you're using the name automatically generated by the webform module, this could be something like "submit_NNNNNNNNNN", where NNNNNNNNNN is a timestamp like '1174926303' or similar. IIRC this should be visible on the webform editing page for the form. Failing that you could look at the HTML code for the finished page and find the "name" the original submit button was given.

Hope that helps. Good luck!

Drupal 5.x fix

kingandy - March 26, 2007 - 16:20

This works fine in my 5.0 installation after addressing one minor change - form_render has been deprecated (in the sense of 'removed') in favour of drupal_render (as mentioned here: http://drupal.org/node/107459).

So the phptemplate_search_theme_form function I have in my template.php file right now is as follows:

<?php
function phptemplate_search_theme_form($form) {
 
$form['submit']['#theme'] = 'button';
 
$form['submit']['#button_type'] = 'image';
 
$form['submit']['#attributes'] = array(
   
'src' => base_path() . path_to_theme() . '/images/btn_search.png',
   
'alt' => t(Search)
  );
  return
drupal_render($form);
}
?>

Code addition to fix edit issue

tklawsuc - April 5, 2007 - 16:01

When overriding the button function I was no longer able to expand any of the fieldsets of options for a node when in edit mode (at least in 5.x). The issue is that the overridden buttons are missing the id attribute which is required by the drupal/upload javascript files for the upload button (attach-button). Minor addition below (added the id attribute) fixed it.

<?php
function phptemplate_button($element) {
 
// following lines are copied directly from form.inc core file:

  //Make sure not to overwrite classes
 
if (isset($element['#attributes']['class'])) {
   
$element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
  }
  else {
   
$element['#attributes']['class'] = 'form-'. $element['#button_type'];
  }

 
// here the novelty begins: check if #button_type is normal submit button or image button
 
$return_string = '<input ';
  if (
$element['#button_type'] == 'image') {
   
$return_string .= 'type="image" ';
  }
  else {
   
$return_string .= 'type="submit" ';
  }
 
$return_string .= (empty($element['#id']) ? '' : 'id="'. $element['#id'] .'" ');
 
$return_string .= (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ');
 
$return_string .= 'value="'. check_plain($element['#value']) .'" ';
 
$return_string .= drupal_attributes($element['#attributes']) ." />\n";
 
  return
$return_string;
}
?>

PS Thanks for the original code Borek!

This can be dropped down even further...

simmerz - May 11, 2007 - 21:39

I found the same problem, but resolved it very simply by adding another condition to replace the "submit" as below. This is using drupal 5.1 and fckeditor 2.4. Thanks for the original code though. Lifesaver.

function phptemplate_button($element) {
  // following lines are copied directly from form.inc core file:

  //Make sure not to overwrite classes
  if (isset($element['#attributes']['class'])) {
    $element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
  }
  else {
    $element['#attributes']['class'] = 'form-'. $element['#button_type'];
  }

  // My change is type="' . (($element['#button_type'] == "image") ? 'image' : 'submit' ) . '"
  return '<input type="' . (($element['#button_type'] == "image") ? 'image' : 'submit' ) . '" '. (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ')  .'id="'. $element['#id'].'" value="'. check_plain($element['#value']) .'" '. drupal_attributes($element['#attributes']) ." />\n";

}

Shortest phptemplate_button yet!

jp.stacey - August 20, 2007 - 19:25

Brilliant. Thanks for that: it saved our bacon during a pair-programming session.

Any reason why the core function we're stubbing out doesn't use the .= operator on the classes? Like this:

<?php
function phptemplate_button($element){
 
// Make sure not to overwrite classes.
 
$element['#attributes']['class'] .= ' form-'. $element['#button_type'];
 
  return
'<input type="'.(isset($element['#button_type']) ? $element['#button_type'] : "submit").'" '. (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ')  .'id="'. $element['#id'].'" value="'. check_plain($element['#value']) .'" '. drupal_attributes($element['#attributes']) ." />\n";
}  
?>

Also, here's a version of the hook_alter_form to use if you prefer that to intercepting the form at the template level rather than using phptemplate_search_theme_form:

<?php
function mymodule_form_alter($form_id, &$form){
  if (
$form_id == 'search_theme_form'){
   
$form['submit'] = array(
     
'#type' => 'submit',
     
'#theme' => 'button',
     
'#button_type' => 'image',
     
'#value' => t('Go'),
     
'#attributes' => array('src' => 'search_go.gif')
    );
  }
}
?>

Expand that if () with else statements for whatever you fancy overriding.

I"ve tried this. To see if

nimzie - February 19, 2008 - 18:52

I"ve tried this. To see if I'm getting hooked, I echo some things and it's getting run.

But, my HTML for the search submit btn isn't including the img src bit. I've verified my path to the image.

Is there anything else people can elaborate on which may fix?

Thanks,

Adam

Explorer 7 problem

nir - February 24, 2008 - 13:18

I tried this code to modify my poll block vote button
the result works in firefox but not in explorer 7

Thanks

form_render() Not Found

asaxe - April 20, 2007 - 16:52

I added both of the noted functions to template.php, but I recevie an error message saying the form_render() is undefined. Any thoughts?

Thanks,
Andrew

yea...look at the above comment

studley181 - April 21, 2007 - 21:10

http://drupal.org/node/62647#comment-214956 I got it to work after i changed the function name.

Parse error

psc - May 5, 2007 - 23:28

Parse error: parse error, unexpected T_VARIABLE in the line

  $form['submit']['#theme'] = 'button';

I tried also with another name instead of 'submit' but the same problem...

Why? (sorry! no idea of PHP but a master on copy-paste ...)

I have Druapl 5.1

psc

Since that line looks OK to

kingandy - May 8, 2007 - 08:21

Since that line looks OK to me, it's possible the problem really lies on the preceding line - it's not expecting to encounter that variable because it's not done with whatever it was doing before.

Check the end of the line before - did the '{' fall off somehow? (Or, if you've added code, did you miss a ';' ?)

...but error persists

psc - May 8, 2007 - 13:24

I copied the two fixes functions for Drupal 5. Yours and tklawsuc's.

The one and only chage I did is the name of the search button image file in my theme images folder.

Is there anything else I should change?

My error message:

Parse error: parse error, unexpected T_VARIABLE in /homepages/24/d32156390/htdocs/drupal5/sites/all/themes/mytheme/template.php on line 31

Line 31 in my template.php is
  $form['enviar']['#theme'] = 'button';

Thanks!

psc

Again, though it's

kingandy - May 8, 2007 - 13:31

Again, though it's encountering the unexpected variable on line 31 it's likely due to a typo on an earlier line (it's one of those subtly misleading, though wholly accurate, error messages) ... if you post the whole function I'll see if I can spot anything obviously out of place.

the function

psc - May 8, 2007 - 15:21

function phptemplate_search_theme_form($form) {
  $form['submit']['#theme'] = 'button';
  $form['submit']['#button_type'] = 'image';
  $form['submit']['#attributes'] = array(
    'src' => base_path() . path_to_theme() . '/images/mysearch.png',
    'alt' => t(Search)
  );
  return drupal_render($form);
}

if i change 'submit' with something different, i get the same error...

should I change something on it (apart form changing my search icon name)?

psc

Try : 'alt' => t('Search')

kenji_kun - June 29, 2007 - 09:28

Try : 'alt' => t('Search')

Added to theme snippets library

seanr - May 17, 2007 - 16:29

Hope you all don;t mind but I found this so incredibly useful that I added it to the snippets library so others would be more readily able to find it and make use of it:

http://drupal.org/node/144758

Sean Robertson
webolutionary@webolutionary.com

thanks

hunthunthunt - May 31, 2007 - 14:30

This is a great snippet.

Agree, this functionality should be in core.

Thanks also to kingandy's comment.

Ugly but much less code

reed.r - June 19, 2007 - 12:38

I did this instead on the output form returned,

<?php
$myVariable
= str_replace('type="submit"', 'type="image"', str_replace('value="Send"', 'src="files/myimage.gif"', my_form() ) );
?>

much easier, even though I have to admit it is a shortcut and I don't know about the efficiency when there's a lot of users...

Anyone achieve to make this

SimonVlc - July 22, 2007 - 17:30

Anyone achieve to make this work in IE? After pressing the submit image button, it didn´t work in this explorer (it only returns to the same comment page). Any idea? Thanks in advance, Simon.

So I must say that this

SimonVlc - July 29, 2007 - 15:53

So I must say that this method don´t work in drupal 5.1. At least, for me.

responded in your other thread

pescobar - August 3, 2007 - 18:42

hi simon,

i think i've found out what the issue is in IE

responded in your other thread:

http://drupal.org/node/160682

CSS can get you there, too...

dgorton - September 6, 2007 - 15:01

I wanted to do the same for one of our sites recently and realized the non-trivial size of the task as well. I decided to handle this on the completely other end (via CSS) - but I do wish I'd seen this thread first.

Big picture - both the search text field and the search button needed to be styled. The text field had an odd background (rounded corners and a slight gradient). The search button was a magnifying glass (or some such thing). The following CSS accomplished it in Win IE6, IE7, Firefox 2 and Mac Firefox 2 and Mac Safari 3 (currently in beta). Mac Safari 2 doesn't allow real styling of buttons, but as our site is under development and Safari 3 solves it, we're considering this a sufficient solution (and I like anything that can keep us from fiddling with php - better upgrade paths, etc.)

So - here's the CSS I put together:

#search {
  background-image: url(images/search_background.gif); /* the fancy-looking text input - rounded corners and gradient */
  background-color:transparent;
  background-repeat: no-repeat;
  background-position: left center;
   width: 208px; /* arbitrary - what was necessary for our images to line up */
  text-align: left; /* see above */
}
#search-theme-form div { /* to deal with some IE6 stupidities - relevant because of the way our page lays out and possibly relevant for others */
  margin-right: 0;
  padding-right: 0;
}
#search #edit-search-theme-form-keys { /* hide the text input box *
  border: none;
  background-color: transparent;
}
#search #edit-submit {  /* hide the search button and put in a fancy little image, instead */
  background-color: transparent;  /* hide standard button display stuff */
  border: none; /* hide standard button display stuff */
  background-image: url(images/search_go_btn.gif); /* put in fancy image */
  background-repeat: no-repeat;
  vertical-align: middle;
  height: 25px; /* fancy image height */
  width: 25px; /* fancy image width */
  text-indent: 25px; /* move the 'Search' text on the button to the right */
  word-spacing: 10em; /* and space it out -- both of these shouldn't be necessary, but the combination makes all our browsers style this correctly */
  text-align: right; /* see above */
  cursor: pointer; /* make the mouse give the right feedback - IE stupidity, again */
}

Took some fiddling to get there, but it works... and it's a pure CSS solution - which means your php can remain untouched.

Drew Gorton
Gorton Studios
Some of our Drupal Sites

I personally had problems in

rtbox - April 9, 2008 - 00:03

I personally had problems in opera with the above code, although it worked fine in every other major browser,

however, I am currently using a solution detailed on the below link, and it seems to work for me on every major browser.

http://www.ampsoft.net/webdesign-l/image-button.html

Accessibility issues

kingandy - April 9, 2008 - 08:26

I remember reading an article somewhere that pointed out those methods will make the page unreadable if you have CSS enabled but don't load images for some reason (either a temporary connection glitch or if you just have images disabled as a matter of course - maybe to conserve bandwidth or some such). Since it's not an actual image object you don't get the luxury of 'Alt' text, so if the background image fails to load for whatever reason you'll just get a blank area.

The article did propose some method of addressing it, but I can't remember what. Possibly placing the image in a separate block area, absolutely positioned so as to appear in front of the text? That technique probably wouldn't be applicable for a Submit button anyway.

That said, I use this method all the time for headers. I just thought it was worth mentioning for those of us who care more than me ;)

--Andy
Developing Drupal websites for Livelink New Media

Hmm, thats a great point.

rtbox - April 11, 2008 - 01:33

Hmm, thats a great point. The problem would also effect to text based browsers, and accessibility to the disabled (such as blind). Not sure if a PA fix is really the idea solution. Plus it may become a little complicated if you start moving stuff around with javascript (such as moofx).

If anyone has ideas on a good solution, please enlighten me. I will look into this myself, if I figure anything else i'll post it up here.

Thanks!
Richard Box

Yes...

dgorton - April 11, 2008 - 20:17

Like Andy, I'm both aware of this issue and also aware of my own failings.

FWIW, you can scrutinize that code in it's real life form at http://www.greenguardian.com/. Having a real life test URL may help any effort to throw lots of different user agents at the code and find it's shortcomings.

Suggestions for further improvements are always welcome!

Drew Gorton
Gorton Studios

For what it's worth...

kingandy - April 17, 2008 - 09:32

FWIW, most text-based browsers and/or readers won't be impacted by a text-indent declaration - likewise the normal document flow returns if CSS is lost altogether. It's only people in the bizarre twilight hinterland of active-CSS-but-no-images that will be affected.

--Andy
Developing Drupal websites for Livelink New Media

Accessible CSS form buttons

Keyz - January 11, 2009 - 10:49

In case anyone reads this down the line... I found this solution which works great and solves the above-mentioned accessibility concerns:
http://fortysevenmedia.com/blog/archives/making_accessible_css_buttons_l...

-- David
davidnewkerk.com | absolutecross.com
View my Drupal lessons & guides

Code causes problems with collapsible fieldsets

kingandy - October 8, 2007 - 09:53

Half a year later, I realise that this is what has caused my collapsible fieldsets to conflict with the inline upload functionality. Comparing it with the core theme_button() function, I've realised this code is neglecting to declare an id attribute in the returned input tag. The following code seems to function correctly:

<?php
function phptemplate_button($element) {
 
// following lines are copied directly from form.inc core file:

  //Make sure not to overwrite classes
 
if (isset($element['#attributes']['class'])) {
   
$element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
  }
  else {
   
$element['#attributes']['class'] = 'form-'. $element['#button_type'];
  }

 
// here the novelty begins: check if #button_type is normal submit button or image button
 
$return_string = '<input ';
  if (
$element['#button_type'] == 'image') {
   
$return_string .= 'type="image" ';
  }
  else {
   
$return_string .= 'type="submit" ';
  }
 
$return_string .= (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ') .'id="'. $element['#id'].'" value="'. check_plain($element['#value']) .'" '. drupal_attributes($element['#attributes']) ." />\n";
  return
$return_string;
}
?>

--Andy
Developing Drupal websites for Livelink New Media

Which is why CSS is nice...

dgorton - October 8, 2007 - 16:04

This is a great case-in-point where PHP changes can cause something unintended, and a reason to consider spending the time to solve these sorts of visual changes through CSS alone wherever possible. It can still break, mind you (if, for example, the HTML output, such as IDs change) - but that sort of break is both quickly obvious (it's visual) as well as extremely unlikely to effect the functionality of anything else (e.g. only if something else where to be output with ' id="search" ').

Not trying to take away from the hard work and usefulness of the above solutions - just been through this sort of ringer before and unhappy with having to go back and fiddle with phptemplate_* functions when oddities such as this are discovered.

Drew Gorton
Gorton Studios

Proper use of Themeable functions

kingandy - October 9, 2007 - 08:48

The other thing that occurred to me while investigating this was that completely overriding the function - ie, duplicating it and making your own changes - means any changes in the core function down the line will not be reflected (which is in fact what's happened here - the 4.7 version of the function doesn't include the id attribute).

Perhaps a better function would be something like:

<?php
function phptemplate_button($element) {
  if (
$element['#button_type'] == 'image') {

    if (isset(
$element['#attributes']['class'])) {
     
$element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
    }
    else {
     
$element['#attributes']['class'] = 'form-'. $element['#button_type'];
    }

    return
'<input type="image" '. (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ')  .'id="'. $element['#id'].'" value="'. check_plain($element['#value']) .'" '. drupal_attributes($element['#attributes']) ." />\n";

  } else {
    return
theme_button($element);
  }
}
?>

... Or, heck, even simpler:

<?php
function phptemplate_button($element) {
 
$return_value = theme_button($element);
  if (
$element['#button_type'] == 'image') {
   
$return_value = str_replace('type="submit"','type="image"',$return_value);
  }
  return
$return_value;
}
?>

... since literally all we're doing is changing the type from "submit" to "image" (all the SRC attributes and such get passed through regardless of the element type.

On a final note I've noticed this comment above by tklawsuc which both identified and resolved the problem about a week after my first post in this thread. I am dumb.

--Andy
Developing Drupal websites for Livelink New Media

This requires no changes to elements and allows for l10n

Dave Cohen - October 29, 2007 - 23:23

Here's a version that looks for images based on the button's #value. This means it will display an image only if the theme has one, but not otherwise (i.e. if 'Submit' was translated to another language).

In this case the theme is called medemcom and images are in themes/medemcom/i/.

<?php
/**
* Replace form submit buttons with images.
*
* Looks for an image file named 'i/b_TITLE.gif', and if found, uses the image.
*/
function medemcom_button(&$element) {
 
// Naming convention: images are stored in this theme's i/ directory.
 
$filename = 'b_' . strtolower($element['#value']) . '.gif';
 
$filepath = drupal_get_path('theme', 'medemcom') . '/i/'.$filename;
 
  if (
file_exists($filepath)) {
   
// This code based on theme_button from form.inc
   
if (isset($element['#attributes']['class'])) {
     
$element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
    }
    else {
     
$element['#attributes']['class'] = 'form-'. $element['#button_type'];
    }
   
   
$output = '<input type="image" src="'. url($filepath) .'" '. (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ')  .'id="'. $element['#id'].'" value="'. check_plain($element['#value']) .'" '. drupal_attributes($element['#attributes']) ." />\n";
  }
  else {
   
$output = theme_button($element);
  }
 
  return
$output;
}
?>

Awesome!

trevorleenc - January 16, 2008 - 21:13

@Dave Cohen

What a great piece of code, while I can see the advantage of using css to do this...was the original direction I was going in, the ability to just create a button say from my own button "dev kit", and then name it like so...drop it in, and forget it...awwww yeah!

thanks!

You know what, unfortunately

Dave Cohen - January 18, 2008 - 18:52

You know what, unfortunately I started to have problems with that code. Damn IE can't cope with image buttons like normal browsers do. So for example if you make all your Submit buttons images, then on IE you'll have trouble submitting nodes.

If you have any tips to solve that please post here.

Why not just use CSS?

dgorton - January 19, 2008 - 04:10

Won't it get you there faster and more reliably? The code in the comment above (http://drupal.org/node/62647#comment-258485) works just fine (you can see it in the wild at http://www.greenguardian.com). Variations on that code exist on most of our sites and it works well. Arguably, the CSS above was a bit dense with the layering of background images and all - but a simpler version can be seen, for example, on the Rake Magazine -- http://www.rakemag.com -- just hit the search button with Firebug to take a look:

#searchbox #edit-submit {
  background:transparent url(images/bg-search-button.gif) no-repeat scroll right center;
  border:medium none;
  color:#FFFFFF;
  height:21px;
  padding-left:3px;
  padding-right:20px;
  text-transform:uppercase;
  width:46px;
}

No fussing about with phptemplate functions, no worries with upgrade paths or unintended consequences - that code is only going to effect the search box - and it will do so in a way that degrades extremely well. I have trouble seeing the downside, I guess.

Regardless, however, the good news is that this will be an obsolete conversation come Drupal 6 - I recall reading a changelog somewhere (* I think *) describing image submit buttons in core.

Drew Gorton
Gorton Studios

what version of IE?

trevorleenc - January 19, 2008 - 11:23

I've got this running on two sites that work well under the following

IE6
IE7
FF2
Opera9
Safari (3.0.4/win)

I have however, not replaced any of drupal's "admin" buttons, but then again, I also use an admin theme anyway.

but I've replaced:
search
advanced search
post comment
preview comment
Log In
Create New Account

and a few others...

what kind of IE issues and where did you encounter them ?

When a button is an image on

Dave Cohen - January 20, 2008 - 00:27

When a button is an image on IE, it neglects to POST the button's value. For many forms this works OK. For the node submit form, Drupal needs to know whether the button pressed was Submit as opposed to Preview or Delete. Since IE never tells the server it was the submit button, nodes can no longer be submitted.

@dgorton: I used code rather than stylesheets because I wanted to very easily support a bunch of different buttons which appear on different forms. In my case the images are pictures of words, and I wanted the proper image to be found on translated pages (and fail gracefully if the translated image was not found).

An (ugly) solution

andrabr - February 29, 2008 - 06:18

I just posted one here: http://drupal.org/node/153902#comment-751457

It works for the edit form, but it does require functional jQuery in IE.

also, meant to add to this...

trevorleenc - January 16, 2008 - 21:21

in order to handle buttons like "Log In" or "Advanced Search" etc, add str_replace() to remove the space in between words.

change this:

$filename = 'b_' . strtolower($element['#value']) . '.gif';

to:

$filename = 'b_' . strtolower(str_replace(" ", "", $element['#value'])) . '.gif';

again...great snipplet!

Just use CSS

coopdrup - November 4, 2007 - 15:47

#mybutton {
background:transparent url(images/mybutton.gif) no-repeat center;
border:none;
cursor:pointer;
font-size:0pt;
color: #ffffff
height:33px; /* or whatever */
width:94px; /* or whatever */
}

This is a presentation-layer problem, so solve it in the presentation layer -- leave your markup and php and modules and API's alone :)

I think you're right:

ragaskar - December 19, 2007 - 20:52

I think you're right: between these two hacks, the CSS option is the least evil.

FWIW, however, I had better luck with the second technique presented at http://www.ampsoft.net/webdesign-l/image-button.html (the above code failed due to the font-size being set to 0pt):

#edit-submit {
  width:118px;
  height: 25px;
  padding: 25px 0 0;
  margin: 0;
  border: 0;
  background: transparent url(my_button.gif) no-repeat center top;
  overflow: hidden;
  cursor: pointer; /* hand-shaped cursor */
  cursor: hand; /* for IE 5.x */
}
form>#edit-submit { /* For non-IE browsers*/
  height: 0px;
}

This one works well

BradleyT - July 15, 2008 - 20:10

Thanks this one works great.

All I changed was to add the search ID in front of #edit-submit so that my admin forms (and other onsite form submit buttons) didn't change to a little search graphic.

#search #edit-submit {
  width:69px;
  height: 20px;
  padding: 25px 0 0;
  margin: 0;
  border: 0;
  background: transparent url('/themes/pushbutton/images/search.gif') no-repeat center top;
  overflow: hidden;
  cursor: pointer; /* hand-shaped cursor */
  cursor: hand; /* for IE 5.x */
}
#search form>#edit-submit { /* For non-IE browsers*/
  height: 0px;
}

Thanks cooperwd, I feel this

ToshoFreny - July 22, 2008 - 06:29

Thanks cooperwd,
I feel this is the best method-- changing the font size to 0px. Other methods mentioned in this page change the padding settings and hide the overflow content, which distorts the placement of the searchbutton in my theme. This one, changing the font-size to 0 is cool, works without distorting my theme alignments.

Loving Life,
Tosho Freny,

Great thanks

JohnnyMoney - September 4, 2008 - 12:06

Works great thanks!
*****************************
Drupal Video Tutorials (Spanish)
www.drupalcarmen.com

Using theme override and javascript

Dave Cohen - April 9, 2008 - 17:25

My earlier approach had the shortcoming that on IE the value of the button was not submitted, and drupal failed to learn the $op of many form submits. (The shortcoming is in IE, not the technique itself). To work around IE's lameness, I'm now using a combination of themeing and javascript. Images are used in place of buttons only when javascript is enabled, and the theme function finds an image for the button in question.

First, the theme function renders both a button and an image. The image is set not to display:

<?php
/**
* Replace form submit buttons with images.
*
* Looks for an image file named 'i/b_TITLE.gif', and if found, uses the image.
*/
function phptemplate_button(&$element) {
 
$text = str_replace(' ', '_', $element['#value']);
 
// Naming convention: images are stored in this theme's i/ directory.
 
$filename = 'b_' . strtolower($text) . '.gif';
 
$filepath = drupal_get_path('theme', 'medemcom') . '/i/'.$filename;
 
 
// Suppress this behavior on node forms because we dont have images
  // for all buttons
 
if (file_exists($filepath)) {
   
// Use the original button
   
$button = theme_button($element);
   
$image = '<input style="display: none;" type="image" src="'.
     
base_path() . $filepath .'" name="'.$element['#name'] .'" id="'. $element['#id'].'" value="'. check_plain($element['#value']) .'-image" '. drupal_attributes($element['#attributes']) ." />\n";
   
// Render the image next to its button equivalent.  Hide the
    // image, it will be shown later only if javascript is enabled.
   
$output = '<span class="buttonreplace">'. $button . $image . '</span>';
  }
  else {
   
$output = theme_button($element);
  }
  return
$output;
}
?>

My theme includes some javascript on every page, and that javascript does two things. First, it hides the buttons and shows the images in their place. Second, when an image is clicked, it triggers the click event on the button. That way its as if the button was pressed, not the image, thus despite the efforts of the developers in Redmond, IE is bent to obey our will:
  /* Buttons are sometimes rendered with their image equivalent, but the image
   is hidden.  If javascript is enabled we can show the image and hide the
   button, then do some work when the click is done to make it work on IE. */
  $('span.buttonreplace input[@type=image]').show().
  click(function (e) {
      // Pass the click on to our button sibing.
      $(this).siblings().click();
      return false;
    });
  $('span.buttonreplace input[@type=submit]').hide().
  click(function (e) {
      // Pass the click on to the browser.
      this.click();
      return true;
    });

@Dave

noahb - May 2, 2008 - 22:48

@Dave
Thanks for this code, it's a big help.
I did notice some strange behavior (in IE of course) on certain forms (specifically the pollfield module), where the form was being submit twice. It seems like the click() function is actually being handled differently on IE vs FF/Safari, so I modified the jQuery:

  $('span.buttonreplace input[@type=image]').show().
  click(function (e) {
    $(this).parents("form").submit();
      return false;
    });
  $('span.buttonreplace input[@type=submit]').hide();

This method might also need a bit of testing to make sure that the direct parent form is being submit, but other than that, I think this should work.

Anyone see any other problems with my changes?

[Update]
Testing indeed... the above bit of jQuery is rubbish. Well, it worked for the pollfield submission form, but seemed to break just about every other form. Needless to say, I would not use it.

[Update Deux]
Ok, I think I've found a solution that works now... Back to Dave's method of emulating the click on the button, with on slight change. I removed (or commented out below) the click() function in the prototype function for the hidden submit button. This second click() was firing a second click event, which broke some forms.

  $('span.buttonreplace input[@type=image]').show().
  click(function (e) {
  // Pass the click on to our button sibing.
    $(this).siblings().click();
    return false;
    });
  $('span.buttonreplace input[@type=submit]').hide().
  click(function (e) {
    // The second click() function was sending a second click event
    //  which broke some forms, so I disabled it, and voila!
    // $(this).click();   
    return true;
    });

Hmmmmm..... I can't recall

Dave Cohen - May 3, 2008 - 15:17

Hmmmmm..... I can't recall exactly which browser or what the circumstances were, but I remember needing that this.click() to get a form to submit properly. And it was this.click() (on the DOM object), not $(this).click() (on the jquery object) that I needed.

Maybe we're using different versions of jquery? I've only used that code in Drupal 5.x.

Thanks for the updates, though. It would be good to be certain that code really works everywhere.

Ahhh... I think you nailed

noahb - May 5, 2008 - 01:28

Ahhh... I think you nailed it, cuz I forgot to mention that I was using a newer version of jquery (1.1.2 from the jquery_update module).

Once again, thanks for posting this in the first place, I now it working on more than 30 or 40 buttons, and can see where this would be very useful for a multi language scenario.

nice - I was looking for something like this - thanks.

pairodimes - May 7, 2008 - 20:09

gracias.

the php part of this works

rpmute - February 17, 2009 - 00:49

the php part of this works great, however, the js is doing nothing. It's been added to the theme template, so it's on all the pages.... any ideas?

running drupal 5x, my site's got jquery updated to 1.2.6 I don't know js well, could the problem be that this code is outdated?

Using Images as Submit

Robert Castelo - October 9, 2008 - 15:16

I recommend using this technique instead:

http://alligatorsneeze.com/node/943

Code Positive Limited
Drupal Developers & Consultants - London, UK

robert: thats a great

rpmute - February 16, 2009 - 22:57

robert: thats a great method but unfortunately it doesn't address the problem with IE. just tried it today.

submit function

mirian - December 29, 2008 - 13:47

Miriam N.
Hi,

The replacement of the button with an image works perfectly to me,

BUT-

I have a submit function to my form and it hasn't been called! just the "form action" was performed..

What did I missed???

thank you,

Miriam

drupal 6

slip - May 31, 2009 - 16:45

Hi, It seems to be working

dsamborschi - July 29, 2009 - 01:06

Hi,

It seems to be working except one thing. For some reasons I end up having two buttons, one is the type of image, the second is type of submit.

How to remove the default one and leave just the new image button in the form?

Thanks,
Dan

Two buttons except just one

dsamborschi - July 29, 2009 - 01:07

Hi,

It seems to be working except one thing. For some reasons I end up having two buttons, one is the type of image, the second is type of submit.

How to remove the default one and leave just the new image button in the form?

Thanks,
Dan

 
 

Drupal is a registered trademark of Dries Buytaert.