Background:
The second "context" argument to the jQuery selector call (e.g: jQuery(selector, context)
) can be provided to give the selector engine a starting point from which to descend.
This is often useful if you need to control content in an IFRAME (in the same domain). You simply pass iframe.contentWindow.document
as the "context" argument.
If any JavaScript code is loaded in the IFRAME which makes use of jQuery, and is CALLED FROM THE SCOPE OF THE OUTER WINDOW, then any reference to $
or jQuery
in that code will actually be the instance of jQuery
from the outer window.
The problem comes when that JavaScript code in the IFRAME (say Bootstrap.js) does something like $(document)
(or does some other selector without a "context" argument). When that code (defined inside the iframe) is called from the outer window, document
refers to the HTMLDocument element from the outer window - which is usually not the desired outcome.
Question:
It would be super useful to be able to create a lexically-scoped copy/wrapper of jQuery that has a default "context" argument, provided by whomever creates it.
Example:
// jQuery already exists out here
var iframe = document.createElement('IFRAME');
iframe.addEventListener('DOMContentLoaded', function(){
// code in here can already refer to $ for 'outer' jQuery
// code in here can refer to $local for 'inner' jQuery by virtue of...
var $local = jQueryWithContext($, iframe.contentWindow.document);
// code loaded with IFRAME will use $local by virtue of ...
iframe.contentWindow.jQuery = iframe.contentWindow.$ = $local;
});
iframe.src = '/path/to/iframe/content.html';
The question is, is it possible to write something like jQueryWithContext
above?
Why?
Sometimes you want to isolate 3rd party HTML components which (while you trust them from a security perspective) are misbehaved from a CSS / JavaScript pollution perspective.
Bootstrap.js is a good example. It calls $(document)
a fair bit, and does other similar context-less selector calls. If jQuery could be re-scoped in the way I describe, then this 'not optimally' written libraries could be isolated quite easily.
Additionally, it can be very helpful to use the same $.data(el, ...)
collection from both frames, and this is quite tricky without some context management.
Actually, it would be rather simple:
But to force it to plugins, you'd probably need to go like this:
This kinda work, but it could break some usage of
$()
(Maybe not now, but it's possible in future jQuery version, or anytime the presence of acontext
parameter break the normal behavior).