How do I prevent loading Javascript twice?

8,437 views
Skip to first unread message

Richard

unread,
Mar 9, 2012, 6:13:27 PM3/9/12
to Joomla! General Development
What's a good way to check to see if I have already loaded a
javascript library or plugin?

The situation I have is this.

In my component I am loading JQuery and some plugins such as Fancy box

However, in one of my templates I also load Javascript for Fancybox
plugin because I need it for regular article pages.

How can I tell in my component whether or not these have already been
loaded by the template?

Many thanks
Richard

Saul Alejandro Martinez Castelo

unread,
Mar 9, 2012, 6:16:35 PM3/9/12
to joomla-de...@googlegroups.com
$document =& JFactory::getDocument();
$scripts = array_keys($document->_scripts);
$scriptFound = false;
for ($i = 0; $i < count($scripts); $i++) {
    if (stripos($scripts[$i], 'script-you-want-to-load.js') !== false) {
        $scriptFound = true;
    }
}
if (!$scriptFound) {
    $document->addScript(JURI::root(true) . 'script-you-want-to-load.js');
}

I hope it helps.

Richard

--
You received this message because you are subscribed to the Google Groups "Joomla! General Development" group.
To post to this group, send an email to joomla-de...@googlegroups.com.
To unsubscribe from this group, send email to joomla-dev-gene...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/joomla-dev-general?hl=en-GB.




--
Saul Martínez

Richard

unread,
Mar 9, 2012, 6:37:46 PM3/9/12
to Joomla! General Development
Thanks for this idea. ...

I had thought of using a flag of some sort that my template would set
if it loaded 'script-you-want.js' ... I seem to remember reading
somewhere that there was something in play like that for Jquery, but I
can't find a reference to it.

Is there any way of 'registering' javascript libraries to avoid
conflicts?

On Mar 9, 3:16 pm, Saul Alejandro Martinez Castelo

Ken Ballou

unread,
Mar 9, 2012, 7:13:55 PM3/9/12
to joomla-de...@googlegroups.com
A flag in your template would not help.  Your component is rendered early in the process of assembling the page.  In fact, the component is rendered first.  Then, the template is loaded and parsed, and then the modules specified for the various positions in the template are rendered.

Richard

unread,
Mar 10, 2012, 2:46:29 AM3/10/12
to Joomla! General Development
That's interesting and i wasn't aware of that.

In that case, how CAN i synchronize things so that there is only one
instantiation of any given script
> >> Saul Mart�nez

Richard

unread,
Mar 10, 2012, 10:31:50 AM3/10/12
to joomla-de...@googlegroups.com
OK, would this approach work?

