/**
  Sets focus to the first text field of the first form having such a field,
  i.e. if the first form has no text fields, uses the second one etc.
  */
function focusForm()
{
    if (document.forms)
    {
	var isFocused = false;

	// process all forms until focus is set
	for (var i=0; !isFocused && (i < document.forms.length); i++)
	{
	    var elements = document.forms[i].elements;

	    // process all form elements until focus is set
	    for (var j=0; !isFocused && (j < elements.length); j++)
	    {
		if ((elements[j].type == "text") ||
		    (elements[j].type == "textarea") ||
		    (elements[j].type == "password"))
		{
		    // too short fields are unimportant
		    if (elements[j].size > 3)
		    {
			elements[j].focus();
			isFocused = true;
		    }
		}
	    }		
	}
    }
}


/**
 * Sets/unsets the pointer in browse mode: if <td>'s id is "tableEvenRow",
 * sets it to "tableEvenRowHilight", otherwise to "tableRowHilight". For
 * de-hillghting, performs reverse operation.
 *
 * @param   object    the table row
 * @param   doHilight true to hilight, false to de-hilight
 * @return  boolean   true on success
 */
function triggerTrHilight (theRow, doHilight)
{
    if (typeof(theRow.style) == 'undefined') {
        return false;
    }
    if (typeof(document.getElementsByTagName) != 'undefined') {
        var theCells = theRow.getElementsByTagName('td');
    }
    else if (typeof(theRow.cells) != 'undefined') {
        var theCells = theRow.cells;
    }
    else {
        return false;
    }

    var rowCellsCnt  = theCells.length;
    for (var c = 0; c < rowCellsCnt; c++)
    {
	/*if (c == 0)
	{
	    var p;
	    for (j in theCells[c])
		p += j + "=" + theCells[c][j] + "\n<br />";

	    document.write (p);
	}*/

	var width = theCells[c].scrollWidth;

	if (width == null)
	    width = theCells[c].width;

	var height = theCells[c].scrollHeight;

	if (height == null)
	    height = theCells[c].height;

	// not a pixel-image row (for custom-drawn tables)
	if (   (theCells[c].tagName.toUpperCase() == 'TD')
	    && (width > 1)
	    && (height > 1))
	{
	    var newId;

	    // set hilight OFF
	    if (!doHilight)
		newId = (theCells[c].id == 'tableEvenRowHilight') ?
			    'tableEvenRow': '';

	    // set hilight ON
	    else
		newId = (theCells[c].id == 'tableEvenRow') ?
			'tableEvenRowHilight': 'tableRowHilight';

	    theCells[c].id = newId;
	}
    }

    return true;
} // end of the 'setPointer()' function

/**
  Appends the value from fromList to toList's, provided that the same item
  (meaning both its value and text) is not there yet.

  toList's selection is then set to the new element to make it scroll there,
  for clarity.

  @param fromList 	<select> object
  @param index 		element index in fromList (0, ..., fromList.length - 1)
  @param toList 	<select> object
  */
function addFromListToList (fromList, index, toList)
{
    sourceOption = fromList.options[index];

    hasAlready = false;
    var i;

    // check if target list already has the same item
    for (i=0; !hasAlready && (i < toList.length); i++)
    {
	if ((toList.options[i].text  == sourceOption.text) &&
	    (toList.options[i].value == sourceOption.value))
	{
	    hasAlready = true;
	}
    }

    // no such element yet - add it; NOTE:
    // options[i+1]=options[i] assignments don't work, one has to create
    // new Option objects each time
    if (!hasAlready)
    {
	/*for (i = toList.length - 1; i >= 0; i--)
	{
	    toList.options[i+1] = new Option (
			    toList.options[i].text,toList.options[i].value);
	}*/

	toList.options[toList.length] = new Option (sourceOption.text, sourceOption.value);

	// make the new element visible (selected), i.e. the list scrolls
	toList.selectedIndex = toList.length - 1;
    }
}

/**
  Empties list.

  @param list 	<select> object
  */
function emptyList (list)
{
    list.length = 0;
}

/**
  Adds all fromList's elements to toList.

  @param fromList 	<select> object
  @param toList 	<select> object
  */
function copyListToList (fromList, toList)
{
    var i;

    for (i=0; i < fromList.length; i++)
    {
	addFromListToList (fromList, i, toList);
    }
}

/**
  Removes list element, sets selection index to 0 to reflect changes (otherwise
  the list loses selection is its current element was deleted).

  @param list 	<select> object
  @param index 	element index (0, ..., list.length - 1)
  */
function removeListElement (list, index)
{
    list.options[index] = null;

    // update selection
    if (list.length > 0)
    {
	list.selectedIndex = 0;
    }
}

