﻿var stack = [],
    interval,
    loaded; // has DOMContentLoaded or window.onload fired

// does the element or one of it's ancestors have a nextSibling?
function hasNextSibling(el) {
  return el.nextSibling ||
         (el.parentNode && hasNextSibling(el.parentNode));
}

function doPoll() {
  var notFound = [];
  for (var i=0; i<stack.length; i++) {
    var el = document.getElementById(stack[i].id);
    
    if (el && (hasNextSibling(el) || loaded)) {
      stack[i].callback();
    } else {
      notFound.push(stack[i]);
    }
  }
  stack = notFound;
  if (notFound.length < 1 || loaded) {
    stopPolling();
  }
}

function startPolling() {
  if (interval) {return;}
  interval = setInterval(doPoll, 10);
}

function stopPolling() {
  if (!interval) {return;}
  clearInterval(interval);
  interval = null;
}

function onContentAvailable(id, callback) {
  stack.push({id:id, callback:callback});  
  startPolling();
}

function lastPoll() {
  if (loaded) {return;}
  loaded = true;
  doPoll();
}

// Force one poll immediately when the document DOMContentLoaded event fires.
// This may be sooner than the next schedualed poll.
// Can't add this listener in at least Firefox 2 through DOM0 property assignment.
if (document.addEventListener) {
  document.addEventListener('DOMContentLoaded', lastPoll, false);
} else if (document.attachEvent) {
  // optimistic that one day Internet Explorer will support this event
  document.attachEvent('onDOMContentLoaded', lastPoll);
}

// Force one poll immediately when window.onload fires. For some pages if
// the brower doesn't support DOMContentLoaded the window.onload event
// may be sooner than the next schedualed poll.
window.onload = lastPoll;