1. in the component that needs foo.js, load it always, since it doesn't know if the template or the modules (or plugins presumably ) will load it.
2. in the template , if it requires foo.js, test if foo.js has been added to the script list (either with a flag that the component has set or else by scouring the _scripts array. 
3. in modules do the same as template
4. in plugins do the same as template

This sounds OK except it seems that most modules don't make tests like this and just load the javascript libraries (or library plugins) that they need, when they need them.

This doesn't feel very well architected though and there must be a better way to coordinate javascript libraries but I can't find it looking through the docs and googling.
I seem to remember Joseph leblanc canvassing joomla day a couple of years ago about this, but at that time i didn't understand the issue and now I think I am beginning to see what he was talking about!

I imagine that this group must run into similar issues all the time so it would be great if you could share any strategies you have for handling it.

many thanks
Richard


> >>> To unsubscribe from this group, send email to

Jeremy Wilken

unread,
Mar 10, 2012, 11:25:36 AM3/10/12
to joomla-de...@googlegroups.com
Currently there is no bulletproof way to prevent duplicates. Templates often load the scripts as <script> tags, while extensions use JDocument::addScript() (not a static method actually), so we have two methods. There is nothing built into the JDocument class that tracks the scripts, the versions, and dependencies. The snippet provided above will not account for any files that are added into the html output of the template directly. The only solution that can work requires every script to be loaded through the same process.

Ironically, Joe has been working on a proof of concept plugin that we could utilize for Joomla (if all extensions used it of course). You can find it here: https://github.com/square-one/square-one-cms/pull/110

Mike Smith

unread,
Mar 10, 2012, 12:26:26 PM3/10/12
to joomla-de...@googlegroups.com
I don't think you can actually prevent a page from LOADING multiple
copies of a js script. The problem is that the script could be loaded
through multiple "doors", the core, the template and any number of
modules and any component loaded with a page. There is also the
problem of additional sub-libs as well...

The only way you could reliably control it is for the core system to
be the defacto library loader and each component and module manager to
have have a flag indicating their need to load said library and any
sub-libs, which the core would only then load it if it is not already
being loaded for another module or component already...

There are many "possible" ways of checking for the existence of a
library, such as scanning the DOM, or the raw output HTML stream and
suppressing any duplicate instances of loading the same js lib before
the page is served, but then how do you control the filename, same lib
files might have different names!.....so I can't see how this could be
done reliably, unless you check every module, template and component
and change the code to not load the library(s).

It seems to me there are only possible 2 ways: pass the responsibility
of loading all js lib files to the core - but needs a new core feature
which all TPD's agree to adopt, or to hack the modules, components,
templates to remove any unwanted loads - never a good thing!

Which means there is no true solution and not likely to be!
Also remember that most browsers would cache the js libs anyway and
not reload with every page request so the problem lies in the browsers
DOM rather than a page loading/server overhead.

Mike

>> > >>> joomla-de...@googlegroups.com.


>> > >>> To unsubscribe from this group, send email to

>> > >>> joomla-dev-gene...@googlegroups.com.


>> > >>> For more options, visit this group at
>> > >>>http://groups.google.com/group/joomla-dev-general?hl=en-GB.
>> > >> --
>> > >> Saul Mart�nez
>

> --
> You received this message because you are subscribed to the Google Groups
> "Joomla! General Development" group.

> To view this discussion on the web, visit
> https://groups.google.com/d/msg/joomla-dev-general/-/UUo4geGNFpIJ.
> To post to this group, send an email to joomla-de...@googlegroups.com.


> To unsubscribe from this group, send email to

> joomla-dev-gene...@googlegroups.com.

Richard

unread,
Mar 10, 2012, 12:34:08 PM3/10/12
to joomla-de...@googlegroups.com
Thanks all of you for the explanation and I understand now why there wasn't an obvious solution.

My situation is a bit simpler because I'm creating the template and main component so I've got a tad more control (eg. I can have a module parameter that  indicates whether or not to load a given library)
I think it means that I need to be careful when I use third party modules and plugins to make sure that they don't add another conflicting library, and if they do then write some sort of over-ride.

Thanks again!

Naouak

unread,
Mar 10, 2012, 7:50:00 PM3/10/12
to joomla-de...@googlegroups.com

if your js code is done well emough, you don't really need to bother about that.

In my js files I always put everything in a single object if I need global vars. Just test the presence of the object at the start of the js file and you can avoid multiple execution. If the requested file is the same, the browser won't ask for it twice if your cache settings ae good enough( should be by default on most servers) and the perfomances on the browser side will be almost the same as if the script is not loaded twice.

--
You received this message because you are subscribed to the Google Groups "Joomla! General Development" group.
To view this discussion on the web, visit https://groups.google.com/d/msg/joomla-dev-general/-/Cs2azHE9CGsJ.

Saul Alejandro Martinez Castelo

unread,
Mar 10, 2012, 7:58:45 PM3/10/12
to joomla-de...@googlegroups.com

I haven't done it myself, but I think modernizr provides such mechanisms to load js files/libraries when required, which I think will be the best, being that you're working javascript. http://html5boilerplate.com does exactly what Nouak says.

Sent from Samsung Mobile

Andy Nagai

unread,
Mar 12, 2012, 1:52:34 AM3/12/12
to joomla-de...@googlegroups.com
Why don't you just add the .js library at the view level using
addScript() for every view that needs it and not stick it in the
template file. Then you have no duplicating .js files with your
component and template.

Richard

unread,
Mar 13, 2012, 2:42:18 AM3/13/12
to joomla-de...@googlegroups.com
Thanks saul. That is what i'd started doing but then realized i needed the same js to be i luded on my article pages and some others (and at some point in modules).

I liked the earlier suggestion that the js libraries cld work thus out for themselves. In fact i did end up doing that when i first ran into the issue. I'm not sure though how to make that work where a library or plugin is brought in from a cdn.

I've taken a quick look at mernozrs loader but not sure if i understand it.

This must be a common issue for all cms's i would think, but as a previous post pointed out , impossible to address fully without some restrictive registration scheme.

piotr_cz

unread,
Mar 13, 2012, 7:11:08 AM3/13/12
to Joomla! General Development
There could be a way worth investigating (I didn't try it out):

Did you notice, how MooTools are loaded? Library may be referenced in
different places, but at the end it's loaded only once using JHtml
class, particularly JHtml::_('behavior.framework');

My idea is to create a system plugin (those are dispatched before any
other extensions: components, modules or templates), which would add
new ('behavior.jquery'). You will reference it later in your
extensions. The registration code would be inspired by
behavior.framework

Take a look at:
http://docs.joomla.org/JHtml::addIncludePath/11.1
http://docs.joomla.org/JHtml::register/11.1

http://api.joomla.org/__filesource/fsource_Joomla-Platform_HTML_librariesjoomlahtmlhtmlbehavior.php.html#a38

subtextproductions

unread,
Mar 13, 2012, 11:08:10 AM3/13/12
to joomla-de...@googlegroups.com
In Joomla 1.6 and later there is a new system event "onBeforeCompileHead". I think that this is the right place to double check javascripts. Hopefully all of the components, plugins, and modules you are using for your site are loading javascript with the document class as mentioned previously in this thread. If so, then everything that is going to be added has been added to the head just before onBeforeCompileHead. Using this event you can loop through the loaded javascripts and filter out the ones you don't want.

The real difficulty is that not every included script will have its version somewhere in the name, so it can be very difficult to try and figure out which of the multiple loading jQuery libraries is the correct one to load. Even more complicated is that the script declaration is not an array that you can loop through. Every new script declaration is simply appended to the end of the existing string.

I think the core team really wants to address this issue, because its a common problem that I see amongst Joomla sites. People download a bunch of different extensions and each one loads its own copy of jQuery without checking to see if it is already loaded. I don't even want to use jQuery, I want to use either MooTools or Prototype, and I think there should be a way to replace the entire UI/UX layer in much the same way we can adjust templates to change the look of the site.

piotr_cz

unread,
Mar 14, 2012, 4:10:06 AM3/14/12
to Joomla! General Development
I still think the way proposed by me is the way to go.

However, did you try simply using addScriptDeclaration or
JHtml::script ? I'm pretty sure there is a built in check to avoid
loading scripts multiple times. If you want to solve the problem just
for specific project, this could be sufficient.

Concerning jQuery, there is an open pull request in Joomla platform
repository (as subtextproductions mentioned) that tackles this issue:
https://github.com/joomla/joomla-platform/pull/736
It's open for 2 months now. I think the devs may be overengineering
the solution but I don't have experience with jQuery and it's
compatibility between versions.
> http://api.joomla.org/__filesource/fsource_Joomla-Platform_HTML_libra...
Reply all
Reply to author
Forward
0 new messages