
// *** detect browser capabilities ********************************************

var rendertype = 'legacy';
if (window.opera) {
  rendertype = 'normal';
}
else if (document.getElementById && !document.all) {
  rendertype = 'normal';
}
else if (document.getElementById) {
  rendertype = 'ie';
}

var noajax = true;
if (window.XMLHttpRequest) {
  noajax = false;
}
else if (window.ActiveXObject) {
  try {
    tmp = new ActiveXObject("Msxml2.XMLHTTP");
  }
  catch (e) {
    noajax = true;
  }
  if (!tmp) {
    noajax = true;
  }
}

if (smallscreen == undefined) {
  var smallscreen = false;
}

if (mygroceries_hash == undefined) {
  var mygroceries_hash = '';
}

// *** various actions ********************************************************

function processLogin () {
  // hide from old browsers
  if (formPass()) { return; }
  
  // check if list name is provided
  if (getValue('frm_txt_name') == '') {
    raiseError('Please enter list name');
    return;
  }

  // get data
  nme = getValue('frm_txt_name');
  pas = getValue('frm_txt_pass');
  
  // check for errors
  if (nme.match(/[\<\>!#\$%^&\*,]+/i)) {
    raiseError('That\'s not what an email address looks like!');
    return;
  }
  else if (nme.length > 50) {
    raiseError('List name must not be longer than 30 characters');
    return;
  }
  else if (pas.length > 30) {
    raiseError('Password must not be longer than 30 characters');
    return;
  }
  
  
  // hide all messages
  hideError();
  hideAction();
  
  // show progress
//  fadeOut('login_form');
//  fadeIn('login_wait');
  
  // send request
  var url = '';
  url += 'name=' + urlEncode(nme);
  url += '&pass=' + urlEncode(pas);
 // if (isChecked('frm_chk_remember')) {
 //   url += '&remember=y';
 // }
 // if (isChecked('frm_chk_default')) {
 //   url += '&default=y';
 // }
  sendRequest('openlist',  url, 'processLoginResult');
}

function processLoginResult (error, response) {
  if (error) {
    fadeOut('login_wait');
    fadeIn('login_form');
  }
  else {
    nme = getElementValue(xml, 'name');
    if (response == 'open') {
      raiseAction('List [' + nme + '] was successfully opened. Redirecting...');
    }
    else if (response == 'create') {
      raiseAction('List [' + nme + '] was successfully created. Redirecting...');
    }
    // redirect to list
    redirectUrl('/' + nme + '/');
  }
}

function generalResult (error, response) {
  // nothing
}

function selectList () {
  redirectUrl('/' + getSelected('frm_sel_list') + '/');
}

// *** list manipulation tools ************************************************

var refresh_timeout = null;

function showTools (oid) {
  obj = getMyObject(oid);
  obj.className = 'item_hover';
  showId('item_tools_' + oid);
}

function hideTools (oid) {
  obj = getMyObject(oid);
  obj.className = 'item';
  if (!smallscreen) {
    hideId('item_tools_' + oid);
  }
  // hideId('item_tools_up_' + oid);
  // hideId('item_tools_down_' + oid);
}

function purgeList () {
  if (formPass()) { return; }
  if (confirm('Are you sure you want to delete all items?')) {
    sendRequest('purgeitems',  '', 'purgeListResult');
  }
}

function purgeListResult (error, response) {
  if (!error) {
    setTimeout('refreshItemList();', 500);
  }
}

function sendList () {
  if (formPass()) { return; }
  eml = trim(getValue('frm_txt_email'));
  msg = trim(getValue('frm_txt_message'));
  sendRequest('sendlist', 'email=' + urlEncode(eml) + '&message=' + urlEncode(msg), 'sendListResult');
}

function sendListResult (error, response) {
  if (!error) {
    hideId('send_form');
    showId('send_form_intro');
  }
}

function refreshItemList () {
  if (formPass()) { return; }
  
  if (isDragging()) {
    // no list manipulations when dragging - it's dangerous :)
    return;
  }
  
  // clear timeout so two processes no overlap
  if (refresh_timeout > 0) {
    clearTimeout(refresh_timeout);
  }
  
  // get up to date item list
  sendRequest('getitems',  '', 'refreshItemListResult');
}

function refreshItemListResult (error, response) {
  if (isDragging()) {
    // no list manipulations when dragging - it's dangerous :)
    return;
  }
  
  if (!error) {
    new_items = xml.getElementsByTagName('item');
    holder = getMyObject('items');
    
    // get current items
    cur_items = new Array();
    cnt = holder.childNodes.length;
    c = 0;
    for (i = 0; i < cnt; i++) {
      if ((holder.childNodes[i].className == 'item' || holder.childNodes[i].className == 'item_new' || holder.childNodes[i].className == 'item_hover') && holder.childNodes[i].id != 'item_template') {
        cur_items[c] = holder.childNodes[i].id;
        c++;
      }
    }
    
    if (isDragging()) {
      // no list manipulations when dragging - it's dangerous :)
      return;
    }
    
    // remove old items
    cnt = cur_items.length;
    for (i = 0; i < cnt; i++) {
      holder.removeChild(getMyObject(cur_items[i]));
    }
    
    // readd new items
    cnt = new_items.length;
    for (i = 0; i < cnt; i++) {
      if (inArray(cur_items, getElementValue(new_items[i], 'id'))) {
        insertItemElement(getElementValue(new_items[i], 'id'), getElementValue(new_items[i], 'quantity'), getElementValue(new_items[i], 'description'), false);
      }
      else {
        insertItemElement(getElementValue(new_items[i], 'id'), getElementValue(new_items[i], 'quantity'), getElementValue(new_items[i], 'description'), true);
      }
    }
    
    // show "list is empty" if ... well it is empty :)
    if (cnt == 0) {
      showId('empty');
    }
    else {
      hideId('empty');
    }
    
    // add suggestions
    clearSuggest();
    suggestions = xml.getElementsByTagName('suggestion');
    cnt = suggestions.length;
    if (cnt > 0) {
      suggest_obj = getMyObject('search_suggest');
      for (i = 0; i < cnt; i++) {
//        suggest_obj.innerHTML += '<div class="suggestion" onclick="insertSuggest(this.innerHTML);" style="display: none;">' + getElementValue(suggestions[i], 'description') + '</div>';
        suggest_obj.innerHTML += '<div class="suggestion" onclick="insertSuggest(this.innerHTML);" >' + getElementValue(suggestions[i], 'description') + '</div>';
      }
    }
  }
    
  // reset timeout counter
  refresh_timeout = setTimeout('refreshItemList();', 60000);
}

function insertItemElement (idx, qty, descr, fade) {
  if (qty != '' && qty != ' ') {
    descr = '<span class="quantity">' + qty + ' x </span>' + descr;
  }
  descr = descr.replace(/(.*)(\(valid.*\))/, "$1<div class=\"suggestion_date_item\" >$2</div>");
  //alert(qty);
  template = getMyObject('item_template');
  new_obj = template.cloneNode(true);
  while (new_obj.innerHTML.match(/__id__/)) {
    new_obj.innerHTML = new_obj.innerHTML.replace(/__id__/, idx);
  }
  //new_obj.innerHTML = new_obj.innerHTML.replace(/__quantity__/, qty);
  new_obj.innerHTML = new_obj.innerHTML.replace(/__description__/, descr);
  new_obj.id = idx;
  
  // set attributes
  itemslist = getMyObject('items');
  itemslist.appendChild(new_obj);
  if (fade) {
//    new_obj.className = 'item_new';
    fadeIn(idx);
  }
  else {
    showId(idx);
  }
}

var suggest_timeout = null;
var suggest_str = '';

function getSuggestion () {
  if (formPass()) { return; }
  if (suggest_timeout) {
    clearTimeout(suggest_timeout);
  }
  if (suggest_str != getValue('frm_txt_item')) {
    suggest_timeout = setTimeout('showSuggest()', 1000);
  }
}

function suggestKeyPressDown (evt) {
  if (evt == undefined) evt = window.event;
  
  // check for tab
  var k;
  if ('keyCode' in evt) { k = evt.keyCode; }
  else if ('which' in window.event ) { k = evt.which; }
  else { k = 0; }
  if (k == 9) {
    getNextSuggestion();
    setCarretFocus('frm_txt_item');
    return false;
  }
  else if (k == 27) {
    resetSuggest();
    return false;
  }
}

function suggestKeyPressUp (evt) {
  if (evt == undefined) evt = window.event;
  
  // check for tab
  var k;
  if ('keyCode' in evt) { k = evt.keyCode; }
  else if ('which' in window.event ) { k = evt.which; }
  else { k = 0; }
  if ((k > 32) || k == 8) {
//    getSuggestion();
    searchSuggest();
  }
}

function getNextSuggestion () {
  holder = getMyObject('search_suggest');
  cnt = holder.childNodes.length;
  selected = false;
  first = true;
  first_obj = null;
  sel_obj = null;
  cnt2 = 0;
  for (i = 0; i < cnt; i++) {
    suggestion = holder.childNodes[i];
    if ((suggestion.className == 'suggestion_active' || suggestion.className == 'suggestion') && suggestion.style.display != 'none') {
      // mark first
      if (first) {
        first_obj = holder.childNodes[i];
        first = false;
      }
      
      // check
      if (suggestion.className == 'suggestion_active') {
        suggestion.className = 'suggestion';
        selected = true;
      }
      else if (selected) {
        sel_obj = holder.childNodes[i];
        selected = false;
      }
      
      cnt2++;
    }
  }
  
  // set first
  if (sel_obj == null) {
    sel_obj = first_obj;
  }
  
  
  if (cnt2 > 0) {
    sel_obj.className = 'suggestion_active';
    setValue('frm_txt_item', formDecode(sel_obj.innerHTML));
  }
  else {
    return;
  }
}

function showSuggest () {
  holder = getMyObject('search_suggest');
  txt = trim(getValue('frm_txt_item'));
  if (txt.length == 0) {
    resetSuggest();
    return;
  }
  cnt = holder.childNodes.length;
  cnt2 = 0;
  for (i = 0; i < cnt; i++) {
    suggestion = holder.childNodes[i];
    if (suggestion.className == 'suggestion' || suggestion.className == 'suggestion_active') {
      ex = "res = suggestion.innerHTML.match(/^" + txt + "/i);";
      eval(ex);
      if (res == null) {
        suggestion.style.display = 'none';
      }
      else {
        suggestion.style.display = '';
        cnt2++;        
      }
    }
  }
  if (cnt2 > 0) {
    showId('search_suggest');
  }
  else {
    hideId('search_suggest');
  }
}

function insertSuggest (txt) {
  setValue('frm_txt_item', formDecode(txt));
  resetSuggest();
}

function clearSuggest () {
  suggest_obj = getMyObject('search_suggest');
  suggest_obj.innerHTML = '';
//  suggest_obj.style.display = 'none';
}

function resetSuggest () {
  holder = getMyObject('search_suggest');
  cnt = holder.childNodes.length;
  for (i = 0; i < cnt; i++) {
    suggestion = holder.childNodes[i];
    if (suggestion.className == 'suggestion' || suggestion.className == 'suggestion_active') {
      suggestion.className = 'suggestion'
//      suggestion.style.display = 'none';
    }
  }
//  holder.style.display = 'none';
}

function closeList () {
  redirectUrl('/?close=' + curlist);
}

var last_item = '';

function addItem () {
  if (formPass()) { return; }
  product = trim(getValue('frm_txt_item'));
  txt = product.replace(/<DIV .*>\(/g, "(");
  txt = txt.replace(/<div .*>\(/g, "(");
  txt = txt.replace(/<\/DIV>/g, "");
  txt = txt.replace(/<\/div>/g, "");
  last_item = txt;
  if (txt.length == 0) {
    raiseError('We can\'t have an invisible item, can we?');
    setCarretFocus('frm_txt_item');
    return;
  }
  
  // call
  sendRequest('additem',  'item=' + urlEncode(txt), 'addItemResult');
  
  // tidy up the form
  setValue('frm_txt_item', '');
  setCarretFocus('frm_txt_item');
  resetSuggest();
}

function addItemResult (error, response) {
  if (!error) {
    hideId('empty');
    insertItemElement(getElementValue(xml, 'id'), getElementValue(xml, 'quantity'), getElementValue(xml, 'description'), true);
  }
}

function moveItem (dir, fld) {
  if (formPass()) { return; }
  obj = getMyObject('items');
  cnode = getMyObject(fld);
  move = false;
  if (dir == 'up') {
    lnode = getPreviousSibling(cnode);
    if (lnode != null) {
      newnode = cnode.cloneNode(true);
      obj.insertBefore(newnode, lnode);
      obj.removeChild(cnode);
      hideTools(newnode.id);
      showTools(lnode.id);
      move = true;
    }
  }
  else if (dir == 'down') {
    lnode = getNextSibling(cnode);
    if (lnode != null) {
      newnode = lnode.cloneNode(true);
      obj.insertBefore(newnode, cnode);
      obj.removeChild(lnode);
      hideTools(newnode.id);
      showTools(cnode.id);
      move = true;
    }
  }
  
  // save to server
  if (move) {
    sendRequest('moveitem',  'dir=' + urlEncode(dir) + '&id=' + urlEncode(fld));
  }
}

function deleteItem (itm) {
  if (formPass()) { return; }
  sendRequest('deleteitem', 'id=' + urlEncode(itm));
  fadeOut(itm);
}

window.onkeydown = windowKeyPress;
var hasfocus = true;

function windowKeyPress (evt) {
  if (hasfocus) {
    return true;
  }
  if (evt == undefined) evt = window.event;
  
  // check if currently not on another form
  if (evt.srcElement) {
    trg = evt.srcElement;
  }
  else if (evt.target) {
    trg = evt.target;
  }
  if (trg) {
    if (trg.type == 'text' || trg.type == 'textarea' || trg.type == 'password') {
      return true;
    }
  }
  
  var k;
  if ('keyCode' in evt) { k = evt.keyCode; }
  else if ('which' in window.event ) { k = evt.which; }
  else { k = 0; }
  if (k == 65 || k == 84) {
    setCarretFocus('frm_txt_item');
    return false;
  }
  return true;
}

function displayTip () {
  hideId('tips');
  txt = tips[Math.floor(Math.random() * (tips.length - 1))];
  obj = getMyObject('tips');
  obj.innerHTML = '<strong>Hot Tip:</strong> ' + txt;
  fadeIn('tips');
  setTimeout('displayTip();', 10000);
  return;
}

function changePassword () {
  if (formPass()) { return; }
  sendRequest('changepass', 'pass=' + urlEncode(getValue('frm_txt_newpass')));
}

function emailItems () {
  if (formPass()) { return; }
  sendRequest('emailitems', 'email=' + urlEncode(getValue('frm_txt_emailitems')));
}

// *** AJAX crap **************************************************************

var xobj          = false;
var xml           = false;
var xloaded       = true;
var xcall         = false;
var timeout       = 0;
var lastcall      = '';
var lastaction    = '';
var started       = false;
var todelay       = 30;
var ajaxqueue     = new Array();
var ajaxqueue_to  = null;

function sendRequest (action, data, call) {
  // use default response handler
  if (call == undefined) {
    call = 'generalResult';
  }
  
  // add to queue
  ajaxqueue.push({action:action, data:data, call:call});
  
  // call AJAX queue processor
  processQueue();
  
  return;
}

function processQueue () {
  // reschedule if necessary
  if (!xloaded) {
    setTimeout('processQueue();', 500);
    return;
  }
  
  // run first command in line
  if (ajaxqueue.length > 0) {
    curop = ajaxqueue.shift();
    innitiateRequest(curop.action, curop.data, curop.call);
    return;
  }
}

function innitiateRequest (action, data, call) {
  // check if another request isn't running 
  // or user is not performing drag operation
  if (!xloaded || isDragging()) {
    // yes it is - reschedule call
    ajaxqueue.unshift({action:action, data:data, call:call});
    return;
  }
  
  // set last call
  lastcall    = "sendRequest('" + action + "', '" + escapeStr(data) + "', '" + call + "');";
  lastaction  = action;
  
  // show loader
  showLoader();
  
  // add list name
  if (curlist != '') {
    data = 'name=' + urlEncode(curlist) + '&' + data;
  }
  
  // add hash
  if (mygroceries_hash != '') {
    data = 'hash=' + urlEncode(mygroceries_hash) + '&' + data;
  }
  
  // render request url
  url = '/api/' + action + '?' + data;
  
  // innitiate request
  if (window.XMLHttpRequest) {
    // mozilla
    xobj = new XMLHttpRequest();
    // xobj.onreadystatechange = handleResponse;
    xobj.open('POST', url, true);
    xobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xobj.send(data);
  }
  else if (window.ActiveXObject) {
    // msie
    xobj = new ActiveXObject('Microsoft.XMLHTTP');
    //xobj.onreadystatechange = handleResponse;
    xobj.open('POST', url, true);
    xobj.setRequestHeader("Content-Type", 'application/x-www-form-urlencoded');
    xobj.send(data);
  }
  
  // set start time
  started = new Date();
  
  // set response handler to run
  setTimeout('handleResponse();', 1000);
  
  // set flags
  xloaded = false;
  xcall = call;
}

function handleResponse () {
  if (!xloaded && xobj && xobj.readyState && xobj.readyState == 4 && xobj.status == 200) {
    // get response
    xml = xobj.responseXML;
    
    // innitiate parsing
    if (xml && xml.hasChildNodes()) {
      //setTimeout('parseResponse("' + xcall +'");', 1000);
      parseResponse(xcall);
    }
    else {
      xobj.abort();
      hideLoader();
      raiseError(getAction(lastaction) + ' failed due to communications error. <a href="#" onclick="' + lastcall + 'return false;">Try again</a>');
    }
    
    // reset flags
    xcall = '';
    xloaded = true;
  }
  else if (timeouted()) {
    // this is taking too long - abort and raise error
    xobj.abort();
    hideLoader();
    raiseError(getAction(lastaction) + ' operation timed out. Check your internet connection and <a href="#" onclick="' + lastcall + 'return false;">retry</a>');
    
    // reset flags
    xcall = '';
    xloaded = true;
  }
  else if (!xloaded) {
    // set response handler to run
    setTimeout('handleResponse();', 500);
  }
}

function timeouted () {
  now = new Date();
  dif = (now - started) / 1000;
  if (dif > 300) {
    started = new Date();
  }
  return dif > 120 ? true : false;
}

function getAction (act) {
  switch (act) {
    case 'additem':
      return 'Add item';
      break;
    case 'deleteitem':
      return 'Delete item';
      break;
    case 'getitems':
      return 'Item list refresh';
      break;
    case 'getsuggest':
      return 'Get suggestion list';
      break;
    case 'moveitem':
      return 'Move item';
      break;
    case 'openlist':
      return 'Open list';
      break;
    case 'purgeitems':
      return 'Purge items';
      break;
    case 'sendlist':
      return 'Share list';
      break;
    default:
      return 'Unknown action';
      break;
  }
}

function parseResponse (callback) {
  // innitialize tmp vars
  errorstr = 'false';
  
  // get response element
  response = getElementValue(xml, 'response');
  
  // detect common response types
  switch (response) {
    case 'relogin':
      if (mygroceries_version != undefined && mygroceries_version == 'igoogle') {
        window.location.reload();
      }
      else {
        redirectUrl('/?relogin=y');
      }
      break;
    case 'error':
      errorstr = 'true';
      raiseError(getElementValue(xml, 'text'));
      break;
    case 'notice':
      raiseAction(getElementValue(xml, 'text'));
      break;
    default:
      // let the callback function handle data 
      // for other types of responses
      break;
  }
  
  // hide loader
  hideLoader();
  
  // invoke callback function
  if (callback != '') {
    eval(callback + "(" + errorstr + ", '" + response + "')");
    xcall = '';
  }
}

function getElementValue (xml, val) {
  tmp = xml.getElementsByTagName(val);
  if (tmp[0].firstChild) {
    return tmp[0].firstChild.nodeValue;
  }
  else {
    return '';
  }
}

function getElementObject (xml, val) {
  tmp = xml.getElementsByTagName(val);
  return tmp[0].firstChild;
}

// *** utilities **************************************************************

function getValue (fld) {
  fldobj = getMyObject(fld);
  return fldobj.value;
}

function setValue (fld, val) {
  fldobj = getMyObject(fld);
  return fldobj.value = val;
}

function getSelected (fld) {
  fldobj = getMyObject(fld);
  return fldobj.options[fldobj.selectedIndex].value;
}

function isChecked (fld) {
  fldobj = getMyObject(fld);
  return fldobj.checked;
}

function trim (str) {
	return str.replace(/^\s+|\s+$/g, '');
}

function urlEncode (str) {
  str = encodeURI(str);
  return str.replace(/&/, '%26');
}

function urlDecode (str) {
  str = decodeURI(str);
  return str.replace(/\%26/, '&');
}

var char_ent = ['"', "'", '<', '>', '&'];
var char_code =  ['&quot;', '&#039;', '&lt;', '&gt;', '&amp;'];

function formEncode (str) {
  cnt = char_ent.length;
  for (x = 0; x < cnt; x++) {
    str = str.replace(char_ent[x], char_code[x]);
  }
  return str;
}

function formDecode (str) {
  cnt = char_ent.length;
  for (x = 0; x < cnt; x++) {
    str = str.replace(char_code[x], char_ent[x]);
  }
  return str;
}

function inArray (arr, val) {
  cntx = arr.length;
  for (x = 0; x < cntx; x++) {
    if (arr[x] == val) {
      return true;
    }
  }
  return false;
}

function setCarretFocus (fld) {
  fldobj = getMyObject(fld);
  fldobj.focus();
}

function setVisibility (fld, set) {
  if (set) {
    showId(fld);
  }
  else {
    hideId(fld);
  }
}

var notice_timeout = null;

function raiseError (err) {
  hideId('action');
  fldobj = getMyObject('error_text');
  fldobj.innerHTML = err;
  fadeIn('error', 7);
  setHideTimeout('error');
}

function hideError () {
  if (notice_timeout) {
    clearTimeout(notice_timeout);
  }
  fadeOut('error');
}

function raiseAction (act) {
  hideId('error');
  fldobj = getMyObject('action_text');
  fldobj.innerHTML = act;
  fadeIn('action', 7);
  setHideTimeout('action');
}

function hideAction () {
  if (notice_timeout) {
    clearTimeout(notice_timeout);
  }
  fadeOut('action');
}

function setHideTimeout (act) {
  if (notice_timeout) {
    clearTimeout(notice_timeout);
  }
  notice_timeout = setTimeout('fadeOut(\'' + act +'\', 7)', 10000);
}

function redirectUrl (url) {
  setTimeout("window.location = '" + url + "';", 1000);
}

function getNextSibling (obj) {
  curtype = obj.nodeType;
  curobj = obj;
  newobj = null;
  while (curobj.nextSibling) {
    if (curobj.nextSibling.nodeType == curtype) {
      return  curobj.nextSibling;
    }
    else {
      curobj = curobj.nextSibling;
    }
  }
  return null;
}

function getPreviousSibling (obj) {
  curtype = obj.nodeType;
  curobj = obj;
  newobj = null;
  while (curobj.previousSibling) {
    if (curobj.previousSibling.nodeType == curtype) {
      return  curobj.previousSibling;
    }
    else {
      curobj = curobj.previousSibling;
    }
  }
  return null;
}

function formPass () {
  return noajax;
}

function escapeStr (str) {
  return str.replace('\'', '\\\'');
}

// *** display control functions **********************************************

function getMyObject (fld) {
  var thisdetail;
  if (document.getElementById && document.getElementById(fld) != null) {
    return document.getElementById(fld);
  }
  else if (document.layers && document.layers[fld] != null) {
    return document.layers[fld];
  }
  else if (document.all) {
    return document.all(fld);
  }
  else {
    return true;
  }
}

function toggleId (fld) {
  fldobj = getMyObject(fld);
  if (fldobj.style.display == 'none') {
    fldobj.style.display = '';
  }
  else {
    fldobj.style.display = 'none';
  }
}

function showId (fld) {
  fldobj = getMyObject(fld);
  if (fldobj != undefined) {
    fldobj.style.display = '';
  }
}

function fadeIn (fld, speed, from) {
  if (speed == undefined) { speed = 4; }
  if (from == undefined)  { from = 0; }
  setOpacity(fld, from);
  showId(fld);
  for (z = from; z <= 100; z++) {
    opc = 100 - z;
    setTimeout('setOpacity("' + fld + '",' + opc + ');', speed * (100 - z));
  }
}

function hideId (fld) {
  fldobj = getMyObject(fld);
  if (fldobj != undefined) {
    fldobj.style.display = 'none';
  }
}

function fadeOut (fld, speed, to) {
  if (speed == undefined) { speed = 4; }
  if (to == undefined)    { to = 100; }
  for (z = 0; z <= to; z++) {
    opc = 100 - z;
    setTimeout('setOpacity("' + fld + '",' + opc + ');', speed * z);
  }
  if (to == 100) {
    setTimeout('hideId("' + fld + '");', speed * (to + z));
  }
}

function setOpacity (fld, opc) {
  fldobj = getMyObject(fld);
  if (rendertype == 'normal') {
    fldobj.style.opacity = opc / 100;
  }
  else if (rendertype == 'ie') {
    fldobj.style.filter = "alpha(opacity=" + opc + ")";;
  }
}

function showLoader () {
  showId('progress');
}

function hideLoader () {
  hideId('progress');
}

// *** dragging functions *****************************************************

document.onmousemove = moveMouse;

var mouse_x       = 0;
var mouse_y       = 0;
var orig_x        = 0;
var orig_y        = 0;
var orig_width    = 0;
var orig_height   = 0;
var offset_x      = 0;
var offset_y      = 0;
var drag_obj      = null;
var drag_targets  = new Array();
var drag_plc      = null;

function updateMouseCoords (evt) {
  if (evt == undefined) evt = window.event;
  if(evt.pageX || evt.pageY){
    mouse_x = evt.pageX;
    mouse_y = evt.pageY;
  }
  else {
    mouse_x = evt.clientX + document.body.scrollLeft - document.body.clientLeft;
    mouse_y = evt.clientY + document.body.scrollTop  - document.body.clientTop;
  }
}

function moveMouse (evt) {
  if (evt == undefined) evt = window.event;
  updateMouseCoords(evt);
  if (drag_obj) {
    //setValue('debug', drag_obj);
    //return;
    // movement
    drag_obj.style.position = 'absolute';
		drag_obj.style.width    = orig_width;
		drag_obj.style.left     = mouse_x + offset_x;
		drag_obj.style.top      = mouse_y + offset_y;
		if (drag_obj.style.zIndex < 1) {
		  drag_obj.style.zIndex   = 1;
		}
		
		// check what we're hovering over
		xx = mouse_x + offset_x;
		yy = mouse_y + offset_y + 15;
		xx2 = xx + drag_obj.clientWidth;
		yy2 = yy + drag_obj.clientHeight;
		cnt = drag_targets.length;
		for (i = 0; i < cnt; i++) {
		  cur_target = drag_targets[i];
		  shown = false;
		  if (
          ((cur_target.x <= xx) && (cur_target.y <= yy) && (cur_target.x2 >= xx) && (cur_target.y2 >= yy))
          ||
          ((cur_target.x <= xx2) && (cur_target.y <= yy) && (cur_target.x2 >= xx2) && (cur_target.y2 >= yy))
         )
      {
        showPlaceholder(cur_target.id, drag_obj.clientWidth, drag_obj.clientHeight);
        shown = true;
		    //setValue('debug', 'mouse: ' + mouse_x + ' x ' + mouse_y + ' | original: ' + orig_x + ' x ' + orig_y + ' | offset: ' + offset_x + ' x ' + offset_y + ' | over: ' + cur_target.id);
		    break;
		  }
		  else {
		    //setValue('debug', 'mouse: ' + mouse_x + ' x ' + mouse_y + ' | original: ' + orig_x + ' x ' + orig_y + ' | offset: ' + offset_x + ' x ' + offset_y);
		  }
		  if (!shown && ((yy + 15) > cur_target.y2)) {
		    showPlaceholder('last', drag_obj.clientWidth, drag_obj.clientHeight);
		  //  removePlaceholder();
		  }
		  else if (drag_plc == null) {
		    // insert placeholder in place of our current item
        showPlaceholder(drag_obj.id, orig_width, orig_height);
		  }
		}
		if (cnt == 0) {
		  showPlaceholder('last', drag_obj.clientWidth, drag_obj.clientHeight);
		}
		return false;
  }
  //setValue('debug', 'mouse: ' + mouse_x + ' x ' + mouse_y + ' | original: ' + orig_x + ' x ' + orig_y + ' | offset: ' + offset_x + ' x ' + offset_y);
}

function showPlaceholder (id, w, h) {
  itemz = getMyObject('items');
  
  if (((drag_plc > 0) || drag_plc == 'last') && drag_plc != id) {
    // remove last placeholder
    itemz.removeChild(getMyObject('plc_' + drag_plc));
  }
  
  if (drag_plc != id) {
    if (id == 'last') {
      // append at the end
      plc = document.createElement('div')
      plc.id = 'plc_' + id;
      plc.style.width = w;
      plc.style.height = h;
      plc.className='placeholder';
      itemz.appendChild(plc);
      drag_plc = 'last';
    }
    else if (id > 0) {
      // show new one
      plc = document.createElement('div')
      plc.id = 'plc_' + id;
      plc.style.width = w;
      plc.style.height = h;
      plc.className='placeholder';
      itemz.insertBefore(plc, getMyObject(id));
      drag_plc = id;
    }
  }
}

function removePlaceholder () {
  if ((drag_plc > 0) || drag_plc == 'last') {
    itemz = getMyObject('items');
    itemz.removeChild(getMyObject('plc_' + drag_plc));
  }
}

function startDrag (obj) {
  // set object
  drag_obj = obj;
  
  // set original coordinates
  orig_x = obj.offsetLeft;
  orig_y = obj.offsetTop;
  orig_width = obj.clientWidth > 0 ? obj.clientWidth : obj.offsetWidth;
  orig_height = obj.clientHeight > 0 ? obj.clientHeight : obj.offsetHeight;
  
  // set offset
  offset_x = orig_x - mouse_x;
  offset_y = orig_y - mouse_y;
  
  // set current targets
  holder = getMyObject('items');
  cnt = holder.childNodes.length;
  c = 0;
  correction = 0;
  for (i = 0; i < cnt; i++) {
    cur_obj = holder.childNodes[i];
    if (cur_obj.id == obj.id) {
      correction = orig_height;
    }
    else if ((cur_obj.className == 'item' || cur_obj.className == 'item_new' || cur_obj.className == 'item_hover') && cur_obj.id != 'item_template') {
      x = cur_obj.offsetLeft;
      y = cur_obj.offsetTop;
      drag_targets[c] = {
        id:cur_obj.id,
        x:x,
        y:y - correction,
        x2:x + cur_obj.clientWidth,
        y2:y + cur_obj.clientHeight - correction
      }
      if (cur_obj.clientWidth == 0) {
        drag_targets[c].x2 = x + cur_obj.offsetWidth;
        drag_targets[c].y2 = y + cur_obj.offsetHeight - correction;
      }
      c++;
    }
  }
}

function endDrag () {
  if ((drag_plc > 0) || drag_plc == 'last') {
    itemz = getMyObject('items');
    if (itemz.insertBefore) {
      itemz.insertBefore(drag_obj, getMyObject('plc_' + drag_plc));
    }
    drag_obj.style.position = 'relative';
    drag_obj.style.left = '';
    drag_obj.style.top = '';
    drag_obj.style.width = '';
    drag_obj.style.zIndex = 0;
    drag_obj.className = 'item';
    setTimeout('hideTools(' + drag_obj.id + ');', 100);
    if (drag_plc != 'last') {
      setTimeout('hideTools(' + drag_plc + ');', 100);
    }
    removePlaceholder();
    act = 'before=' + urlEncode(drag_plc) + '&id=' + urlEncode(drag_obj.id);
    drag_plc = null;
    drag_obj = null;
    sendRequest('dragitem',  act);
  }
  else {
    drag_plc = null;
    drag_obj = null;
  }
}

function isDragging () {
  return drag_obj == null ? false : true;
}

//Gets the browser specific XmlHttpRequest Object
function getXmlHttpRequestObject() {
	if (window.XMLHttpRequest) {
		return new XMLHttpRequest();
	} else if(window.ActiveXObject) {
		return new ActiveXObject("Microsoft.XMLHTTP");
	} else {
		alert("Unfortunately your browser will not work with MyGroceries.com.au. Please upgrade to a later version of browser!");
	}
}

//Our XmlHttpRequest object to get the auto suggest
var searchReq = getXmlHttpRequestObject();

//Called from keyup on the search textbox.
//Starts the AJAX request.
function searchSuggest() {
	if (searchReq.readyState == 4 || searchReq.readyState == 0) {
		var str = escape(document.getElementById('frm_txt_item').value);
		if (str.length > 3 && str.length < 13) {
					searchReq.open("GET", '/searchSuggest.php?listname=' + curlist + '&search=' + str, true);
					searchReq.onreadystatechange = handleSearchSuggest; 
					searchReq.send(null);
				}
		if (str.length < 4) {
			clearSuggest();
		}
	}		
}

//Called when the AJAX response is returned.
function handleSearchSuggest() {
	if (searchReq.readyState == 4) {
		var ss = document.getElementById('search_suggest')
		ss.innerHTML = '';
		var str = searchReq.responseText.split("\n");
		var suggest = '';
		for(i=0; i < str.length - 1; i++) {
			if (str[i] == "TAGSPECIALS") {
				suggest = '<div class="suggestion_specials"><img src=\"/lib/img/specials_dropdown.jpg\"></div>';
				ss.innerHTML += suggest;
			} else if (str[i] == "TAGGROCERIES") {
				suggest = '<div class="suggestion_title"><img src=\"/lib/img/mygroceries_dropdown.jpg\"></div>';
				ss.innerHTML += suggest;
			} else if (str[i] == "TAGBASICS") {
				suggest = '<div class="suggestion_title"><img src=\"/lib/img/basics_dropdown.jpg\"></div>';
				ss.innerHTML += suggest;
			} else {
				var product = str[i];
				product_code = product.replace(/(.*)(\(valid.*\))/, "$1<div class=\"suggestion_date\" >$2</div>");
				suggest = '<div onmouseover="javascript:suggestOver(this);" ';
				suggest += 'onmouseout="javascript:suggestOut(this);" ';
				suggest += 'onclick="javascript:setSearch(this.innerHTML);" ';
				suggest += 'class="suggestion">' + product_code;
				suggest += '</div>';
				ss.innerHTML += suggest;
			}
		}
	}
}

//Mouse over function
function suggestOver(div_value) {
	div_value.className = 'suggestion_active';
}
//Mouse out function
function suggestOut(div_value) {
	div_value.className = 'suggestion';
}
//Click function
function setSearch(value) {
	document.getElementById('frm_txt_item').value = value;
	document.getElementById('search_suggest').innerHTML = '';
	addItem(); return formPass();
}

