[Seaside] RE: cssClass and cssID (was testing framework)

Brian Brown rbb at techgame.net
Fri Jul 23 17:52:57 CEST 2004


On Jul 22, 2004, at 4:30 PM, Avi Bryant wrote:

> One thing this encourages is adding good CSS ids throughout the 
> render, which is something that's always seemed overly clunky to me.  
> That is, the necessity to put #cssClass: and #cssId:, as well as 
> #div:, #span:, etc everywhere, clutters up the more interesting parts 
> (like anchors and callbacks) of any given render method.  Anyone have 
> any good ideas to keep these separated?  I'm just throwing out random 
> thoughts here, but one possible pattern that occurs to me would be to 
> introduce a higher level wrapper around the HtmlRenderer, that was 
> specific to a particular component.  For lack of a more imaginative 
> name, let's call this a View.  The idea would be that the *structure* 
> of the rendering is still controlled by the component, but the 
> specifics (the actual tags and ids) are filled in by the View.  So, 
> for example, take the following fairly typical render method:
>
> MyComponent>>renderItems: aCollection on: html
> 	html cssClass: 'item-list'.
> 	html unorderedList:
> 		[aCollection do:
> 			[:ea |
> 			html listItem:
> 				[html cssClass: 'item-choose'.
> 				html anchorWithAction: [self choose: ea] text: ea description.
> 				html spanClass: 'item-actions' with: [html anchorWithAction: [self 
> remove: ea] text: '(remove)']]]]
>
> Would it be better, or just more confusing and cumbersome, to split 
> this into something like:
>
> MyComponent>>renderItems: aCollection on: view
> 	view itemList:
> 		[aCollection do:
> 			[:ea |
> 			view item:
> 				[view chooseItem: [self choose: ea] text: ea description.
> 				view itemActions: [view removeItem: [self remove: ea]]]]]
>
> MyView>>itemList: aBlock
> 	html cssClass: 'item-list'.
> 	html unorderedList: aBlock
>
> MyView>>item: aBlock
> 	html listItem: aBlock
>
> MyView>>chooseItem: actionBlock text: aString
> 	html cssClass: 'item-choose'.
> 	html anchorWithAction: actionBlock text: aString
>
> MyView>>itemActions: aBlock
> 	html spanClass: 'item-actions' with: aBlock
>
> MyView>>removeItem: actionBlock
> 	html anchorWithAction: actionBlock text: '(remove)'
>
> Anyway, just a thought.
>
> Cheers,
> Avi
>

I think the second way introduces an unnecessary layer of abstraction - 
yes, each individual method is cleaner to read the CSS info, but 
overall it would be much more difficult building that component; I like 
the conciseness of the first one.

What about the idea of assigning each component a default css name 
based on the name of the component. All elements rendered in that 
component would be in a namespace (from a CSS perspective) like:

MyComponent.table
MyComponent.h3

etc. This would follow the standard CSS inheritance, giving very fine 
grained control to each component only if desired.

This doesn't help with <div /> but those are structural anyway, and it 
is very useful to see what is being rendered inside of a particular div 
element when editing the render methods. Just for various text styles, 
spanClass:with: and spanNamed:with: don't seem too cumbersome. Using 
this scheme, a #spanText: could also be created that acted like #text:  
So instead of:

	html span: [html text: 'Some words']

you would have:

	html spanText: 'Some words'. "This span would be covered by the 
default css component name space."

I may be missing some things here, and I certainly am not using CSS to 
it's full potential in my own Seaside work, but what do you think?

Brian



More information about the Seaside mailing list