diff --git a/administrator/templates/isis/component.php b/administrator/templates/isis/component.php
index d4b429302d38d..0895339929ca2 100644
--- a/administrator/templates/isis/component.php
+++ b/administrator/templates/isis/component.php
@@ -18,32 +18,8 @@
// Output as HTML5
$doc->setHtml5(true);
-// Add JavaScript Frameworks
-JHtml::_('bootstrap.framework');
-
-$doc->addScriptVersion($this->baseurl . '/templates/' . $this->template . '/js/template.js');
-
-// Add Stylesheets
-$doc->addStyleSheetVersion($this->baseurl . '/templates/' . $this->template . '/css/template.css');
-
-// Load optional RTL Bootstrap CSS
-JHtml::_('bootstrap.loadCss', false, $this->direction);
-
-// Load specific language related CSS
-$file = 'language/' . $lang->getTag() . '/' . $lang->getTag() . '.css';
-
-if (is_file($file))
-{
- $doc->addStyleSheet($file);
-}
-
-// Load custom.css
-$file = 'templates/' . $this->template . '/css/custom.css';
-
-if (is_file($file))
-{
- $doc->addStyleSheetVersion($file);
-}
+// Load the template asset
+JHtml::_('asset.load', $doc->direction == 'rtl' ? 'template.isis.rtl' : 'template.isis.ltr');
// Link color
if ($this->params->get('linkColor'))
diff --git a/administrator/templates/isis/index.php b/administrator/templates/isis/index.php
index 2b659f53284ab..7ec969bbc1826 100644
--- a/administrator/templates/isis/index.php
+++ b/administrator/templates/isis/index.php
@@ -25,29 +25,8 @@
$frontEndUri->setScheme(((int) $app->get('force_ssl', 0) === 2) ? 'https' : 'http');
$mainPageUri = $frontEndUri->toString();
-// Add JavaScript Frameworks
-JHtml::_('bootstrap.framework');
-
-$doc->addScriptVersion($this->baseurl . '/templates/' . $this->template . '/js/template.js');
-
-// Add Stylesheets
-$doc->addStyleSheetVersion($this->baseurl . '/templates/' . $this->template . '/css/template' . ($this->direction == 'rtl' ? '-rtl' : '') . '.css');
-
-// Load specific language related CSS
-$languageCss = 'language/' . $lang->getTag() . '/' . $lang->getTag() . '.css';
-
-if (file_exists($languageCss) && filesize($languageCss) > 0)
-{
- $doc->addStyleSheetVersion($languageCss);
-}
-
-// Load custom.css
-$customCss = 'templates/' . $this->template . '/css/custom.css';
-
-if (file_exists($customCss) && filesize($customCss) > 0)
-{
- $doc->addStyleSheetVersion($customCss);
-}
+// Load the template asset
+JHtml::_('asset.load', $doc->direction == 'rtl' ? 'template.isis.rtl' : 'template.isis.ltr');
// Detecting Active Variables
$option = $input->get('option', '');
diff --git a/administrator/templates/isis/joomla.asset.json b/administrator/templates/isis/joomla.asset.json
new file mode 100644
index 0000000000000..8a5f3b741aab2
--- /dev/null
+++ b/administrator/templates/isis/joomla.asset.json
@@ -0,0 +1,43 @@
+{
+ "title" : "Joomla! isis template",
+ "name" : "template.isis",
+ "author" : "Joomla! CMS",
+ "version": "1.0",
+
+ "assets": [
+ {
+ "name": "template.isis",
+ "versionAttach": true,
+ "dependency": [
+ "bootstrap.js"
+ ],
+ "js": [
+ "template.js"
+ ]
+ },
+ {
+ "name": "template.isis.ltr",
+ "versionAttach": true,
+ "dependency": [
+ "template.isis"
+ ],
+ "css": [
+ "template.css",
+ "language/[LANGUAGE_TAG]/[LANGUAGE_TAG].css",
+ "custom.css"
+ ]
+ },
+ {
+ "name": "template.isis.rtl",
+ "versionAttach": true,
+ "dependency": [
+ "template.isis"
+ ],
+ "css": [
+ "template-rtl.css",
+ "language/[LANGUAGE_TAG]/[LANGUAGE_TAG].css",
+ "custom.css"
+ ]
+ }
+ ]
+}
diff --git a/administrator/templates/isis/login.php b/administrator/templates/isis/login.php
index 1c1ff71c421a5..348f126480c40 100644
--- a/administrator/templates/isis/login.php
+++ b/administrator/templates/isis/login.php
@@ -24,31 +24,8 @@
$background_color = $this->params->get('loginBackgroundColor') ? $this->params->get('loginBackgroundColor') : '';
$color_is_light = ($background_color && colorIsLight($background_color));
-// Add JavaScript Frameworks
-JHtml::_('bootstrap.framework');
-JHtml::_('bootstrap.tooltip');
-
-// Add Stylesheets
-$doc->addStyleSheetVersion($this->baseurl . '/templates/' . $this->template . '/css/template' . ($this->direction == 'rtl' ? '-rtl' : '') . '.css');
-
-// Load optional RTL Bootstrap CSS
-JHtml::_('bootstrap.loadCss', false, $this->direction);
-
-// Load specific language related CSS
-$file = 'language/' . $lang->getTag() . '/' . $lang->getTag() . '.css';
-
-if (is_file($file))
-{
- $doc->addStyleSheet($file);
-}
-
-// Load custom.css
-$file = 'templates/' . $this->template . '/css/custom.css';
-
-if (is_file($file))
-{
- $doc->addStyleSheetVersion($file);
-}
+// Load the template asset
+JHtml::_('asset.load', $doc->direction == 'rtl' ? 'template.isis.rtl' : 'template.isis.ltr');
// Detecting Active Variables
$option = $app->input->getCmd('option', '');
diff --git a/administrator/templates/isis/templateDetails.xml b/administrator/templates/isis/templateDetails.xml
index 4f94210feb6f9..f68dce55ffd5c 100644
--- a/administrator/templates/isis/templateDetails.xml
+++ b/administrator/templates/isis/templateDetails.xml
@@ -13,6 +13,7 @@
cpanel.php
favicon.ico
index.php
+ joomla.asset.json
login.php
templateDetails.xml
template_preview.png
diff --git a/layouts/joomla/form/field/checkboxes.php b/layouts/joomla/form/field/checkboxes.php
index e1cba39033cce..36985a9dd849d 100644
--- a/layouts/joomla/form/field/checkboxes.php
+++ b/layouts/joomla/form/field/checkboxes.php
@@ -43,8 +43,7 @@
*/
// Including fallback code for HTML5 non supported browsers.
-JHtml::_('jquery.framework');
-JHtml::_('script', 'system/html5fallback.js', false, true);
+JHtml::_('asset.load', 'html5fallback');
/**
* The format of the input tag to be filled in using sprintf.
diff --git a/layouts/joomla/form/field/file.php b/layouts/joomla/form/field/file.php
index 4100a3ad501b7..3b94d99ec099e 100644
--- a/layouts/joomla/form/field/file.php
+++ b/layouts/joomla/form/field/file.php
@@ -46,8 +46,7 @@
*/
// Including fallback code for HTML5 non supported browsers.
-JHtml::_('jquery.framework');
-JHtml::_('script', 'system/html5fallback.js', false, true);
+JHtml::_('asset.load', 'html5fallback');
?>
addScriptDeclaration(
"
diff --git a/layouts/joomla/html/formbehavior/chosen.php b/layouts/joomla/html/formbehavior/chosen.php
index ecf59023c9cbe..f821a2ec911ef 100644
--- a/layouts/joomla/html/formbehavior/chosen.php
+++ b/layouts/joomla/html/formbehavior/chosen.php
@@ -20,10 +20,7 @@
extract($displayData);
-// Include jQuery
-JHtml::_('jquery.framework');
-JHtml::_('script', 'jui/chosen.jquery.min.js', false, true, false, false, $debug);
-JHtml::_('stylesheet', 'jui/chosen.css', false, true);
+JHtml::_('asset.load', 'chosen');
// Options array to json options string
$options_str = json_encode($options, ($debug && defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : false));
diff --git a/layouts/joomla/html/sortablelist.php b/layouts/joomla/html/sortablelist.php
index b7815ba27f62e..caf4e7ec1f3df 100644
--- a/layouts/joomla/html/sortablelist.php
+++ b/layouts/joomla/html/sortablelist.php
@@ -23,11 +23,7 @@
extract($displayData);
-// Depends on jQuery UI
-JHtml::_('jquery.ui', array('core', 'sortable'));
-
-JHtml::_('script', 'jui/sortablelist.js', false, true);
-JHtml::_('stylesheet', 'jui/sortablelist.css', false, true, false);
+JHtml::_('asset.load', 'sortablelist');
// Attach sortable to document
JFactory::getDocument()->addScriptDeclaration(
diff --git a/libraries/cms/html/asset.php b/libraries/cms/html/asset.php
new file mode 100644
index 0000000000000..6b7351a84ec08
--- /dev/null
+++ b/libraries/cms/html/asset.php
@@ -0,0 +1,140 @@
+getName();
+ $factory->addAsset($asset);
+ }
+
+ $factory->setAssetState($name, JAssetItem::ASSET_STATE_ACTIVE);
+
+ return $factory->getAsset($name);
+ }
+
+ /**
+ * Make the asset inactive
+ *
+ * @param string|JAssetItem $asset Asset instance or name
+ *
+ * @return JAssetItem
+ */
+ public static function unload($asset)
+ {
+ $name = ($asset instanceof JAssetItem) ? $asset->getName() : $asset;
+ $factory = JAssetFactory::getInstance();
+
+ $factory->setAssetState($name, JAssetItem::ASSET_STATE_INACTIVE);
+
+ return $factory->getAsset($name);
+ }
+
+ /**
+ * Add asset to the collection of known assets
+ *
+ * @param JAssetItem $asset Asset instance
+ *
+ * @return void
+ */
+ public static function add(JAssetItem $asset)
+ {
+ JAssetFactory::getInstance()->addAsset($asset);
+ }
+
+ /**
+ * Adds a script to the page
+ *
+ * @param string $content Script
+ * @param array $deps The script dependancy
+ * @param string $type Scripting mime (defaults to 'text/javascript')
+ *
+ * @return void
+ */
+ public static function scriptDeclaration($content, array $deps = array(), $type = 'text/javascript')
+ {
+ static $loaded = array();
+ $key = md5($content);
+
+ // Avoid duplication
+ if (!empty($loaded[$key]))
+ {
+ return;
+ }
+
+ // Load dependancy
+ if (!empty($deps))
+ {
+ foreach($deps as $dep) {
+ static::load($dep);
+ }
+ }
+
+ // Attach the script to the Document
+ $doc = JFactory::getDocument();
+ $doc->addScriptDeclaration($content, $type);
+
+ $loaded[$key] = true;
+ }
+
+ /**
+ * Adds a stylesheet declaration to the page
+ *
+ * @param string $content Style declarations
+ * @param array $deps The style dependancy
+ * @param string $type Type of stylesheet (defaults to 'text/css')
+ *
+ * @return void
+ */
+ public static function styleDeclaration($content, array $deps = array(), $type = 'text/css')
+ {
+ static $loaded = array();
+ $key = md5($content);
+
+ // Avoid duplication
+ if (!empty($loaded[$key]))
+ {
+ return;
+ }
+
+ // Load dependancy
+ if (!empty($deps))
+ {
+ foreach($deps as $dep) {
+ static::load($dep);
+ }
+ }
+
+ // Attach the script to the Document
+ $doc = JFactory::getDocument();
+ $doc->addStyleDeclaration($content, $type);
+
+ $loaded[$key] = true;
+ }
+}
diff --git a/libraries/cms/html/behavior.php b/libraries/cms/html/behavior.php
index 9d74142dbf183..c9a498284ecd7 100644
--- a/libraries/cms/html/behavior.php
+++ b/libraries/cms/html/behavior.php
@@ -39,35 +39,11 @@ abstract class JHtmlBehavior
*/
public static function framework($extras = false, $debug = null)
{
- $type = $extras ? 'more' : 'core';
-
- // Only load once
- if (!empty(static::$loaded[__METHOD__][$type]))
- {
- return;
- }
+ $type = $extras ? 'mootools-more' : 'mootools';
+ JHtml::_('asset.load', $type);
JLog::add('JHtmlBehavior::framework is deprecated. Update to jquery scripts.', JLog::WARNING, 'deprecated');
- // If no debugging value is set, use the configuration setting
- if ($debug === null)
- {
- $config = JFactory::getConfig();
- $debug = $config->get('debug');
- }
-
- if ($type != 'core' && empty(static::$loaded[__METHOD__]['core']))
- {
- static::framework(false, $debug);
- }
-
- JHtml::_('script', 'system/mootools-' . $type . '.js', false, true, false, false, $debug);
-
- // Keep loading core.js for BC reasons
- static::core();
-
- static::$loaded[__METHOD__][$type] = true;
-
return;
}
@@ -82,14 +58,7 @@ public static function framework($extras = false, $debug = null)
*/
public static function core()
{
- // Only load once
- if (isset(static::$loaded[__METHOD__]))
- {
- return;
- }
-
- JHtml::_('script', 'system/core.js', false, true);
- static::$loaded[__METHOD__] = true;
+ JHtml::_('asset.load', 'core');
return;
}
@@ -111,10 +80,7 @@ public static function caption($selector = 'img.caption')
return;
}
- // Include jQuery
- JHtml::_('jquery.framework');
-
- JHtml::_('script', 'system/caption.js', false, true);
+ JHtml::_('asset.load', 'caption');
// Attach caption to document
JFactory::getDocument()->addScriptDeclaration(
@@ -172,24 +138,7 @@ public static function formvalidation()
*/
public static function formvalidator()
{
- // Only load once
- if (isset(static::$loaded[__METHOD__]))
- {
- return;
- }
-
- // Include core
- static::core();
-
- // Include jQuery
- JHtml::_('jquery.framework');
-
- // Add validate.js language strings
- JText::script('JLIB_FORM_FIELD_INVALID');
-
- JHtml::_('script', 'system/punycode.js', false, true);
- JHtml::_('script', 'system/validate.js', false, true);
- static::$loaded[__METHOD__] = true;
+ JHtml::_('asset.load', 'validate');
}
/**
@@ -207,10 +156,7 @@ public static function switcher()
return;
}
- // Include jQuery
- JHtml::_('jquery.framework');
-
- JHtml::_('script', 'system/switcher.js', true, true);
+ JHtml::_('asset.load', 'switcher');
$script = "
document.switcher = null;
@@ -238,15 +184,7 @@ public static function switcher()
*/
public static function combobox()
{
- if (isset(static::$loaded[__METHOD__]))
- {
- return;
- }
- // Include core
- static::core();
-
- JHtml::_('script', 'system/combobox.js', false, true);
- static::$loaded[__METHOD__] = true;
+ JHtml::_('asset.load', 'combobox');
}
/**
@@ -355,12 +293,7 @@ public static function modal($selector = 'a.modal', $params = array())
// Load the necessary files if they haven't yet been loaded
if (!isset(static::$loaded[__METHOD__]))
{
- // Include MooTools framework
- static::framework(true);
-
- // Load the JavaScript and css
- JHtml::_('script', 'system/modal.js', true, true);
- JHtml::_('stylesheet', 'system/modal.css', array(), true);
+ JHtml::_('asset.load', 'modal');
}
$sig = md5(serialize(array($selector, $params)));
@@ -391,9 +324,6 @@ public static function modal($selector = 'a.modal', $params = array())
$opt['onShow'] = (isset($params['onShow'])) ? $params['onShow'] : null;
$opt['onHide'] = (isset($params['onHide'])) ? $params['onHide'] : null;
- // Include jQuery
- JHtml::_('jquery.framework');
-
if (isset($params['fullScreen']) && (bool) $params['fullScreen'])
{
$opt['size'] = array('x' => '\\jQuery(window).width() - 80', 'y' => '\\jQuery(window).height() - 80');
@@ -468,13 +398,7 @@ public static function multiselect($id = 'adminForm')
return;
}
- // Include core
- static::core();
-
- // Include jQuery
- JHtml::_('jquery.framework');
-
- JHtml::_('script', 'system/multiselect.js', false, true);
+ JHtml::_('asset.load', 'multiselect');
// Attach multiselect to document
JFactory::getDocument()->addScriptDeclaration(
@@ -502,19 +426,12 @@ public static function multiselect($id = 'adminForm')
*/
public static function tree($id, $params = array(), $root = array())
{
- // Include MooTools framework
- static::framework();
-
- JHtml::_('script', 'system/mootree.js', true, true, false, false);
- JHtml::_('stylesheet', 'system/mootree.css', array(), true);
-
if (isset(static::$loaded[__METHOD__][$id]))
{
return;
}
- // Include jQuery
- JHtml::_('jquery.framework');
+ JHtml::_('asset.load', 'mootree');
// Setup options object
$opt['div'] = (array_key_exists('div', $params)) ? $params['div'] : $id . '_tree';
@@ -571,18 +488,14 @@ public static function calendar()
return;
}
- $document = JFactory::getDocument();
- $tag = JFactory::getLanguage()->getTag();
-
- JHtml::_('stylesheet', 'system/calendar-jos.css', array(' title' => JText::_('JLIB_HTML_BEHAVIOR_GREEN'), ' media' => 'all'), true);
- JHtml::_('script', $tag . '/calendar.js', false, true);
- JHtml::_('script', $tag . '/calendar-setup.js', false, true);
+ $asset = JHtml::_('asset.load', 'calendar');
+ $asset->setAttributes('system/calendar-jos.css', array('title' => JText::_('JLIB_HTML_BEHAVIOR_GREEN')));
$translation = static::calendartranslation();
if ($translation)
{
- $document->addScriptDeclaration($translation);
+ JHtml::_('asset.scriptDeclaration', $translation);
}
static::$loaded[__METHOD__] = true;
@@ -603,11 +516,8 @@ public static function colorpicker()
return;
}
- // Include jQuery
- JHtml::_('jquery.framework');
+ JHtml::_('asset.load', 'jquery-minicolors');
- JHtml::_('script', 'jui/jquery.minicolors.min.js', false, true);
- JHtml::_('stylesheet', 'jui/jquery.minicolors.css', false, true);
JFactory::getDocument()->addScriptDeclaration("
jQuery(document).ready(function (){
jQuery('.minicolors').each(function() {
@@ -647,11 +557,8 @@ public static function simplecolorpicker()
return;
}
- // Include jQuery
- JHtml::_('jquery.framework');
+ JHtml::_('asset.load', 'jquery-simplecolorpicker');
- JHtml::_('script', 'jui/jquery.simplecolors.min.js', false, true);
- JHtml::_('stylesheet', 'jui/jquery.simplecolors.css', false, true);
JFactory::getDocument()->addScriptDeclaration("
jQuery(document).ready(function (){
jQuery('select.simplecolors').simplecolors();
@@ -753,13 +660,7 @@ public static function highlighter(array $terms, $start = 'highlighter-start', $
return;
}
- // Include core
- static::core();
-
- // Include jQuery
- JHtml::_('jquery.framework');
-
- JHtml::_('script', 'system/highlighter.js', false, true);
+ JHtml::_('asset.load', 'highlighter');
foreach ($terms as $i => $term)
{
@@ -806,11 +707,8 @@ public static function noframes()
return;
}
- // Include core
- static::core();
-
- // Include jQuery
- JHtml::_('jquery.framework');
+ JHtml::_('asset.load', 'core');
+ JHtml::_('asset.load', 'jquery');
$js = 'jQuery(function () {
if (top == self) {
@@ -957,13 +855,6 @@ protected static function calendartranslation()
*/
public static function tabstate()
{
- if (isset(self::$loaded[__METHOD__]))
- {
- return;
- }
- // Include jQuery
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/tabs-state.js', false, true);
- self::$loaded[__METHOD__] = true;
+ JHtml::_('asset.load', 'tabs-state');
}
}
diff --git a/libraries/cms/html/bootstrap.php b/libraries/cms/html/bootstrap.php
index f88a106aede7c..365f41f61aaa4 100644
--- a/libraries/cms/html/bootstrap.php
+++ b/libraries/cms/html/bootstrap.php
@@ -210,24 +210,7 @@ public static function dropdown($selector = 'dropdown-toggle')
*/
public static function framework($debug = null)
{
- // Only load once
- if (!empty(static::$loaded[__METHOD__]))
- {
- return;
- }
-
- // Load jQuery
- JHtml::_('jquery.framework');
-
- // If no debugging value is set, use the configuration setting
- if ($debug === null)
- {
- $config = JFactory::getConfig();
- $debug = (boolean) $config->get('debug');
- }
-
- JHtml::_('script', 'jui/bootstrap.min.js', false, true, false, false, $debug);
- static::$loaded[__METHOD__] = true;
+ JHtml::_('asset.load', 'bootstrap.js');
return;
}
@@ -888,15 +871,14 @@ public static function loadCss($includeMainCss = true, $direction = 'ltr', $attr
// Load Bootstrap main CSS
if ($includeMainCss)
{
- JHtml::_('stylesheet', 'jui/bootstrap.min.css', $attribs, true);
- JHtml::_('stylesheet', 'jui/bootstrap-responsive.min.css', $attribs, true);
- JHtml::_('stylesheet', 'jui/bootstrap-extended.css', $attribs, true);
+ JHtml::_('asset.load', 'bootstrap.responsive');
+ JHtml::_('asset.load', 'bootstrap.extended');
}
// Load Bootstrap RTL CSS
if ($direction === 'rtl')
{
- JHtml::_('stylesheet', 'jui/bootstrap-rtl.css', $attribs, true);
+ JHtml::_('asset.load', 'bootstrap.css.rtl');
}
}
}
diff --git a/libraries/cms/html/jquery.php b/libraries/cms/html/jquery.php
index 06d6046c541f2..3115499b02ed6 100644
--- a/libraries/cms/html/jquery.php
+++ b/libraries/cms/html/jquery.php
@@ -37,34 +37,7 @@ abstract class JHtmlJquery
*/
public static function framework($noConflict = true, $debug = null, $migrate = true)
{
- // Only load once
- if (!empty(static::$loaded[__METHOD__]))
- {
- return;
- }
-
- // If no debugging value is set, use the configuration setting
- if ($debug === null)
- {
- $config = JFactory::getConfig();
- $debug = (boolean) $config->get('debug');
- }
-
- JHtml::_('script', 'jui/jquery.min.js', false, true, false, false, $debug);
-
- // Check if we are loading in noConflict
- if ($noConflict)
- {
- JHtml::_('script', 'jui/jquery-noconflict.js', false, true, false, false, false);
- }
-
- // Check if we are loading Migrate
- if ($migrate)
- {
- JHtml::_('script', 'jui/jquery-migrate.min.js', false, true, false, false, $debug);
- }
-
- static::$loaded[__METHOD__] = true;
+ JHtml::_('asset.load', 'jquery');
return;
}
@@ -83,27 +56,15 @@ public static function framework($noConflict = true, $debug = null, $migrate = t
*/
public static function ui(array $components = array('core'), $debug = null)
{
- // Set an array containing the supported jQuery UI components handled by this method
- $supported = array('core', 'sortable');
-
- // Include jQuery
- static::framework();
-
- // If no debugging value is set, use the configuration setting
- if ($debug === null)
- {
- $config = JFactory::getConfig();
- $debug = (boolean) $config->get('debug');
- }
+ $factory = JAssetFactory::getInstance();
// Load each of the requested components
foreach ($components as $component)
{
- // Only attempt to load the component if it's supported in core and hasn't already been loaded
- if (in_array($component, $supported) && empty(static::$loaded[__METHOD__][$component]))
+ // Only attempt to load the component if it's supported in core
+ if ($factory->getAsset('jquery.ui.' . $component))
{
- JHtml::_('script', 'jui/jquery.ui.' . $component . '.min.js', false, true, false, false, $debug);
- static::$loaded[__METHOD__][$component] = true;
+ JHtml::_('asset.load', 'jquery.ui.' . $component);
}
}
diff --git a/libraries/cms/html/searchtools.php b/libraries/cms/html/searchtools.php
index 6120738a4af30..0ae2d9185eb02 100644
--- a/libraries/cms/html/searchtools.php
+++ b/libraries/cms/html/searchtools.php
@@ -33,21 +33,7 @@ abstract class JHtmlSearchtools
*/
public static function main()
{
- // Only load once
- if (empty(static::$loaded[__METHOD__]))
- {
- // Requires jQuery but allows to skip its loading
- if ($loadJquery = (!isset($options['loadJquery']) || $options['loadJquery'] != 0))
- {
- JHtml::_('jquery.framework');
- }
-
- // Load the jQuery plugin && CSS
- JHtml::_('script', 'jui/jquery.searchtools.min.js', false, true);
- JHtml::_('stylesheet', 'jui/jquery.searchtools.css', false, true);
-
- static::$loaded[__METHOD__] = true;
- }
+ JHtml::_('asset.load', 'jquery.searchtools');
return;
}
diff --git a/libraries/cms/version/version.php b/libraries/cms/version/version.php
index d276866c9a8c0..4ff428a936f26 100644
--- a/libraries/cms/version/version.php
+++ b/libraries/cms/version/version.php
@@ -237,16 +237,26 @@ public function getUserAgent($component = null, $mask = false, $add_version = tr
* Generate a media version string for assets
* Public to allow third party developers to use it
*
+ * @param string $version Optinal version of the media
+ * @param bool $attachDate Whether attach current date while hash calculation
+ *
* @return string
*
* @since 3.2
*/
- public function generateMediaVersion()
+ public function generateMediaVersion($version = null, $attachDate = true)
{
- $date = new JDate;
- $config = JFactory::getConfig();
+ $config = JFactory::getConfig();
+ $string = $version ? $version : $this->getLongVersion();
+ $string .= $config->get('secret');
+
+ if ($attachDate)
+ {
+ $date = new JDate;
+ $string .= $date->toSql();
+ }
- return md5($this->getLongVersion() . $config->get('secret') . $date->toSql());
+ return md5($string);
}
/**
diff --git a/libraries/joomla/asset/factory.php b/libraries/joomla/asset/factory.php
new file mode 100644
index 0000000000000..1b6239111e285
--- /dev/null
+++ b/libraries/joomla/asset/factory.php
@@ -0,0 +1,740 @@
+ DATAFILE_NEW/DATAFILE_PARSED
+ *
+ * @example of data file:
+ * {
+ * "title" : "Example",
+ * "name" : "com_example",
+ * "author": "Joomla! CMS",
+ * "assets": [
+ * {
+ * "name": "library1",
+ * "version": "3.5.0",
+ * "versionAttach": true,
+ * "js": [
+ * "com_example/library1.min.js"
+ * ]
+ * },
+ * {
+ * "name": "library2",
+ * "version": "3.5.0",
+ * "js": [
+ * "com_example/library2.min.js"
+ * ],
+ * "css": [
+ * "com_example/library2.css"
+ * ],
+ * "dependency": [
+ * "core",
+ * "library1"
+ * ],
+ * "attribute": {
+ * "com_example/library2.min.js": {
+ * "attrname": "attrvalue"
+ * },
+ * "com_example/library2.css": {
+ * "media": "all"
+ * }
+ * }
+ * },
+ * ]
+ * }
+ *
+ */
+ protected $dataFiles = array();
+
+ /**
+ * Available Assets
+ *
+ * @var array
+ */
+ protected $assets = array();
+
+ /**
+ * Weight of the most heavier active asset
+ *
+ * @var float $lastItemWeight
+ */
+ protected $lastItemWeight = 1;
+
+ /**
+ * Deafult defer mode for attached JavaScripts
+ *
+ * @var bool $jsDeferMode
+ */
+ protected $jsDeferMode = null;
+
+ /**
+ * Mark the new data file
+ *
+ * @var int
+ */
+ const DATAFILE_NEW = 1;
+
+ /**
+ * Mark already parsed data file
+ *
+ * @var int
+ */
+ const DATAFILE_PARSED = 2;
+
+ /**
+ * Global Asset Factory object
+ *
+ * @var JAssetFactory
+ * @since 5.0
+ */
+ public static $instance = null;
+
+ /**
+ * Class constructor
+ */
+ public function __construct()
+ {
+ $this->searchForDataFiles();
+ }
+
+ /**
+ * Return the JAssetFactory object
+ *
+ * @return JAssetFactory object
+ *
+ * @since 5.0
+ */
+ public static function getInstance()
+ {
+ if (!self::$instance)
+ {
+ self::$instance = new JAssetFactory;
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * Add asset to collection of known assets
+ *
+ * @param JAssetItem $asset Asset instance
+ *
+ * @return JHtmlAssetFactory
+ */
+ public function addAsset(JAssetItem $asset)
+ {
+ $name = $asset->getName();
+ $this->assets[$name] = $asset;
+
+ return $this;
+ }
+
+ /**
+ * Remove Asset by name
+ *
+ * @param string $name Asset name
+ *
+ * @return JHtmlAssetFactory
+ */
+ public function removeAsset($name)
+ {
+ if (!empty($this->assets[$name]))
+ {
+ unset($this->assets[$name]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get asset by it's name
+ *
+ * @param string $name Asset name
+ *
+ * @return JAssetItem|bool Return asset object or false if asset doesnot exists
+ */
+ public function getAsset($name)
+ {
+ // Check if there any new data file was added
+ $this->parseDataFiles();
+
+ if (!empty($this->assets[$name]))
+ {
+ return $this->assets[$name];
+ }
+
+ return false;
+ }
+
+ /**
+ * Return dependancy for Asset as array of AssetItem objects
+ *
+ * @param JAssetItem $asset Asset instance
+ *
+ * @return JAssetItem[]
+ *
+ * @throws RuntimeException When Dependency cannot be found
+ */
+ public function getAssetDependancy(JAssetItem $asset)
+ {
+ $assets = array();
+
+ foreach ($asset->getDependency() as $depName)
+ {
+ $dep = $this->getAsset($depName);
+
+ if (!$dep)
+ {
+ throw new RuntimeException('Cannot find Dependency "' . $depName . '" for Asset "' . $asset->getName() . '"');
+ }
+
+ $assets[$depName] = $dep;
+ }
+
+ return $assets;
+ }
+
+ /**
+ * Change the asset State
+ *
+ * @param string $name Asset name
+ * @param int $state New state
+ * @param bool $force Force weight calculation if the Asset alredy was enabled previously
+ *
+ * @return JHtmlAssetFactory
+ *
+ * @throws RuntimeException if asset with given name does not exists
+ */
+ public function setAssetState($name, $state = JAssetItem::ASSET_STATE_ACTIVE, $force = false)
+ {
+ $asset = $this->getAsset($name);
+
+ if (!$asset)
+ {
+ throw new RuntimeException('Asset "' . $name . '" do not exists');
+ }
+
+ // Asset alredy has the requested state, so stop here, prevent Weight recalulation
+ if ($asset->isActive() === $state && !$force)
+ {
+ return $this;
+ }
+
+ // Change state
+ $asset->setState($state);
+
+ // Calculate weight
+ if ($state !== JAssetItem::ASSET_STATE_INACTIVE)
+ {
+ $dependency = $asset->getDependency();
+ $this->lastItemWeight = $this->lastItemWeight + count($dependency) + 1;
+ $asset->setWeight($this->lastItemWeight);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Search for all active assets.
+ *
+ * @return JAssetItem[] Array with active assets
+ */
+ public function getActiveAssets()
+ {
+ $assets = array_filter(
+ $this->assets,
+ function($asset)
+ {
+ return $asset->isActive();
+ }
+ );
+
+ // Order them by weight
+ $this->sortByWeight($assets);
+
+ return $assets;
+ }
+
+ /**
+ * Search for assets with specific state.
+ *
+ * @param int $state Asset state
+ *
+ * @return JAssetItem[] Array with active assets
+ */
+ public function getAssetsByState($state)
+ {
+ $assets = array_filter(
+ $this->assets,
+ function($asset) use ($state)
+ {
+ return $asset->getState() === $state;
+ }
+ );
+
+ // Order them by weight
+ $this->sortByWeight($assets);
+
+ return $assets;
+ }
+
+ /**
+ * Allow to change default defer behaviour forJavaScript files
+ *
+ * @param bool $defer Default "defer" mode for all javascrip files
+ *
+ * @return JHtmlAssetFactory
+ */
+ public function deferJavaScript($defer = null)
+ {
+ $this->jsDeferMode = $defer;
+
+ return $this;
+ }
+
+ /**
+ * Attach active assets to the Document
+ *
+ * @param JDocument $doc Document for attach StyleSheet/JavaScript
+ *
+ * @return void
+ */
+ public function attach(JDocument $doc)
+ {
+ $app = JFactory::getApplication();
+
+ // Resolve Dependency
+ $this->resolveDependency();
+
+ // Trigger the onBeforeHeadAttachHtmlAsset event
+ $app->triggerEvent('onBeforeHeadAttachHtmlAsset', array($this));
+
+ // Attach an active assets do the document
+ $assets = $this->getActiveAssets();
+
+ // Presave existing Scripts, and attach them after requested assets.
+ $jsBackup = $doc->_scripts;
+ $doc->_scripts = array();
+
+ foreach ($assets as $asset)
+ {
+ if ($this->jsDeferMode !== null)
+ {
+ $asset->deferJavaScript($this->jsDeferMode);
+ }
+
+ $asset->attach($doc);
+ }
+
+ // Add previously added scripts
+ $doc->_scripts = array_merge($doc->_scripts, $jsBackup);
+ }
+
+ /**
+ * Resolve Dependency for just added assets
+ *
+ * @return JHtmlAssetFactory
+ *
+ * @throws RuntimeException When Dependency cannot be resolved
+ */
+ protected function resolveDependency()
+ {
+ $assets = $this->getAssetsByState(JAssetItem::ASSET_STATE_ACTIVE);
+
+ foreach ($assets as $asset)
+ {
+ $this->resolveItemDependency($asset);
+ $asset->setState(JAssetItem::ASSET_STATE_RESOLVED);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Resolve Dependency for given asset
+ *
+ * @param JAssetItem $asset Asset instance
+ *
+ * @return JHtmlAssetFactory
+ *
+ * @throws RuntimeException When Dependency cannot be resolved
+ */
+ protected function resolveItemDependency(JAssetItem $asset)
+ {
+ foreach ($this->getAssetDependancy($asset) as $depItem)
+ {
+ $oldState = $depItem->isActive();
+
+ // Make active
+ if (!$oldState)
+ {
+ $depItem->setState(JAssetItem::ASSET_STATE_DEPENDANCY);
+ }
+
+ // Calculate weight, make it a bit lighter
+ $depWeight = $depItem->getWeight();
+ $assetWeight = $asset->getWeight();
+
+ $depWeight = $depWeight === 0 ? $this->lastItemWeight : $depWeight;
+ $weight = $depWeight > $assetWeight ? $assetWeight : $depWeight;
+ $weight = $weight - 0.1;
+
+ $depItem->setWeight($weight);
+
+ // Prevent duplicated work if Dependency already was activated
+ if (!$oldState)
+ {
+ $this->resolveItemDependency($depItem);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Sort assets by it`s weight
+ *
+ * @param JAssetItem[] &$assets Linked array of assets
+ * @param bool $ask Order direction: true for ASC and false for DESC
+ *
+ * @return JHtmlAssetFactory
+ */
+ protected function sortByWeight(array &$assets, $ask = true)
+ {
+ uasort(
+ $assets,
+ function($a, $b) use ($ask)
+ {
+ if ($a->getWeight() === $b->getWeight())
+ {
+ return 0;
+ }
+
+ if ($ask)
+ {
+ return $a->getWeight() > $b->getWeight() ? 1 : -1;
+ }
+ else
+ {
+ return $a->getWeight() > $b->getWeight() ? -1 : 1;
+ }
+ }
+ );
+
+ return $this;
+ }
+
+ /**
+ * Register new file with asset info
+ *
+ * @param string $path Relative path
+ *
+ * @return JHtmlAssetFactory
+ *
+ * @throws UnexpectedValueException If file does not exists
+ */
+ public function registerDataFile($path)
+ {
+ $path = JPath::clean($path);
+
+ if (!is_file(JPATH_ROOT . '/' . $path))
+ {
+ throw new UnexpectedValueException('Asset data file do not available');
+ }
+
+ if (!isset($this->dataFiles[$path]))
+ {
+ $this->dataFiles[$path] = static::DATAFILE_NEW;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Search for joomla.asset.json filse in the Media folder
+ *
+ * @return void
+ */
+ protected function searchForDataFiles()
+ {
+ $files = array_merge(
+ glob(JPATH_ROOT . '/media/*/joomla.asset.json'), // Search extension assets, in /media
+ glob(JPATH_BASE . '/templates/*/joomla.asset.json') // Search the template assets
+ );
+
+ if (empty($files))
+ {
+ return;
+ }
+
+ foreach ($files as $file)
+ {
+ $path = preg_replace('#^' . JPATH_ROOT . '/#', '', $file);
+ $this->registerDataFile($path);
+ }
+ }
+
+ /**
+ * Parse registered data files
+ *
+ * @return void
+ */
+ protected function parseDataFiles()
+ {
+ // Filter new asset data files and parse each
+ $constantIsNew = static::DATAFILE_NEW;
+ $files = array_filter(
+ $this->dataFiles,
+ function($state) use ($constantIsNew) {
+ return $state === $constantIsNew;
+ }
+ );
+
+ foreach (array_keys($files) as $path)
+ {
+ $this->parseDataFile($path);
+
+ // Mark as parsed (not new)
+ $this->dataFiles[$path] = static::DATAFILE_PARSED;
+ }
+ }
+
+ /**
+ * Parse data file
+ *
+ * @param string $path Relative path to the data file
+ *
+ * @return void
+ *
+ * @throws RuntimeException If file is empty or invalid
+ */
+ protected function parseDataFile($path)
+ {
+ $data = json_decode(@file_get_contents(JPATH_ROOT . '/' . $path), true);
+
+ if (!$data)
+ {
+ throw new RuntimeException('Asset data file "' . $path . '" is incorrect or broken');
+ }
+
+ // Asset exists but empty, skip it silently
+ if (empty($data['assets']))
+ {
+ return;
+ }
+
+ // Prepare AssetItem instance
+ $owner = $data;
+ $owner['dataFile'] = $path;
+ unset($owner['assets']);
+
+ foreach ($data['assets'] as $item)
+ {
+ if (empty($item['name']))
+ {
+ throw new RuntimeException('Asset data file "' . $path . '" contains incorrect asset defination');
+ }
+
+ $assetItem = $this->prepareAssetInstance($item['name'], $item, $owner);
+ $this->addAsset($assetItem);
+ }
+ }
+
+ /**
+ * Prepare Asset instance
+ *
+ * @param string $name Asset name
+ * @param array $info Asset information
+ * @param array $owner Asset data file-owner info
+ *
+ * @return JAssetItem
+ */
+ public function prepareAssetInstance($name, array $info = array(), array $owner = array())
+ {
+ $version = !empty($info['version']) ? $info['version'] : null;
+
+ /*
+ Check for specific class
+ @TODO whether it realy can be usefull ???
+
+ $class = 'JAsset' . implode('', array_map('ucfirst', explode('.', $name)));
+ $class = class_exists($class) ? $class : 'JAssetItem';
+ $asset = new $class($name, $version, $owner);
+ */
+
+ $asset = new JAssetItem($name, $version, $owner);
+
+ if (!empty($info['js']))
+ {
+ $asset->setJs((array) $info['js']);
+ }
+
+ if (!empty($info['css']))
+ {
+ $asset->setCss((array) $info['css']);
+ }
+
+ if (!empty($info['dependency']))
+ {
+ $asset->setDependency((array) $info['dependency']);
+ }
+
+ if (array_key_exists('versionAttach', $info))
+ {
+ $asset->versionAttach($info['versionAttach']);
+ }
+
+ if (!empty($info['attribute']) && is_array($info['attribute']))
+ {
+ foreach ($info['attribute'] as $file => $attributes)
+ {
+ $asset->setAttributes($file, $attributes);
+ }
+ }
+
+ return $asset;
+ }
+
+ /**
+ * Helper method to build the joomla.asset.json data from files in the media folder
+ *
+ * @param string $pathBase Relative path to Folder for scan for files
+ * @param string $prefix Media prefix. Example com_example for com_example/file.js
+ * @param string $title The collection title
+ * @param string $author The collection author
+ *
+ * @return string JSON data
+ */
+ public function buildDataFileContent($pathBase, $prefix = null, $title = '', $author = 'Joomla! CMS')
+ {
+ jimport('joomla.filesystem.path');
+ jimport('joomla.filesystem.folder');
+
+ $title = $title ? $title : 'Autogenerated assets collection';
+ $assets = array();
+ $prefix = $prefix === null ? preg_replace('#^media\/#', '', $pathBase) : $prefix;
+ $pathBase = JPath::clean(JPATH_ROOT . '/' . trim($pathBase, '/'));
+
+ // Search for JavaScript files
+ $js = JFolder::files($pathBase, '\.js$', true, true);
+
+ if (!empty($js))
+ {
+ foreach ($js as $file)
+ {
+ // Remove base path
+ $relative = preg_replace('#^' . $pathBase . '/#', '', $file);
+
+ // Remove "js/"
+ $parts = explode('/', $relative);
+ $sIndex = count($parts) - 2;
+
+ if (!empty($parts[$sIndex]) && $parts[$sIndex] === 'js')
+ {
+ unset($parts[$sIndex]);
+ }
+
+ $relative = implode('/', $parts);
+ $name = preg_replace(array('#-uncompressed\.js$#', '#\.min\.js$#', '#\.js$#'), '', $relative);
+
+ if (empty($assets[$name]))
+ {
+ $assets[$name] = array(
+ 'name' => $name,
+ 'version' => '1.0',
+ 'js' => array(),
+ 'css' => array(),
+ 'dependency' => array(),
+ );
+ }
+
+ $assets[$name]['js'][$name] = $prefix . '/' . $relative;
+ }
+ }
+
+ // Search for StyleSheet files
+ $css = JFolder::files($pathBase, '\.css$', true, true);
+
+ if (!empty($css))
+ {
+ foreach ($css as $file)
+ {
+ // Remove base path
+ $relative = preg_replace('#^' . $pathBase . '/#', '', $file);
+
+ // Remove "css/"
+ $parts = explode('/', $relative);
+ $sIndex = count($parts) - 2;
+
+ if (!empty($parts[$sIndex]) && $parts[$sIndex] === 'css')
+ {
+ unset($parts[$sIndex]);
+ }
+
+ $relative = implode('/', $parts);
+ $name = preg_replace(array('#\.min\.css$#', '#\.css$#'), '', $relative);
+
+ if (empty($assets[$name]))
+ {
+ $assets[$name] = array(
+ 'name' => $name,
+ 'version' => '1.0',
+ 'js' => array(),
+ 'css' => array(),
+ 'dependency' => array(),
+ );
+ }
+
+ $assets[$name]['css'][$name] = $prefix . '/' . $relative;
+ }
+ }
+
+ // Remove asset "keys", and empty valuse
+ foreach ($assets as $name => $asset)
+ {
+ if (empty($asset['js']))
+ {
+ unset($assets[$name]['js']);
+ }
+ else
+ {
+ $assets[$name]['js'] = array_values($asset['js']);
+ }
+
+ if (empty($asset['css']))
+ {
+ unset($assets[$name]['css']);
+ }
+ else
+ {
+ $assets[$name]['css'] = array_values($asset['css']);
+ }
+ }
+
+ // Prepare base
+ $data = array(
+ 'title' => $title,
+ 'author' => $author,
+ 'assets' => array_values($assets),
+ );
+
+ return json_encode($data, JSON_PRETTY_PRINT);
+ }
+}
diff --git a/libraries/joomla/asset/item.php b/libraries/joomla/asset/item.php
new file mode 100644
index 0000000000000..9f13c6de9c853
--- /dev/null
+++ b/libraries/joomla/asset/item.php
@@ -0,0 +1,534 @@
+name = $name;
+ $this->version = $version;
+ $this->owner = $owner;
+ }
+
+ /**
+ * Return asset name
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Return asset version
+ *
+ * @return string
+ */
+ public function getVersion()
+ {
+ return $this->version;
+ }
+
+ /**
+ * Set JavaScript files
+ *
+ * @param array $js Array of JavaScript files
+ *
+ * @return JAssetItem
+ */
+ public function setJs(array $js)
+ {
+ $this->js = $js;
+
+ return $this;
+ }
+
+ /**
+ * Return JavaScript files
+ *
+ * @return array
+ */
+ public function getJs()
+ {
+ return $this->js;
+ }
+
+ /**
+ * Allow to change default defer behaviour forJavaScript files
+ *
+ * @param bool $defer Default "defer" mode for all javascrip files
+ *
+ * @return JAssetItem
+ */
+ public function deferJavaScript($defer = true)
+ {
+ $this->jsDeferMode = (bool) $defer;
+
+ return $this;
+ }
+
+ /**
+ * Set StyleSheet files
+ *
+ * @param array $css Array of StyleSheet files
+ *
+ * @return JAssetItem
+ */
+ public function setCss(array $css)
+ {
+ $this->css = $css;
+
+ return $this;
+ }
+
+ /**
+ * Return StyleSheet files
+ *
+ * @return array
+ */
+ public function getCss()
+ {
+ return $this->css;
+ }
+
+ /**
+ * Set dependency
+ *
+ * @param array $dependency The array of the names of the asset dependency
+ *
+ * @return JAssetItem
+ */
+ public function setDependency(array $dependency)
+ {
+ $this->dependency = $dependency;
+
+ return $this;
+ }
+
+ /**
+ * Return dependency
+ *
+ * @return array
+ */
+ public function getDependency()
+ {
+ return $this->dependency;
+ }
+
+ /**
+ * Set Attributes for asset file
+ *
+ * @param string $file JavaScript/StyleSheet asset file
+ * @param array $attributes Attributes array
+ *
+ * @return JAssetItem
+ */
+ public function setAttributes($file, array $attributes = array())
+ {
+ if (empty($this->attribute[$file]))
+ {
+ $this->attribute[$file] = array();
+ }
+
+ $this->attribute[$file] = array_merge($this->attribute[$file], $attributes);
+
+ return $this;
+ }
+
+ /**
+ * Return Attributes for asset file
+ *
+ * @param string $file JavaScript/StyleSheet asset file
+ *
+ * @return array
+ */
+ public function getAttributes($file)
+ {
+ if (!empty($this->attribute[$file]))
+ {
+ return $this->attribute[$file];
+ }
+
+ return array();
+ }
+
+ /**
+ * Set asset Weight
+ *
+ * @param float $weight The asset weight
+ *
+ * @return JAssetItem
+ */
+ public function setWeight($weight)
+ {
+ $this->weight = (float) $weight;
+
+ return $this;
+ }
+
+ /**
+ * Return asset Weight
+ *
+ * @return float
+ */
+ public function getWeight()
+ {
+ return $this->weight;
+ }
+
+ /**
+ * Set asset State
+ *
+ * @param int $state The asset state
+ *
+ * @return JAssetItem
+ */
+ public function setState($state)
+ {
+ $this->state = (int) $state;
+
+ return $this;
+ }
+
+ /**
+ * Get asset State
+ *
+ * @return int
+ */
+ public function getState()
+ {
+ return $this->state;
+ }
+
+ /**
+ * Check asset state
+ *
+ * @return bool
+ */
+ public function isActive()
+ {
+ return $this->state !== self::ASSET_STATE_INACTIVE;
+ }
+
+ /**
+ * Set Version Attach property
+ *
+ * @param bool $value True for attach the version parameter to the file
+ *
+ * @return JAssetItem
+ */
+ public function versionAttach($value)
+ {
+ $this->versionAttach = (bool) $value;
+
+ return $this;
+ }
+
+ /**
+ * Check Version Attach property
+ *
+ * @return bool
+ */
+ public function isVersionAttach()
+ {
+ return $this->versionAttach;
+ }
+
+ /**
+ * Attach active asset to the Document
+ *
+ * @param JDocument $doc Document for attach StyleSheet/JavaScript
+ *
+ * @return JAssetItem
+ *
+ * @throws RuntimeException If try attach inactive asset
+ */
+ public function attach(JDocument $doc)
+ {
+ if (!$this->isActive())
+ {
+ throw new RuntimeException('Incative Asset cannot be attached');
+ }
+
+ $version = false;
+
+ // Calculate the version hash based on the asset version,
+ if ($this->isVersionAttach())
+ {
+ $jversion = new JVersion;
+ $version = $jversion->generateMediaVersion($this->getVersion(), false);
+ }
+
+ $this->attachCss($doc, $version)->attachJs($doc, $version);
+
+ return $this;
+ }
+
+ /**
+ * Attach StyleSheet files to the document
+ *
+ * @param JDocument $doc Document for attach StyleSheet/JavaScript
+ * @param string $version Version to be attached, or false
+ *
+ * @return JAssetItem
+ */
+ protected function attachCss(JDocument $doc, $version = false)
+ {
+ foreach ($this->getCss() as $path)
+ {
+ $file = $path;
+ $isExternal = $this->isPathExternal($path);
+
+ if (!$isExternal)
+ {
+ // Check for Placeholders
+ $path = $this->replacePlaceholders($path);
+
+ // Get the file path
+ $file = JHtml::_('stylesheet', $path, array(), $this->isPathRelative($path), true);
+ }
+
+ if ($file)
+ {
+ $attribute = $this->getAttributes($path);
+ $type = empty($attribute['type']) ? 'text/css' : $attribute['type'];
+ $media = empty($attribute['media']) ? null : $attribute['media'];
+
+ unset($attribute['type'], $attribute['media']);
+
+ ($version === false || $isExternal)
+ ? $doc->addStyleSheet($file, $type, $media, $attribute)
+ : $doc->addStyleSheetVersion($file, $version, $type, $media, $attribute);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Attach JavaScript files to the document
+ *
+ * @param JDocument $doc Document for attach StyleSheet/JavaScript
+ * @param string $version Version to be attached, or false
+ *
+ * @return JAssetItem
+ */
+ protected function attachJs(JDocument $doc, $version = false)
+ {
+ foreach ($this->getJs() as $path)
+ {
+ $file = $path;
+ $isExternal = $this->isPathExternal($path);
+
+ if (!$isExternal)
+ {
+ // Check for Placeholders
+ $path = $this->replacePlaceholders($path);
+
+ // Get the file path
+ $file = JHtml::_('script', $path, false, $this->isPathRelative($path), true);
+ }
+
+ if ($file)
+ {
+ $attribute = $this->getAttributes($path);
+ $type = empty($attribute['type']) ? 'text/javascript' : $attribute['type'];
+ $defer = empty($attribute['defer']) ? $this->jsDeferMode : (bool) $attribute['defer'];
+
+ unset($attribute['type'], $attribute['defer']);
+
+ // @TODO: Pass $attribute to addScript() when JDocument will support it
+ ($version === false || $isExternal)
+ ? $doc->addScript($file, $type, $defer)
+ : $doc->addScriptVersion($file, $version, $type, $defer);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Replace Placeholders to the real values.
+ * Supported placeholders:
+ * [LANGUAGE_TAG] Will be replaced to current language tag, eg: en-GB
+ *
+ * @param string $string String to check for the placeholders
+ *
+ * @return string
+ */
+ protected function replacePlaceholders($string)
+ {
+ if (strpos($string, '[') === false)
+ {
+ // Nothing here
+ return $string;
+ }
+
+ // Replace known placeholders
+ // @TODO: Is it a good idea to allow to register custom placeholders, in the future ???
+ $string = str_replace(array(
+ '[LANGUAGE_TAG]'
+ ), array(
+ JFactory::getLanguage()->getTag()
+ ), $string);
+
+ return $string;
+ }
+
+ /**
+ * Check if the Path is External
+ *
+ * @param string $path Path to test
+ *
+ * @return bool
+ */
+ protected function isPathExternal($path)
+ {
+ return strpos($path, 'http') === 0 || strpos($path, '//') === 0;
+ }
+
+ /**
+ * Check if the Path is relative to /media folder
+ *
+ * @param string $path Path to test
+ *
+ * @return bool
+ */
+ protected function isPathRelative($path)
+ {
+ if (is_file(JPATH_ROOT . '/' . $path))
+ {
+ // We have a full path
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/libraries/joomla/document/renderer/html/head.php b/libraries/joomla/document/renderer/html/head.php
index 17f6ec4ae3032..869d2b941aae4 100644
--- a/libraries/joomla/document/renderer/html/head.php
+++ b/libraries/joomla/document/renderer/html/head.php
@@ -53,6 +53,9 @@ public function fetchHead($document)
$document->_metaTags['name']['tags'] = implode(', ', $tagsHelper->getTagNames($document->_metaTags['name']['tags']));
}
+ // Attach the assets
+ JAssetFactory::getInstance()->attach($document);
+
// Trigger the onBeforeCompileHead event
$app = JFactory::getApplication();
$app->triggerEvent('onBeforeCompileHead');
diff --git a/libraries/joomla/form/fields/calendar.php b/libraries/joomla/form/fields/calendar.php
index 1bf8678c9421d..a6a94301b847f 100644
--- a/libraries/joomla/form/fields/calendar.php
+++ b/libraries/joomla/form/fields/calendar.php
@@ -205,8 +205,7 @@ protected function getInput()
}
// Including fallback code for HTML5 non supported browsers.
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/html5fallback.js', false, true);
+ JHtml::_('asset.load', 'html5fallback');
return JHtml::_('calendar', $this->value, $this->name, $this->id, $format, $attributes);
}
diff --git a/libraries/joomla/form/fields/checkbox.php b/libraries/joomla/form/fields/checkbox.php
index 2e448d3063c0f..8d01d59c75d2d 100644
--- a/libraries/joomla/form/fields/checkbox.php
+++ b/libraries/joomla/form/fields/checkbox.php
@@ -132,8 +132,7 @@ protected function getInput()
$onchange = !empty($this->onchange) ? ' onchange="' . $this->onchange . '"' : '';
// Including fallback code for HTML5 non supported browsers.
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/html5fallback.js', false, true);
+ JHtml::_('asset.load', 'html5fallback');
return 'isRTL() ? ' dir="ltr" style="text-align:right"' : '';
// Including fallback code for HTML5 non supported browsers.
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/html5fallback.js', false, true);
+ JHtml::_('asset.load', 'html5fallback');
JHtml::_('behavior.colorpicker');
diff --git a/libraries/joomla/form/fields/email.php b/libraries/joomla/form/fields/email.php
index bca65da708041..18994dc3b3eaa 100644
--- a/libraries/joomla/form/fields/email.php
+++ b/libraries/joomla/form/fields/email.php
@@ -59,8 +59,7 @@ protected function getInput()
$onchange = $this->onchange ? ' onchange="' . $this->onchange . '"' : '';
// Including fallback code for HTML5 non supported browsers.
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/html5fallback.js', false, true);
+ JHtml::_('asset.load', 'html5fallback');
return 'onchange) ? ' onchange="' . $this->onchange . '"' : '';
// Including fallback code for HTML5 non supported browsers.
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/html5fallback.js', false, true);
+ JHtml::_('asset.load', 'html5fallback');
return 'onchange) ? ' onchange="' . $this->onchange . '"' : '';
// Including fallback code for HTML5 non supported browsers.
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/html5fallback.js', false, true);
+ JHtml::_('asset.load', 'html5fallback');
return 'onchange ? ' onchange="' . $this->onchange . '"' : '';
// Including fallback code for HTML5 non supported browsers.
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/html5fallback.js', false, true);
+ JHtml::_('asset.load', 'html5fallback');
return 'onchange) ? ' onchange="' . $this->onchange . '"' : '';
// Including fallback code for HTML5 non supported browsers.
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/html5fallback.js', false, true);
+ JHtml::_('asset.load', 'html5fallback');
$datalist = '';
$list = '';
diff --git a/libraries/joomla/form/fields/textarea.php b/libraries/joomla/form/fields/textarea.php
index ef61fa5ea26e6..cbb1d2bf259e1 100644
--- a/libraries/joomla/form/fields/textarea.php
+++ b/libraries/joomla/form/fields/textarea.php
@@ -157,8 +157,7 @@ protected function getInput()
$onclick = $this->onclick ? ' onclick="' . $this->onclick . '"' : '';
// Including fallback code for HTML5 non supported browsers.
- JHtml::_('jquery.framework');
- JHtml::_('script', 'system/html5fallback.js', false, true);
+ JHtml::_('asset.load', 'html5fallback');
return '