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 '