Best practice vs javascript in module templates

Do something cool with CMS? Show us ...
This board is for 'Answers', and the discussion of answers... Not for questions.
Locked
psy
Power Poster
Power Poster
Posts: 463
Joined: Sat Jan 22, 2005 11:19 am

Best practice vs javascript in module templates

Post by psy »

It's generally accepted best practice to load javascripts after the content of your page. Which is fine until you have a module that by default inserts javascript in its template. If you haven't pre-loaded any dependencies, eg jQuery in the head section, you're up the creek.

My solution is to load all dependencies esp jQuery as per 'best practice' after the content. Then in the module template, capture the script into an array and add it after the dependency. Eg:

In my module template:

Code: Select all

{capture assign=js}
{literal}
<__script__>
$(document).ready(function()({
...
});
</__script>
{/literal}
{/capture}
{append var=pagejs value=$js}
Then in my page template immediately above the <__body> tag:

Code: Select all

<__script__ src="source/to/jquery"></__script>
{if is_array($pagejs)}
{foreach from=$pagejs item=js}
{$js}
{/foreach}
{/if}
This drops all module template js (or hidden popup divs etc) at the bottom of the page.

All worked well until this week I tried it with CGGoogleMaps2. Sure, the script went to the bottom of the page but so did the displayed map!

Solution was to on my page:

Code: Select all

{capture assign=js}{CGGoogleMaps2 map='mymap'}{/capture}{append var=pagejs value=$js}
and in the map template:

Code: Select all

{* map template *}
<__script__ src="http://maps.google.com/maps/api/js?libraries=geometry{if $map->sensor}&sensor=true{else}&sensor=false{/if}"></__script>
<__script__ src="{$mod->GetModuleURLPath()}/lib/js/infobox_packed.js"></__script>
<__script__ src="{$mod->GetModuleURLPath()}/lib/js/map_tooltip.js"></__script>
<__script__ src="{$mod->GetModuleURLPath()}/lib/js/jquery.cggm_map.js"></__script>

<div id="cggm_map_{$mapinstance}" class="col-sm-12 cgmap"></div>
{if $map->directions}
  {* enable directions *}
  {$generator->get_directions_form()}
{/if}

{* javascript is on the bottom incase some smarty variables we need were set in the various generator calls *}
<__script__ type="text/javascript">
if( typeof(jQuery) == 'undefined' ) {
  var div = document.getElementById('cggm_map_{$mapinstance}').
  div.innerHTML = '<h3 style="color: red;">jQuery and jQuery UI Are Required</h3>';
  throw new Error('jQuery and jQuery UI Are Required');
}
$(document).ready(function(){
  var obj = $('#cggm_map_{$mapinstance}');
  obj.cggm2({$generator->get_map_options_js()});
  {if $map->directions && isset($directions_form_id)}$obj.cggm2('options','directions_form','#{$directions_form_id}');{/if}

obj.detach().appendTo('.maintext');

});
</__script>
Note the "obj.detach().appendTo('.maintext'); line.

The important things above were that the module was executed in the page so all the vars were filled, then in the script, the displayed map gets moved from below the page to the right place within the content with '.maintext' class .

Everything we do is a compromise and it's been said before that {capture} is not hugely efficient. On the other hand, the output scores way higher on page audits using the above technique.

Just saying...

psy
Last edited by psy on Sat May 10, 2014 9:11 am, edited 1 time in total.
User avatar
Jo Morg
Dev Team Member
Dev Team Member
Posts: 1921
Joined: Mon Jan 29, 2007 4:47 pm

Re: Best practice vs javascript in module templates

Post by Jo Morg »

psy wrote:Everything we do is a compromise and it's been said before that {capture} is not hugely efficient.

Code: Select all

{CGGoogleMaps2 map='mymap' assign='js'}{append var=pagejs value=$js}
Wouldn't this work? I seem to recall that by default in CMSMS all module calls could be assigned directly. Didn't test this with CGGoogleMaps2 though.
But nice tip indeed.
"There are 10 types of people in this world, those who understand binary... and those who don't."
* by the way: English is NOT my native language (sorry for any mistakes...).
Code of Condut | CMSMS Docs | Help Support CMSMS
My developer Page on the Forge
GeekMoot 2015 in Ghent, Belgium: I was there!
GeekMoot 2016 in Leicester, UK: I was there!
DevMoot 2023 in Cynwyd, Wales: I was there!
psy
Power Poster
Power Poster
Posts: 463
Joined: Sat Jan 22, 2005 11:19 am

Re: Best practice vs javascript in module templates

Post by psy »

Very probably JoMorg :)
Guess my thinking was stuck.
It's good to share ideas.
uniqu3

Re: Best practice vs javascript in module templates

