creates CSS hooks (ID tags) for each .form-item
| Project: | FriendsElectric |
| Version: | HEAD |
| Component: | Suggestions |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | needs review |
Jump to:
this glob of code goes in template.php. I wrote it in order to 'tidy-up' node-editing pages, but it could be modified to make it much more powerful (the form-item DIV seems to be used everywhere!). This is my first really useful hack & I'm sure it can be improved upon (eg it has no useful identifiers for form-items which do not include some kind of input field).
What it does is generate an ID tag from the name-attribute of the input field. The tag is inserted into the <DIV class="form-item"> tag so that it encloses the whole form-item: $title (the label) $description (the help text) and $value (the input field itself). This makes instances of the ubiquitous <DIV class="form-item"> less anonymous and more themeable via CSS. Eg. <DIV class="form-item" id="css_edit_title"> and <DIV class="form-item" id="css_edit_flexinode_4">(which is a flexinode field, not a flexinode!).
/* ------------------------------------------------------*/
/* re-organise presentation of form elements / form-item */
/* ------------------------------------------------------*/
/* first we need this function locally? */
function form_clean_id($id = NULL) {
$id = str_replace('][', '-', $id);
return $id;
}
/* then we need to get our $idname */
function form_item_get_idname($value) {
$nameregexp = '/name=\"(.*?)\"/i';
preg_match ($nameregexp, $value, $matches);
$sensitive = array ('@\[@si','@\]@si','@:@si');
$replace = array ('_','','');
$idname0 = preg_replace($sensitive, $replace, $matches[1]);
$idname = 'css_'.$idname0;
return $idname;
}
/* Catch the theme_form_element function, and redirect through the template api */
function phptemplate_form_element($title, $value, $description = NULL, $id = NULL, $required = FALSE, $error = FALSE) {
$output = '<div class="form-item" id="'. form_item_get_idname($value) .'">'."\n" ;
// $output = '<div class="form-item" id="'. 'idname' .'">'."\n";
$required = $required ? '<span class="form-required">*</span>' : '';
if ($title) {
if ($id) {
$output .= ' <label for="'. form_clean_id($id) .'">'. $title .':</label>'. $required ."\n";
}
else {
$output .= ' <label>'. $title .':</label>'. $required ."\n";
}
}
if ($description) {
$output .= ' <span class="description">('. $description .")</span><br />\n";
}
$output .= " $value\n";
$output .= "</div>\n";
return $output;
}
/** note on CSS definitions:
* When there is no name= attrubute to the element, the generic id will be id="css_".
* These are common on ordinary node pages eg .node #css_ {} so be careful!
* I used .node-form #css_ {display: none} to hide the 'formatting guidelines' that
* normally appear under textareas (WYSIWYG editor makes them redundant).
**/
/* --------------------------------------*/BTW It also (by introducing <span>tags) tweeks the html layout of these elements within the form item, from
$label :
[ $value ]
$description
to
$label : $description
[ $value ]
Any and all feedback welcome.

#1
this is exactly what I needed in order to hide certain fields by loading in different CMS based on the current user role
#2
...sorry, that's CSS not CMS :)
#3
I really find the addition of the id attribute to the <div class='form-item'> very useful and think that it should be added to the core drupal code rather than having specify it per theme. I prefer my theme's default form layout however.
#4
it doesnt seem to work in drupal5+.. in default garland theme...
any help?
#5
I'm not really surprised this patch applies to D5 & garland theme ... it's a long time ago !!! There's been a new Forms API and a lot of code under the bridge since then :-P
Recently I was playing with Nedjo's new Formfilter module which is still quite a young module but a very good starting place if you are trying to tidy-up the UI on your D5 input forms.
A quick look at theme_form_element in Drupal APIs shows that it still exists and still does a similar job ;-) It looks a lot easier to do this id-trick in D5 ... I just tried this in D5 Garland template.php and as far as I can see it works just fine:
<?php
/**********************************************************************/
/** Put form-element id into form-item div tag - <a href="http://drupal.org/node/33850" title="http://drupal.org/node/33850" rel="nofollow">http://drupal.org/node/33850</a> **/
/**********************************************************************/
function phptemplate_form_element($element, $value) {
// $output = '<div class="form-item">'."\n";
$output = '<div class="form-item" id="' . $element['#id'] . '">'."\n";
$required = !empty($element['#required']) ? '<span class="form-required" title="'. t('This field is required.') .'">*</span>' : '';
if (!empty($element['#title'])) {
$title = $element['#title'];
if (!empty($element['#id'])) {
$output .= ' <label for="'. $element['#id'] .'">'. t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
}
else {
$output .= ' <label>'. t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
}
}
$output .= " $value\n";
if (!empty($element['#description'])) {
$output .= ' <div class="description">'. $element['#description'] ."</div>\n";
}
$output .= "</div>\n";
return $output;
}
/**********************************************************************/
?>
Now that we have these fieldsets everywhere, I guess we might want to give them the same treatment ... but we'll use the fieldset title as the tag:
<?php
/**********************************************************************/
/** Do the same to the fieldset tag - <a href="http://drupal.org/node/33850" title="http://drupal.org/node/33850" rel="nofollow">http://drupal.org/node/33850</a> **/
/**********************************************************************/
function phptemplate_fieldset($element) {
if ($element['#collapsible']) {
drupal_add_js('misc/collapse.js');
if (!isset($element['#attributes']['class'])) {
$element['#attributes']['class'] = '';
}
$element['#attributes']['class'] .= ' collapsible';
if ($element['#collapsed']) {
$element['#attributes']['class'] .= ' collapsed';
}
}
return '<fieldset' . drupal_attributes($element['#attributes']) . ' id="' . $element['#title'] . '">' . ($element['#title'] ? '<legend>'. $element['#title'] .'</legend>' : '') . ($element['#description'] ? '<div class="description">'. $element['#description'] .'</div>' : '') . $element['#children'] . $element['#value'] . "</fieldset>\n";
}
/**********************************************************************/
?>
I have not tested these extensively ... they seem OK but feedback would be very welcome.