/*

filename: core.js
purpose:  various core functionality for davesrecipes

*/

/* ************************************************************************* */
// EVENT HANDLING

/* ************************************************************************* */
// function to register event handler
//  @ obj = the object to attach event handler to
//  @ evt = the event to trap; WITHOUT "on"; ie: click / mouseover
//  @ fn = the function to call when event triggered
function add_event_simple(obj, evt, fn)
{
   if (obj.addEventListener)
      obj.addEventListener(evt, fn, false);
   else if (obj.attachEvent)
      obj.attachEvent('on'+evt, fn);
} // end FUNCTION

/* ************************************************************************* */
// function to deregister event handler
//  @ obj = the object to detach event handler from
//  @ evt = the event; WITHOUT "on"; ie: click / mouseover
//  @ fn = the function called when event triggered
function remove_event_simple(obj, evt, fn)
{
   if (obj.removeEventListener)
      obj.removeEventListener(evt, fn, false);
   else if (obj.detachEvent)
      obj.detachEvent('on'+evt, fn);
} // end FUNCTION

/* ************************************************************************* */
// DATA RETRIEVAL FRAMEWORK

var XMLHttpFactories = [
   function () { return new XMLHttpRequest() },
   function () { return new ActiveXObject('Msxml2.XMLHTTP') },
   function () { return new ActiveXObject('Msxml3.XMLHTTP') },
   function () { return new ActiveXObject('Microsoft.XMLHTTP') }
];

/* ************************************************************************* */
// function to initialise object
function createXMLHTTPObject()
{
   var xmlhttp = false;
   for (var i=0; i<XMLHttpFactories.length; i++)
   {
      try { xmlhttp = XMLHttpFactories[i](); }
      catch (e)   { continue; }
      break;
   }
   return xmlhttp;
} // end FUNCTION

/* ************************************************************************* */
// function to send request
function sendRequest(url,callback,postData)
{
   var req = createXMLHTTPObject();
   if (!req)
      return;
   var method = (postData) ? "POST" : "GET";
   req.open(method,url,true);
   req.setRequestHeader('User-Agent','XMLHTTP');
   if (postData)
      req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
   req.onreadystatechange = function () {
      if (req.readyState != 4) return;
//      if (req.status != 200 && req.status != 304)  { alert('HTTP Error '+req.status); return; }
      // execute callback function, if not null
      if (callback != null)
         callback(req);
   }
   if (req.readyState == 4) return;
   req.send(postData);
   return true;
} // end FUNCTION


/* ************************************************************************* */
// FIND POSITION OF OBJECTS FUNCTIONS 

/* ************************************************************************* */
// function to find position of object (x)
//  @ obj = object to find pos of
// returns object with properties x=left; y=top
function find_pos(obj)
{
	var pos = new Object();
	pos.x = 0;
	pos.y = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			pos.x += obj.offsetLeft;
			pos.y += obj.offsetTop;
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
	{
		pos.x += obj.x;
		pos.y += obj.y;
	}
	pos.top = pos.y;
	pos.left = pos.x;
	return pos;
} // end FUNCTION

/* ************************************************************************* */
// DRAG AND DROP MAGNETS

var drag_active = false;      // whether we're dragging
var drag_obj;                 // object we're dragging
var drag_offset;              // offset clicked INTO drag obj
var magnets = new Object();   // array containing all magnet ids we find: [magnet_id] = obj {x / y}
var magnetlist = '';          // , seperated list of magnet ids we want to fetch

var load_timer = false;       // timer that loads position of magnets
var save_timer = false;       // timer that saves position of magnets

// initialise
add_event_simple(window, "load", drag_init);
//drag_init();


/* ************************************************************************* */
// function to init drag/drop magnets
function drag_init()
{
   // look for divs with classname magnets
   var divs = document.getElementsByTagName("div");
   for (var i=0; i<divs.length; i++)
   {
      if (divs[i].className.search(/magnet/gi) != -1)
      {
         // now look for ANY spans (these are our magnets)
         var spans = divs[i].getElementsByTagName("span");
         for (var s=0; s<spans.length; s++)
         {
            // MUST have an id
            if (spans[s].id != '')
            {
               spans[s].onmousedown = drag_start;
               spans[s].style.cursor = 'move';
               spans[s].style.position = 'absolute';
               magnetlist += spans[s].id+'=1&';
            }
         }
      }
   }
   
   // set timer to initialise header in a bit - or NOW - depending on if immediate defined
   if (document.body.className.search(/immediate/gi) == -1)
      var temptimer = setTimeout(header_init, 2000);
   else
      header_init();
   
   // load magnet positions
   load_positions();

   return true;
} // end FUNCTION

/* ************************************************************************* */
// function to init header magnets (davesrecipes)
function header_init()
{
   // look for h1 with classname magnets
   var h1s = document.getElementsByTagName("h1");
   for (var i=0; i<h1s.length; i++)
   {
      if (h1s[i].className.search(/magnet/gi) != -1)
      {
         // now look for ANY spans (these are our magnets)
         var spans = h1s[i].getElementsByTagName("span");
         for (var s=0; s<spans.length; s++)
         {
            // MUST have an id
            if (spans[s].id != '')
            {
               spans[s].onmousedown = drag_start;
               spans[s].style.cursor = 'move';
               spans[s].style.position = 'absolute';
               magnetlist += spans[s].id+'=1&';
            }
         }
      }
   }

   return true;
} // end FUNCTION

