Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

jQuery and Smarty3 - "Enqueue" Scripts - Best Prac

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> General
View previous topic :: View next topic  
Author Message
dbj
Smarty Rookie


Joined: 16 Nov 2017
Posts: 7

PostPosted: Thu Nov 16, 2017 11:04 am    Post subject: jQuery and Smarty3 - "Enqueue" Scripts - Best Prac Reply with quote

Hi,

I'm using jQuery on my website. For performance reasons, I would like to load jQuery just before the </body>-Tag. My sub-templates, which are included in the main template, access the jQuery object ($) or even load jQuery plugins.

But of course this does not work because $ is undefined - I would have to load it inside the <head>.

I'm wondering what would be a good way to have jQuery loaded before </body> and still use jQuery (plugins) on-demand in sub-pages.

My first thought was to write a plugin `enqueue_script` which I'm using in the subtemplates and which then is inserted after the <script src="jquery.js"> line - so jQuery is defined and can be used.

I "stole" this idea from Wordpress, where a function named `wp_enqueue_script` exists and does exactly that.

But maybe there is another solution and maybe I don't even need to write a plugin but can use already existing functionality.

(It would be great to check for duplicate entries, so for example if "jquery-ui.js" is enqueued twice, it is only loaded once.)

Thanks!
Back to top
View user's profile Send private message
bsmither
Smarty Elite


Joined: 20 Dec 2011
Posts: 322
Location: West Coast

PostPosted: Thu Nov 16, 2017 7:38 pm    Post subject: Reply with quote

Please be aware that you may not have a complete understanding of when Smarty does its thing.

The complete web page is built by Smarty according to Smarty tags in the template code, then given to the web server (via PHP) to send out to the web client (that's you). Once the web server receives the document to send to the client, PHP shuts down (destroys classes, etc) and Smarty with it.

It is the responsibility of your web browser to run any javascript that that document may contain or link to. In this respect, executing javascript code in the received document (that was populated and constructed via dynamic data) is no different than executing javascript code in a static web page.

So, solving javascript problems is from the point of view of after the browser having received a web document - from where and how that document was constructed is irrelevant.

That said, code your includes such that any javascript that needs to be executed is wrapped with a ready command:
https://stackoverflow.com/questions/799981/document-ready-equivalent-without-jquery
Back to top
View user's profile Send private message
dbj
Smarty Rookie


Joined: 16 Nov 2017
Posts: 7

PostPosted: Thu Nov 16, 2017 8:05 pm    Post subject: Reply with quote

I think you may have misunderstood me.

The current situation (kind of pseudo code):

index.tpl:

Code:
<html>
<head>
<script src="jquery.js">
</head>
<body>
<!-- common stuff like header html -->
{include "content.tpl"}
<!-- common stuff like footer html-->
</body>
</html>


content.tpl:

Code:
<script src="jquery-ui.js">
<!-- and a lots more stuff -->


... this works. BUT I want to move the `<script src="jquery.js">` out of the head just before </body>.

And if I do this... the page breaks! because at the time jquery-ui.js is included, the jQuery object is not available! And the included file has NO way of writing something "behind" the `<!-- common stuff like footer html-->` part.

So what I want is something like this:


index.tpl:

Code:
<html>
<head>
</head>
<body>
<!-- common stuff like header html -->
{include "content.tpl"}
<!-- common stuff like footer html-->
<script src="jquery.js">
{paste stuff from all `enqueue-script` commands}
</body>
</html>


content.tpl:

Code:
{enqueue-script "<script src="jquery-ui.js">"}
<!-- and a lots more stuff -->
Back to top
View user's profile Send private message
dbj
Smarty Rookie


Joined: 16 Nov 2017
Posts: 7

PostPosted: Thu Nov 16, 2017 8:56 pm    Post subject: Reply with quote

It looks like `{block name="..." append}` would be the perfect solution?
Back to top
View user's profile Send private message
bsmither
Smarty Elite


Joined: 20 Dec 2011
Posts: 322
Location: West Coast

PostPosted: Fri Nov 17, 2017 1:06 am    Post subject: Reply with quote

One approach I take, which may or may not be a solution for you is:
Code:
<html>
<head>
</head>
<body>
<!-- common stuff like header html -->
{include "content.tpl"}
<!-- common stuff like footer html-->
<script src="jquery.js">
<script src="jquery-ui.js">
</body>
</html>

That is, at the bottom, I load all the libraries. Any script that uses these libraries gets wrapped in a 'wait for the document to finish loading' condition.

That said, I realize that a library may not be needed for a number of dynamic content sections. But load it anyway. Try for a CDN source. That way, there is a chance the visitor will have that library in their browser cache anyway.

Also, since the final page is being built by Smarty, under PHP code control (if you have access to the PHP code), think about having PHP determine what content is being embedded in the page, identify the libraries needed, assign the collection to a Smarty variable, then in the template, iterate through the array building the complete sequence of <script> tags.
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Fri Nov 17, 2017 4:54 pm    Post subject: Reply with quote

Read the documentation already. And leave a space between "{" and the following JavaScript code.
It will prevent Smarty from parsing JavaScript code as Smarty tags.
What to your document loading questions, ask them on JS-competent forums.
But generally, the time of loading jQuery bootstrap is (a) negligible and (b) done only on first page load. Then it is cached.
If you are using shared bootstrap from google CDN, then it is cached even before your first page is requested.
Back to top
View user's profile Send private message
dbj
Smarty Rookie


Joined: 16 Nov 2017
Posts: 7

PostPosted: Thu Jan 18, 2018 8:33 pm    Post subject: Reply with quote

AnrDaemon wrote:
Read the documentation already. And leave a space between "{" and the following JavaScript code.

No need for a space. Just use {literal}, as the documentation says (maybe just read it).

And to answer my own question if someone else is reading this thread:
Yes, inheritance would be the best solution.

If it's not available (e.g. Smarty 2), use {assign} or {capture} to write the JS code to a variable, then output this variable in the included footer template after loading jquery... et voila...

bsmither wrote:
Any script that uses these libraries gets wrapped in a 'wait for the document to finish loading' condition.


That would work too, yes. But JS before the footer may delay page loading and cause a FOUC (or similiar)
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Fri Jan 19, 2018 6:19 am    Post subject: Reply with quote

dbj wrote:
No need for a space.

Space is faster and easier to insert, as it does not clog the code.
That's why I've suggested it.
However, when using external inserts, such as counter code snippets, I do use {literal} to wrap the template being included.
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> General All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP