Assets
Assets
Assets centralizes shared assets like jQuery, Bootstrap, and various JavaScript and CSS libraries. This registry, extendable by packages and custom code, allows each asset to specify its position (header or footer), supports minification, and enables combining assets to reduce HTTP requests. Developers can assign handles to assets, supporting local or remote access, independent of file names. Themes and packages can prevent automatic asset inclusion. The system also accommodates block custom template auto-loaded assets (view.js, view.css).
Assets refer to CSS and JavaScript files, essential for functionality. For instance, Redactor's functionality needs these files:
- concrete/js/redactor.js
- concrete/css/redactor.css
- concrete/js/file-manager.js
- concrete/css/file-manager.js
- concrete/js/sitemap.js
- concrete/css/sitemap.css
Previously, we'd use $view->addHeaderItem()
and $view->addFooterItem()
. These are still there but not ideal for dynamic asset requirements.
Asset Framework
The Asset Framework in the \Concrete\Core\Asset
namespace allows registering assets, handling minification, versioning, and paths. Grouping assets simplifies their inclusion. To use Redactor's assets:
$this->requireAsset('redactor');
Theme Assets
Themes can include assets. Our bootstrap3 theme comes with bootstrap CSS and JS. To avoid conflicts and duplicate assets, we add to the PageTheme class:
public function registerAssets()
{
$this->providesAsset('javascript', 'bootstrap/*');
$this->providesAsset('css', 'bootstrap/*');
$this->providesAsset('css', 'blocks/form');
$this->providesAsset('css', 'core/frontend/*');
$this->requireAsset('javascript', 'jquery');
}
Registering an Asset in Concrete CMS
To use an asset in Concrete CMS, it must be registered, letting the system know how to include it. For instance, registering jQuery (already included in Concrete) involves a simple PHP block:
$al = \Concrete\Core\Asset\AssetList::getInstance();
$al->register('javascript', 'jquery', 'js/jquery.js');
- Obtain the Asset List class instance using
getInstance()
. - Use
register()
with arguments: asset type ('javascript' or 'css'), handle ('jquery'), path/URL, options array (optional), and \Concrete\Core\Package\Package object or package handle (optional).
Asset Types in Concrete
Supported asset types:
- css: CSS style sheets.
- css-inline: Inline style elements.
- css-localized: TBD
- javascript: JavaScript files.
- javascript-inline: Inline JavaScript.
- javascript-conditional: TBD
- javascript-localized: TBD
Path Specification
Paths in register()
are relative to application/
, packages/package_handle/
, or concrete/
directories.
Handle Uniqueness
Handles must be unique across asset types, allowing one CSS and one JavaScript file per handle.
Usage Contexts
- Register assets in
application/bootstrap/app.php
, package'son_start()
, or a block type'son_start()
method. - For blocks, add registration in the block's
on_start()
method. - For packages, include asset registration in the package controller's
on_start()
method.
register()
Options
Options include position (\Concrete\Core\Asset\Asset::ASSET_POSITION_HEADER
or FOOTER
), local
(default true), version
, combine
, and minify
. Note: combine
and minify
were removed in Concrete CMS v9 but remain for backward compatibility.
Example with Options
$al->register(
'javascript', 'mediaelement', 'blocks/audio/mediaelement/mediaelement-and-player.min.js',
array('version' => '2.16.3', 'minify' => false, 'combine' => true)
);
$al->register(
'css', 'mediaelement', 'blocks/audio/mediaelement/mediaelementplayer.min.css',
array('version' => '2.16.3', 'minify' => false, 'combine' => true)
);
Grouping Assets
Asset Groups in Concrete CMS allow bundling related assets for simultaneous inclusion. For instance, grouping Mediaelement.js JavaScript and CSS with jQuery:
$al = \Concrete\Core\Asset\AssetList::getInstance();
$al->registerGroup('mediaelement', array(
array('css', 'mediaelement'),
array('javascript', 'jquery'),
array('javascript', 'mediaelement')
));
- Use
registerGroup()
with a unique group handle and an array of asset arrays. - Each asset array includes the asset type and handle as registered.
Registered asset groups can then be easily included in pages as needed.
Requiring an Asset
In Concrete CMS, requiring assets or asset groups for pages or blocks is straightforward.
Requiring an Asset Group in Page Controllers
In page type or single page controllers:
public function view() {
$this->requireAsset('mediaelement');
}
Requiring a Single Asset in Page Controllers
In page type or single page controllers:
public function view() {
$this->requireAsset('javascript', 'jquery');
}
Requiring an Asset Group in Block "Add" Interface
In block controllers:
public function add() {
$this->requireAsset('core/filemanager');
}
Requiring an Asset Group for Block Viewing
In block controllers:
public function registerViewAssets($outputContent = '') {
$this->requireAsset('mediaelement');
}
Requiring or Providing Assets in Themes
Refer to theme documentation for handling core JavaScript/CSS: - Requiring Core JavaScript/CSS in a Theme - Overriding/Providing Core JavaScript/CSS in a Theme
Streamlining Theme Customization with CSS Classes
We've enhanced our theme with a grid, block classes, and assets. Next, we'll customize blocks, areas, and the Rich Text Editor with CSS classes.
Simple Customization
Concrete CMS's custom templates offer alternate block views, but sometimes a custom class suffices. In version 9, you can define these classes in the PageTheme file for a user-friendly selection.
Area-Specific Classes
To add a class to an area:
public function getThemeAreaClasses()
{
return array(
'Welcome' => array('templatemo-team')
);
}
This makes "templatemo-team" available for any "Welcome" area in the Custom Design toolbar.
Block-Specific Classes
To assign classes to blocks:
public function getThemeBlockClasses()
{
return array(
'image' => array(
'img-thumbnail'
),
'*' => array(
'highlighted'
)
);
}
"img-thumbnail" becomes available for Image blocks, and "highlighted" for all blocks.
Editor Classes
Adding editor-specific classes:
public function getThemeEditorClasses()
{
return array(
array('title' => t('Orange Button'), 'menuClass' => '', 'spanClass' => 'btn btn-orange'),
array('title' => t('Green Button'), 'menuClass' => '', 'spanClass' => 'btn btn-green')
);
}
These classes will appear in the rich text editor, allowing for easy CSS customization without custom templates.
Requiring Core JavaScript or CSS in a Theme
Including core JavaScript and CSS directly in theme templates isn't the best approach. Directly embedding them, like this:
<script type="text/javascript" src="<?=ASSETS_URL_JAVASCRIPT?>/js/jquery.js"></script>
<link rel="stylesheet" media="screen" type="text/css" href="<?=ASSETS_URL_CSS?>/font-awesome.css" />
can cause issues, such as duplications or JavaScript conflicts.
A better method is using Concrete's Assets system, which ensures scripts and stylesheets are never included twice and supports on-the-fly minifying and combining for better performance.
To include core assets like jQuery and Font Awesome in your theme, utilize the requireAsset
method in the PageTheme class. For example:
public function registerAssets()
{
$this->requireAsset('css', 'font-awesome');
$this->requireAsset('javascript', 'jquery');
}
This approach guarantees that your theme properly loads these assets without duplication, maintaining efficient performance and avoiding conflicts.
Simplifying Core Asset Overrides in Concrete CMS
Overriding Core JavaScript and CSS Libraries
To override core JavaScript and CSS in Concrete CMS:
Via application Directory
- Find the file (e.g.,
concrete/js/jquery.js
). - Turn off Overrides Caching in Dashboard > Optimization settings.
- Place your new file (e.g.,
application/js/jquery.js
).
Via Asset System
For package-based overrides:
public function on_start()
{
$al = \AssetList::getInstance();
$al->register('javascript', 'jquery', '//ajax.googleapis.com/ajax/libs/jquery/2.0/jquery.min.js', array('local' => false, 'version' => '2.0'));
}
Overriding Core Block JavaScript and CSS Libraries
To override block-level assets:
- Locate the file (e.g.,
core/blocks/date_navigation/view.css
). - Disable Overrides Caching in Dashboard settings.
- Place your new file in the corresponding
application/blocks/
folder.
Registering Theme-Provided Assets
For Core Libraries
If your theme includes core libraries (like Bootstrap in Urbanic theme), inform Concrete not to load its own assets. Use Theme::providesAsset
in PageTheme
class:
public function registerAssets()
{
$this->requireAsset('css', 'font-awesome');
$this->requireAsset('javascript', 'jquery');
$this->providesAsset('javascript', 'bootstrap/*');
$this->providesAsset('css', 'bootstrap/*');
}
For Block Assets
To declare block assets provided by your theme:
public function registerAssets()
{
// ... Existing code ...
$this->providesAsset('css', 'blocks/form');
$this->providesAsset('css', 'blocks/date_navigation');
// ... Add more as needed ...
}
Handling Miscellaneous Core CSS
For Bootstrap-based themes:
- Mark Bootstrap-dependent core CSS as provided.
- Use wildcards for efficiency:
$this->providesAsset('css', 'core/frontend/*');
This setup ensures your theme correctly handles Concrete's core and block assets, avoiding duplication and potential conflicts.
Using CSS Selectors for Page Types and Templates in Concrete CMS
The Page::getPageWrapperClass()
function, crucial for UI elements, outputs CSS classes that theme developers can utilize for specific styling. The mandatory ccm-page
class is essential for panels, while other classes represent the page type and template. For instance:
<div class="ccm-page page-type-blog page-template-full">
...
</div>
Here, page-type-blog
and page-template-full
are dynamic classes based on the page type and template.
Different pages yield distinct classes. For example:
<div class="ccm-page page-type-portfolio-project page-template-left-sidebar">
</div>
In Concrete CMS, underscores in handles (like portfolio_project
) are converted to dashes in class names.
This feature is useful for advanced theming. For instance, the following CSS targets the sidebar on the blog entry page:
div.ccm-page.page-type-blog-entry div.col-sidebar {
padding-top: 40px;
}
Asset Groups
Wherever possible, you should use requireAsset() with a single asset group, rather than individual assets. There are certain exceptions (like requiring the jQuery JavaScript library) but in general most Concrete CMS functionality has already been separated into semantic groups, which will include all the CSS and JavaScript necessary.
- ace
- core/account (Feature: account)
- core/app
- core/app/editable-fields
- core/colorpicker (Feature: cms)
- core/conversation (Feature: conversations)
- core/file-manager (Feature: cms)
- core/gathering
- core/groups (Feature: cms)
- core/imageeditor
- core/legacy
- core/lightbox (Feature: imagery)
- core/rating (Feature: cms)
- core/sitemap (Feature: cms)
- core/style-customizer (Feature: cms)
- core/topics (Feature: taxonomy)
- core/translator
- dashboard (Feature: cms)
- dropzone
- dynatree
- font-awesome
- jquery/fileupload (Feature: cms)
- jquery/ui (Feature: cms)
- jquery/visualize
- redactor
- responsive-slides (Feature: imagery)
- select2
- swfobject
Individual Assets
Individual JavaScript Files
- ace
- awesome-rating (Feature: cms)
- backbone
- backstretch
- bootstrap-editable
- bootstrap/alert
- bootstrap/button
- bootstrap/dropdown
- bootstrap/popover
- bootstrap/tooltip
- bootstrap/transition
- core/account (Feature: account)
- core/app
- core/conversation (Feature: conversations)
- core/events (Feature: cms)
- core/file-manager (Feature: cms)
- core/frontend/parallax-image
- core/gathering
- core/groups (Feature: cms)
- core/imageeditor
- core/imageeditor_locale
- core/legacy
- core/lightbox (Feature: imagery)
- core/lightbox/launcher
- core/localization
- core/sitemap (Feature: cms)
- core/style-customizer (Feature: cms)
- core/topics (Feature: taxonomy)
- core/translator
- dashboard (Feature: cms)
- dropzone
- dynatree
- dynatree_locale
- html5-shiv
- jquery
- jquery/fileupload
- jquery/form
- jquery/textcounter
- jquery/touch-punch
- jquery/tristate
- jquery/ui (Feature: cms)
- jquery/visualize
- kinetic
- picturefill
- redactor
- redactor_locale
- respond
- responsive-slides (Feature: imagery)
- select2
- select2_locale
- spectrum
- swfobject
- underscore
Individual CSS Files
- awesome-rating (Feature: cms)
- bootstrap
- bootstrap/alert
- bootstrap/button
- bootstrap/dropdown
- bootstrap/popover
- bootstrap/tooltip
- bootstrap/transition
- core/account (Feature: account)
- core/app
- core/app/editable-fields
- core/conversation (Feature: conversations)
- core/file-manager (Feature: cms)
- core/frontend/captcha
- core/frontend/errors
- core/frontend/pagination (Feature: bedrock)
- core/gathering/base
- core/gathering/display
- core/imageeditor
- core/legacy
- core/lightbox (Feature: imagery)
- core/sitemap (Feature: cms)
- core/style-customizer (Feature: cms)
- core/topics (Feature: taxonomy)
- core/translator
- dropzone
- dynatree
- font-awesome
- jquery/ui (Feature: cms)
- jquery/visualize
- redactor
- responsive-slides (Feature: imagery)
- select2
- spectrum
Asset Links
- ace - https://ace.c9.io
- awesome-rating - http://rcugut.github.io/jqAwesomeStarRating/
- backbone - http://backbonejs.org/
- backstretch - http://srobbin.com/jquery-plugins/backstretch/
- bootstrap-editable - http://vitalets.github.io/x-editable/
- bootstrap/alert - http://getbootstrap.com/javascript/#alerts
- bootstrap/button - http://getbootstrap.com/javascript/#buttons
- bootstrap/dropdown - http://getbootstrap.com/javascript/#dropdowns
- bootstrap/popover - http://getbootstrap.com/javascript/#popovers
- bootstrap/tooltip - http://getbootstrap.com/javascript/#tooltips
- bootstrap/transition - http://getbootstrap.com/javascript/#transitions
- core/lightbox - http://dimsemenov.com/plugins/magnific-popup/
- dropzone - http://www.dropzonejs.com/
- dynatree - https://github.com/mar10/dynatree
- font-awesome - http://fortawesome.github.io/Font-Awesome/
- html5-shiv - https://github.com/aFarkas/html5shiv
- jquery - https://jquery.com/
- jquery/fileupload - https://blueimp.github.io/jQuery-File-Upload/
- jquery/form - http://jquery.malsup.com/form/
- jquery/textcounter - https://github.com/ractoon/jQuery-Text-Counter
- jquery/touch-punch - http://touchpunch.furf.com/
- jquery/tristate - http://vanderlee.github.io/tristate/
- jquery/ui - https://jqueryui.com/
- jquery/visualize - https://github.com/filamentgroup/jQuery-Visualize
- kinetic - http://www.kineticjs.com/
- picturefill - http://scottjehl.github.io/picturefill/
- respond - https://github.com/scottjehl/Respond
- responsive-slides - http://responsiveslides.com/
- select2 - https://select2.github.io/
- spectrum - http://bgrins.github.io/spectrum/
- swfobject - https://github.com/swfobject/swfobject
- underscore - http://underscorejs.org/