/**
  Searches for and removes the value from the list. Unlike in
  removeListElement(), we don't know where the value actually is.

  @param list 	<select> object
  @param value 	value to remove
  */
function removeListValue (list, value)
{
    for (i=0; i < list.length; i++)
    {
	if (list.options[i].value == value)
	{
	    list.options[i] = null;
	}
    }
}

/**
  Returns all field values as a single space-separated string. Spaces (as well
  as all special URL characters) are URL-escaped, so spaced inside list
  elements are passed as %20.

  @param list 	<select> object
  @return "elem1 elem2 ele%20m3 etc"
  */
function collectListValues (list)
{
    str = "";

    for (i=0; i < list.length; i++)
    {
	if (str.length != 0)
	{
	    str += " ";
	}

	str += escape (list.options[i].value);
    }

    return str;
}

/**
  Checks if record is bookmarked or not.

  @param cookieName 	cookie where bookmarked ID's are stored
			(comma-separated string)

  @param recordId 	record ID (should not contain commas!)
  @return bool 		true if record is bookmarked
  */
function isRecordBookmarked (cookieName, recordId)
{
    var isBookmarked = false;

    var cookie = getCookie (cookieName);

    // no cookie exists
    if ((cookie == null) || (cookie == 'undefined'))
    {
	cookie = "";
    }

    ids = cookie.split (",");

    // find recordId in array
    for (var i=0; !isBookmarked && (i < ids.length); i++)
    {
	if (ids[i] == recordId)
	{
	    isBookmarked = true;
	}
    }

    return isBookmarked;
}

/**
  Bookmarks a record (whatever) by storing it in a cookie (comma-separated
  string of ID's).

  There's a limit of maximal cookie length, so if there're already
  100 bookmarks set, this function displays an error message
  and doesn't set the bookmark.
  
  Final bookmark value (boolean) is returned so it could be e.g. assigned
  to a checkbox which whould otherwise remain checked even if bookmarking 
  ailed.

  @param cookieName 	cookie name to store bookmarks of this type
  @param recordId 	record ID (should not contain commas!)
  @param isBookmarked 	bookmark status (true/false)
  @return bool 		final bookmark value (false if limit was exceeded)
  */
function bookmarkRecord (cookieName, recordId, isBookmarked)
{
    // bookmark limit
    var nMaxBookmarks = 100;

    var cookie = getCookie (cookieName);

    // no cookie exists
    if ((cookie == null) || (cookie == 'undefined'))
    {
	cookie = "";
    }

    ids = cookie.split (",");

    // check if bookmark limit has not been exceeded yet
    if (isBookmarked)
    {
	// reset bookmark (so e.g. just clicked checkbox becomes unchecked)
	if (ids.length >= nMaxBookmarks)
	{
	    alert (  "Sorry, only max "
		   + nMaxBookmarks
		   + " bookmarks can be set.");

	    isBookmarked = false;
	}

	// store bookmark if it's not stored yet (thus multiple calls with
	// the same parameters won't cause multiple copies stored)
	else if (!isRecordBookmarked (cookieName, recordId))
	{
	    var separator = (cookie.length > 0) ? ",": "";
	    setCookie (cookieName, cookie + separator + recordId, null, "main_shop.php@command=shop_products_offers.htm");
	}
    }

    // unset bookmark
    else
    {
	newCookie = "";

	// create a new string by storing all its elements but recordId
	for (i=0; i < ids.length; i++)
	{
	    if (ids[i] != recordId)
	    {
		// separate from the previous record
		if (i > 0)
		{
		    newCookie += ",";
		}

		newCookie += ids[i];
	    }
	}

	setCookie (cookieName, newCookie, null, "main_shop.php@command=shop_products_offers.htm");
    }

    return isBookmarked;
}



function getCookie(name)
{
    var bites = document.cookie.split("; "); // break cookie into array of bites

    for (i=0; i < bites.length; i++)
    {
	nextbite = bites[i].split("="); // break into name and value

	if (nextbite[0] == name) // if name matches
	    return unescape(nextbite[1]); // return value
    }

    return null; // if no match return null
}


// Example for expiry:
// var expiry = new Date(today.getTime() + 28*24*60*60 * 1000); = +28 days
function setCookie(name, value, expiry, path)
{
    if (value == null)
    {
	value = "";
    }

    value = escape (value);

    expiry = ((expiry != null) &&  (expiry != 'undefined')) ?
		"; expires=" + expiry.toGMTString(): "";

    path = ((path != null) &&  (path != 'undefined')) ?
		"; path=" + path: "";

    document.cookie = name
	    + "=" + value
	    + expiry
	    + path;
}