/* ************************************************************************* */
// function to start drag/drop
//  @ e = event info
function drag_start(e)
{
   // fetch event and event target info (QUIRKSMODE)
   var targ;
   if (!e) var e = window.event;
   if (e.target) targ = e.target;
   else if (e.srcElement) targ = e.srcElement;
   if (targ.nodeType == 3) // defeat Safari bug
      targ = targ.parentNode;

   // we MUST have an ID
   if (!targ || targ.id == "")
      return true;

   // any existing drag?
   if (drag_obj)
      drag_finish();
   
   // set drag object
   drag_obj = targ;

   // set drag offset (offset clicked INTO object)
	var pos = new Object();
	if (e.pageX || e.pageY)
	{
		pos.x = e.pageX;
		pos.y = e.pageY;
	}
	else if (e.clientX || e.clientY)
	{
		pos.x = e.clientX + document.body.scrollLeft;
		pos.y = e.clientY + document.body.scrollTop;
	}
	
	// parent node
	var ppos = find_pos(drag_obj.parentNode);
	var opos = find_pos(drag_obj);

	// set offset
   drag_offset = new Object();
   drag_offset.x = ppos.x + (pos.x - opos.x);
   drag_offset.y = ppos.y + (pos.y - opos.y);

   drag_obj.style.top = (pos.y - drag_offset.y) + 'px';
   drag_obj.style.left = (pos.x - drag_offset.x) + 'px';

   // start drag
   document.onmousemove = drag_move;
   document.onmouseup = drag_finish;
   
   return true;
} // end FUNCTION

/* ************************************************************************* */
// function to carry out drag move
//  @ e = event info
function drag_move(e)
{
   // fetch event and event target info (QUIRKSMODE)
   var targ;
   if (!e) var e = window.event;
   if (e.target) targ = e.target;
   else if (e.srcElement) targ = e.srcElement;
   if (targ.nodeType == 3) // defeat Safari bug
      targ = targ.parentNode;

   // need drag object
   if (!drag_obj)
      return true;

   // get current pos
   var pos = new Object();
   pos.x = 0;
   pos.y = 0;
	if (e.pageX || e.pageY)
	{
		pos.x = e.pageX;
		pos.y = e.pageY;
	}
	else if (e.clientX || e.clientY)
	{
		pos.x = e.clientX + document.body.scrollLeft;
		pos.y = e.clientY + document.body.scrollTop;
	}

   // work out top / left
   var top = (pos.y - drag_offset.y);
   var left = (pos.x - drag_offset.x);
   // keep in fridge
   var container = document.getElementById("container");
   if (top < -30)
      top = -30;
   var maxh = container.offsetHeight - drag_obj.parentNode.offsetTop - drag_obj.offsetHeight;
   if (top > maxh)
      top = maxh;
   if (left < 0)
      left = 0;
   var maxw = container.offsetWidth - drag_obj.offsetWidth - 15;
   if (left > maxw)
      left = maxw;

   // place
   drag_obj.style.top = top + 'px';
   drag_obj.style.left = left + 'px';

   // stop event here
   if (e.stopPropogation)
      e.stopPropogation();
   e.cancelBubble = true;

   return false;
} // end FUNCTION

/* ************************************************************************* */
// function executed when draggable object is moved
function drag_finish()
{
   // cancel drag
   document.onmousemove = null;
   document.onmouseup = null;

   // store new position + fact we've moved it
   if (drag_obj)
   {
      drag_pos = find_pos(drag_obj);
      parent_pos = find_pos(drag_obj.parentNode);
      magnets[drag_obj.id] = { "x": (drag_pos.x - parent_pos.x), "y": (drag_pos.y - parent_pos.y) };
   }
   // set save timer; if not set
   if (!save_timer)
      save_timer = setTimeout(save_positions, 5);

   // unset drag object/vars ready for next time
   drag_obj = null;
   drag_offset = null;

   return true;
} // end FUNCTION

/* ************************************************************************* */
// function to save the location of any magnets on this page
function save_positions()
{
   // formulate requst
   var requestvars = '';
   for (var magnetid in magnets)
   {
      requestvars += magnetid+'='+magnets[magnetid].x+"|"+magnets[magnetid].y+'&';
   }

   // send data
   sendRequest('/save-positions.php', null, requestvars);

   // reset object to save
   magnets = new Object();

   save_timer = false;

   // set timer to load in a bit
//   magnet_timer = setTimeout(load_positions, 2000);

} // end FUNCTION

/* ************************************************************************* */
// function to load the location of any magnets on this page (from other's
//  changes)
function load_positions()
{
   // send request
   load_timer = false;
   sendRequest('/load-positions.php', positions_loaded, magnetlist);

} // end FUNCTION

/* ************************************************************************* */
// function to position magnets from loaded data
function positions_loaded(req)
{
   if (req.readyState == 4)
   {
      var positions = eval('(' + req.responseText + ')');
      for (var mangnetid in positions)
      {
         var magnet = document.getElementById(mangnetid);
         if (magnet)
         {
            magnet.style.left = positions[mangnetid].x+'px';
            magnet.style.top = positions[mangnetid].y+'px';
         }
      }
   }
   // set timer to load again soon
   if (load_timer == false)
      load_timer = setTimeout(load_positions, 5000);

} // end FUNCTION
