Welcome Guest, Not a member yet? Register   Sign In
Dynamically loading assets, a question
#1

[eluser]kyleect[/eluser]
Today, I've started a project to take a fresh install of CI and start to extend it with changes I've either implemented with apps I've worked on or things I've wanted to do. One thing I've wanted to do is to implement a way to display headers and footers on all pages separate from the content. I've seen a lot of ways to do this but this is the method I've come up with and it seems to work except for one issue. I need a way to dynamically set what assets (css, javascript) a page is going to use inside the child controllers/methods. This seems to be an issue however as the header is processed and outputted during the construction of MY_Controller. Does anyone have any advice?


MY_Controller:
Code:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

    class MY_Controller extends Controller
    {
        protected $view_data;
        protected $view_parts;
        
        public function __construct()
        {
            parent::Controller();
            
            $this->config->load('application', TRUE);        
            
            
            
            //SET DEFAULT VIEW VARIABLES
            $this->view_data['page_title'] = 'Default';
            $this->view_data['application'] = $this->config->item('application');
            
            //This sets the pages body id to "controller_method". This allows for more standardized css handling.
            if($this->router->method = 'index')
            {
                $this->view_data['body_id'] = ($this->router->class);
            }
            else
            {
                $this->view_data['body_id'] = ($this->router->class).'_'.(($this->router->method));
            }
            
            
            
            //The header and footer views have to be loaded in to variables so the footer can be loaded on the controllers destruction
            $this->view_parts['header'] = $this->load->view('header', $this->view_data, TRUE);
            $this->view_parts['footer'] = $this->load->view('footer', $this->view_data, TRUE);
            
            echo $this->view_parts['header'];
        }
        
        public function __destruct()
        {
            print_r($this->view_parts['footer']);
        }
    }
?>
#2

[eluser]Dam1an[/eluser]
Has the header is just a string variable, you could always just put a placeholder in there for CSS and JS includes, add the files to relevant arrays throughout the application as you need them, and then just before the output, do a replace in the header putting the full includes in place of the placeholder

This is what I plan to do, as I'm in a similar situation to you (so if you do it first, feel free to share the code Wink)
#3

[eluser]John_Betong[/eluser]
 
I have adopted this approach and it seems to account for every eventuality:
 
Try this in your controller:   $data['css_file'] = '/wherever_the_file_is_located/style.css';
 
Then in your controller use MY_Controller->v_main($data);
Code:
//==============================================
  //
    // called from every controller
    // usage:
    //       $this->load->view('v_home', $data);
  //
  //==============================================
  function v_main($data)
  {
       $data['error_msg']= ''; // maybe populated but prevents output error

        // model stuff
        $data['userids']    = ul($this->m_skyhook->get_userid_menu(), $this->attributes);
        $data['pageids']    = ul($this->m_skyhook->get_page_ids(),         $this->attributes);
        $data['contribs']    = ul($this->m_skyhook->get_userids(NULL), $this->attributes);
    
      // fixed parameters
      $data['doctype']    = doctype();
        $data['title']        = 'Skyhook-PRO';
        $data['elapsed']    =    $this->benchmark->elapsed_time();

        // above info passed to these partial views
        $data['header']        = $this->load->view('_header',                 $data, TRUE);
        $data['left']            = $this->load->view('_left',                     $data, TRUE);
        $data['main']            = $this->load->view('_main',                     $data, TRUE);
        $data['footer']        = $this->load->view('_footer',                 $data, TRUE);
        $data['right']        = LOCALHOST ? anchor('ci_svn/user_guide/', 'User Guide') : $this->load->view('_google_160x600', $data, TRUE);
        
        // call main view
        $result = $this->load->view('v_main', $data, FALSE);// FALSE so that benchmark works
    }
 
 
 
#4

[eluser]kyleect[/eluser]
[quote author="Dam1an" date="1251768623"]Has the header is just a string variable, you could always just put a placeholder in there for CSS and JS includes, add the files to relevant arrays throughout the application as you need them, and then just before the output, do a replace in the header putting the full includes in place of the placeholder

