Welcome Guest, Not a member yet? Register   Sign In
Best Practice for dynamic header content
#1

[eluser]Chillahan[/eluser]
I am wondering how people currently handle dynamic headers. I've seen discussion of how to bundle header, page, and footer view loading into master template files, which I was thinking of doing, but decided against (since it only saves a couple of lines of code and then makes it actually harder to customize the header in each case. Anyway, that's not my question - my question is if anyone has what they feel to be the Holy Grail of handling dynamic header content (and still applying the concept of Don't Repeat Yourself).

To start, some common needs I see in customizing a "header":

- customizing navigation - either showing different navigation (for tabbed approaches) or at least highlighting the currently selected part of the navigation;
- customizing JavaScript loaded in header to support dynamic functionalities in the page
- custom data display - showing login box vs. "Welcome, Username" + Logout (this isn't so bad since it is independent of which page you're on)

The first two are major ones. Here are some approaches I've thought of:

1. instead of having one header (which contains HTML declaration tags, complete HEAD section, and BODY open tag), have two (or more) header files... one would load HTML doc tags, the next would cover the HEAD section, and the last would cover the BODY open tag and the navigation (or one view could handle the first two of these)
2. sending text to be injected into HEAD via a $data parameter, and dealing with customizing nav some other way that makes it independent (i.e., it could look in cookie for currently active site section so as to know which section to highlight/display)
3. using native PHP include files within the master header view file to load what's needed based on some sort of switch statement and cascading file include system (i.e., a default file for HEAD content, and then override files if needed for each page of the site, located in a subdirectory to the main HEAD file, and only loaded instead of default if located)
4. just have different header files for different site pages, and repeat yourself

This seems to be a common need - it almost seems like CI should address this at the platform level, having HEAD files be a separate entity for sure, and then having some sort of navigation helper (even if only cookie/session based) to help developers automate the showing/highlighting of correct navigation areas.

For now, out of the four approaches I've outlined, $2 would be the most proper, but also one of the uglier options, since HTML/JS code would be pushed to a view by the controller (or it could push it a name of a file to include instead - then it becomes more like #3, or the same really). #1 seems to be the simplest, and isn't so bad in terms of being elegant. Again, it's really a different take on #3 and #2, and keeps "control" in the controller where it belongs (but makes HTML/CSS/JS dev even more segregated).

Thoughts?
#2

[eluser]charlie spider[/eluser]
First off, when i say header and footer here i am talking about the design elements of the page, not the actual html components. So a header is the area at the top of the visible page with the company logo, login info, navigation, etc. and the footer is the info bar at the bottom of the page with site navigation text links, copyright info, link to our business, etc.

Anyways, i find that most sites my wife and i build will have the exact same footer for every page and only a handful of different headers. So i'll take all of the pages with the same header and footer and use one view as an overall page template. So typically i end up with a view called "home_view", then a general content page called "inner_view" then other pages like "all_products_view" and "product_details_view". Then i load my content into those dynamically through different modules:

Code:
$this->data['content'] = $this->load->view('modules/product_shirts_details', $this->data, TRUE);

or

$this->data['content'] = $this->load->view('modules/product_footwear_details', $this->data, TRUE);

which loads into:

Code:
$this->load->view(product_details_view, $this->data);



As for the actual html header information that you were referring to, i use a basic CMS that i built to store the page name, page title, url, nav level, path, meta keywords, meta description, etc, etc, etc in the database. All of this info gets dumped into an array called $page that's loaded into the view through $data.

i should also point out that i typically only use one controller for the frontend of my sites which starts by looking at the incoming url:

Code:
$url = $this->Site_model->get_pageID($this->uri->segment(1));

and then loads all applicable content based on that. The beauty of this is that if we do a site redesign and restructure the site map, i can grab all of the incoming links to old pages and redirect them to the new content in it's new location.

All of my navigation is built dynamically and also loaded as a module, like:

Code:
$this->data['menu'] = $this->load->view('modules/site_menu', $this->data, TRUE);
$this->data['site_info'] = $this->load->view('modules/site_info', $this->data, TRUE);

As for highlighting the current page, you just use an if statement when generating the navigation to compare each page name against the value you passed in the $page array and then change the css class for that link:

Code:
echo '<ul class="topNav">';
foreach ($nav as $link)
{
    if ( $link['pageTitle'] == $page['pageTitle'] )
    {
        echo '<li class="'.$page['pageTitle'].'">';
    }
    else
    {
        echo '<li>';
    }
    
    echo '<a  href="'.base_url() . $link['pageURL'].' title=">'.strtoupper( $link['pageName'] ).'</a></li>';
}
echo '</ul>';


So ultimately my "product_details_view" page might look kinda like:


Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
&lt;html &gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;META NAME="keywords" CONTENT="&lt;?=$page['pageKeywords'];?&gt;"&gt;
&lt;META NAME="description" CONTENT="&lt;?=$page['pageDesc'];?&gt;"&gt;
&lt;title&gt;&lt;?=$page['pageTitle'];?&gt; - &lt;?=$website;?&gt;&lt;/title&gt;
&lt;?=$style;?&gt;
&lt;?=$javascript;?&gt;
&lt;?=$menu_scripts;?&gt;
&lt;/head&gt;
&lt;body&gt;
<div id="wrapper">
&lt;?=$search_header;?&gt;
<h2 class="hdr">&lt;?=$website;?&gt;</h2>
<h1 class="hdr">&lt;?=ucwords($page['pageName']);?&gt;</h1>
&lt;?=$menu;?&gt;
&lt;?=$content;?&gt;
&lt;?=$side_bar;?&gt;
</div>
&lt;?=$site_info;?&gt;
&lt;/body&gt;
&lt;/html&gt;


All pretty simple stuff, no rocket science, but still pretty flexible. It also saves me a lot of time as i get to reuse a ton of code from project to project, even if i always do end up tweaking and modifying and refining and tweaking it so more every time.

i know this goes a little beyond what you were talking about but i just wanted to suggest an alternative to what i feel is the pretty limited, typical
load header,
load body,
load footer

hope this helps
#3

[eluser]Chillahan[/eluser]
Wow, first off, what a great response! Thank you so much! Besst of all, it's great to see a system that's been used across many "real" projects. I am not sure if you've posted this before on here, but this definitely beats other "view within view" systems I've seen mentioned on the forums (including layouts).

So in the end, it seems the answer is to not think in terms of "header", "body", and "footer", which is the direction I was starting to take in my critical thinking - for example, JavaScript located in the HEAD needs to be customized perhaps for every page, and then navigation is best served by its own generation code (as you do with your own custom module). Page-specific information doesn't always get listed only in the header, either, so why force it into that structure.

I like how you do the detection of whether the current page is the one whose link is being built. I'd seen use of URI to do this, but obviously the URL will NOT always correlate to the page the user is actually on. Your system seems to be the best - since you're powering the nav bar links and the page-specific data from the same CMS repository, it's fail-safe to just compare the two to see if you're building the current page's link. Very elegant!

Again, thanks for sharing your time-tested method for dealing with this common issue. I really think it's the best I've seen - concise, doesn't ruin the ease-of-use of view files themselves, and still keeps things pretty DRY! In fact, other than the super front end controller pattern that you use (probably too sophisticated for most users' needs, although it's very powerful), I am pretty sure THIS should be how CI presents itself in the User Guide (or at least it should be an Intermediate-Advanced topic, but something introduced early on). Ever since I saw the first mention of loading header, content, and footer in the User Guide when I got started with CI a few weeks ago I've spent my spare moments thinking of what the "right" way would be to template pages and compartmentalize all the standard dynamic parts, and I think this is it! Wink




Theme © iAndrew 2016 - Forum software by © MyBB