Last updated October 29, 2009. Created by mooffie on September 7, 2008.
Edited by quicksketch, bekasu. Log in to edit this page.
The previous recipe explained how to show an image beside the text.
But what if we want to replace the whole text with an image?
There's a certain CSS solution to this as well. But you may find that it's not perfect, so in this recipe we're not going to use CSS: we're going to use HTML's{IMG} tag.
We have explained previously that Flag uses a template to generate the output. Embedded in this template are some variables, among them $link_text, which is the textual label for the link. Fortunately, Drupal lets as alter variables before they arrive at the template, and we're going to use this mechanism to replace this text with an image tag.
Instructions for Drupal 6
Put the following preprocess function in your 'template.php'.
function phptemplate_preprocess_flag(&$vars) {
$image_file = path_to_theme() . '/flag-' . $vars['flag']->name . '-' . ($vars['action'] == 'flag' ? 'off' : 'on') . '.png';
// Uncomment the following line when debugging.
//drupal_set_message("Flag is looking for '$image_file'...");
if (file_exists($image_file)) {
$vars['link_text'] = '<img src="' . base_path() . $image_file . '" />';
}
}However, for the theming system to notice this function you'll have to copy 'flag.tpl.php' into your theme folder (better still, create a symlink). (This also makes path_to_theme() point to this theme folder and not to Flag's folder.)
And remember to clear Drupal's cache.
How does it work?
The function above is called whenever a flag is about to be printed. It looks for an image with the name flag-bookmarks-on.png or flag-bookmarks-off.png --depending on the state of the flag-- and, if exists, it shows it instead of the text. "bookmarks" is only an example: the machine-name of the actual flag used will be used. The images should be placed in your theme folder.
Instructions for Drupal 5
We'll use the function above. Paste it into your template.php. However, Drupal 5 is less elegant and is not going to call it. So we're going to call it ourselves, by adding yet more code:
function _phptemplate_variables($hook, $vars) {
if ($hook == 'flag') {
phptemplate_preprocess_flag($vars);
return $vars;
}
return array();
}(If you already have a _phptemplate_variables() function in your template.php, PHP will shout at you. You'll have to merge this code into your existing _phptemplate_variables().)
For all this Drupal 5 trickery to work, you must first copy the little glue function shown in Flag's 'theme/README.txt' into your template.php.
Another Simple Option
For anyone else interested in this, a simple way is to add your images to the appropriate .css class (add flag and unflag), in the admin section set the link text to something short--like ( + ) and ( - ) .
Then, override the flag-wrapper a { class, and set the link color the background (usually white, #FFF ).
Comments
file_exists, is that expensive?
In the above 6.x version refer to this code
if (file_exists($image_file)) {Is the file_exists check above expensive? Meaning will the existance of file will be checked for every node view, meaning disk access for each page view?
Good recipe. Very clearly
Good recipe. Very clearly explained. 5/5 :-)
Thank you,
Pradeep
http://www.netinterviewquestions.com
I was wondering if someone
I was wondering if someone could help achieve the same thing above for Flag Form where it uses Checkboxes. I would like to replace the checkbox icon (image?) with a custom one for checked/unchecked targeting only a specific flag type. Can anyone assist? Thanks!
CSS Solution
I was able to use a variation of the above to achieve an image with a rollover. I used the preprocess hook to add an empty span instead of the image. No check is needed to see if the file exists.
function phptemplate_preprocess_flag(&$vars) {$vars['link_text'] = '<span></span>';
}
For the CSS, we use a single image (32px by 64 px) with the icons being stacked. In this case, the off image is on top and the on image is on the bottom. On the hover, it simply adjusts the image to show only the part of the background we're interested in.
span.flag-bookmarks a span{display:inline-block;
height:32px;
width:32px;
background-image: url('images/flag-bookmarks.png');
}
span.flag-bookmarks a.unflag-action span{
background-position: 0px 32px;
}
span.flag-bookmarks a.unflag-action span:hover {
background-position: 0px 0px;
}
span.flag-bookmarks a.flag-action span{
background-position: 0px 0px;
}
span.flag-bookmarks a.flag-action span:hover {
background-position: 0px 32px;
}
Try theme_preprocess_flag
I could not get this function to fire, but using my theme name instead of phptemplate worked great - hope this saves someone else some time.
error when declaring the function
Fatal error: Cannot redeclare acquia_marina_preprocess_flag() (previously declared in C:\wamp\www\drupal-6.22\sites\default\themes\acquia_marina\flag.tpl.php:44) in C:\wamp\www\drupal-6.22\sites\default\themes\acquia_marina\flag.tpl.php on line 49
a little clean-up for D6
<?phpfunction THEMENAME_preprocess_flag(&$vars) {
$image_file = $vars['directory'] . '/flag-' . $vars['flag']->name . '-' . ($vars['action'] == 'flag' ? 'off' : 'on') . '.png';
if (file_exists($image_file)) {
$vars['link_text'] = theme('image', $image_file, $vars['link_title'], $vars['link_title']);
}
}
?>
Thanks a lot.
Thanks a lot.