is it possible to load and use jquery in the parent iframe page & inside the iframe whithout loading jquery twice,
meaning to load jquery just once in the page and using it in the ifrmae within.
Sure, just make sure the <iframe> isn't loading the jQuery script i.e. <script src="...."> then you can access the jQuery instance in the parent like so:
var $ = window.top.$;
Be sure to use the correct context using the second parameter:
$('img', document);
If this isn't possible you can't "prevent" a script from being downloaded and executed.
You can give the child frame a reference to the jQuery object from the parent frame, but you'd have to be very careful about using it because in various places, jQuery uses the document object of the context in which it was loaded, which will (of course) be the parent's document. In some places you can override that (for instance, when searching for elements via $() you can give a context in which to search as a second parameter), but it's likely to be more trouble than it's worth.
But re-loading jQuery shouldn't be an issue. It should come from cache. Granted, there may be an extra HTTP GET with an "unmodified" response, although by using proper cache headers when serving the jQuery file, you could avoid even that. (I haven't checked the cache headers of the various CDNs that host it.)
Related
I am using jQuery on my website and Honeybadger to get notified about javascript exceptions. The tool shows me many errors that occurr because the global jQuery and $ variables are overwritten by another jQuery-Version (e.g. from https://ajax.googleapis.com/...)
So I am thinking about using jQuery.noConflict to use another variable for jQuery (e.g. $j). Since I use a few addons for jQuery, this must happen right after all of them are loaded, right?
But does it work all the time or might another jQuery be injected before all my addons are loaded?
As long as all your plugins know to use $j it won't matter when the other jquery is loaded.
I'm trying to get around iframe by using ajax/jquery.load() and inject a third party page on my site (CORS requirements are not a issues here as the third party sets the appropriate CORS response headers).
So my question is: Let's say that the main host site loads jquery 1.x and a bunch of other libs. And let's say that the third party page loads jquery 2.x and some other conflicting libraries with the main site.
How can I refactor my JS on the third party page so that it's not loadedin JS global scope but in a shielded child scope.
Can I wrap everything in function(){}?? Including the jquery libs etc? If so how do I access the methods/vars in this child scope on the third party page?
Let me know if I need to provide any more details...
iframes by default load an entire document on their own, and are pretty much shielded to everything, you can allow modals/popup/etc with the sandbox attribute, if none specified it will just show content, and won't interact with the upper layer.
To access the function inside an iframe, you can:
document.getElementById("resultFrame").contentWindow.Reset()
This will run the Reset() Global Function inside the iframe with resultFrame ID.
I have a existing file ajax,js in my website that makes an ajax request and creates a global JSON object, searchResult using that response. Now I am creating a Chrome plugin, that requires this JSON Object inside it. I have a content script for the plugin viz. plugin.js and I want to include the object inside plugin.js file.
When I try to log window.searchResult from within plugin.js, it shows as undefined.
but when I use browser console, it shows the value as expected.
Please help me with this.
Problem
Chrome content scripts and the page's own scripts live in isolated worlds.
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page.
Your code works in the console, since you execute it by default in the page's context. To see what the extension sees, you need to switch it.
Solution 1a
First, the generic solution (works even if you don't control the webpage)
There is a way around this, by injecting some code directly into the page's "world" (or properly called, context).
After injecting the code, your page-level script needs to communicate with the content script to pass the data. It's possible with custom DOM events (as, as you remember, DOM is shared). The page-level script sends an event with the data in the event's details.
Alternatively, you can just attach the data to some DOM node, say, an invisible <div>.
Solution 1b
Since you said it's your page, you can skip the inject-into-the-page step and have a listener ready in the page's own code.
The content script sends a custom event to request the data, and the page answers passes the data back as described in 1a.
Solution 2
In theory, you don't even need a content script.
You can use the "externally_connectable" mechanism to speak with the page directly.
Note though that the page has to initiate the conversation.
Here is a wireframe to ilustrate the structure of a legacy project that shows some performance issue:
For all dialogs (From jQuery UI) open a new iframe are created and all js from Home are re-downloaded and all objects are re-instanced. Can I create a reference from jQuery from Home to all new iframes and work in each iframe isolated scope?
For example:
[Home scope]
$("#some-el").data('foo', 'bar');
console.log($("#some-el").data('foo')); // results bar
[App1 scope]
//after defined in Home first run
console.log($("#some-el").data('foo')); // results undefined
PS: Remember this is a legacy architeture and all solutions must be consider this scenario.
I've encountered this situation before. One approach is to define some javascript that gets loaded into the iframes that just reroutes any function calls to top.functionCall() instead of containing their actual definition. It becomes very simple if all of your functions are under one namespace, like so:
Parent window js:
var namespace = (function () {
// all of your functions are in here as properties of namespace
})();
iframe window js:
var namespace = top.namespace;
One issue with this is any context sensitive functions (functions that rely or operate on the window object) will most likely break.
Actually, if all of these are hosted in the same place, the browser will NOT be downloading the files multiple times. Rather, it will be caching the first result, and then pulling from cache in the second. Iframes are treated as a separate context, so you won't need to worry about variable or form conflicts.
Assuming that downloading the same file twice is your primary concern, then you should be ok there.
An alternative design would be to use AJAX instead of iframed content - but having been where you are in working with legacy apps, I realize how hard that can be to do without real JSON / REST calls available. One thing I've done is changed the views inside the iframes to be "partials," returning only the necessary HTML contents without the HTML head etc., and loading them using $.load(). This gets complex as you will need to execute bindings post-load and carefully track form ID's etc., but it can be done.
Using yepnope.js. I need to "refresh" the script, but yepnope prevents files with the same url from being re-loaded.
In the documentation, they suggest using a plugin to allow files to refresh. Is there such a plugin available? What are my other options for refreshing a script during runtime in Javascript?
I tried appending a random number as a query argument to the url. That worked, but made it much more difficult to set breakpoints while debugging, so I'd rather not do this.
Any suggestions? Thanks!
IMHO it is not possible do that using any yepnope method.
I think you only has two possibilities:
Adding a random parameter to the querystring (your current solution)
Changing the yepnope script to:
expose the scriptCache yepnope var
reset the scriptCache[url]
and finally remove the created DOM img node that has your url as src.
In addition set the cache headers to expired, to prevent browser cache.
good luck