I'm developing a theme that looks like this:
http://www.asgardforge.com/web-design/web-design-company/wireframe.html

I hope to place unique graphics in location #1, #2 and #3 based on the current node. I've looked at the page, node and block template files but haven't figured out yet how to do this. (Well, other than simply using the Drupal blocks interface to put blocks in those spots, specific to each node. THAT'S a brutal approach.) Please could someone advise how to use a template or function override to do this?

Comments

Stéphane53’s picture

Hello.

I think you should have to look at the .css page of your drupal website, and then create special "Div" for each regions. For instance create the "header block" region into the "Header region", and so on... In these "header block", "unique graphic", "xxx" regions, you write your picture address/width/height...

You'll have to declare these news regions into the .info file of your theme also...

thorshammer’s picture

... is not how to place those images - it's how to write code so they are DIFFERENT as you surf through the site Navigation. I hope to include code that detects "node 1" for example has been clicked on, and then builds that node1 page with site Navigation "node1link" background image (#1 in the wireframed example linked to above), "node1header.jpg" in the the header region (#2), and "node1page.jpg" at the top of the node content section (#3).

If for example there's a variable unique to each node, graphics would be labeled that could then be inserted with PHP code like:

<img src='../sites/default/files/'.$node_variable.'header.jpg'

I haven't succeeded in ascertaining such variable, how and where to grab it, or if that's even the path to accomplishing this. But I want to use a template or function override, so that no extra work is needed from the site administration side when adding new content (other than naming the images according to that pattern). ??

WorldFallz’s picture

You can grab the node id with the http://api.drupal.org/api/function/arg function so you could do something like:

<?php
if (arg(0) == 'node') {
 echo '<img src="/sites/default/files/node'. arg(1) .'header.jpg"';
}
?>
thorshammer’s picture

In all three page locations, the images are background. So rather than just displaying them inside a block using echo, I need to define the block's background-image - still using the logic you describe. How?

