Fields output currently only includes css zebra striping (even/odd) information for themers. This is an attempt to add the more additional classes to make their lives easier.
The first addition is a bookend class (e.g. field-item-first, field-item-last) that themers can use to specially treat the bookends of their design elements.
The second is a delta (e.g. field-item-1, field-item-2, etc)that they can use to force clears or apply arbitrary styling via.
And finally the even odd class is updated to improve its namespacing a little (even -> field-item-even).
The end result of a multivalue text field field rendered with these im mind would look like the following:
<div class="field field-name-field-test-text field-type-text field-label-above">
<div class="field-label">Test Text: </div>
<div class="field-items">
<div class="field-item field-item-odd field-item-1 field-item-first">One</div>
<div class="field-item field-item-even field-item-2">Two</div>
<div class="field-item field-item-odd field-item-3 field-item-last">Three</div>
</div>
</div>
| Comment | File | Size | Author |
|---|---|---|---|
| #31 | drupal-n964288-31-d8.patch | 2.13 KB | damienmckenna |
| #30 | drupal-n964288-30-d7.patch | 2.09 KB | damienmckenna |
| #27 | drupal-n964288-27.patch | 1.71 KB | damienmckenna |
| #25 | before.PNG | 15.24 KB | dcam |
| #25 | after.PNG | 22.69 KB | dcam |
Comments
Comment #1
dawehnerThis output is not from views.
This is core field.tpl.php/template_preprocess_field
There is not first/last set.
Comment #2
ryan.armstrong commentedOk, I'm moving this issue over to Drupal core. This seems like something that needs to be addressed, as it makes it difficult to theme fields with multiple content, such as images. Thanks Dereine!
Comment #3
damien tournoud commentedThis is called a feature request. It's a small one so if someone rolls a patch we might be able to get this into D7.
Comment #4
ryan.armstrong commentedOo whoops, yea my fault, put it in the wrong category!
Comment #5
rjgoldsborough commentedHere is a patch that adds first and last classes to core fields.
Comment #6
nlounds commentedThanks for the patch. Unfortunately, for me, it is applying the 'last' class to the last even item. So if the last item happens to be odd, the 'last' class gets applied to the next to last item.
Comment #7
yched commented$delta == count($delta) + 1should probably be$delta == count($variables['items']) + 1.Although, for performance reasons, it would be best to precompute the value outside the loop.
Also, note that there is a template version of this output as well (field.tpl.php), that would need to be updated accordingly (the count should in this case be precomputed in preprocess)
Powered by Dreditor.
Comment #8
yched commentedBetter title. This is not for Views.
Comment #9
gddSubscribe, would like to see this and will reroll when i have time
Comment #10
mstrelan commentedReroll of the patch with yched's suggestions. For an additional performance boost I have precomputed the maximum delta rather than the item count so we can compare
$delta == $max_deltarather than$delta == $item_count - 1.Comment #11
mstrelan commentedComment #12
mstrelan commentedHere's another one with consistent spacing before the classes added by PHP. By adding the spaces before the class there is never a leading or trailing space. The patch in #10 also ensured this, however the odd/even class was inconsistent with the first/last class.
Comment #13
dawehnerAs yched said before
This is too much php for a template file. Please move it to the preprocess function.
Comment #14
mstrelan commentedI thought yched was talking about precomputing the max delta, rather than the classes for a field item. Nonetheless I agree that it is really messy in the template file, so I'd be happy to give this another go.
I have a couple of questions though.
Question 1: does $delta == position in array?
The code below suggests that the first key of $variables['items'] might not be 0 and the last key might not be equal to the last key of $element['#items'].
This would mean to get the first and last classes we would have to do something like below.
Note that
$iis required because it is not guaranteed that every delta value of$element['#items']will end up in $variables['items'].For the same reason we can't just say
$variables['item_attributes'][0]['class'] = 'first';And once again we can't say
$max_delta = array_pop(array_keys($element['#items'])); $variables['item_attributes'][$max_delta]['class'] = 'last';And finally, the current logic to determine even and odd is flawed because there may be a gap in delta values, ie you might have 0, 1, 2, 4, 5, 7, 10.
ON THE OTHER HAND is it safe to assume that every delta value will exist in both arrays, ordered in increments of 1 from 0 to n? This will make the code a little more manageable.
Question 2: what are the policies with changing theme functions and template files in a point release?
If we change the preprocess function to precompute the classes in $item_attributes[$delta]['class'] and then update field.tpl.php to match then we will be messing up people who have overridden one or the other but not both, as they will lose their "field-item" and "even/odd" classes.
If we have to wait for Drupal 8 then will Drupal even support browsers that don't support :first-child and :last-child or :first-of-type and :last-of-type selectors? Probably.
Comment #15
philsward commentedI would like to throw in my $0.02 about this issue and expand it further to having a unique css value for each field value. Maybe this is where the delta stuff comes into play, I don't know but I just got done setting up a small used car website where the customer wanted an "availability" field of "In Stock" or "SOLD!". I easily enough setup a Boolean field and proceeded with the true false setup of the field. It works perfect, except that I want the false statement, in this case "SOLD!", to be nice big bold letters colored red. Unfortunately, there is no "smartness" to the fields in a way that lets you theme individual field values. It's all or nothing. It would be nice if there was some way to have a unique css class tied to the true statement, and another unique class for the false statement.
Doing this type of setup would open a lot of theming doors in other facets of the fields as well.
I also just realized this is something that needs to be pushed to all contrib facets of Drupal. Views, Panels etc. Anything that displays the content of Drupal. I just noticed that views rewrites all of the css to accommodate their own styling which is different than the default values. I'm not saying all of the contrib modules need to use the default drupal css, but it would be awesome if they could call on certain aspects of a unique theming approach.
Just thought of something else, what about adding an option for each field for theming purposes. Allow the user to checkbox enable additional css classes to make it more unique. It would be turned off by default therefore not creating a messy environment for all of the fields but only enabling the unique css across the fields that are needing it.
Comment #16
Zachmo commentedI took a stab at patching this issue. I'm not too happy about the extra loop through the items but it gets the job done. Let me know if you see a more efficient way to do this.
Basically we loop through the items again after the first items array is created and add our first last and even odd classes. These are then added a new item in variables called delta_classes which is a an array of all of the classes for each item keyed on its delta. The loop is based on the item's position in the array and not its delta so we should be getting the true even/odd state.
When a field item is rendered we call this new variable, delta_classes, instead of $delta % 2 ? ' odd' : ' even'. This has been updated in both the fields theme function and the template file.
Comment #17
loopy1492 commentedI'd like to add to this while we're at it. I think that an identifier should be added for all of the items (not just the first and the last) so that they may be individually selected with css cross-browser. Something like this for the current line 1201 (not sure what it would be on the various suggested patches above)...
That would add a "item-1" class to the first item, a "item-2" to the second item, etc. Then you'd only have to check for the last one and add a "last" class.
I've tried this on my own install and it seems to work just fine.
Comment #18
michaelfavia commentedPerhaps I'm missing something but this might be a solution that doesn't require a for() loop in D7 (the platform I had the issue in). Ill attach a patch for D8 next and once its accepted/rejected backport to this.
Comment #19
michaelfavia commentedPatch for drupal 8 as promised. Can i get a witness?
What do you think Zachmo?
I can speed it up by avoiding the classes as attributes and just implode them myself if wed like but i though it simplified it quite a bit.
Comment #20
Anthony Pero commentedJust trying to do this today, actually. My use case is printing taxonomy tags in my tpl file as inline tags in the "posted by" section. I need to add commas to each item, but, obviously, not to the last. Is there a theme function I can override in template.php to get this working in D7 right away without hacking core? If this should go in the forum instead of here, just let me know... I'm not in the issue queues much, so I'm not sure if this is even appropriate to ask.
Comment #21
effulgentsia commentedNot sure yet if #1649780: Remove first/last/odd/even classes in favor of CSS3 pseudo selectors will fly, but linking that here, since if it does, that will affect this issue.
Comment #22
jenlamptonWe decided not to support first and last CSS classes in D8 because we can now use CSS3 psuedo-selectors to grab the first and last items. I'm changing the version back to D7 since you still may want these classes on older versions of Drupal, but the patch will need to be re-rolled so I'm also changing the status back.
*edit* looks like @effulgentsia and I were cross-posting :) Sorry about that.
Comment #23
damienmckennaRerolled against D7.
Comment #24
sokrplare commented#23 applied beautifully for me. Probably can RTBC here.
Comment #25
dcam commented#23 works for me too. Before and after images are attached.
Comment #26
yched commentedReplacing "odd" with "field-item-odd" cannot fly for D7. We cannot change existing markup, existing sites rely on that.
Comment #27
damienmckennaRerolled to fix the issue raised by yched.
Comment #28
yched commentedThanks !
Looks good to me :-)
Comment #29
David_Rothstein commented#1649780: Remove first/last/odd/even classes in favor of CSS3 pseudo selectors hasn't had any activity in two months, and we can't guarantee that it will make it into Drupal 8. To avoid introducing regressions, we have to have some fix for this in Drupal 8 before we fix Drupal 7, so that means either postponing this issue on that one (which seems silly) or just fixing this in Drupal 8 quickly first (which seems a lot simpler).
(Actually, the current patch there looks like it still leaves the
<div class="...">stuff behind, so it's missing some good things that this patch does, so we really should just keep this issue separate.)Looking at the patch, it looks good but why doesn't it change field.tpl.php also? That was discussed earlier in the issue, but I'm not sure why it was dropped.
In general, see http://drupal.org/node/1527558. So, this is definitely worth thinking about.
As far as I understand this patch, it will not affect someone who has overridden field.tpl.php or theme_field() (although I suppose it could result in them getting something like
<div class=".." class="..">in their HTML)? It will affect someone who has totally replaced template_preprocess_field() but hasn't replaced the theme function itself. That seems relatively unlikely to me, but at least we'd need a release notes mention for this.Keeping the changes inside the theme/template only (for Drupal 7) does sound like it'd be a bit safer overall, though...
Comment #30
damienmckenna@David_Rothstein: Going back to D7 for a second, just to make sure I'm making the correct change, is this what you're thinking of? The change to field.tpl.php feels a little unwieldy, any tips for streamlining it?
Comment #31
damienmckennaA d8 version of the patch from #30.
Comment #33
David_Rothstein commentedDamien, yeah, something along those lines - if we don't do it in preprocess we'd have to do it inline (and repeat the code in theme_field() and field.tpl.php). It's ugly and I'm not sure there's any way to simplify it (it could be made more readable by breaking it up onto multiple lines, though).
For Drupal 8, I'd definitely stick with doing it in preprocess, as the earlier patches did (since that is clearly better); I apologize if I implied otherwise. For Drupal 7, I guess it's still an open question which way to go, depending on what we think we might break.
Comment #34
mpotter commentedPatch in #30 is failing in 7.22Sorry, nevermind, wrong patch
Comment #34.0
mpotter commentedAdd the delta case and spell out the issue clearly
Comment #35
loopy1492 commentedSo, it looks like the patch works for D7. I was wondering if we need to do anything to have it rolled into a release? Sorry if that's a dumb question, but I'm ignorant of how this works.
Comment #36
star-szr#1649780: Remove first/last/odd/even classes in favor of CSS3 pseudo selectors got in so this won't fly for Drupal 8. I'm going to close this issue because I don't think we can change any D7 core markup, even just adding new classes has the potential of breaking existing sites.
It seems to me that if these classes are needed for a D7 theme they can be added in a theme or module preprocess function or template override.
Comment #37
loopy1492 commentedSo, I am far more seasoned with Drupal than I used to be and I feel Cottser is completely right here. I took an hour and modified field.tpl.php to give us classes for first, last, and the numerical order of the field item.
Of course, I don't think this is in the "Drupal" way, but I absolutely hate the convoluted nature of in-line conditionals, so someone can do it up proper if they want. At any rate, this works a treat on my site.
Of course, you don't want to alter the one in the core field module. You'll want to put this template in your Theme folder.