Hi.
There's the "
Refreshing the Jenkins UI" thread that's been going. I decided to split out a new thread for this because the other thread has long since become a bit unwieldy.
So I've been playing around with trying to replace raw <img> tags in Jenkins with a new <l:icon> tag. I did a version that also included doing the actual icons with <div>s + CSS, but after talking to Stephen Connolly I went back and more-or-less started from scratch again. This time, we dropped the goal of introducing CSS based icons (for now only... that will be in a followup I hope) and instead just concentrated on creating a jelly tag for doing icons.
The new <l:icon> tag in this branch is basically the same as an <img>. In terms of porting existing scripts to use it, all you need to do is rename "<img " to "<l:icon " (/lib/layout namespace). In this form (<l:icon src"path-to-icon-image" ... />), the tag simple renders the icon <img> using the 'src' attribute value provided on the icon tag. This makes it easy to do a basic migration.
This on it's own is useful (a single point of control for rendering icon images), but of course we also want to get away from using image urls in the markup and move towards a CSS based approach (with divs etc). To help us get there, this new <l:icon> tag supports a 'class' attribute. We purposely chose this attribute name because it matches how we intend using it's value i.e. basically as a CSS class selector... it's value is a set of space separated icon class specs and it will map directly to CSS etc. Note that the 'class' attribute takes precedence over the 'src' attribute. In any case, it would not really make sense to specify both.
The following are a few examples of how you'd specify core Jenkins icons, comparing doing it the current way (using <img>s) and the newer proposed way (using <l:icon>s):
| <img> | <l:icon> (using the 'class' attribute) |
| <img src="${imagesURL}/48x48/warning.png" height="48" width="48" /> | <l:icon class="icon-warning icon-xlg"/> |
| <img src="${imagesURL}/32x32/clipboard.png" width="32" height="32" /> | <l:icon class="icon-clipboard icon-lg"/> |
| <img src="${imagesURL}/48x48/${it.icon}" width="48" height="48" /> | <l:icon class="${h.toNormalizedIconNameClass(it.icon)} icon-xlg" /> |
| <img src="${imagesURL}/24x24/grey_anime.gif" alt="" height="24" width="24"/> | <l:icon class="icon-grey-anime icon-md"/> |
Of course you can also just rename the <img> tag to <l:icon> and that will work too e.g. <l:icon src="${imagesURL}/48x48/warning.png" height="48" width="48" />.
As I already said, the 'class' attribute specifies a class spec for the icon you want to use.
"icon-warning icon-xlg" is the extra-large warning icon, while "icon-warning icon-sm" is the small version of the same icon. The current version of the <l:icon> tag relies on a lookup to convert the class spec to the actual image url. See the IconSet class if you want more details on that.
The next thing I'm going to look at will be how will this work for Plugins i.e. how will plugins be able to define their own set of icons. My current thinking is that each plugin will be able to define it's own CSS/Less file for it's icon-set. So, taking the git plugin as an example, it's logo icon might be done as follows:
| Small: | <l:icon class="icon-git-logo icon-sm"/> |
| Medium: | <l:icon class="icon-git-logo icon-md"/> |
| Large: | <l:icon class="icon-git-logo icon-lg"/> |
Of course this relies on the plugin author making sure to pick class names that don't clash with other plugins. That should not be a problem if we follow a simple convention of "icon-[plugin-name]-XXX".
Obviously we don't want Jenkins to be loading potentially 100s of CSS files, so that's where I think Less might come into the picture i.e. use Less to build a single css file for all the installed plugins. Maybe this could be built into the plugin/update-centre components i.e. each time a plugin is installed or uninstalled we run Less to create the new CSS. Using a preprocessor like Less should (I think !! ) also mean we can still resolve relative paths (e.g. to a background-image) after preprocessing is complete.
That's it for now... please send feedback :)
Regards,
Tom.