/*
 *  popover dialogs © 2008-2010, Horus Web Engineering Ltd
 *
 *  $Id: popover.js,v 1.26 2010-09-09 15:44:46 horus Exp $
 *
 *  licensed under the terms of the GNU Lesser General Public License:
 *    http://www.opensource.org/licenses/lgpl-license.php
 *
 *  needs horus.js, dom.js
 *  uses xmlhttp.js, status.js if go/nogo are used
 *
 */

horus.script.load('dom');


horus.popover=
  function ( popover, options ) {
    popover=horus.getElement(popover);
    horus.popover.options(popover, options);

    if (popover.$moveable) {
      horus.insertChild(popover);

      if (!popover.$mover) {
	popover.$mover=horus.getTags.find(popover, '.titlebar');
	popover.$mover=popover.$mover.isEmpty() ? popover : popover.$mover[0];
	popover.$mover.onmousedown=horus.popover.mover;
      }
    }

    if (popover.$height) popover.style.height=horus.sizeValue(popover.$height);

    if (popover.$width)
      popover.style.width=horus.sizeValue(popover.$width);
    else if (horus.brokenDOM)
      popover.style.width=(horus.windowSize().width>>1)+'px';

    var windowsize=horus.windowPos();
    var maxtop=windowsize.bottom-popover.offsetHeight-4;
    var maxleft=windowsize.right-popover.offsetWidth-4;

    var position=popover.$reference ?
      horus.getPosition(popover.$reference) :
      { top: horus.scrollv(), left: horus.scrollh() };

    position.top+=popover.$y;
    position.left+=popover.$x;
    if (position.top>maxtop) position.top=maxtop;
    if (position.left>maxleft) position.left=maxleft;
    popover.style.top=position.top+'px';
    popover.style.left=position.left+'px';
    popover.style.visibility='visible';
    popover.onkeyup=horus.popover.key;
    popover.onmouseover=horus.popover.raise;
    popover.$form=horus.firstTag(popover, 'form');

    if (horus.brokenDOM && popover.$form) {
      if (horus.ieold) popover.$form.style.width=popover.$form.offsetWidth;
      popover.$form.style.height='100%';
    }

    if (popover.$focus) {
      if (typeof popover.$focus=='boolean') {
	popover.$focus=horus.searchTag(popover, false, horus.getTags.input);

	if (popover.$focus && horus.hasClass(popover.$focus, 'closebox')) {
	  var node=horus.searchTag(popover, false, horus.getTags.input, '.closebox');
	  if (node) popover.$focus=node;
	}
      } else if (typeof popover.$focus=='string')
	popover.$focus=document.getElementById(popover.$focus);

      if (popover.$focus) horus.focus(popover.$focus);
    }

    horus.popover.$pending=popover;
    horus.popover.restack();
    return popover;
  };


horus.popover.options=
  function ( popover, options ) {
    popover=horus.getElement(popover);

    for (var key in horus.popover.options.defaults)
      popover['$'+key]=horus.popover.options.defaults[key];

    if (options!=null)
      switch (typeof options) {

      case 'string':  popover.$reference=options; break;
      case 'number':  popover.$y=options;         break;
      case 'boolean': popover.$moveable=options;  break;

      case 'object':
        if (horus.isElement(options))
	  popover.$reference=options;
	else
	  for (key in options)
	    if (key in horus.popover.options.defaults) popover['$'+key]=options[key];


      }

    if (popover.$reference) popover.$reference=horus.getElement(popover.$reference);
  };


horus.popover.options.defaults=
  { reference:   null,
    y:           20,
    x:           80,
    height:      null,
    width:       null,
    moveable:    false,
    focus:       true,
    escape:      true,
    method:      null,
    action:      null,
    callback:    null,
    params:      false,
    formparams:  false,
    ajaxoptions: null };


