When you convert an html theme to concrete5 theme and/or add your own stuff to exist Concrete5 theme :) page_theme.php class methods: requireAsset and providesAsset could be your best freinds :) I think this issue its little confusing so i add "non developer" / "simple words" guide.

For deep/full understand of this issues you most read C5 official docs.

Preface:

CSS - How the site looks (colors, spaces, size etc.)

JS - Behavior (open modal or dropdown etc.)

Very simple and obvious idea before we start:

Like other popular CMSs, Concrete5 is web content management ("lives in your broswer"). Concrete5 will use JS and CSS (For the admin panels, drop downs and so on) Your theme will also use JS and CSS. Some of these assets could cause conlict and problems so you must have some way to manage this in simple and elegant way.

In simple words

"Hey Theme I am the interface, please remember we live together and I need the right CSS and JS Assets to look and work fine :)".

"Stupid abstract example" - Lets learn the trick

Imagine you are buying new home and this home comes with build-in red Kitchen and the option to add Extra money for premium blue Kitchen :) Now you have 2 scenarios:

  • scenario1: I really love the red Kitchen.

  • scenario2: I dont like red, i want the Blue Kitchen.

If this scenario was in some computer program you should have option to "keep red + abort the blue option" or "replace to blue, abort red option" (otherwise you find in your home red and blue kitchen together)

So i create some function tell my home - i require this red kitchen :)

//scenario1:
$this->requireFurniture('kitchen', 'red');

Or I want to provide my own kitchen so dont use the red one.

//scenario2
$this->providesFurniture('kitchen', 'blue');

Now depending on the scenario I will choose to "require" red or "provide" blue :)

From this really stupid example to Concrete5

Assets in Concrete5 refer to JavaScript or CSS files required to make something work.

Concrete5 comes with build-in Assets :) If you inspect the element when you are logged in you will find a call to external assets files like: query, boostrap, font-awesome. Of course Concrete5 needs those asset to work and look fine.

You find some of those assets here: /SiteName/concrete/js/* /SiteName/concrete/css/*

Also look at the full asset list: Asset-list

For the simplicity lets imagine the red kitchen is the core "build-in" jquery.js located her: /SiteName/concrete/js/jquery-ui.jsand the blue kitchen is your custom-jquery.js

When you are developing a theme again you have two scenarios:

  • scenario1: I really love the "build-in" jquery.js - i want do use this asset in my theme (Always - Not only when I am logged in and the system add this asset for the Admin Interface)
// scenario1: Require - "to demand" something.
 $this->requireAsset('javascript', 'jquery');

Now logout: In your html you will find a "magic" point to an external JavaScript file: <script type="text/javascript" src="/SiteName/concrete/js/jquery.js"></script>

  • scenario2: Oh no I don't want to use the "build-in" jquery.js - I really like my own custom-jquery.js file ("I want to ovveride the core file").
//scenario2 : provides - "to supply (something that is wanted or needed)" 
$this->providesAsset('javascript', 'jquery'); 

This step only tell the system "hey I don't want the "build-in" jquery.js. In other words now "you don't have any jquery.js file in your site".

Now the admin interface will not work well and the code will throw errors like this: Uncaught ReferenceError: jQuery is not defined(anonymous function) @ tooltip.js:1

How to FIX this error? Like we promise lets provide/supply this asset.

In this example I put custom-jquery.js in this location: siteName\application\themes\my_theme_name\assets\js

Now lets point to this external JavaScript file: Go to your theme and put this line of code: <script src="<?php echo $view->getThemePath()?>/assets/js/custom-jquery.js"></script>

Thats it :)

Font-awesome example

Concrete5 admin uses the icon font - font-awesome.css, when you are login this asset will load automatically.

Do this simpele test:

  • Step 1: Login

  • Step 2: Put this font-aswome markup in your theme template: <i class="fa fa-camera-retro fa-lg"></i>

  • Step 3: Refresh your page and "WOW" you will get nice camera icon.

How this is happening without any link in your theme to font-awesome? Remember in the Preface section we tell you the admin and theme live toghever. And also we learned that Concrete5 admin loads Font Awesome automatically.

Inspect your site and "ctr+f" (find) "font-awesome". You will find this line: <link href="/SiteName/concrete/css/font-awesome.css" rel="stylesheet" type="text/css" media="all">

  • Step 4: Thats nice. Go to this /SiteName/concrete/css/ folder. Here you will find "font-awesome.css" and other useful CSS assets (Look for JS assets here /SiteName/concrete/js/)

Lets Load Font Awesome Twice

In your theme you want to add (supply/provide) font-awesome so you add this line of code in your <head>

<link href="<?php echo $view->getThemePath()?>/assets/css/font-awesome.css" type="text/css" rel="stylesheet">

Whats happens? When you login you will see this asset loaded twice!! (inspect element and test this).

Look close at the different "href" addresses.

"Hey i am point to an external JavaScript file you put in the - theme level"

<link href="/mySiteName/application/themes/my_theme_name/assets/css/font-awesome.css"
type="text/css" rel="stylesheet">

"Hey i am point to an external JavaScript file from the - Concrete5 Admin interface level

<link href="/mySiteName/concrete/css/font-awesome.css" rel="stylesheet" type="text/css" media="all">

Summary: In this example we load font-awesome twice. Besides performance issue, loading Font-awesome twice is not "big-issue", but loading twice Jquery, bootstrap.js and other files could cause a lot of bugs

After you learn about: requireAsset and providesAsset its really easy to solve this problem. In this example we only need to tell the system we provide/supply this asset: $this->providesAsset('css', 'font-awesome');

Small boostrap issue:

Also remember to provide the corret code. In Bootstrap for example the framework is modular.

Boostrap docs: Plugins can be included individually (using Bootstrap's individual *.js files), or all at once (using bootstrap.js or the minified bootstrap.min.js).

So its really important to provide the correct CSS and JS that the C5 admin intereface needs (Asset list will be helpful here).

Also when you Require the core Bootstrap - remember to check if you have all the CSS and JS plugins thats you need in your theme level.

Appendix : page_theme.php example code:

<?php
namespace Application\Theme\ThemeName;

use Concrete\Core\Area\Layout\Preset\Provider\ThemeProviderInterface;

class PageTheme extends \Concrete\Core\Page\Theme\Theme
{   
    public function registerAssets()
    {   
        $this->providesAsset('css', 'font-awesome');
        $this->requireAsset('css', 'bootstrap/*');
    }
}

Summary:

C5 page_theme class gives you a lot of control over asset loading. When you want to use the core assets - Require/Demand them, or when you want to override the core assets (provide/supply your own files).

Full developers guide docs:

Loading Conversation