Post by uniqu3 »

JoMorg is right, smarty tags, module tags all can be assigned with assign.
Regarding capture, why not simply assign, only drawback is that you need to take care of proper escaping or not mixing up single and double quotes.

Code: Select all

{$js = "
<__script__ type=\"text/javascript\"> <!-- double quote needs escaping -->

$(document).ready(function() {
    console.log('Yay ready'); // single quote not
});
</__script>
"}
But ideal solution would be a simple block type smarty plugin, so you would simply do something like {js_block assign='js'} my js content {/js_block} or actually i think CGExtensions comes with {jsmin} {/jsmin} or so, so that might work to, only problem is it minifies your code, which is nice for production, not so nice while developing :-D
psy
Power Poster
Power Poster
Posts: 463
Joined: Sat Jan 22, 2005 11:19 am

Re: Best practice vs javascript in module templates

Post by psy »

Thanks uniqu3

I actually do encase all my js in {jsmin} but not everyone installs CGExtensions so I removed it from the above example. Hehe, I like your idea.... maybe simply {jsmin assign='js'}?

While the focus seems to be on my (resolved) issue with CGGoogleMaps2, the main point of the tip was to capture module template scripts/hidden divs etc and drop them to the end of the page without breaking the page.

Gladly accepting suggestions to make the solution more elegant.
fprm67
New Member
New Member
Posts: 6
Joined: Thu Apr 03, 2014 10:22 pm

Re: Best practice vs javascript in module templates

Post by fprm67 »

Hi,
I would use {jsmin} {/jsmin} in a template of the Gallery Muldule, but it does not work. You have any suggestions?
Another question that how I could do minify css in a template of the Gallery Module?

Thank you
psy
Power Poster
Power Poster
Posts: 463
Joined: Sat Jan 22, 2005 11:19 am

Re: Best practice vs javascript in module templates

Post by psy »

The Gallery module does not evaluate smarty tags in the Javascript or CSS textareas of the template.

To move the js to the end of your page, you would have to assign it in the layout textarea where you have your smarty tags.

Not tested, but for the CSS, maybe you could also put it in the layout section encased in {strip assign='gallerycss'} tags then put the {$gallerycss} tag in the head section of your page template? You will of course have to include the start and end <style> tag in the var.

The body area of a page is processed before the head section so the {$gallerycss} var should be available.

Alternatively, you could put the {$gallerycss} in the metadata box on the Options tab of your page edit screen of the page containing the Gallery tag.
User avatar
Rolf
Dev Team Member
Dev Team Member
Posts: 7825
Joined: Wed Apr 23, 2008 7:53 am
Location: The Netherlands
Contact:

Re: Best practice vs javascript in module templates

Post by Rolf »

Kind of related to this topic. I made a blog about combining JS files into one. Very simple solution, almost too good to be true. Can't think of any cons at the moment...
https://www.cmscanbesimple.org/blog/eas ... s-and-code
- + - + - + - + - + - + -
LATEST TUTORIAL AT CMS CAN BE SIMPLE:
Migrating Company Directory module to LISE
- + - + - + - + - + - + -
Image
psy
Power Poster
Power Poster
Posts: 463
Joined: Sat Jan 22, 2005 11:19 am

Re: Best practice vs javascript in module templates

Post by psy »

Sweet idea, Rolf. There are definitely benefits in loading only one js file. :)

BTW, JoMorg, had occasion to use CGGoogleMaps2 on another site today with the extra jQuery obj.detach().appendTo('.maintext'); line in the map template.

Using my method and your tag suggestion, ie {CGGoogleMaps2 map='mymap' assign=js}{append var=pagejs var=$js} worked a treat!

Just pure CMSMS, module templates and the magic of Smarty.
psy
Power Poster
Power Poster
Posts: 463
Joined: Sat Jan 22, 2005 11:19 am

Re: Best practice vs javascript in module templates

Post by psy »

Re uniqu3's comment about every tag having the ability to be assigned...

Absolutely this is true but found an example today that caused a problem.

Older tags, esp plugins, do assign but a few also output the result at the same time.

I wanted to assign the {title} tag to {title assign='title'}. The tag was assigned to the var $title but it also output the page title which at that point in my template, was not what I wanted.

Solution was {assign var='title' value="{title}"}
uniqu3

Re: Best practice vs javascript in module templates

Post by uniqu3 »

I always assign title Tag and it never outputs any things except when explicitly calling assigned variable.
psy
Power Poster
Power Poster
Posts: 463
Joined: Sat Jan 22, 2005 11:19 am

Re: Best practice vs javascript in module templates

Post by psy »

Yes, realised that after I'd posted it. The tag wasn't 'title', was some other old tag. Solution was the same.
Locked

Return to “Tips and Tricks”