addHeaderItem from package controller on_start

Permalink
I'm attempting to create a package that loads some animation css from the package controller on_start and contains an array of custom templates.

Unfortunately, I'm stuck adding the css file to the header. I've poked around the forums and google search and found a few resources. Most notably this one:
http://www.concrete5.org/community/forums/customizing_c5/loading-ex...

Although, I'm not able to get this working. The css file is contained in /package_name/css/ and the current code I'm trying to use is as follows:
public function on_start() {
      $html = Loader::helper('html');
      $this->addHeaderItem($html->css('animationcss.css','enlil_animations'));
   }


Any assistance would be much appreciated!

enlil
 
JohntheFish replied on at Permalink Reply
JohntheFish
The usual pattern is to use on_start to set up an on_before_render handler, then in the on_before_render handler, get a view instance and use that as the object to call addHeaderItem from.

on_before_render is not called until the page is known, so you can use tests on the page and path within the handler to filter out including the css for dashboard pages or other pages where it isn't wanted.

public function on_start(){
  Events::extend('on_before_render', 'ThisPackageClass', 'on_before_render_handler', DIR_PACKAGES.'/this_package_class/controller.php');
}
public function on_before_render_handler(){
  $html = Loader::helper("html");
  $view = View::getInstance();
  $view->addHeaderItem($html->css("your.css", 'your_package'));
}
enlil replied on at Permalink Reply
enlil
Thank you for that John! I was able to get it working simply using:

public function on_start() {
      $html = Loader::helper('html');
      $view = View::getInstance();
      $view->addHeaderItem($html->css('animationcss.css','enlil_animations'));
   }


Time to make some custom templates :)
JohntheFish replied on at Permalink Reply
JohntheFish
What you have will work. However, the on_start handler is run for every single page, including dashboard pages. The advantage of the on_before_render handler is that the page is known by then, so you can check the current page, whether it is in edit mode, whether it is in the dashboard, whether it has an attribute, or whatever you want to check that is page related before loading the css.

Also there were some issues with code directly in on_start with core upgrades. If this is going in an addon that is compatible before 5.6.2.1, you should check what you have does not allow the c5 upgrade bug to manifest.

The situation for individual page type controllers (such as dashboard single pages) is different, because the on_start handler in page controllers is only run when that page is loaded.
enlil replied on at Permalink Reply
enlil
Excellent info. Do you know any direct links to info on the upgrade bug?

The idea here is the css will be loaded not only for the package, but also for developers to use anywhere within code, and works well. If someone wants to hack their dashboard pages and add classes to their elements that's on them :)

I've done some testing in 5.6.1.2 in dashboard pages, etc. and everything is looking good so far.
JohntheFish replied on at Permalink Reply
JohntheFish
Here is one I reported. There are others.
http://www.concrete5.org/developers/bugs/5-6-2-1/event-handlers-dur...

Its just not good practice to load stuff like extra js or css globally across the dashboard. If a developer wants to create a dashboard single page to use it, they can explicitly load as and when they need it in their own single page controller. So your package should only load for front-end pages.

So - some examples of the sort of things you can do with on_before_render that you can't do wit on_start (not sure that all this is quite correct, but it will give you the idea):
function on_before_render(){
  $page = Page::getCurrentPage()
  if(!is_object($page) || $page->isError()){
    return;
  }
  if($page->isSystemPage()){
    return;
  }
  if($page->isEditMode()){
    return;
  }
  $path=$page->getCollectionPath();
  if(strpos($path, '/dashboard/') !== false){
    return;
  }