Forums / Developer / Smart loading of JavaScript

Smart loading of JavaScript

Author Message

Fredrik Ardmar

Tuesday 20 January 2009 7:26:20 pm

Hi

We are trying to figure out a smart way to load external JS and CSS files.
From my best knowledge the built in solution allows you to specify what JavaScripts or CSS files that should be loaded. But the problem with this approach is that you need to load the same JavaScripts on every page.

We have extending this solution slightly so that you can set different JavaScripts for different class types and browser types. This goes for both CSS and JS. For example

ad_image_gallery[]=prototype.js
ad_image_gallery[]=scriptaculous.js

Then we do some simple check in include that handles CSS and JS.
Add correct caching and this works fine.

This approach is definitively an improvement over the deafault but not enough.

Lets say we use a magnifier zoom on selected images. The user can set a specific tag for activating this effect in the admin. So what do we do now, do we load CSS and JavaScript for this on every page? What if there are no images with zoom? Images can be used on many types of pages so how would that be defined?

We tried to use the persistent variables to set the files needed and then use that in pagelayout.tpl but that seemed to be very tricky.

So I would humbly like to ask the community if anyone has faced the same challenge?
Any input or ideas would be apriciated...

Fredrik

http://www.areadigital.org

Custom google maps with eZ Publish

http://www.meresverige.dk
http://dsbfirst.meresverige.dk

Łukasz Serwatka

Wednesday 21 January 2009 12:36:01 am

Hi,

In case when current view need JavaScript files and CSS files and other don't then you can load it when view template is processed.

Let's say that your fancy gallery require extra JavaScripy and CSS, then you can load JavaScript directly in gallery template using <script type="text/javascript" src={"javascript/script.js"|ezdesign}></script> which proper way of doing it. In case when you need CSS file in addition you can use persistent_variable to transport it to pagelayout.

{set scope=global persistent_variable=hash('css_file', 'mycssfile.css')}

You can also use JavaScript, e.g YAHOO.util.get() to load CSS programmatically.

Personal website -> http://serwatka.net
Blog (about eZ Publish) -> http://serwatka.net/blog

André R.

Wednesday 21 January 2009 1:32:57 am

We tried to use the persistent variables to set the files needed and then use that in pagelayout.tpl but that seemed to be very tricky.

From ezoe:
view:

{set scope=global persistent_variable=hash('title', 'New %tag_name tag'|i18n('design/standard/ezoe', '', hash( '%tag_name', concat('&lt;', $tag_name, '&gt;') )),
                                           'scripts', array('javascript/ezoe/ez_core.js',
                                                            'javascript/ezoe/ez_core_animation.js',
                                                            'javascript/ezoe/ez_core_accordion.js',
                                                            'javascript/ezoe/popup_utils.js'),
                                           'css', array()
                                           )}

popup_pagelayout (slightly modified):

{if is_set( $module_result.content_info.persistent_variable.scripts )}
{foreach $module_result.content_info.persistent_variable.scripts as $script}
    <script type="text/javascript" src={$script|ezdesign}></script>

{/foreach}
{/if}

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Thomas Koch

Wednesday 21 January 2009 2:32:25 am

I just posted a draft for a requirements document to the ezcomponents mailing list. The requested component should solve the problems you describe:

http://lists.ez.no/pipermail/components/2009-January/004021.html

---
Thomas Koch | http://koch.ro
YMC - eZ Publish in Switzerland | http://ymc.ch

André R.

Wednesday 21 January 2009 4:47:14 am

In response to Thomas proposal for ezc, in eZ Publish you can already archive this.
Install ezcore extensions and change the pagelayout javascript /css loading to look something like this:

{def $css_include_list = array(
                "core.css",
                "pagelayout.css",
                "content.css",
                "websitetoolbar.css",
                ezini( 'StylesheetSettings', 'CSSFileList', 'design.ini' ),
                first_set( $module_result.content_info.persistent_variable.css_files, array() )
         )
         $js_include_list  = array(
                ezini( 'JavaScriptSettings', 'JavaScriptList', 'design.ini' ),
                first_set( $module_result.content_info.persistent_variable.scripts, array() )
         )}
{* If you use ezflow, should have been sent as part of persistent_variable in timeline.php though *}
{if is_set( $display_timeline_sider )}
    {set $css_include_list = $css_include_list|append('calendar/yui-calendar.css',
                                                      'timeline/timeline.css')}
{/if}

{* Dependancy on ezcore, packs css files togheter to improve performance *}
{ezcss( $css_include_list )}

{* Dependancy on ezcore, packs js files togheter to improve performance, 3 = use jsmin *}
{ezscript( $js_include_list,,,3 )}

Note that the file packing is automatically disabled if site.ini[TemplateSettings]DevelopmentMode is enabled to help you during development.
Also note that there are similar functions in oe 5.0 (ezoecss and ezoescript), but jsmin is not bundeled so not so strong minification.
Also also note that the code above should be inside a uri specific cache block.

