This was originally posted in a support thread by Borek, but I believe it needs to be posted here as well. This works perfectly in Drupal 5.x.

I have a form function in my module that looks like this:

/**
 * Contribution Form
 */
function ngplinks_form_contribute() {
  $form = array();

  $form['amount'] = array(
    '#type' => 'textfield',
    '#title' => t('Amount'),
    '#default_value' => '',
    '#size' => 7,
    '#maxlength' => 256,
    '#description' => NULL,
    '#attributes' => NULL,
    '#required' => TRUE,
  );
  if (variable_get('ngplinks_subscribe_inline', 1)) {
    $form['amount']['#title'] = '';
    $form['amount']['#default_value'] = t('Amount');
    $form['amount']['#attributes'] = array('onclick' => "if(this.value=='". t('Amount') ."'){this.value='';}");
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Contribute'),
  );

  return $form;
}

Pretty simple form with a single field and a submit button. Now to change the submit button to an image, I created the following function in my template.php file (should be in your theme's folder, create it if you don't have one):

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

You should have one of those for each of the forms you wish to alter. Them make sure this generic theme function is also added to template.php to handle the theming of the buttons:

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";
}

That's all there is to it. Your form will now show your images instead of the default buttons and they will work as expected. Thanks to Borek, kingandy, and simmerz for this incredibly useful tip.

An alternative method would be to use the method described at http://drupal.org/node/153902 to add the image button to your form array and use a simple if check against $_POST to have it submit properly.

If you are having issues in EI try this method below written by geo-ego.

After reviewing many solutions offered for Submit Buttons with images, such as
http://drupal.org/node/153902
http://drupal.org/node/51526
http://drupal.org/node/144758

I came up with a simple one that uses little bit from all those ideas (except CSS and backgrounds).

The idea was to make use of coordinate variable 'op_x' or 'op_y' which is returned through $_POST by all browsers, including IE.

I took all snippets from http://drupal.org/node/51526 but made few changes:
1. Completely removed function hook_imagebutton_process($form)
2. Removed line '#name' => 'op' from function hook_elements()
3. Added line '#name' => 'delete_' . $op_index into my own hook_form() function:


$form['group'][$op_index]['delete'] = array(
                    '#type' => 'imagebutton',
                    '#image' => 'action_del.gif', 
                    '#default_value' => 'Delete' ,
            '#title' => t('Delete this item'),
            '#name' => 'delete_' . $op_index,
                    );

Here, $op_index is an index from my foreach loop i use to generate a sequence of groups in my long form. Each group of items can be moved up, down or deleted from the form by user using icons (images) . I have similar elements for 'up', 'down' and 'delete'.
Before concatenating '#name' => 'delete_' . '$op_index' there was no way to tell which group user wants to move or delete in hook_submit().
Now IE returns me ready to use unique button name: [delete_1_x] or [delete_2_x] etc. :

function hook_form_submit($form_id, $form_values) {
/****************************************************************************
* we use $_POST to avoid IE annoyance: IE doesn't pass values from image inputs!
* so we cannot use [op] from an image button.
* As a workaround, the #name attribute of all image buttons contains operation
* and group index: "down_" .  $op_index.  IE returns coordinates using this name:
*    [down_1_x] => 8, [down_1_y] => 5 etc. 
* We have to parse all $_POST variables from this form to capture this information
*****************************************************************************/
    if (!$form_values['op']) {
      foreach($_POST as $post_var => $post_data) {
          if (substr($post_var,-2) == "_x") { // x coordinate variable
            $op = explode("_", $post_var);
                switch ($op[0]) {  // $op[0] is operation name, $op[1] - button index
                  case 'delete':

                      drupal_set_message($op[0] . ' index: ' . $op[1]);
                    break;
                   
                    case 'up':
                      drupal_set_message($op[0] . ' index: ' . $op[1]);
                    break;
                   
                    case 'down':
                      drupal_set_message($op[0] . ' index: ' . $op[1]);
                    break;
               
                  }
              }
          }
        }
    if ($form_values['op']) {
   
      // Put you standard Submit button processing here;
      }   
}

Now it works with all browsers for any type of operations and number of repeating blocks.

Comments

awm6392’s picture

How do i do this in Drupal 6.x?

Sagar Ramgade’s picture

Hi,

You do not need to follow this in drupal 6,
check this http://api.drupal.org/api/drupal/developer--topics--forms_api_reference....

Acquia certified Developer, Back end and Front specialist
Need help? Please use my contact form

mdshields’s picture

wow, so, it seems in Drupal, '#type' = image_button as the form API is coded TOTALLY different from '#type' = button.

When using '#type' = button, then '#executes_submit_callback' => FALSE works.

When using '#type' = image_button, anything that has an #ajax callback invokes ONLY the #ajax callback on the '#type' = image_button handler.

Wierd, looked into the includes, image_button is doing it's own thing and doesn't behave like a normal submit button.