.. _require_once:
Require once - Guarding Javascript against multiple inclusion
=============================================================
Under certain circumstances, it can happen that a page loads a static
resource more than once. Most of the time this will lead to desastrous
results, as objects already known inside the page are replaced by
freshly created ones, destroying a great deal of state. Consider the
following situation
.. code-block:: html
Now let's assume we render a snippet of HTML through an AJAX-call that
replaces the **#replace_me**-element, which looks like this
.. code-block:: html
Super!
Because of the second inclusion of the `jquery`-library, the functionality of `cool_plugin.js` from the inital page-load is gone!
To prevent this, ToscaWidgets has grown a feature (Since version **0.9.8**) that prevents this from happening. It's called `require once` and
is globally activated through the configuration option **toscawidgets.middleware.require_once**. See :doc:`configuration`
on how to enable it.
If this option is set to ``True``, all static javascript is surrounded automatically by guarding-statements that look
like this:
.. code-block:: javascript
if(typeof(tw_jquery_static_jquery_js) === "undefined") {
// - the actual static file content
tw_jquery_static_jquery_js = true;
}
This will make sure that additional includes won't be re-defining objects.
Turning `require once` on on individual resources
-------------------------------------------------
Since the introduction of `require once`, it is also possible to define for a given resource individually if it is
supposed to be guarded against multiple inclusion. This can be done through setting :attr:`tw.api.JSLink.require_once`
to either ``True`` or ``False``.
All :class:`~tw.api.JSLink`-instances that don't explictly define it are bound to the globally configured behavior.
Gotchas when using `require once`
---------------------------------
There are two known gotchas when using require once:
- Some static javascript might rely on side-effects when being included. For example, there are `jquery`-plugins that
look like this
.. code-block:: javascript
(function($) {
// define the plugin
})(jQuery);
// automatically do stuff for specific elements
$(document).ready(function() {
$("#some_class").do_something();
}
So what happens is that the plugin is not only declared, but also automatically performs some initialization on
certain elements after being loaded.
This won't work of course after being guarded through `require once`! The solution is simple though: simply render
the code yourself using :class:`~tw.api.JSSource` yourself. This has the additional benefit of being finer granulated,
e.g. only attaching events to the replaced parts of the page.
- The :attr:`tw.api.JSLink.require_once` attribute is only effective if ToscaWidget itself serves the static resources.
It's implemented via passing an extra parameter to the **GET**-request.
When serving the static resources through e.g. apache, you can only chose to either serve all or none of them with
guarding statements.