While I am working on the Search block, I would imagine that this will come into play with the pre-processing of any block.

My goal is simple; I want to turn this:
<input type="submit" id="edit-submit" name="op" value="Search" class="form-submit">

into this:
<button type="submit" id="edit-submit" name="op" class="form-submit">Submit</button>

Basically, moving the value to the correct spot and changing the element. All of the searches I have done explain how to change attributes, but not necessarily the element or moving the value for the element.

Comments

pbose_drupal’s picture

If it is a search block created using Views module (views exposed filter), then the easiest way is to make a copy of the related template in your theme folder, edit it and make changes there.

Tregonia’s picture

I am using the standard search block that comes stock with Drupal.

I have the following in as a hook, but this feels like a hack. I would love to know the correct way.

function sitetheme_form_alter(&$form, &$form_state, $form_id) {
	if ($form_id == 'search_block_form') {
		$form['search_block_form']['#attributes']['placeholder'] = t('Search');
		$form['button'] = array(
			'#type' => 'item',
			'#markup' => '<button type="submit" id="edit-submit-btn" name="op" class="form-submit"></button>',
			'#weight' => 1000,
		);
	}
}

The main reason for this is to have access to CSS pseudo-elements; something that input elements do not have.

Jaypan’s picture

You will need to implement hook_form_alter() for this. Here is the rough example. Let's say your form key is 'some_form_key' and the key for the submit button is 'submit_button':

function my_module_form_alter(&$form, &$form_state, $form_id)
{
  if($form_id == 'some_form_key')
  {
    $form['submit_button']['#type'] = 'button';
  }
}
Tregonia’s picture

That does not actually create a button element; it creates a input element. See the code below taken directly from the browser. I added comments

<div class="container-inline">
	<h2 class="element-invisible">Search form</h2>
	<div class="form-item form-type-textfield form-item-search-block-form">
		<label class="element-invisible" for="edit-search-block-form--2">Search </label>
		<input title="Enter the terms you wish to search for." placeholder="Search" type="search" id="edit-search-block-form--2" name="search_block_form" value="" size="15" maxlength="128" class="form-text">
	</div>
	// This is what is produced from: $form['submit_button']['#type'] = 'button';
	<input type="submit" id="edit-submit-button" name="op" value="" class="form-submit">
	//This is the default button
	<div class="form-actions form-wrapper" id="edit-actions">
		<input type="submit" id="edit-submit" name="op" value="Search" class="form-submit">
	</div>
	// This is the button I created using #markup
	<div id="edit-button" class="form-item form-type-item">
		<button type="submit" id="edit-submit-btn" name="op" class="form-submit"></button>
	</div>
</div>

Here is the hook code; i just added the bottom line today with your suggestion.

function sitetheme_form_alter(&$form, &$form_state, $form_id) {
	if ($form_id == 'search_block_form') {
		$form['search_block_form']['#attributes']['placeholder'] = t('Search');
		$form['button'] = array(
			'#type' => 'item',
			'#markup' => '<button type="submit" id="edit-submit-btn" name="op" class="form-submit"></button>',
			'#weight' => 1000,
		);
    $form['submit_button']['#type'] = 'button';
	}
}
Jaypan’s picture

You're right, it does create an input.

One note before I get started, you don't need to set '#type' => 'item' (or anything else) when you set #markup, because the default #type is 'markup' if nothing else is set.

Anyways, since you want a <button/> tag, you can do this:

$form['button'] = array
(
  '#prefix' => '<button type="submit" id="edit-submit-btn" name="op" class="form-submit">',
  '#suffix' => '</button>',
  '#markup' => '', // This line is required to force the element to render
'#weight' => 1000,
);

But it's not fundamentally different than what you have. You could also pass a render array set to #theme => html_tag. This will work, however I don't believe the values will be processed on the server side. To do that, you'll have to implement hook_element_info(), and the relevant callbacks from there. But that all said and done, I don't think your current method (passing the button in the #markup) will process the value on the server-side either.

Tregonia’s picture

I think the code you have is the better solution. I wonder if the ability to change this would ever find it's way into the API.

None-the-less, I thank you for the response.

reepy’s picture

I found I had to specify '#type' => 'markup' explicitly before it worked in Drupal 7.54. Otherwise the above solution worked.

Ratul Saha’s picture

This works fine, except I am not sure how to remove the actual form-actions <input>. Is adding 'element-invisible' class the only option?

stuart_wagner’s picture

@Ratul Saha, did you solve this? i have the same issue (submit button added, but original submit input remains). there must be a way to unset or remove the unneeded submit input, but i couldn't crack it.

waqarit’s picture

Add the following code snippet to template.php of your theme and you can:

  • change the submit button to an image
  • change the text of the submit button to 'Go!' (just remove the // in front of that line of code, and delete the image_button code below it)
  • add default 'Search this site' text in the input form and make it disappear when users click in the input form
<?php

function YOURTHEME_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'search_block_form') {
    $form['search_block_form']['#title'] = t('Search'); // Change the text on the label element
    $form['search_block_form']['#title_display'] = 'invisible'; // Toggle label visibilty
    $form['search_block_form']['#size'] = 40; // define size of the textfield
    $form['search_block_form']['#default_value'] = t('Search'); // Set a default value for the textfield
    $form['actions']['submit']['#value'] = t('GO!'); // Change the text on the submit button
    $form['actions']['submit'] = array('#type' => 'image_button', '#src' => base_path() . path_to_theme() . '/images/search-  button.png');

// Add extra attributes to the text box
    $form['search_block_form']['#attributes']['onblur'] = "if (this.value == '') {this.value = 'Search';}";
    $form['search_block_form']['#attributes']['onfocus'] = "if (this.value == 'Search') {this.value = '';}";

// Prevent user from searching the default text
   $form['#attributes']['onsubmit'] = "if(this.search_block_form.value=='Search'){ alert('Please enter a search'); return false; }";

// Alternative (HTML5) placeholder attribute instead of using the javascript
   $form['search_block_form']['#attributes']['placeholder'] = t('Search');

  }
}
?>
Bahson’s picture

I was able to do this through this code: In MYTHEME template.php
function MYTHEMENAME_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'search_block_form') {
$form['actions']['submit']['#type'] = 'button';
$form['actions']['submit']['#attributes']['class'][] = 'submit_search-btn';
}
}

I also added a class because I needed it