/*
  -------------------------------------------------------------------------------------------------

  : frame.js
  : ben miller : ben@hyl.co.uk : http://digital.hyl.co.uk

  : dynamic iframe into which content can be inserted programatically

  : requires
  : hyl_client/1_0/blank.html
  : hyl_client/1_0/util.js
  : hyl_client/1_0/util_dhtml.js

  -------------------------------------------------------------------------------------------------
*/
var hyl = hyl || {};
hyl.resourcePath = hyl.resourcePath || '/hyl_client/1_0/';

__hylFrame = [];
hylFrame_dragging = false;

/*
  params
  ------
  0 : parent document
  1 : id
  -------------------------------------------------------------------------------------------------
*/
hyl.Frame = function()
{
  this.index = __hylFrame.length;
  __hylFrame.push(this);

  this.parentDoc    = arguments[0] || document;
  this.frm          = this.parentDoc.createElement('IFRAME');
  this.frm.id       =
  this.frm.name     = arguments[1] || 'hylFrame_' + this.index;
  this.frm.src      = hyl.resourcePath + 'blank.html';
  this.href         =
  this.content      =
  this.relPos       = null; // tt, tb, bt, bb / rr, rl, lr, ll
  this.docType      =
  this.baseHref     =
  this.CSS          = null;
  this.shuntX       =
  this.shuntY       = 0;
  this.draggable    = false;
  this.appendToNode = this.parentDoc.body;

  this.dragHandle;
  this.frmMDStart   = { x:0, y:0 };
  this.frmPos       = { x:0, y:0 };
  this.frmDim       = { w:0, h:0 };
  this.parentWinDim = { w:0, h:0 };

  this.doc = function() { return (this.frm.contentDocument)?this.frm.contentDocument:this.parentDoc.frames[this.frm.name].document; };
  this.win = function() { return (this.frm.contentWindow)?this.frm.contentWindow:this.parentDoc.frames[this.frm.name]; }
}

/*
  should be called from or after page load event
  -------------------------------------------------------------------------------------------------
*/
hyl.Frame.prototype.load = function()
{
  this.appendToNode.appendChild(this.frm);
}

/*
  updates frame content
  -------------------------------------------------------------------------------------------------
*/
hyl.Frame.prototype.update = function()
{
  if(this.href != null)
  {
    this.doc().location.replace(this.href);
  }
  else
  {
    var _doc = this.doc();
    _doc.open('text/html');
    if(this.docType) { _doc.write(this.docType); }
    _doc.write('<html id="', this.frm.id, '"><head>');
    if(this.baseHref) { _doc.write('<base href="', this.baseHref, '" />'); }
    if(this.CSS) { _doc.write('<style type="text/css">', this.CSS, '</style>'); }
    _doc.write('</head><body>', this.content, '</body></html>');
    _doc.close();
  }
}

/*
  positions frame relative to named anchor element (anc)
  needs to be called after frame is displayed.
  -------------------------------------------------------------------------------------------------
*/
hyl.Frame.prototype.position = function(anc)
{
  if(this.relPos != null && this.relPos.length==4)
  {
    var ancH = anc.offsetHeight;
    var ancW = anc.offsetWidth;
    var ancOffsetPos = hyl.elOffset(anc);
    var ancT = ancOffsetPos.y;
    var ancL = ancOffsetPos.x;
    var frmH = this.frm.offsetHeight;
    var frmW = this.frm.offsetWidth;
    var frmT = frmL = 0;

    switch(this.relPos.substr(0, 2)) // vertical
    {
      case 'tt': frmT = ancT; break;
      case 'tb': frmT = ancT - frmH; break;
      case 'bt': frmT = ancT + ancH; break;
      case 'bb': frmT = ancT + ancH - frmH; break;
    }

    switch(this.relPos.substr(2, 2)) // horizontal
    {
      case 'll': frmL = ancL; break;
      case 'lr': frmL = ancL - frmW; break;
      case 'rl': frmL = ancL + ancW; break;
      case 'rr': frmL = ancL - frmW + ancW; break;
    }

    frmT += this.shuntX;
    frmL += this.shuntY;

    var parentWinDim = hyl.winDim(this.parentDoc);
    if(frmT + frmH > parentWinDim.h) { frmT = parentWinDim.h - frmH; }
    if(frmL + frmW > parentWinDim.w) { frmL = parentWinDim.w - frmW; }

    frmT = Math.max(frmT, 0);
    frmL = Math.max(frmL, 0);

    this.frm.style.top = frmT + 'px';
    this.frm.style.left = frmL + 'px';
  }
}

