/*
  -------------------------------------------------------------------------------------------------

  : popframe.js
  : ben miller : ben@hyl.co.uk : http://digital.hyl.co.uk
  : 28 October 2004

  - collection methods plus constructor for creating a dynamic iframe into which content can be
    inserted programatically.
    as it's an iframe it won't be obscured by dropdowns, other frames and objects.

  - usage:
    create new popframe:
      var foo = new PopFrame('fooey');
      foo.content = '<div>hello</div>';
    insert content after page load:
      foo.content = '<p>goodbye</p>';
      foo.content += '<p>cruel world</p>';
      foo.Update();
    toggle visibility
      <span onclick="__getPopFrame('fooey').ToggleVisibility(this, event);">toggle frame</span>

  - required files:
    utils.js

  -------------------------------------------------------------------------------------------------
*/

/*
  -- PopFrame Collection methods ------------------------------------------------------------------
*/

var __aPopFrames = [];

/*
  -- __getPopFrame
  - returns popframe with id of parameter _id
*/
function __getPopFrame(_id)
{
  for(var i=0;i<__aPopFrames.length;i++)
  {
    if(__aPopFrames[i].id==_id)
    {
      return __aPopFrames[i];
    }
  }
  return false;
}

/*
  -- PopFrame Constructor -------------------------------------------------------------------------
*/
function PopFrame(_id)
{
  if(arguments.length>0){ this.Init(_id); }
}

//
// initialise
//
PopFrame.prototype.Init = function(_id)
{
  this.index = __aPopFrames.length;
  __aPopFrames.push(this);
  this.id = _id || 'popframe_'+this.index;

  this.content = '';
  this.shuntX = 0;
  this.shuntY = 0;
  this.width;
  this.height;
  this.stylesheet;
  this.relPos;
  this.visible = false;
  this.positioned = true;
  this.alwaysOnTop = true;
  this.autoResize = false;

  // load frame initially with blank page from this domain.
  // this seems to satisfy the security requirements of the tested browsers
  document.write('<iframe id="', this.id, '" name="', this.id, '" src="/hyl_client/blank.html" style="display:none;"></iframe>');
  this.frame = document.getElementById(this.id);

  this.frameDoc = function(){ return (this.frame.contentDocument)?this.frame.contentDocument:document.frames[this.frame.name].document; }
  this.frameWin = function(){ return (this.frame.contentWindow)?this.frame.contentWindow:document.frames[this.frame.name]; }
}

//
// called after page load
//
PopFrame.prototype.Load = function()
{
  this.frame.style.display = this.visible?'block':'none';
  if(this.alwaysOnTop) { this.frame.style.zIndex = 100; } // TODO: more reliable way
  if(this.width) { this.frame.style.width = this.width; }
  if(this.height) { this.frame.style.height = this.height; }
  this.frame.style.position = (this.positioned)?'absolute':'relative';
  this.frame.style.border = this.frame.style.margin = this.frame.style.padding = 0;

  if(this.autoResize)
  {
    var frm = this.frame;
    AEL(frm, 'load', function()
    {
      if(frm.contentDocument && frm.contentDocument.body.offsetHeight)
      {
        frm.height = frm.contentDocument.body.offsetHeight;
      }
      else if(frm.document && frm.document.body.scrollHeight)
      {
        frm.height = frm.document.body.scrollHeight;
      }
    }, false);
  }

  this.Update();
}

//
// update frame content
//
PopFrame.prototype.Update = function(_src)
{
  // a parameter to this method indicates that an external file is to be loaded
  if(_src)
  {
    this.frame.src = _src;
  }
  else
  {
    this.frameWin().focus();

    var frameDoc = this.frameDoc();
    frameDoc.open('text/html');
    frameDoc.write('<html><head>');
    frameDoc.write('<style type="text/css" media="all">', this.stylesheet, '</style>');
    frameDoc.write('</head><body>', this.content, '</body></html>');
    frameDoc.close();
  }
}

//
// toogle frame visibility
//
PopFrame.prototype.ToggleVisibility = function(sender, ev)
{
  if(this.frame.style.display=='none')
  {
    this.Display();

    safeStopPropagation(ev);

    if(this.positioned)
    {
      if((!isUndefined(this.relPos))&&(this.relPos.length==4))
      {
        var sdrH = sender.offsetHeight;
        var sdrW = sender.offsetWidth;
        var sdrT = sender.offsetTop + sender.offsetParent.offsetTop;
        var sdrL = sender.offsetLeft + sender.offsetParent.offsetLeft;
        var frmH = this.frame.offsetHeight;
        var frmW = this.frame.offsetWidth;
        var frmT = 0;
        var frmL = 0;

        switch(this.relPos.substr(0,1)) // sender vertical
        {
          case 't': frmT = sdrT; break;
          case 'm': frmT = sdrT + (sdrH / 2); break;
          case 'b': frmT = sdrT + sdrH; break;
          default : throw new Error('relPos char 1 \''+ this.relPos.substr(0,1) +'\' must be \'t\', \'m\' or \'b\'');
        }
        switch(this.relPos.substr(1,1)) // frame vertical
        {
          case 't': break;
          case 'm': frmT -= (frmH / 2); break;
          case 'b': frmT -= frmH; break;
          default : throw new Error('relPos char 2 \''+ this.relPos.substr(1,1) +'\' must be \'t\', \'m\' or \'b\'');
        }


        switch(this.relPos.substr(2,1)) // sender horizontal
        {
          case 'l': frmL = sdrL; break;
          case 'c': frmL = sdrL + (sdrW / 2); break;
          case 'r': frmL = sdrL + sdrW; break;
          default : throw new Error('relPos char 3 \''+ this.relPos.substr(2,1) +'\' must be \'l\', \'c\' or \'r\'');
        }
        switch(this.relPos.substr(3,1)) // frame horizontal
        {
          case 'l': break;
          case 'c': frmL -= (frmW / 2); break;
          case 'r': frmL -= frmW; break;
          default : throw new Error('relPos char 4 \''+ this.relPos.substr(3,1) +'\' must be \'l\', \'c\' or \'r\'');
        }

        this.frame.style.top = frmT + this.shuntX + 'px';
        this.frame.style.left = frmL + this.shuntY + 'px';
      }
      else
      {
        this.frame.style.top = this.shuntX + 'px';
        this.frame.style.left = this.shuntY + 'px';
      }
    }
  }
}

//
// hide frame
//
PopFrame.prototype.Hide = function()
{
  this.frame.style.display = 'none';
}

//
// display frame
//
PopFrame.prototype.Display = function()
{
  this.frame.style.display = 'block';
}
