views:

368

answers:

6

I'm using Simile to draw dynamic timelines. I am also using an in-house library to add a comment blog. Our in-house library uses the body element's onload event to initialize.

<body onload="initComments('myID')">

But Simile seems to have hijacked the onload for their own purpose so that initComments('myID') never executes.

Short of changing the Simile code, how could I get my initializer to run?

I would prefer not to add another library (i.e. jQuery) just to solve the problem.

+1  A: 

Use jQuery's $(document).ready event, which lets you add an arbitrary number of handlers (unlike onload).

Matt Ball
An entire library to solve an onload problem seems like too much.
dacracot
If you don't want to use jQuery, you could still use it as a reference to how it might be done.
Hanno Fietz
Although you say an "entire library" is too much, the minified version of jQuery is only 55k. If you meant that you don't want to learn a new library, see AndreasKnudsen's answer. I write as much Javascript as I can using jQuery.
Matt Ball
A: 

Apart from the aforementioned jQuery solution (I however highly recommend to use it, it's great) here's the plain vanilla JS solution (as you didn't mention anything about jQuery in your question):

Edit: improved answer to match your actual problem:

// Add this to top of your script.
window.onload = function () {
    for (var i = 0; arguments.callee.functions.length > i; i++) {
        arguments.callee.functions[i]();
    }
};
window.onload.functions = [];

// Now for every onload function you want to add, do:
window.onload.functions.push(initComments('myID'));
BalusC
Geez, downvoters are triggerhappy again. I admit that jQuery is the way to go, but the OP didn't mention anything about it. Why is plain vanilla JS that *bad*?
BalusC
Now, you're hijacking the handler and Simile loses, right? Shouldn't he also store the value somewhere and call it from inside his handler?
Hanno Fietz
The down vote was for not answering the question. As Hanno pointed out, you're blocking one for the other.
Justin Johnson
Oh that way, OK I'll edit my answer soon.
BalusC
+1  A: 

Add in jQuery and use

$(document).ready(function(){
  // Your code here...
});

There are a couple of other ways to write this in jQuery, but I find this is the most explanatory.

If you're doing any kind of JavaScript development, you need to be looking at jQuery. It's totally sweet!

AndreasKnudsen
An entire library to solve an onload problem seems like too much.
dacracot
You don't *need* to be looking at jQuery. Don't get me wrong, I think it's a pretty sweet library, but depending on the project, it may or may not be the right choice.
Justin Johnson
I stand by my comment, if you do ANY javascript work AT ALL then you NEED to spend an hour checking out what jQuery gives you. I'm 95% confident that any javascript work more than 3 lines of code will hugely benefit from that framework. It's light and lean, and if you reference it from google code: http://jqueryjs.googlecode.com/files/jquery-1.3.1.min.js odds are 90% of your users will already have it so they won't even have to download it
AndreasKnudsen
+1  A: 

First off, as a general rule, you want to stay away from embedding JavaScript in your HTML as tag attributes.

Secondly, Simile is likely overwriting the onload (using it the same way you are). So, you'll want to add your onload event after you've included Simile.

Using jQuery:

<script src="/js/blah/simile.js" type="text/javascript"></script>
<script type="text/javascript">
    $(document).ready(function() {
        initComments('myID');
    });
</script>

Using no library (found here):

<script src="/js/blah/simile.js" type="text/javascript"></script>
<script type="text/javascript">
  function addOnloadEvent(fnc){
    if ( window.addEventListener ) {
      window.addEventListener( "load", fnc, false );
    } else if ( window.attachEvent ) {
      window.attachEvent( "onload", fnc );
    }
    else {
      var oldOnload = window.onload || function() {};
      window.onload = function(e) {
        oldOnload(e);
        window[fnc](e);
      };
    }
  }

  addOnloadEvent(function() { initComments('myID'); });
</script>
Justin Johnson
Isn't $(document).ready a jQuery construct?
dacracot
Yes it is. I've added a non-jquery solution.
Justin Johnson
Tried your "no library" solution and got a "initComments is not defined" error. I made sure my JS script which defines initComments was prior to the embedded script you provided.
dacracot
I've made some modifications. Give it another shot.
Justin Johnson
A: 

By hijacked, you mean, Simile loads after your code and overwrites onload? In that case, make sure you get behind it (as Justin says), and before you overwrite it yourself, store the value of onload somewhere, so it still gets called (from your own handler).

That is, if you don't use jQuery.

Hanno Fietz
A: 

If you look here you will see a solution that is what jQuery uses, I believe, or a modification of it, but it should work for your needs.

http://dean.edwards.name/weblog/2006/06/again/

// Dean Edwards/Matthias Miller/John Resig

function init() {
  // quit if this function has already been called
  if (arguments.callee.done) return;

  // flag this function so we don't do the same thing twice
  arguments.callee.done = true;

  // kill the timer
  if (_timer) clearInterval(_timer);

  // do stuff
};

/* for Mozilla/Opera9 */
if (document.addEventListener) {
  document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
  document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
  var script = document.getElementById("__ie_onload");
  script.onreadystatechange = function() {
    if (this.readyState == "complete") {
      init(); // call the onload handler
    }
  };
/*@end @*/

/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
  var _timer = setInterval(function() {
    if (/loaded|complete/.test(document.readyState)) {
      init(); // call the onload handler
    }
  }, 10);
}

/* for other browsers */
/*window.onload = init; */

You will see that the last line is commented out. In the event it gets that far either you will clobber them (uncomment) or your code won't run, but this will work for the major browsers.

James Black