And I'm not sure of the context wherein I can use the function you've described (and thanks for it!). For example, if I did write this within the given block (such as location #2, a block along the bottom of the Header region), is arg(1) exposed at that level?

mndonx’s picture

About how many different images/nodes are you envisioning? I think the best way for doing this is to keep your images in the theme folder (the file folder is generally for keeping images submitted as content -- that file folder shouldn't really be touched outside of the UI).

Do you use the $body_classes variable? If not, in your page.tpl.php, change your body tag from:

<body> to <body class="<?php print $body_classes; ?>">

This will add some really useful classes to your body tag, like whether you are on the front page or not, logged in or not, or which content type the node is.

In your case, however, you would need to add some other stuff to your $body_classes, which you can do in template.php.

The first section defines how to build a safe id/class (no spaces, no caps, etc.) The second section grabs the path, manipulates it, and adds it to your $body_classes variable.

<?php
/**
 * Converts a string to a suitable html ID attribute.
 *
 * http://www.w3.org/TR/html4/struct/global.html#h-7.5.2 specifies what makes a
 * valid ID attribute in HTML. This function:
 *
 * - Ensure an ID starts with an alpha character by optionally adding an 'id'.
 * - Replaces any character except A-Z, numbers, and underscores with dashes.
 * - Converts entire string to lowercase.
 *
 * @param $string
 *   The string
 * @return
 *   The converted string
 */
function YOURTHEME_id_safe($string) {
  // Replace with dashes anything that isn't A-Z, numbers, dashes, or underscores.
  $string = strtolower(preg_replace('/[^a-zA-Z0-9_-]+/', '-', $string));
  // If the first character is not a-z, add 'n' in front.
  if (!ctype_lower($string{0})) { // Don't use ctype_alpha since its locale aware.
    $string = 'id' . $string;
  }
  return $string;
}

/**
 * Intercept page template variables
 *
 * @param $vars
 *   A sequential array of variables passed to the theme function.
 */
function YOURTHEME_preprocess_page(&$vars) {

  if (!$vars['is_front']) {
    // Add unique classes for each page and website section
    $path = drupal_get_path_alias($_GET['q']);
    list($section, ) = explode('/', $path, 2);
    $vars['body_classes'] .= ' ' . YOURTHEME_id_safe('page-' . $path) . ' ';
    $vars['body_classes'] .= ' ' . YOURTHEME_id_safe('section-' . $section) . ' ';
  }
}
?>

Replace YOURTHEME with the name of your theme (or really it can be anything as long as it is consistent).

So, now you have a class on each node, specific to that node. From there, you can define specific bg images to your heart's content on each node with CSS.

Hope that is useful -
Amanda

dalegrebey’s picture

<?php print $body_classes; ?>.

This is definitely the approach I would take to solve this. Depending on the node type and whether it's the front page or not, it will automatically change the css classes. This does not just have to be used on the body tag, it can be used on any other divs as well.

For example:
- Front: front logged-in page-frontpage no-sidebars
- User: not-front logged-in page-user no-sidebars
- Forum: not-front logged-in page-forum no-sidebars

I would than target those classes accordingly:

.page-frontpage {
  background:url(images/image1.png);
  }

.page-user {
  background:url(images/image2.png);
  }

.page-forum {
  background:url(images/image3.png);
  }

...so on and so forth for your various node types.

thorshammer’s picture

Thanks Dale.
I am headed for defining a custom node type for the page contents of all the website's pages, to brings in the custom background image among other things (location #3 in my wireframe). I'd imagine that once I've created a page node with, say, mynode, I can then style the class .page-mynode - yes?

That being said, I would still need a mechanism to differentiate each of those customs nodes - since each page contents area needs to have a different background image. Perhaps per the previous responses above - haven't fully digested those yet. (And more questions asked there, always more questions with this guy. :o)

thorshammer’s picture

Thanks aMaNDa - that's triple-A advice!
And ever the rookie still, I don't know how I would reference the new classes defined in the function you've described above. Help again?

(As for my images folder, when I discovered that nodes look up paths from a different starting point than the surrounding framework - I opted for a more standardized location. I also previously implemented image_assist module on another website, which references that file path by default. Now that I've begun theming, yes I certainly will start using an /images folder within the theme.)

mndonx’s picture

No problem. Here's an example:

Say you want to put a background image behind your header div, but only on a node with the path about/history. The instructions above will produce a body tag that looks like this:

<body class="section-about page-about-history">

So, when you need to give your header div on that page a specific background image, you would do something like this in your css:

.page-about-history #header {
  background-image: url(images/myimage.jpg);
}
thorshammer’s picture

I've now been able to pull specific graphics into all the page locations I've described, using both the args() function WorldFallz described, and also using the $title variable I realized is available in page.tpl.php. THAT one makes the most sense for my job, because as soon as someone has created a new node - and given it a title - one knows immediately what to name the graphic for that page: that title.

A couple of provisos though.
(1) I have to use path ".../" prefix, both in the node (where I expected it) and also in the block and the template region (where I did not, based on prev. experience).

(2) these only work when I use them inside the respective containers - using a PRINT or ECHO statement inside a div (or inside a node body). When I try to use the images as backgrounds, they don't show up. Here's an example:

<?php print '<div id="siteNavigation"  style="background-image:url(../sites/all/themes/af_marketing/images/'. $title .'.jpg)" >'; ?>

I can use precisely that same url syntax as a PRINT statement inside that same div, and it shows up. (I checked "view source" and it constructs precisely right for that page.) I even pulled out the variable and placed a hard-coded name, still nothing shows up. Any ideas? (Thanks for indulging me.)

mndonx’s picture

Not sure this will solve the problem, but it's best to use base_path() and path_to_theme() to construct the path:

<?php print '<div id="siteNavigation"  style="background-image:url(' . base_path() . path_to_theme() . '/images/' . $title .'.jpg)" >'; ?>

Can you post the HTML that your statement above is producing?

thorshammer’s picture

Yes, I've done so - the page source now shows:

<div id="siteNavigation"  style="background-image:url(/web-design/web-design-company/sites/all/themes/af_marketing/images/NEW CLIENT INFO.jpg)" >

I've installed Drupal inside a couple of sub-folders from my root site, ergo the first two items in that path.
________________________________________

AHA! I checked the same pages in I.E. browser (I develop in Firefox), and the background images show up!

But only when the absolute path is used (as above) - heady with this improved condition, I tried the path from theme level (/images...) and then site level (/sites...) but they failed.

BTW, here's the development site: www.asgardforge.com/web-design/web-design-company. You will notice that the front_page doesn't display the background-image in the siteNavigation (top-right) - there are several other differences I won't address now. Click on any of the 3 links in the siteNavigation, those pages are where the backgrounds do and don't show up (depending on browser).

Currently the code to generate that region is:

	<?php print '<div id="siteNavigation"  style="background-image:url('. base_path() . path_to_theme() .'/images/'. $title .'.jpg)" >'; ?>
		<?php print $sitenav; ?>
		<?php 
			 print '$title is: '. $title;
			
			if (arg(0) == 'node') {
			echo '<img src="../sites/default/files/'. arg(1) .'.gif"/>';
			}
		?>

And I've place Primary Links in that region ($sitenav).

mndonx’s picture

You have to be careful with your file naming conventions. You never want to have spaces in your file names. That is breaking them in certain browsers.

If you pop open Firebug and change the path to background-image:url(/web-design/web-design-company/sites/all/themes/af_marketing/images/NEW%20CLIENT%20INFO.jpg), the image appears.

That's why an id_safe function (like the one I have posted above) is really handy. You can grab that and wrap your $title in that, I believe.

Amanda

thorshammer’s picture

For now... Thanks so much Amanda, the id_safe did it of course. That's gives me lots of room to move now, working on my theming skills now that I have a starting point for customizing those areas (without ridiculous measures like a unique block for each page, etc.)

WorldFallz' reference to the args() function needs some more exploring by me also. Meantime, I have to find out why that siteNavigation region doesn't show the background on the Homepage - while the Homepage is the only page that DOES display the background for the block that's placed along the bottom of the Header. (Where it says - this is:)
__________________________________________

I don't want to press my luck, you guys have been so helpful already. If however you've got nothing better to do...

the Header region has a custom block placed in it (along the bottom of the Header) in which I placed code:

<?php
echo "<div style=background-image:url(sites/default/files/topTheme2.jpg);width:620px;height:190px>";
echo "</div>";
if (arg(0) == 'node') {
echo 'This is: '. arg(1);
}
?>

(Naturally input format is set to PHP Code.)
Oddly enough, on the Homepage that background image shows up, but the display of arg(1) does not. On siteNavigation pages, it's the reverse. ??

WorldFallz’s picture

If you use the default home page (http://example.com/node) there is no arg(1) since there is no node number.