(function() {

//only load once
if(typeof tableau != "undefined") return;

var debug = false;

var serverRoot = function() {
  var scriptEls = document.getElementsByTagName('script');
  var e = scriptEls[scriptEls.length - 1];
  var r = /.*?[^/:]\//.exec(e.src);
  if (!r || r.toString().indexOf('http://') == -1 )
    r = /.*?[^/:]\//.exec(window.location.href);
  return r;
}();

var tableauGCS = function(e, p) {
  if (window.getComputedStyle)
    return window.getComputedStyle(e, p);
  else
    return e.currentStyle;
};

var filterFromOpts = function(opts)
{
    var url = '';
    
    for(var f=0; f<opts['filter'].length; ++f) {
      url += '&' + opts['filter'][f];
    }

    return url;
};

var urlFromOpts = function(name, opts)
{
    var url = serverRoot;
    url += 'views/' + name;
    url += '?:embed=y';
    
    // any option not named a few special ones are appended to the URL
    for(var p in opts) {
      if( p != 'load-order' && p != 'width' && p != 'height' && p != 'embed' && p != 'filter' ) {
        url += '&:' + p + '=' + opts[p];
      }
    }

    return url;
};

tableau = {

Viz: function(name, node, opts) {
  this._name       = name;
  this._node       = node;
  this._filterArgs = '';
  this._filterOpts = filterFromOpts(opts);
  this._baseUrl    = urlFromOpts(this._name, opts);
  this._loadOrder  = opts['load-order'] ? opts['load-order'] : 0;
  this._filter     = {};
},

// an array which holds the vizs on this page, the array is ordered
// from top to bottom on the page.
vizs: [], 

createViz: function(name, refnode, opts) {
    var attrs = refnode.attributes;
    var elType = (debug) ? 'DIV' : 'IFRAME';
    var ifr = document.createElement(elType);
    ifr.frameBorder = '0';
    ifr.marginHeight = '0';
    ifr.marginWidth = '0';
    //copy the attributes from the object to the iframe
    for (var j = 0; j < attrs.length; ++j)
    {
      if (!attrs[j].specified) continue;
      ifr.setAttribute(attrs[j].name, attrs[j].value);
    }
    //IE doesn't seem to carry the style through the 'attributes' collection
    //so set it here manually 
    ifr.style.cssText = refnode.style.cssText;

    if (debug)
    {
        var dbgTxt = "src=" + urlFromOpts(name, opts); + filterFromOpts(opts) + "<br>";
        dbgTxt += "<ul>";
        for(var p in opts)
          dbgTxt += "<li>" + p + "=" + opts[p];
        dbgTxt += "</ul>";
        ifr.style.overflow = 'auto';
        ifr.innerHTML = dbgTxt;
    }


    refnode.parentNode.replaceChild(ifr, refnode);
    var v = new tableau.Viz(name, ifr, opts);
    // must show it as soon as its created since a properly specified object
    // is initially hidden
    v.show();
    vizs_loadOrder.push(this.vizs.length);
    this.vizs.push(v);
    this.vizs[name] = v;

    if( !window.postMessage ) {
      // only use these methods if postMessage isn't available
      if( navigator.userAgent.indexOf("MSIE") > -1 && !window.opera ){
        ifr.onreadystatechange = checkForDone1;
      } else {
        ifr.onload = checkForDone1;
      }
    }
}

};

// load the original viz as it was defined in the object
tableau.Viz.prototype.load = function()
{
  this._node.src = this._baseUrl + this._filterOpts;
};
tableau.Viz.prototype.show = function()
{
  this._node.style.display = '';
};

tableau.Viz.prototype.hide = function()
{
  this._node.style.display = 'none';
};

tableau.Viz.prototype.refresh = function()
{
  this._node.src = this._baseUrl + this._filterOpts + this._filterArgs + '&:refresh=true';
};

// load the viz without any filters at all
tableau.Viz.prototype.revert = function()
{
  this._node.src = this._baseUrl + '&:revert=all';
  this._filterArgs = '';
  this._filter   = {};
};

tableau.Viz.prototype.filter = function(filt)
{
  if( filt == null ) {
    this.revert();
    return;
  }

  for(var p in filt) {
    this._filter[p] = filt[p];
  }

  this._filterArgs = '';
  for(var p in filt) {
    this._filterArgs += "&" + encodeURIComponent(p) + "=";

    if( typeof(filt[p]) == "string" ) {
      this._filterArgs += encodeURIComponent(filt[p]);
    } else {
      this._filterArgs += encodeURIComponent(filt[p].join(','));
    }
  }

  this._node.src = this._baseUrl + this._filterOpts + this._filterArgs;
};

var sortVizs = function(a, b)
{
  var viza = tableau.vizs[a]._loadOrder;
  var vizb = tableau.vizs[b]._loadOrder;

  if( viza < vizb ) {
    return -1;
  } else if( viza == vizb ) {
    return 0;
  } else {
    return 1;
  }
};

// an array which holds the indexes of the vizs sorted in loadOrder
var vizs_loadOrder = [];

var loadIndex = 0;

var checkForDone2 = function()
{
  if( navigator.userAgent.indexOf("MSIE") > -1 && !window.opera ){
    var viz = tableau.vizs[vizs_loadOrder[loadIndex]];

    if( viz && viz._node.readyState == 'complete' ) {
      loadIndex++;
      loadNextViz();
    }
  } else {
    loadIndex++;
    loadNextViz();
  }
};

var checkForDone1 = function()
{
  setTimeout(checkForDone2, 3000);
};

var loadNextViz = function()
{
  var viz = tableau.vizs[vizs_loadOrder[loadIndex]];

  if( viz ) {
     viz.load();
  }
};

function _onMessage(e)
{
  if( e.data == 'completed' ) {
    loadIndex++;
    loadNextViz();
  }
};

function _initViews()
{
  var els = document.getElementsByTagName('object');
  var elsNew = [];
 
  // find all object tags in the document and collect their associated information 
  for (var i = 0; i < els.length; ++i)
  {
    var e = els[i];
    if ((' ' + e.className + ' ').indexOf(' tableauViz ') == -1)
      continue;
    var params = {};
    var children = e.childNodes;
    var viewName = "";

    params['filter'] = [];

    for (var j = 0; j < children.length; ++j)
    {
      if (children[j].nodeType == 1 &&
          children[j].tagName == 'PARAM' &&
          children[j].name)
      {
        var name = children[j].name;
        var value = children[j].value ? children[j].value : null;

        if (name == 'name') {
          viewName = value;
        } else if( name == 'filter' ) {
          params['filter'].push(value);
        } else {
          params[name] = value;
        }
      }
    }
    params.width = parseInt(tableauGCS(e,null).width);
    if (params.width == Number.NaN)
      delete params.width;
    params.height = parseInt(tableauGCS(e,null).height);
    if (params.height == Number.NaN)
      delete params.height;

    elsNew.push({n: viewName, r: e, p: params});
  }
  
  //for each object tag, instantiate a viz object
  for (var i = 0; i < elsNew.length; ++i) {
    tableau.createViz(elsNew[i].n, elsNew[i].r, elsNew[i].p);
  }

  // load'em up!
  vizs_loadOrder.sort(sortVizs);
  loadNextViz();
};

if (window.addEventListener)
{
  window.addEventListener("load", _initViews, false);
  window.addEventListener("message", _onMessage, false);
}
else if (window.attachEvent)
{
  window.attachEvent("onload", _initViews);
  window.attachEvent("onmessage", _onMessage);
}
else
{
  window.onload = _initViews;
  window.onmessage = _onMessage;
}

})();

