How can I inject Javascript (including Prototype.js) in other sites without cluttering the global namespace?
Asked Answered
S

2

6

I'm currently on a project that is a big site that uses the Prototype library, and there is already a humongous amount of Javascript code.

We're now working on a piece of code that will get "injected" into other people's sites (picture people adding a <script> tag in their sites) which will then run our code and add a bunch of DOM elements and functionality to their site. This will have new pieces of code, and will also reuse a lot of the code that we use on our main site.

The problem I have is that it's of course not cool to just add a <script> that will include Prototype in people's pages. If we do that in a page that's already using ANY framework, we're guaranteed to screw everything up.
jQuery gives us the option to "rename" the $ object, so it could handle this situation decently, except obviously for the fact that we're not using jQuery, so we'd have to migrate everything.

Right now i'm contemplating a number of ugly choices, and I'm not sure what's best...

  • Rewrite everything to use jQuery, with a renamed $ object everywhere.
  • Creating a "new" Prototype library with only the subset we'd be using in "injected" code, and renaming $ to something else. Then again I'd have to adapt the parts of my code that would be shared somehow.
  • Not using a library at all in injected code, to keep it as clean as possible, and rewriting the shared code to use no library at all. This would obviously degenerate into us creating our own frankenstein of a library, which is probably the worst case scenario ever.

I'm wondering what you guys think I could do, and also whether there's some magic option that would solve all my problems...

For example, do you think I could use something like Caja / Cajita to sandbox my own code and isolate it from the rest of the site, and have Prototype inside of there? Or am I completely missing the point with that?

I also read once about a technique for bookmarklets, were you add your code like this:

(function() {  /* your code */ })();

And then your code is all inside your anonymous function and you haven't touched the global namespace at all. Do you think I could make one file containing:

(function() { 
   /* Full Code of the Prototype file here */
   /* All my code that will run in the "other" site */

   InitializeStuff_CreateDOMElements_AttachEventHandlers();
})();

Would that work? Would it accomplish the objective of not cluttering the global namespace, and not killing the functionality on a site that uses jQuery, for example?

Or is Prototype too complex somehow to isolate it like that?
(NOTE: I think I know that that would create closures everywhere and that's slower, but I don't care too much about performance, my code is not doing anything that complex)

Suppress answered 5/8, 2009 at 2:57 Comment(1)
Usually, when you are injecting your code on other websites, you are providing a small fraction of the functionality from your main application, so it makes sense to just code the required features in "native" javascript . However, seems that's not the case on your project. I think it would work with the anonymous wrapper function. Some bookmarklets have routines that dynamically load required libraries. Performing some tests to confirm that the technique actually works, should be quick. :)Riptide
I
2

If you're injecting your code into other sites, either require that they also include prototype, or don't use a library at all.

Any other option is, in my opinion, far too intrusive.

Illegality answered 5/8, 2009 at 3:40 Comment(2)
I would love to require prototype, but unfortunately this is supposed to work on every single site on Earth. In fact, I'm looking forward to some FUN with quirks mode too. And I agree with the intrusive part, which is why I want to minimize it as much as possible. Would adding jQuery with its renamed $ object also be too intrusive?Suppress
Prototyüe sucks :) way too intrusive. Go with jQuery.Cavallaro
U
0

Daniel,

I am running into the same issue for some of the same reasons. Thanksfully, I am able to use jquery. What I want to do is create a single js file that will load up an instance of jquery and any dependent libraries I need. Then I want to load up css in the same way.

I found a script that will load these files into the DOM, but they don't seem to work. Here is what I am using:

function loadjscssfile(filename, filetype){
 if (filetype=="js"){ //if filename is a external JavaScript file
  var fileref=document.createElement('script')
  fileref.setAttribute("type","text/javascript")
  fileref.setAttribute("src", filename)
 }
 else if (filetype=="css"){ //if filename is an external CSS file
  var fileref=document.createElement("link")
  fileref.setAttribute("rel", "stylesheet")
  fileref.setAttribute("type", "text/css")
  fileref.setAttribute("href", filename)
 }
 if (typeof fileref!="undefined")
  document.getElementsByTagName("head")[0].appendChild(fileref)
}

I can see in firebug that the css is loaded, but the contents of my css file are not coming through. I had hoped that I could dynamically load the libraries I needed based on the tools that this WIDGET used. So I would like to do some programmatic logic that would determine which libraries and css files should be "imported".

Not sure if this line of thinking plays into your efforts, but I would love to get your thoughts, or see where you end up going with this.

Unlettered answered 14/4, 2010 at 0:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.