horus.popover.create=
  function ( id, createoptions, displayoptions ) {
    var node=horus.getElement(id, true);

    if (!node) {
      if (!createoptions) createoptions={};
      var formname=createoptions.formname || 'popoverform'+document.forms.length;
      var title=createoptions.title || 'Please Confirm';
      var content=createoptions.content || '';
      var yesclass=createoptions.yesclass || 'del';
      var yeslabel=createoptions.yeslabel || 'yes';
      var noclass=createoptions.noclass || 'reset';
      var nolabel=createoptions.nolabel || 'no';
      var contentclass=createoptions.contentclass;

      if (contentclass && horus.isString(contentclass) && !/^\./.test(contentclass))
	contentclass={ classname: contentclass };

      node=horus.insertChild(document.body, [ 'div', '.popover' ]);
      node.$form=horus.appendChild(node, [ 'form', { name: formname } ]);
      node.$title=horus.appendChild(node.$form, [ 'h2', null, title ]);
      node.$content=horus.appendChild(node.$form, [ 'div', contentclass ]);
      if (content) horus.appendChild(node.$content, content);

      horus.appendChild
	(node.$form,
         [ 'div', '.endbutton',
	   [ 'input',
	     { type: 'button', classname: yesclass+' small button', value: yeslabel,
	       onclick: horus.popover.go } ], ' ',
	   [ 'input',
	     { type: 'button', classname: noclass+' small button', value: nolabel,
	       onclick: horus.popover.nogo } ] ]);

    }

    if (displayoptions!=null) node=horus.popover(node, displayoptions);
    return node;
  };


horus.popover.raise=
  function ( event ) {
    var target=new horus.event(event).control('.popover');

    if (target && horus.popover.$pending!=target) {
      horus.popover.$pending=target;
      setTimeout(horus.popover.restack, 400);
    }
  };


horus.popover.$restacking=0;


horus.popover.restack=
  function () {
    if (++horus.popover.$restacking==1) {
      var target=horus.popover.$pending;
      horus.popover.$pending=null;

      if (target && horus.popover.$raised!=target) {
	if (horus.popover.$raised) {
	  if (target.$over) target.$over.$under=target.$under;

	  if (target.$under) {
	    target.$under.$over=target.$over;

	    while (target.$under) {
	      target.$under.style.zIndex=Number(target.$under.style.zIndex)-1;
	      target.$under=target.$under.$under;
	    }
	  }

	  horus.popover.$raised.$under=target;
	  target.$over=horus.popover.$raised;
	  target.style.zIndex=Number(horus.popover.$raised.style.zIndex)+1;
	} else
	  target.style.zIndex=20001;

	horus.popover.$raised=target;
      }
    }

    horus.popover.$restacking--;
    if (horus.popover.$pending) setTimeout(horus.popover.restack, 100);
  };


horus.popover.key=
  function ( event ) {
    event=new horus.event(event);
    var target=event.target;

    switch (event.keyCode) {

    case 27:
      var onescape=horus.popover.get(target).$escape;

      if (onescape)
	switch (typeof onescape) {

	case 'boolean':  horus.popover.nogo(event); break;
	case 'function': onescape(event); break;
	case 'string':   document.getElementById(onescape).onclick(event); break;
	case 'object':   onescape.onclick(event); break;

	}

      break;

    case 37:
      if (horus.checkTag(target, 'input:type=button=submit,button')) {
	target=horus.previousTag(event.target, horus.getTags.input);
	if (target) horus.focus(target);
      }

      break;

    case 39:
      if (horus.checkTag(target, 'input:type=button=submit,button')) {
	target=horus.nextTag(event.target, horus.getTags.input);
	if (target) horus.focus(target);
      }

      break;

    }

    return true;
  };


