[rfc] Assets factory, manage JavaScript/StyleSheet collections and their dependency#8913
[rfc] Assets factory, manage JavaScript/StyleSheet collections and their dependency#8913Fedik wants to merge 44 commits intojoomla:stagingfrom
Conversation
…Prevent duplicated loop while dependacy resloving.
| * @param string $version The asset version | ||
| * @param array $owner Asset data file-owner info. | ||
| */ | ||
| public function __construct($name, $version = null, array $owner = array()) |
There was a problem hiding this comment.
is it possible to generate the assset without the name.
The idea is: i develop an extension and will not need to use the asset name after, we could use:
$asset = new JAssetItem();And this could generate a random asset identifier.
Even then (if we need) we could also get the random generated asset name with getName later.
There was a problem hiding this comment.
The idea was, to be able to interact with assets by name, so you can load/unload the asset at any time until it will be rendered.
Not sure that it is good idea to use random name.
If you very want, then you can use new JAssetItem(uniqid()); 😉
It also can make a problem for other extension to identify your asset.
There was a problem hiding this comment.
the random name was just when we don't need to interact with the asset, just add a js or css file.
There was a problem hiding this comment.
it one of "Drawbacks", when you need just add single file, it should be part of some asset :/
|
@Fedik just saw this PR now. It seems like a very good idea. If so, some questions:
For what i understand, and please correct if i'm wrong, if want to add a jquery dependent js script (without adding a json file), we'll do this: $jsAsset = new JAssetItem('myCustomAsset')->setDependency(array('jquery'))->setJs(array('myjsfile.js'));
JHtml::_('asset.load', $jsAsset);And now we use something like this: JHtml::_('jquery.framework');
JHtml::_('script', 'myjsfile.js');So actually we can add it with the same lines of code (and without json). But yes, is not simple as the current method. But if this is merged we can in the future modify the addScript (and other script css related methods) to use this to generate the css/js assets, right? |
it do not have a conflicts, so I guess it is valid 😄
It only for files, however if we allow "custom class" for each asset https://github.com/joomla/joomla-cms/pull/8913/files#diff-5dbc66d167ed44e3946ee1a79efb5201R574 then the class can have some own logic for add inline css/jss when Also there #6357 is additional idea for reduce to zero the inline js.
The Asset factory it is just a layer over, it does not do more than
Nope, the reason the same, it just a layer 😉
yes, you can do as in your example, JHtml::_('asset.load', 'my-cool-asset-name');And AssetFactory automatically will load all css/js dependencies. Also this allow to reuse your asset by other extensions, easily ... in theory 😄 |
Since it was travis errors i thought it was "abandoned" :) I think the concept is very good, and i understand that now we can only use what JDocument allows. If with this we could implement a component with js/css files, inline js/css, dependencies, data-* attributes, async, defer, etc using only Asset factory layer (one to rule then all :) ) i think it would be more easy and logic to everyone, than using a bunch of different methods, ex: JHtml (script, stylesheet, asset), addScript, addScriptVersion, addStyleSheet, etc. |
With assets I mean only files, here. However you can make one more asset for your extension with "behavior-colorbox.js" (see other pull request) with "colorbox" as dependency, and putt there all code that will handle Well I am bad in good explanation 😄 |
|
ok, this is only for external js/css files. I understand why, but from a developer learning curve perspective don't you agree with me that can be rather confusing having so many methods for js/css inline external, versioning, etc? |
|
well, yes .. learning is hard here, can be ... So after all it can looks like: JHtml::_('behavior.core');
JHtml::_('jquery.framework');
JHtml::_('stylesheet', 'extension/some-library.css', false, true);
JHtml::_('script', 'extension/some-library.js', false, true);
$doc->addScriptDeclaration('some init code');It not hard if I have it in single layout, but a bit annoying if need to edit it in couple different layouts. After and in layout just: JHtml::_('asset.scriptDeclaration', 'alert("blabla")', $deps = array('some-library'));hm |
|
yes, it seems good. or for just jquery dependency something like this. $inlineJs = '$( document ).ready(function() { alert("blabla"); });';
JHtml::_('asset.scriptDeclaration', $inlineJs, array('jquery'));or for vanilla js without dependencies something like this. JHtml::_('asset.scriptDeclaration', 'alert("blabla");'); |
….styleDeclaration', $content) helper methods
… Protostart and Isis templates.
|
I have added: JHtml::_('asset.scriptDeclaration', $content, $dependancy); // Adds an inline script to the page
JHtml::_('asset.styleDeclaration', $content, $dependancy); // Adds an inline style declaration to the pageAnd now the AssetFactory pick up |
Conflicts: administrator/templates/isis/index.php libraries/cms/html/behavior.php libraries/joomla/form/fields/file.php
Conflicts: administrator/templates/isis/component.php administrator/templates/isis/index.php administrator/templates/isis/login.php libraries/cms/html/behavior.php templates/protostar/component.php templates/protostar/index.php
|
Any word on this? |
|
Sadly it cannot be synced easily (more easy to write new). I kept it open to get some feedback, but seems not much interest in it. I am closing it, |
This is the last piece of puzzle: how to throw away JHtml behaviors.
Other parts is #6357 und #3072
How we add js/css in current Joomla API
Advantage:
Drawback
cssandjsI need to add them both in each layout file. And if in some point of time the file name is changed, I need to edit all entry where I added them. Or I should use my own behavior helper.What I suggest
I suggest to add one more abstraction level 👽
JHtmlAssetItemrepresent single asset, and it`s dependency.JHtmlAssetFactoryfor manage all available assets, end resolve their dependency.Previous example can become:
Just a single line
Or with inline script:
How it works
Each Asset collection defined by
joomla.asset.json, that stored aside js/css in the/mediafolder (see for/media/jui/joomla.asset.json,/media/system/joomla.asset.jsonfor example), or it can be added at the run time (seeJHtmlAssetFactory::registerDataFile($path)).Example, when I want to use
bootstrapI callJHtml::_('asset.load', 'bootstrap');. At this pointAssetFactoryparse all newjoomla.asset.json(if it first call ofasset.load) and check whether exist the Asset with this name, and set it toactive.AssetFactorydo NOT add any style/script to the document until header render.Joomla call
AssetFactory->attach()before start render the header. At this timeAssetFactorycheck for all active assets and load all their dependency, in case withbootstrapit also will loadjqueryasset, and then will attach all required css/js files to the document.Note: For now
AssetFactorycalculate the dependency only by name and ignore versions.Advantage:
attach()Drawback
joomla.asset.json, but it is also the Advantage, as I do not need to write my custom behavior helper 😄Possible Advantage:
JHtmlAssetFactory::prepareAssetInstance()), that will allow to do more tricky stuff (example, attach the files depend from language, etc)<link href="index.php?com_ajax&getStyleAsset=bootstrap,calendar" >and<script src="index.php?com_ajax&getScriptAsset=bootstrap,calendar" >API
joomla.asset.jsonexample:{ "title" : "Example", "name" : "com_example", "author": "Joomla! CMS", "assets": [ { "name": "asset1", "version": "3.5.0", "versionAttach": true, "js": [ "com_example/library1.min.js" ] }, { "name": "assetname2", "version": "3.5.0", "js": [ "com_example/library2.min.js" ], "css": [ "com_example/library2.css" ], "dependency": [ "core", "asset1" ], "attribute": { "com_example/library2.min.js": { "attrname": "attrvalue" }, "com_example/library2.css": { "media": "all" } } }, ] }I hope the Root Elements is clear, all it just for information, and not required.
Children of
"assets": []is actually provided assets .Each asset can have:
name(required) The name of asset. Would be good if it will be compatible withBowernaming.versionOptional version of the assetversionAttachOptional. Whether the files will be attached with the version variable (byaddScriptVersion/addStyleSheetVersion)jsOptional. JavaScript files. Path can be relative to/mediafolder, relative to Joomla root or external.cssOptional. StyleSheet files. Path can be relative to/mediafolder, relative to Joomla root or external.dependencyOptional dependency. Name(s) of assets that required to make current Asset work.attributeOptional attributes that will be attached with related css/js file.JHtmlAssethelper methods:Final words
It is already worked solution. However I do not replace all Joomla stuff to use Asset factory, as it much work. And before do it, I need to know that this will be accepted.
In combination with #6357 und #3072 (after some refinement there) we can make life more easy (or harder, depend from point of view 😄). In theory