View previous topic :: View next topic |
Author |
Message |
dbj Smarty Rookie
Joined: 16 Nov 2017 Posts: 7
|
Posted: Thu Nov 16, 2017 11:04 am Post subject: jQuery and Smarty3 - "Enqueue" Scripts - Best Prac |
|
|
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 |
|
bsmither Smarty Elite
Joined: 20 Dec 2011 Posts: 322 Location: West Coast
|
Posted: Thu Nov 16, 2017 7:38 pm Post subject: |
|
|
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 |
|
dbj Smarty Rookie
Joined: 16 Nov 2017 Posts: 7
|
Posted: Thu Nov 16, 2017 8:05 pm Post subject: |
|
|
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 |
|
dbj Smarty Rookie
Joined: 16 Nov 2017 Posts: 7
|
Posted: Thu Nov 16, 2017 8:56 pm Post subject: |
|
|
It looks like `{block name="..." append}` would be the perfect solution? |
|
Back to top |
|
bsmither Smarty Elite
Joined: 20 Dec 2011 Posts: 322 Location: West Coast
|
Posted: Fri Nov 17, 2017 1:06 am Post subject: |
|
|
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 |
|
AnrDaemon Administrator
Joined: 03 Dec 2012 Posts: 1785
|
Posted: Fri Nov 17, 2017 4:54 pm Post subject: |
|
|
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 |
|
dbj Smarty Rookie
Joined: 16 Nov 2017 Posts: 7
|
Posted: Thu Jan 18, 2018 8:33 pm Post subject: |
|
|
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 |
|
AnrDaemon Administrator
Joined: 03 Dec 2012 Posts: 1785
|
Posted: Fri Jan 19, 2018 6:19 am Post subject: |
|
|
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 |
|
|