FAPI: Add name/type as CSS class for form elements

Montuelle - January 5, 2006 - 22:15
Project:Drupal
Version:7.x-dev
Component:forms system
Category:feature request
Priority:normal
Assigned:sun
Status:closed
Issue tags:needs themer review
Description

Currently a form item (and its label) is surrounded by <DIV class="form-item"> and </DIV>.
It would be good to add a second class giving the type of form-item beside the class="form-item", for example: class="textarea" or class="radio" or class="select".
giving something like: <DIV class="form-item textarea"> wich could be referenced in a CSS file by a .textarea. When this feature is not needed nothing has to be changed in the CSS files because the .form-item definitions are applied as usual.

This will allows to easily style form-items according to their type (textarea, radio, select, ...).

(I have classified this feature under "base system" because I don't know really which component(s) has to be modified. Sorry if this is wrong).

Thanks for considering this proposition.

#1

LAsan - March 26, 2008 - 16:07
Version:x.y.z» 7.x-dev
Component:base system» forms system
Priority:normal» minor
Status:active» fixed

Old topic with no feedback.

Moving to fixed.

#2

Anonymous (not verified) - April 9, 2008 - 16:14
Status:fixed» closed

Automatically closed -- issue fixed for two weeks with no activity.

#3

sun - June 6, 2008 - 00:53
Title:Allow flexible styling for form-item according to their type» FAPI: Add name/type as CSS class for form elements
Priority:minor» normal
Assigned to:Anonymous» sun
Status:closed» needs review

+1

This is what we're actually doing in a per-se default override of theme_form_element() in all of our Drupal sites. Theming forms based on these classes is *a lot* easier, because you simply can't differ between div.form-item and div.form-item in CSS.

Attached patch adds the element's #name (if set) to the .form-item container (resulting in <div class="form-item elementname">), and the element's #type to the label of radio buttons and checkboxes (resulting in <label class="radio">), which is usually needed to take the special rendering/layout of single radio buttons/checkboxes into account.

AttachmentSizeStatusTest resultOperations
drupal.form-element-class.patch1.41 KBIdleFailed: Failed to install HEAD.View details | Re-test

#4

lilou - August 23, 2008 - 21:23

Patch still applied.

#5

System Message - November 16, 2008 - 21:40
Status:needs review» needs work

The last submitted patch failed testing.

#6

sun - December 4, 2008 - 02:05
Status:needs work» needs review

Re-test.

AttachmentSizeStatusTest resultOperations
drupal.form-element-class.patch1.41 KBIdleFailed: 7658 passes, 1 fail, 0 exceptionsView details | Re-test

#7

Wim Leers - December 4, 2008 - 21:52

+1

This also allows for less tricky/more readable JS code.

From:
$('div.form-item[select]')
To:
$('.select')

#8

System Message - December 14, 2008 - 04:55
Status:needs review» needs work

The last submitted patch failed testing.

#9

SocialNicheGuru - February 17, 2009 - 14:19

will this also work on D5 or D6? This is a great idea.

For those of us who just want to theme a form we created in using cck like a node profile for example, I would love to easily get to the element to theme instead of having to do form manipulation heavy lifting with hook form alter.

Is there a D5 or D6 equivalent?

If something like this is already available, you can contact me and let me know. I have been looking and have not found or understood as much as I should.

Thanks,
Chris

#10

stBorchert - April 26, 2009 - 09:06
Status:needs work» needs review

This patch additionally adds the classes from the element to the surrounding div. In combination with #342316: FAPI: Turn options and optgroups into proper #types this allows you to style the complete element (including label), e.g. a checkbox with class="default".

Imo its no necessary to set the class to the label because you can style it with div.form-item.form-radio label {} for example.

AttachmentSizeStatusTest resultOperations
43494_drupal.form-element-class_10.patch889 bytesIdleFailed: 10931 passes, 0 fails, 4432 exceptionsView details | Re-test

#11

stBorchert - April 26, 2009 - 09:12

Argh, its not always good to use drupals functions (e.g. form_clean_id).
Here's a retry.

AttachmentSizeStatusTest resultOperations
43494_drupal.form-element-class_11.patch891 bytesIdleFailed: 10931 passes, 0 fails, 4432 exceptionsView details | Re-test

#12

stBorchert - April 26, 2009 - 09:22

Hm, seems to be to early this morning. Here's the working patch.

AttachmentSizeStatusTest resultOperations
43494_drupal.form-element-class_12.patch872 bytesIdleFailed: Failed to run tests.View details | Re-test

#13

stBorchert - April 26, 2009 - 10:27

This gets even more complicate. Updated some style rules and js-magic to work with the new classes.

AttachmentSizeStatusTest resultOperations
43494_drupal.form-element-class_13.patch2.16 KBIdleFailed: Failed to apply patch.View details | Re-test

#14

sun - April 26, 2009 - 11:00
Status:needs review» needs work

I advanced on this in one of my latest themes. Will post a new patch shortly.

#15

sun - April 26, 2009 - 11:06

And, btw, the reason why we need to add those classes also to checkboxes/radios is:

<div class="form-item" id="edit-checkbox-wrapper">
  <label class="option" for="edit-checkbox"><input type="checkbox" name="checkbox" id="edit-checkbox" value="1"  checked="checked"  class="form-checkbox" /> Checkbox</label>
  <div class="description">Checkbox description.</div>
</div>

1 label here.

<div class="form-item">
  <label>Checkboxes: </label>
  <div class="form-item" id="edit-checkboxes-one-wrapper">
    <label class="option" for="edit-checkboxes-one"><input type="checkbox" name="checkboxes[one]" id="edit-checkboxes-one" value="one"   class="form-checkbox" /> One</label>
  </div>
  <div class="form-item" id="edit-checkboxes-two-wrapper">
    <label class="option" for="edit-checkboxes-two"><input type="checkbox" name="checkboxes[two]" id="edit-checkboxes-two" value="two"  checked="checked"  class="form-checkbox" /> Two</label>
  </div>
</div>

Multiple labels here.

However, my new patch probably won't need it anymore.

#16

sun - April 26, 2009 - 12:09
Status:needs work» needs review

So here is the new patch.

- Adds the element's #type as class.

- Adds the element's #name as class.

- Changes the CSS class name for fieldset descriptions to "fieldset-description".

Reasoning:

a) When implementing a custom form layout in your theme (e.g. a two-column form layout, with floating form item labels to the left), you currently have no way to target a certain kind (#type) of form item. This patch adds the class "form-item-<#type>" to all form items. That makes it easy to specifically target all elements of type "checkboxes", or all elements of type "textarea", aso. Absolutely required for advanced theming of forms.

b) In addition, the element's #name is added as "<#name>-wrapper" class to the form item. Yes, we already introduced "edit-<#name>-wrapper" CSS ids, but CSS ids must be unique and thus can only exist once on a page. In addition, those existing CSS ids are not added to the wrapping form items for checkboxes and radios.

c) When styling forms, you have all kind of ".description" classes flowing around. However, the description of fieldsets is not really comparable to regular form item descriptions: they usually contain more lengthy guidelines and explanation for all form items contained in the fieldset. Yes, it is a description, but logically and semantically, it is intended and displayed differently than those form item descriptions (usually displayed relatively small below the form element, or rendered completely differently using JS tooltips).

AttachmentSizeStatusTest resultOperations
drupal.form-element-theming.patch2.47 KBIdleFailed: Failed to run tests.View details | Re-test

#17

sun - May 3, 2009 - 21:51

.

#18

sun - May 17, 2009 - 15:56

Someone up for testing?

#19

sime - June 1, 2009 - 05:28

Updated the patch to latest HEAD, hopefully the bot doesn't get angry, out of practice.

This is a very useful patch for theming.

AttachmentSizeStatusTest resultOperations
drupal.form-element-theming-2.patch2.54 KBIdlePassed: 11116 passes, 0 fails, 0 exceptionsView details | Re-test

#20

sime - June 1, 2009 - 05:36
Status:needs review» reviewed & tested by the community

Oops, comment cut off somehow.

I meant to add that I did the following:
-- applied to HEAD
-- visually checked form html to see the extra classes
-- ran the Form API tests
-- validated a random form (content type creation) through w3org.

#21

akahn - June 2, 2009 - 12:40
Status:reviewed & tested by the community» needs work

This line catches my eye:

<?php
return '<fieldset' . drupal_attributes($element['#attributes']) . '>' . ($element['#title'] ? '<legend>' . $element['#title'] . '</legend>' : '') . (isset($element['#description']) && $element['#description'] ? '<div class="fieldset-description">' . $element['#description'] . '</div>' : '') . (!empty($element['#children']) ? $element['#children'] : '') . (isset($element['#value']) ? $element['#value'] : '') . "</fieldset>\n";
?>

That's pretty gruesome. Why the need for hyper-compact, unreadable code? Since this is a theme function that designers/themers (who may not be PHP-savvy) will want to override, this code should be as friendly as possible.

What if, before the return statement, we do all the conditional stuff and store things in $legend, $description, and $children, and then concatenate all that in the return statement? That would make this a lot more readable and expressive. What do people think of this approach?

#22

sun - June 2, 2009 - 12:56
Status:needs work» reviewed & tested by the community

@akahn: Not invented here. If we want to make those theme functions for form elements cleaner for themers, then we should tackle them all at once in a separate issue.

#23

akahn - June 2, 2009 - 13:35

Point taken. Anyone think it would be worthwhile to get rid of this kind of dense, hard-to-read code from Drupal core?

#24

sime - June 2, 2009 - 22:56