horus.popover.mover=
  function ( event ) {
    event=new horus.event(event);
    var popover=event.control('.popover');
    if (!popover.$moveable) return;
    popover.top=popover.offsetTop;
    popover.left=popover.offsetLeft;
    popover.$ey=event.y;
    popover.$ex=event.x;
    if (horus.popover.$moving) horus.popover.endmove();
    horus.popover.$moving=popover;
    horus.eventListener(document.body, 'mousemove', horus.popover.move);
    horus.eventListener(document.body, 'mouseup', horus.popover.endmove);
    horus.eventListener(document.body, 'selectstart', horus.popover.skip);
    horus.eventListener(document.body, 'dragstart', horus.popover.skip);
    popover.$mover.style.cursor='move';
  };


horus.popover.move=
  function ( event ) {
    var popover=horus.popover.$moving;
    if (!popover) return;
    event=new horus.event(event);
    var dy=event.y-popover.$ey;
    var dx=event.x-popover.$ex;
    if (dy*dy<9 && dx*dx<9) return;
    popover.style.top=(popover.top+=dy)+'px';
    popover.style.left=(popover.left+=dx)+'px';
    popover.$ey=event.y;
    popover.$ex=event.x;
    return false;
  };


horus.popover.endmove=
  function () {
    var popover=horus.popover.$moving;
    if (!popover) return;
    popover.$mover.style.cursor=null;
    horus.removeListener(document.body, 'dragstart', horus.popover.skip);
    horus.removeListener(document.body, 'selectstart', horus.popover.skip);
    horus.removeListener(document.body, 'mouseup', horus.popover.endmove);
    horus.removeListener(document.body, 'mousemove', horus.popover.move);
    horus.popover.$moving=false;
  };


horus.popover.skip=function () { return false };


horus.popover.hide=
  function ( popover ) {
    popover=horus.getElement(popover);

    if (!horus.hasClass(popover, 'popover'))
      popover=horus.parentTag(popover, 'div.popover');

    horus.visibility(popover, false);
    if (popover.$reference) horus.focus(popover.$reference);
    return popover.$params;
  };


horus.popover.get=
  function ( popover ) {
    if (!horus.isElement(popover)) {
      if (!(popover instanceof horus.event)) popover=new horus.event(popover);
      popover=popover.target;
    }

    if (!horus.hasClass(popover, 'popover'))
      popover=horus.parentTag(popover, 'div.popover');

    return popover;
  };


horus.popover.go=
  function ( popover, params, method, action, callback, ajaxoptions ) {
    var direct=!horus.isElement(popover);
    popover=horus.popover.get(popover);
    var async;

    if (direct || !params)
      params=popover.$params;
    else if (popover.$params)
      for (var tag in popover.$params)
	if (!(tag in params)) params[tag]=popover.$params[tag];

    if (popover.$form && popover.$formparams) {
      if (!params) params={};

      for (var i=0; i<popover.$form.elements.length; i++) {
	var field=popover.$form.elements[i];
	if (field.name) params[field.name]=horus.getvar(field);
      }
    }

    if (direct || method==null) method=popover.$method;
    if (direct || action==null) action=popover.$action;
    if (direct || callback==null) callback=popover.$callback;

    if (callback)
      if (callback instanceof Array)
	callback.push(params, popover);
      else
	callback=[ callback, params, popover ];

    var response;

    if (typeof method=='function' || action && typeof action=='object') {
      if (!action) action=window;
      if (typeof method!='function') method=action[method];
      response=method.call(action, params);
    } else {
      if (direct || ajaxoptions==null) ajaxoptions=popover.$ajaxoptions;

      if (callback) {
	async=true;
	horus.ajax(action, method, params, callback, ajaxoptions);
      } else
	response=horus.ajax(action, method, params, null, ajaxoptions);

    }

    if (!async)
      if (callback)
	horus.call(callback, response, null);
      else if (response || response==null)
	horus.popover.hide(popover);

    return false;
  };


horus.popover.nogo=
  function ( popover ) {
    popover=horus.popover.get(popover);
    var callback=popover.$callback;

    if (callback) 
      horus.call(callback, false, [ popover.$params, popover ]);
    else {
      horus.popover.hide(popover);
      horus.status.clear();
    }
  };


horus.script.loaded('popover');