This is what I plan to do, as I'm in a similar situation to you (so if you do it first, feel free to share the code Wink)[/quote]

This is what I came up with and seems to work pretty well. Do you see any disadvantages to doing a lot of the work in the __destruct() method with how CI works? Something I'm overlooking?

Code:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
* MY_Controller
*
* Consider this the application controller.
*
* @package Firestarter
* @subpackage Core Extension
* @author Kylee Tilley <[email protected]>
*/

// ------------------------------------------------------------------------

/**
* @package Firestarter
* @subpackage Core Extension
**/

/* TODO:

    I need to create an assest management library so clean up the code in $this->embed_assests

*/

/*

    NOTE: Using this controller will change how you are using views.
    You will need to load a view in to a variable called $this->views['content']

*/

    class MY_Controller extends Controller
    {
        protected $view_data;
        protected $assests;
        protected $views;
        
        public function __construct()
        {
            parent::Controller();
            
            $this->config->load('application', TRUE);            
            
            //SET DEFAULT VIEW VARIABLES
            $this->view_data['page_title'] = 'Home';
            $this->view_data['application'] = $this->config->item('application');
                //To help standardize page specific CSS, we are setting the body id of the page to "controller__method"            
            $this->view_data['body_id'] = ($this->router->method = 'index') ? ($this->router->class) : ($this->router->class).'__'.(($this->router->method));
            
            //SET DEFAULT ASSESTS
            
            /* ---- Stylesheets ----
            
                In order to include a stylesheet on to the page, you must define it in the $this->assests['css'] variable.
                
                By default, you will set just a single string. You can set an array if you need to set options like media type.
                
                EXAMPLE:
                
                    $this->assests['css'][] = array('print', media="print");
            
            */
            $this->assests['css'] = array('main');
            $this->assests['javascript'] = array();

            //LOAD VIEWS
            //The header and footer views have to be loaded in to variables so they can be outputted on the controllers destruction
            $this->views['header'] = $this->load->view('header', $this->view_data, TRUE);
            $this->views['footer'] = $this->load->view('footer', $this->view_data, TRUE);
            $this->views['view_content'] = NULL;
        }
        
        private function embed_assests()
        {
            $stylesheets = NULL;
            $javascripts = NULL;
            
            
            
            //STYLESHEETS
            
            if(!empty($this->assests['css']))
            {            
                foreach($this->assests['css'] as $stylesheet)
                {
                    if(is_array($stylesheet))
                    {
                        if(isset($stylesheet['media']))
                        {
                            $stylesheets .= '&lt;link rel="stylesheet" href="'.$this-&gt;view_data['application']['assests_dir'].'css/'.$stylesheet[0].'.css" media="'.$stylesheet['media'].'" type="text/css">'."\n";
                        }
                        else
                        {
                            $stylesheets .= '&lt;link rel="stylesheet" href="'.$this-&gt;view_data['application']['assests_dir'].'css/'.$stylesheet.'.css" type="text/css">'."\n";
                        }
                    }
                    else
                    {
                        $stylesheets .= '&lt;link rel="stylesheet" href="'.$this-&gt;view_data['application']['assests_dir'].'css/'.$stylesheet.'.css" type="text/css">'."\n";
                    }
                }
            }
            
            
                
            //JAVASCRIPT
            
            if(!empty($this->assests['javascript']))
            {    
                foreach($this->assests['javascript'] as $javascript)
                {
                    $javascripts .= '[removed][removed]'."\n";
                }
            }
            
            
            
            $this->views['header'] = str_replace('#load_css#', $stylesheets, $this->views['header']);
            $this->views['header'] = str_replace('#load_javascript#', $javascripts, $this->views['header']);    
        }
        
        public function __destruct()
        {    
            $this->embed_assests();
            
            echo $this->views['header'];
            echo $this->views['view_content'];
            echo $this->views['footer'];
        }
    }
?&gt;




Theme © iAndrew 2016 - Forum software by © MyBB