/*
  tries to resize iframe width and height to contents
  -------------------------------------------------------------------------------------------------
*/
hyl.Frame.prototype.autofit = function()
{
  var frmDim = hyl.winDim(this.doc());
  this.frm.style.width = frmDim.w + 'px';
  this.frm.style.height = frmDim.h + 'px';
}

/*
  registers frame's drag handle and adds event handlers
  -------------------------------------------------------------------------------------------------
*/
hyl.Frame.prototype.addDrag = function(_el)
{
  this.dragHandle = _el || this.doc();
  var _df = this;

  // start drag
  AEL(this.doc(), 'mousedown', function(e)
  {
    e = e || window.event;
    if(!_df.draggable || hyl.srcEl(e) != _df.dragHandle) return;

    _df.frmMDStart = hyl.ePos(e, _df.parentDoc);
    _df.parentWinDim = hyl.winDim(_df.parentDoc);
    _df.frmDim = { h:_df.frm.offsetHeight, w:_df.frm.offsetWidth };

    hylFrame_dragging = true;
  }, false);

  // drag
  AEL(this.doc(), 'mousemove', function(e)
  {
    if(!_df.draggable) return;

    if(hylFrame_dragging)
    {
      var pos = hyl.ePos(e || window.event, _df.parentDoc);

      var x = parseInt(_df.frm.style.left) - 0 + pos.x - _df.frmMDStart.x;
      var y = parseInt(_df.frm.style.top) - 0 + pos.y - _df.frmMDStart.y;

      _df.frm.style.left = ((x < 0) ? 0 : (x + _df.frmDim.w > _df.parentWinDim.w) ? _df.parentWinDim.w - _df.frmDim.w : x) + 'px';
      _df.frm.style.top  = ((y < 0) ? 0 : (y + _df.frmDim.h > _df.parentWinDim.h) ? _df.parentWinDim.h - _df.frmDim.h : y) + 'px';

      if(document.selection && document.selection.type != 'none')
      {
        document.selection.empty();
      }
    }
  }, false);

  // end drag
  AEL(this.doc(), 'mouseup', function()
  {
    hylFrame_dragging = false;
  }, false);
}

/*
  enables frame resizing
  -------------------------------------------------------------------------------------------------
*/
hyl.Frame.prototype.addResize = function()
{
  this.frmPos = hyl.elOffset(this.frm);
  this.frmDim = { h:this.frm.offsetHeight, w:this.frm.offsetWidth };

  var _df = this;
  // start resize
  AEL(this.parentDoc, 'mousedown', function(e)
  {
    if(!_df.resizeSE){ return; }
    hylFrame_dragging = true;
    _df.frmPos = hyl.elOffset(_df.frm);
    _df.frmMDStart = hyl.ePos(e, _df.parentDoc);
  }, false);

  // resize in iframe
  AEL(this.doc(), 'mousemove', function(e)
  {
    if(hylFrame_dragging)
    {
      var pos = hyl.ePos(e || window.event);

      _df.frm.style.width = ((pos.x < 20) ? 20 : pos.x) + 'px';
      _df.frm.style.height = ((pos.y < 20) ? 20 : pos.y) + 'px';
    }
  }, false);

  // resize in parent doc
  AEL(this.parentDoc, 'mousemove', function(e)
  {
    e = e || window.event;
    _df.frmPos = hyl.elOffset(_df.frm);
    var pos = hyl.ePos(e, _df.parentDoc);
    var r = _df.frmPos.x + _df.frm.offsetWidth -5;
    var b = _df.frmPos.y + _df.frm.offsetHeight -5;

    if(pos.x > r && pos.x < r+10 && pos.y > b && pos.y < b+10)
    {
      _df.resizeSE = true;
      hyl.srcEl(e).style.cursor = 'se-resize';
    }
    else
    {
      _df.resizeSE = false;
      hyl.srcEl(e).style.cursor = 'default';
    }

    if(hylFrame_dragging)
    {
      _df.frm.style.width = ((pos.x - _df.frmPos.x < 20) ? 20 : pos.x - _df.frmPos.x) + 'px';
      _df.frm.style.height = ((pos.y - _df.frmPos.y < 20) ? 20 : pos.y - _df.frmPos.y) + 'px';

      if(document.selection && document.selection.type != 'none')
      {
        _df.parentDoc.selection.empty();
      }
    }
  }, false);

  // end resize
  AEL(this.doc(), 'mouseup', function() { hylFrame_dragging = false; }, false);
  AEL(this.parentDoc, 'mouseup', function() { hylFrame_dragging = false; }, false);
}