@akahn, my opinion is you'd prefer not to override this theme function if you could avoid it. But I take your point.

#25

emmajane - June 3, 2009 - 03:46

I don't do a lot of javascript, so this patch seems overkill for my needs as a themer; however, merlinofchaos and quicksketch both suggested in IRC the idea could be useful. Hopefully they'll get a chance to look at the patch directly and add their comments. HINT, HINT, HINT. :)

#26

quicksketch - June 3, 2009 - 04:05

I really like the change to include "form-item-[type]" to the wrapper, but I'm not so sure about the "form-item-[name]" change. For everything except checkboxes/radios, this is going to be nearly identical to the ID. Seems like we should either A) remove the ID entirely or B) add an ID to checkboxes/radios. New classes are great, redundant ones not so much.

To compromise, could we add a #wrapper_attributes property and then run drupal_attributes() on it and tack that onto the wrapper div? Then anyone interested could add back in the "form-item-[name]" class through a hook_elements() and an extra #process function. Of course its usefulness would be different than the original patch... maybe that change should be elsewhere, but still I'd like to see a different alternative that having an id and class attribute that are nearly identical.

#27

sun - June 3, 2009 - 04:21

Given that form_clean_id() will rename any ID that appears more than once on a page, no developer should rely on those IDs, but classes instead. That issue bit me just recently when I mistakenly tried to target the username field on the user login block form. However, on the path user/login, the regular user login form is rendered already, so my login block suddenly used a different ID. So neither my JS nor my CSS did apply anymore.

#28

quicksketch - June 4, 2009 - 00:56

I've had that exact same situation happen with the login form when using LoginToboggin's fancy login form. Per your description, "no developer should rely on those IDs, but classes instead," it sounds like that's the exact reason why we shouldn't have the automatic ID at all. I'm not opposed to adding more classes, I'm opposed to having an ID and Class that are identical 90% of the time. If we add this wrapper class based on the element name, we should get rid of the ID, since it serves no functional purpose that the class cannot provide.

#29

sun - June 4, 2009 - 01:28

Yeah, I agree. Remaining question is: Tackle that duplicate ID/class in this issue or in a separate? I'm not entirely sure about how much CSS/JS we need to change accordingly for that, so I'd rather prefer to move that into a separate issue.

#30

sime - June 4, 2009 - 03:08

I'm in support of just adding the "form-item-[type]" to make life easier 90% of the time.

As long as I can avoid overriding theme_form_element().

For example, if I could over-ride individual element types, I could then simply implement phptemplate_form_element_item() or phptemplate_form_element_radios() to just sort out the weirdness that happens from design to design. Is this out of scope?

#31

webchick - June 4, 2009 - 03:24
Status:reviewed & tested by the community» needs review

Does this still need more discussion?

#32

quicksketch - June 5, 2009 - 04:31
Status:needs review» reviewed & tested by the community

The changes from removing the #edit-[name]-wrapper ID doesn't look drastic, but would clearly be dependent upon this patch. I made a separate issue in #482636: Remove "edit-[name]-wrapper" ID from form element wrappers that contains a dependent patch for removing the ID attribute entirely from all CSS and JS, though it's not removed from the markup (yet) until this patch is committed. So let's do one step at a time, get this in and finish it in the other issue.

sime, I think restructuring the form element function calls is probably not part of this issue either. It'd be a more signficant code change, but at least after this patch the need to override it should be reduced quite a bit.

#33

Rob Loach - June 5, 2009 - 14:10

Although it's probably un-related I ran into this a little while ago. It's unsetting the ID of any conditional form element........

AttachmentSizeStatusTest resultOperations
form-item-wtf.patch548 bytesIdlePassed: 11116 passes, 0 fails, 0 exceptionsView details | Re-test

#34

System Message - June 13, 2009 - 13:05
Status:reviewed & tested by the community» needs work

The last submitted patch failed testing.

#35

lilou - June 13, 2009 - 13:47
Status:needs work» reviewed & tested by the community

Setting to rtbc - testbot was broken.

#36

Dries - June 13, 2009 - 19:33

So #33 is the patch that should get committed?

#37

sun - June 13, 2009 - 22:49

#19 it is. I've sent that patch for re-testing now.

quicksketch was so kind to already create #482636: Remove "edit-[name]-wrapper" ID from form element wrappers, so #19 is ready to go.

I'm not sure what the patch of Rob Loach in #33 is for, but it sounds like a different issue.

#38

Dries - June 14, 2009 - 08:04
Status:reviewed & tested by the community» fixed

Alright. Thanks! Committed to CVS HEAD. See you in #482636: Remove "edit-[name]-wrapper" ID from form element wrappers. ;-)

#39

System Message - June 28, 2009 - 08:10
Status:fixed» closed

Automatically closed -- issue fixed for 2 weeks with no activity.

 
 

Drupal is a registered trademark of Dries Buytaert.