Topic: Function: per page components.

For a layout I was messing around with I wanted to be able to adjust the footer for certain pages only. As I thought I had seen something like that here on the forum I did a little search. I found a question by TwentyTwoBelow asking about the ability to set up components on a per page basis.

Chris came up with a way to do it:

if ( return_page_slug() == 'about' ) {
    get_component('about-component');
} elseif ( return_page_slug() == 'index' ) {
    get_component('homepage-component');
} else {
    get_component('generic-component');
}

However, I feel this will get very frustrating in the long run as I will have to edit the template for every page I want to use a different component on. I do like the idea Chris coined, placing different labels in front of the component name. If only this could be automated...

Well, of course it can be automated!

I wrote my own get_component() function called component_master(), that you can find at the bottom of this topic. If you want to use it for your template just put it in the functions.php that you have (or must create) in your theme folder.

How to use it, an example.

In the basic theme Cardinal you will find the following piece of code in the template.php:

        <div class="section">
            <?php get_component('sidebar'); ?>
        </div>

Change it to this:

        <div class="section">
            <?php component_master('sidebar'); ?>
        </div>

That's all. Nothing should break and it should still include the contents of the sidebar component.

To change the sidebar on the homepage we don't have to change anything in the theme any more. All we do is add a new component on the components page of the admin panel. If we create a component called index-sidebar this component will overwrite the one called sidebar on our homepage but on no other pages!

By simply putting the slug of the page we want to target in front of the component name it will show up. Of course, all pages that you don't specifically target with different components get the one with the name we put into the component_master() function. In the case of our example all pages that don't have a matching component will be showing the content of the component called sidebar.

What if I don't want to overwrite but just want to add something?

I thought about this and came up with a solution. If you want the generic component to show but want to add a per page component you can create components named with the following pattern: slug-extra-component. To fall back on my previous example I could create a component called index-extra-sidebar and this one will be appended to the sidebar component. Of course if slug-component (eg. index-sidebar) exists the extra component is ignored.

In case your template needs the extra addition to the component to not follow the generic one but be rendered before it you want to change your template.php a little.

You will need to call the component_master() function with an extra argument:

component_master('sidebar',true);

Now the order of the way it prints the components will be turned around.

The function as is.

I provide this function as it is. I will probably update it when a GetSimple update breaks it or when others come up with suggestions, but I won't promise that. If anything suddenly wipes your system clean when you use this, don't look at me either.

    function component_master($id,$first=false) {
        if (file_exists('data/other/components.xml')) {
            $master = return_page_slug();
            $extra = false;
            $standard = false;
            $thisfile = file_get_contents("data/other/components.xml");
            $data = simplexml_load_string($thisfile, NULL, LIBXML_NOCDATA);
            $components = $data->item;
            
            if (count($components) != 0) {
                foreach ($components as $component) {
                    if ($master.'-'.$id == $component->slug) {
                        eval("?>" . stripslashes(htmlspecialchars_decode($component->value, ENT_QUOTES)) . "<?php ");
                        return;
                    } elseif ($master.'-extra-'.$id == $component->slug) {
                        $extra = $component->value;
                    } elseif ($id == $component->slug) {
                        $standard = $component->value;
                    }
                }
                if ($standard) {
                    eval("?>" . ($extra&&$first?stripslashes(htmlspecialchars_decode($extra, ENT_QUOTES)):'') . stripslashes(htmlspecialchars_decode($standard, ENT_QUOTES)) . ($extra&&!$first?stripslashes(htmlspecialchars_decode($extra, ENT_QUOTES)):'') . "<?php ");
                }
            }
        }
    }

Last edited by Zegnåt (2009-11-16 14:03:27)

Re: Function: per page components.

Thanks for this!

Re: Function: per page components.

GetSimple.RU wrote:

Thanks for this!

Nice to hear someone likes it. Be sure to let me know how it works out for you!

Re: Function: per page components.

Hi Zegnåt,
thanks for sharing this !
is very usefull
and  great explanation ... (mm teacher?)

I'm trying to implement it, but got some on function.php pasted code ... Could you check it please?  or just attach the file.
thanks again

Re: Function: per page components.

focoves wrote:

is very usefull

Thanks!

focoves wrote:

teacher?

Hahaha, far from. I’m only 18 years old, sorry to let you down ;-)

focoves wrote:

I'm trying to implement it, but got some on function.php pasted code ... Could you check it please?

If you have nothing else in functions.php be sure to not forget the <?php and ?> around the function, to make it PHP.

Still problems? Attach your functions.php and I’ll be happy to take a look.

Re: Function: per page components.

This is great. I'm going to try it now. I have been using WolfCMS which like GS is small and fast. It also has this feature called "Page Parts" which is the same as per page components.

One thing I am concerned with is that all these addons (which are awesome, btw) should be included as plugins and not code hacking. I was using sNews a few years ago but left that because all they would do is hack the code, which works, but on program update, you have to hack it all again just to get what you had. That was very frustrating to say the least. I hope GS does not turn into this. I know GS is young and growing which is great, but I hope feature additions will be done as plugins.

Keep up the good work everyone!

Re: Function: per page components.

Update! Installed fine. I put a slideshow in the sidebar and it only shows on the index page which is correct. However, on the other pages Firefox is now giving me a warning that "DIV with ID XX not found on page". Of course Firefox, it's not supposed to be there. The thing is the slideshow script is in the head of the template and that's why Firefox is expecting that DIV.

Am I missing something here? Can I not use a slideshow script in the head of the template??

Update - Found bug in slideshow.js

Last edited by tyee (2010-02-10 02:40:55)

Re: Function: per page components.

I just wanted to say your solution works great. I'd love the ability to add multiple sidebar components for each specific page, but this much, much easier than the