@Thomas: code can be found her(very eZ Publish specific though):
http://svn.projects.ez.no/ezcore/trunk/ezcore/classes/ezpacker.php
The concept is simple, calculate where the js/css files are (eZ Publish design specific), fix the image include paths(css), minify the total js/css code and cache the result so you don't have to do it all over again.

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Fredrik Ardmar

Wednesday 21 January 2009 6:32:14 pm

Great response in record time. Fantastic.

Seems like a very powerful solution and we will be sure to try it out.

We are using a widget system allowing for the user to create and add widgets such as, weather, latest pictures, related document etc. This is built on top of the standard toolbar solution.

As I understand it the toolbar is processed after the view? Any idea to how a similar approach could be achieved for these widgets?

Fredrik

http://www.areadigital.org

Custom google maps with eZ Publish

http://www.meresverige.dk
http://dsbfirst.meresverige.dk

Fredrik Ardmar

Thursday 22 January 2009 1:51:00 am

Just to make sure im not missing something.

With this approach would it be possible to collect more values to the persistent variable?

Lets say I want to add a few CSS files in the main template and then in the image template we want to add some more. Basically appending to the persistent_variable.

Fredrik

http://www.areadigital.org

Custom google maps with eZ Publish

http://www.meresverige.dk
http://dsbfirst.meresverige.dk

André R.

Thursday 22 January 2009 4:52:54 am

It would probably be best to write a small template operator to append / set hash values, something like persistent_variable_append('key', 'value') for appending to array values and persistent_variable_set('key', 'value') for clearing it or setting single values.
Cause if you do it from templates you'll have to do a lot of if is_set checks to see if it is already set, so a template operator would be faster and cleaner. (less template code)

Inside the template operator you can work with template variables the following way:

$persistentVariable = array();
$persistentVariableKey = $namedParameters['key'];
$persistentVariableValue = $namedParameters['value'];
if ( $tpl->hasVariable('persistent_variable') && is_array( $tpl->variable('persistent_variable') )  )
{
    $persistentVariable = $tpl->variable('persistent_variable');
}

// set / append the key of the array depending on $operatorName value ( 'persistent_variable_append' or 'persistent_variable_set' )

$tpl->setVariable('persistent_variable', $persistentVariable);

You might need to look into namespaces as well, but I don't think so. If you do, var_dump $tpl->Variables to see the structure of the template variables.

Note: This will only work in node templates, as content/view and content/versionview are the only views that sends this value to pagelayout in the 'content_info' hash.

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Peter Putzer

Thursday 22 January 2009 5:47:44 am

I've been thinking about such a template operator for some time now. I'll probably write one when I've got the time.

As for <i>Note: This will only work in node templates, as content/view and content/versionview are the only views that sends this value to pagelayout in the 'content_info' hash.</i>:

That's quite unfortunate (and has been reported as a bug/feature request before). It shouldn't be a problem to add the persistent_variable to other views, should it? Does it help if we provide patches (i.e. would it get into the eZ Publish kernel in a reasonable amount of time)? And (as a workaround), should it be possible to set a global variable in a template operator if the corresponding template variable does not exist?

Accessible website starting from eZ publish 3.0 (currently: 4.1.0): http://pluspunkt.at

André R.

Thursday 22 January 2009 6:55:40 am

It shouldn't be a problem to add the persistent_variable to other views, should it?

Not a 'problem', but you/we'll have to do it for all views, including the ones in extensions and so on..
After writing the post above, I modified ezwebin 1.4 locally to add these template functions, and also made it store the persistent_variable to a protected method on the template operator class for use by the function called in pagelayout (currently called ezpagedata in ezwebin trunk). I think this is a easier solution, as no views need to be modified..

I'll add a note when / if it is committed to svn.
(I need to find some time to test it, if any have some spare time click on my name..)

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Fredrik Ardmar

Tuesday 27 January 2009 7:30:29 pm

André, that sounds like a very interesting idea.
Let me know if there is anyway of us sharing the fruits of your work :)

Fredrik

http://www.areadigital.org

Custom google maps with eZ Publish

http://www.meresverige.dk
http://dsbfirst.meresverige.dk

André R.

Thursday 05 February 2009 8:17:10 am

Patch for webin with the functionality mentioned above can be found here:
http://issues.ez.no/IssueView.php?Id=14193&activeItem=2

It does not have code to use persistent_variable for css / js loading yet, but thats easy to do now, even for non content/view pages.

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

André R.

Thursday 19 March 2009 12:19:52 am

Patch above is part of ezwebin 1.4 included in eZ Publish 4.1, just use ezpagedata_set and ezpagedata_append to add parameters to persistent_variable (and protected member if persistent_variable is not supported by current view).

_set: set an index on the persistent_variable hash
_append: append a variable on a index on the persistent_variable hash

ex:

{ezpagedata_set('script_list', array( 'some.js' ))}
{ezpagedata_append('script_list', 'someother.js')}

persistent_variable will now be:
hash( 'script_list', array( 'some.js', 'someother.js' ) )

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom