// =========================================================================================
// MYFOCUS SYSTEMS
// Librería de funciones JAVASCRIPT
// =========================================================================================

// Definición de navegadores
browser_opera     = ( navigator.userAgent.toUpperCase().indexOf( 'OPERA' ) != -1 );
browser_safari    = ( navigator.userAgent.toUpperCase().indexOf( 'SAFARI' ) != -1 );
browser_konqueror = ( !browser_safari && ( navigator.userAgent.toUpperCase().indexOf( 'KONQUEROR' ) != -1 ) ) ? true : false;
browser_mozilla   = ( ( !browser_safari  &&  !browser_konqueror ) && ( navigator.userAgent.toUpperCase().indexOf( 'GECKO' ) != -1 ) ) ? true : false;
browser_ie        = ( ( navigator.userAgent.toUpperCase().indexOf( 'MSIE' ) != -1 ) && !browser_opera );

// Bloquea la pulsación de Enter
function LibBlockEnter(k)
{
	var keycode = document.all ? event.keyCode : k.which;
	if (keycode == 13) return false;
}

// Imprime el DIV indicado
function LibPrintDIV( DivName )
{
  var DivObject = document.getElementById( DivName );
	var DivHTML   = LibWindowPopupW(' ', 'Print', 1024, 700);
	
  DivHTML.document.write( DivObject.innerHTML );
  DivHTML.document.close();
  DivHTML.print();
  DivHTML.close();
}

// Abre una ventana emergente
// @@@ VCORREA 20090417 : Devuelve 'false'.
// @@@ VCORREA 20091014 : Permite indicar si la ventana puede cambiar de tamaño (resizeable).
//
function LibWindowPopup( url_page, window_name, w, h, resizable )
{
  if( LibTypeOf( resizable ) === 'undefined' )  { resizable = false; }
  LibWindowPopupW( url_page, window_name, w, h, resizable );
  return false;
}

// Abre una ventana emergente
// @@@ VCORREA 20090417 : Devuelve el nuevo objeto 'window' creado.
// @@@ VCORREA 20091014 : Permite indicar si la ventana puede cambiar de tamaño (resizeable).
//
function LibWindowPopupW( url_page, window_name, w, h, resizable )
{
  if( LibTypeOf( resizable ) === 'undefined' )  { resizable = false; }
	var winl = (screen.width  - w ) / 2;
	var wint = (screen.height - h ) / 2;
	if( winl < 0 ) winl = 0;
	if( wint < 0 ) wint = 0;
	
	windowprops = "height=" + h
              + ",width=" + w
              + ",top=" + wint
              + ",left="+ winl
              + ",resizable=" + ( resizable ? "yes" : "no" )
              + ",scrollbars=no"
              + ",location=no"
              + ",menubar=no,toolbar=no,status=no,directories=no,titlebar=no";
	
	var new_win = window.open( url_page, window_name, windowprops, resizable );
	return new_win;
}

// Abre una ventana emergente con scroll
// @@@ VCORREA 20090417 : Devuelve 'false'.
// @@@ VCORREA 20091014 : Permite indicar si la ventana puede cambiar de tamaño (resizeable).
//
function LibWindowPopupScroll( url_page, window_name, w, h, resizable )
{
  if( LibTypeOf( resizable ) === 'undefined' )  { resizable = false; }
  LibWindowPopupScrollW( url_page, window_name, w, h, resizable );
  return false;
}

// Abre una ventana emergente con scroll
// @@@ VCORREA 20090417 : Devuelve el nuevo objeto 'window' creado.
// @@@ VCORREA 20091014 : Permite indicar si la ventana puede cambiar de tamaño (resizeable).
//
function LibWindowPopupScrollW( url_page, window_name, w, h, resizable )
{
  if( LibTypeOf( resizable ) === 'undefined' )  { resizable = false; }
	var winl = (screen.width  - w ) / 2;
	var wint = (screen.height - h ) / 2;
	if( winl < 0 ) winl = 0;
	if( wint < 0 ) wint = 0;
	
	windowprops = "height=" + h
              + ",width=" + w
              + ",top=" + wint
              + ",left="+ winl
              + ",resizable=" + ( resizable ? "yes" : "no" )
              + ",scrollbars=yes"
              + ",location=no"
              + ",menubar=no,toolbar=no,status=no,directories=no,titlebar=no";

	var new_win = window.open( url_page, window_name, windowprops );
	return new_win;
}

// Abre una ventana emergente con scroll y maximizable
//
function LibWindowPopupScrollSize(url_page, window_name, w, h)
{
	var winl = (screen.width-w)/2;
	var wint = (screen.height-h)/2;
	if (winl < 0) winl = 0;
	if (wint < 0) wint = 0;
	
	windowprops = "height="+h+",width="+w+",top="+ wint +",left="+ winl +",location=no,"
	+ "scrollbars=yes,menubar=no,toolbar=no,resizable=yes,status=no,directories=no,titlebar=no";

	var new_win = window.open(url_page, window_name, windowprops);
	return new_win;
}

// Abre una ventana emergente con scroll, con confirmacion previa
//
function LibWindowPopupScrollConfirm(url_page, window_name, w, h, message)
{
	var Value = confirm( message );
	if (Value)
	{
		var winl = (screen.width-w)/2;
		var wint = (screen.height-h)/2;
		if (winl < 0) winl = 0;
		if (wint < 0) wint = 0;
		
		windowprops = "height="+h+",width="+w+",top="+ wint +",left="+ winl +",location=no,"
		+ "scrollbars=yes,menubar=no,toolbar=no,resizable=no,status=no,directories=no,titlebar=no";

		window.open(url_page, window_name, windowprops);
	}
	
	return false;
}

// Comprueba si un valor está en un array
function LibInArray(List,Object)
{
  var i = List.length - 1;
  if (i >= 0) {
		do {
			// alert( i + ' | ' + List[i] + ' | ' + Object.value );
			// alert( i + ' | ' + List[i].toLowerCase() + ' | ' + Object.value.toLowerCase() );
			// if (List[i] === Object.value) {
			if (List[i].toLowerCase() === Object.value.toLowerCase()) {
				return true;
			}
		} while (i--);
  }
	
  return false;
}

// Comprueba si un email es válido		
function LibIsValidEmail(Object)
{
	var CheckString = /^[\w\.\-]+\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
	return ( CheckString.exec( Object.value ) );
}

// Comprueba si un campo está vacío
function LibIsEmpty(Object)
{
	return ( Object.value == "" );
}

// @@@ VCORREA 20090926 : Nueva función.
//
// Es equivalente a la función 'empty()' de PHP.
// Devuelve 'true' si el parámetro pasado se puede evaluar como 'false' o no existe.
//
function LibIsEmpty2( anything )
{
//alert( 'Tipo: [ ' + LibTypeOf( anything ) + ' ]' );
//alert( 'Valor: [' + anything + ']' );
  switch( LibTypeOf( anything ) ) {
    case 'string' :
      if( null == anything  ||  trim( anything ) == '' )  { return true; }
      return false;

    case 'number' :
      return ( 0 == anything );

    case 'boolean' :
      return ( anything == false );

    case 'array' :
      if( 0 == anything.length )  { return true; }
      return false;

    case 'null' :
      return true;

    case 'object' :
      if( anything.hasOwnProperty( 'value' ) ) {
        var value = parseFloat( anything.value );
        if( isNaN( value ) ) {
          if( null == value  ||  trim( value ) == '' )  { return true; }
          return false;
        } else {
          return ( 0 == value );
        }
      } else if( anything.hasOwnProperty( 'checked' ) ) {
        if( anything.checked )  { return false; }
        return true;
      } else if( anything.hasOwnProperty( 'length' ) ) {
        if( 0 == anything.length )  { return true; }
        return false;
      } else {
        return true;
      }

    case 'function' :
      return false;

    case 'undefined' :
    default :
      alert( LibTypeOf( anything ) );
      return true;
  }
}

// Numeric check
function LibNumCheck( InputNum, Max )
{
  var Num = InputNum * 1; // Pasamos a numérico

  // Comprobamos que ho haya pasado el límite
  if( Num < 0 )
  {
			alert( "El importe debe ser mayor de cero" );
			return false;
	}
	else
	{
    if( Num > Max )
		{
			alert( "Ha sobrepasado el saldo (" + Max + ")" );
			return false;
		}
	}
	
  return true;
}

// Autocorrección de número en el input
function LibNumInput (str, dec, bNeg)
{
	var cDec 	= '.'; // Símbolo para decimales
	var bDec 	= 0;
	var val 	= "";
	var strf 	= "";
	var neg 	= "";
	var i		 	= 0;

	if (str == "") {
		str=0;
	}
	
	round_number (parseFloat ("0"), dec);
	
	if (bNeg && str.charAt (i) == '-') { neg = '-'; i++; }

	for (i; i < str.length; i++) {
		val = str.charAt (i);
		if (val == cDec) {
			if (!bDec) {
				strf += val; bDec = 1;
			}
		}
		else if (val >= '0' && val <= '9') {
			strf += val;
		}
	}
	
	strf = (strf == "" ? 0 : neg + strf);
	
	return round_number (parseFloat (strf), dec);
}

// strpos('Buffer', 'Char', Init);
function strpos( haystack, needle, offset)
{
  var i = (haystack+'').indexOf( needle, offset ); 
  return i===-1 ? false : i;
}

function round_number (num, dec)
{ // low-level numeric format with upward rounding at 5+
 var cDec = '.'; // decimal point symbol
 if (!(dec >= 0 && dec <= 9))
  dec = 2;
 if (isNaN (num) || num == '')
 { // zero values are returned in proper decimal format
  var sdec = "";
  for (var i = 0; i < dec; i++)
   sdec += '0';
  return "0" + (sdec != "" ? cDec + sdec : "");
 }
 var snum = new String (num);
 var arr_num = snum.split (cDec);
 var neg = '';
 var nullify = 0;
 dec_a = arr_num.length > 1 ? arr_num[1].length : 0;
 if (dec_a <= dec)
 { // fill decimal places with trailing zeros if necessary
  if (!dec_a)
   arr_num[1] = "";
  for (var i = 0; i < dec - dec_a; i++)
   arr_num[1] += '0';
  dec_a = dec;
 }
 // total decimal places in value before rounding and formatting
 dec_i = dec_a;
 dec_a -= dec;
 if (arr_num[0].charAt(0) == '-')
 { // preserve negative symbol, remove from value (calculations)
  neg = '-';
  arr_num[0] = arr_num[0].substring (1, arr_num[0].length);
 }
 if (!parseInt (arr_num[0])) // case when whole value is 0
 { // nullify a zero whole value for correct decimal point placement
  arr_num[0] = "1"; // 0 whole # would not preserve amount in calc.
  nullify = 1; // flag to remove greatest 1 portion from whole #
 }
 var whole = parseInt (arr_num[0] * Math.pow (10, arr_num[1].length));
 // remove leading zeros
 for (i = 0; i < arr_num[1].length; i++)
  if (arr_num[1].charAt (i) != '0')
   break;
 if (arr_num[1].length == i) // decimal portion blank or all zeros
  return (neg + arr_num[0] + (arr_num[1] != "" ? (cDec + arr_num[1]) : ""));
 whole += parseInt (arr_num[1].substring (i, arr_num[1].length));
 if (arr_num[1].length != dec)
 { // round number affecting appropriate cluster of decimal places
  var diff = "";
  var str = new String (whole);
  for (i = dec_a; i > 0; i--)
   diff += str.charAt (str.length - i);
  diff = Math.pow (10, dec_a) - parseInt (diff);
  whole += ((diff <= 5 * Math.pow (10, dec_a - 1)) ? diff : 0);
 }
 str = new String (whole);
 var str_f = "";
 var j = 0;
 var k = 0;
 if (nullify)
 {
  arr_num[0] = "0"; // remove 1 from greatest decimal place (restoration)
  str = (parseInt (str.charAt(0)) - 1) + str.substring (1, str.length);
 }
 else // re-assign whole numeric portion from entire numeric string value
  arr_num[0] = str.substring (0, str.length - dec_i);
 for (i = 0; i < str.length; i++)
 { // combine portions of decimal number (whole, fraction, sign)
  if (k - 1 > dec)
   break; // fraction termination case
  if (j == arr_num[0].length)
  {
   if (!j)
    str_f += 0;
   str_f += (dec != 0 ? cDec : ''); // insert decimal point
   --i; // backtrack one character
   k++; // signal fraction count
  }
  else // assign character by character
   str_f += str.charAt (i);
  j++;
  if (k) // fractional counter increment
   k++;
 }
 return neg + str_f;
} 

// Date
// Simulates PHP's date function
Date.prototype.format = function(format) {
        var returnStr = '';
        var replace = Date.replaceChars;
        for (var i = 0; i < format.length; i++) {
                var curChar = format.charAt(i);
                if (replace[curChar])
                        returnStr += replace[curChar].call(this);
                else
                        returnStr += curChar;
        }
        return returnStr;
};

Date.replaceChars = {
        shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
        longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
        shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
        longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
        
        // Day
        d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
        D: function() { return Date.replace.shortDays[this.getDay()]; },
        j: function() { return this.getDate(); },
        l: function() { return Date.replace.longDays[this.getDay()]; },
        N: function() { return this.getDay() + 1; },
        S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 13 && this.getDate() != 1 ? 'rd' : 'th'))); },
        w: function() { return this.getDay(); },
        z: function() { return "Not Yet Supported"; },
        // Week
        W: function() { return "Not Yet Supported"; },
        // Month
        F: function() { return Date.replace.longMonths[this.getMonth()]; },
        m: function() { return (this.getMonth() < 11 ? '0' : '') + (this.getMonth() + 1); },
        M: function() { return Date.replace.shortMonths[this.getMonth()]; },
        n: function() { return this.getMonth() + 1; },
        t: function() { return "Not Yet Supported"; },
        // Year
        L: function() { return "Not Yet Supported"; },
        o: function() { return "Not Supported"; },
        Y: function() { return this.getFullYear(); },
        y: function() { return ('' + this.getFullYear()).substr(2); },
        // Time
        a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
        A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
        B: function() { return "Not Yet Supported"; },
        g: function() { return this.getHours() == 0 ? 12 : (this.getHours() > 12 ? this.getHours() - 12 : this.getHours()); },
        G: function() { return this.getHours(); },
        h: function() { return (this.getHours() < 10 || (12 < this.getHours() < 22) ? '0' : '') + (this.getHours() < 10 ? this.getHours() + 1 : this.getHours() - 12); },
        H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
        i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
        s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },
        // Timezone
        e: function() { return "Not Yet Supported"; },
        I: function() { return "Not Supported"; },
        O: function() { return (this.getTimezoneOffset() < 0 ? '-' : '+') + (this.getTimezoneOffset() / 60 < 10 ? '0' : '') + (this.getTimezoneOffset() / 60) + '00'; },
        T: function() { return "Not Yet Supported"; },
        Z: function() { return this.getTimezoneOffset() * 60; },
        // Full Date/Time
        c: function() { return "Not Yet Supported"; },
        r: function() { return this.toString(); },
        U: function() { return this.getTime() / 1000; }
}

// NAVs
var treeopened = null;
function opentree(tree)
{
	var cls = '';
	if (document.getElementById) {
		var el = document.getElementById (tree);
		if (el && el.className) {
			el.className = (el.className == 'navOpened') ? 'navClosed' : 'navOpened';
		}
	}
	if (navigator.appName == 'Microsoft Internet Explorer' && document.documentElement && navigator.userAgent.indexOf ('Opera') == -1) parent.setScrollInIE();
	return false;
}

// CATALOG
function domSetInnerHTML(obj, html_string)
{
  // IE ... and other browsers that support innerHTML
  if (obj.innerHTML != null)
    {
      obj.innerHTML = html_string;
    }
  // W3C method ... this *should* work
  else if (document.createRange)
    {
      	var rng = document.createRange();

	if (rng.setStartBefore && rng.createContextualFragment &&
	    obj.removeChild && obj.appendChild) {
           rng.setStartBefore(obj);
           htmlFrag = rng.createContextualFragment(content);
           while (obj.hasChildNodes())
      	      obj.removeChild(obj.lastChild);
           obj.appendChild(htmlFrag);
	}
    }
  else if (obj.document != null && obj.document.open != null)
    {

      /* this NS 4.x way is *almost* as trivial ... note you cannot do this
         *  with relatively positioned <div>'s or <layers>'s - it will puke.
       */
      obj.document.open ();
      obj.document.write (html_string);
      obj.document.close ();
    }
}


// dropdownCellId - the <td> id where the dropdown is in
// selectName - the <select> name
// selectID - the <select> id
// selectText - the empty option value text (ie: "Choose One", "Select"... etc; not displayed if empty)
// optionList - the list of arguments for <option> values (ie: "value1", 1, "value2", 2, etc.)
// if only one option is given, a hidden variable is set (rather than a one-option menu being displayed)
function newDropdownWithValues(dropdownCellId, selectName, selectID, selectText, changeAction, optionList) {
    var dropdownCell = document.getElementById(dropdownCellId);
    var selectBox;
    // There must be at least the selectText to create a new dropdown
    if (arguments.length > 3) {
        if (arguments.length > 7) { 
            var numOfOptions = arguments.length - 1;
						//selectBox = '<select name="' + selectName + '" id="' + selectID + '">"';
						// selectBox = '<select name="' + selectName + '" id="' + selectID + '" class="commerce_size">"';
						
						if( changeAction != "" ) {
							selectBox = '<select name="' + selectName + '" id="' + selectID + '" class="commerce_size" onchange="' + changeAction + '">"';
						}
						else {
							selectBox = '<select name="' + selectName + '" id="' + selectID + '" class="commerce_size">"';
						}
																		
            // Set the first option to be empty, with selectText
            if (selectText != "") {
                selectBox += '<option value="">' + selectText + '</option>';
            }
            // loop through and set the rest of the options (increments of 2)
            for (var i = 5; i < numOfOptions; i++) { 
                selectBox += '<option value="' + arguments[i] + '">' + arguments[i + 1] + '</option>';
                i++;
            }
            selectBox += '</select>';
            domSetInnerHTML(dropdownCell, selectBox);
        } else {
            document.getElementById(selectName).value = arguments[5]; 
        }
    }
}

// selectId - the id of the <select>
// optionValue - the value of <option> that you want it changed to
function populateDropdown(selectId, optionValue) {
    var field;
    var selected = 0;
    // make sure the <select> exists
    if (document.getElementById(selectId)) {
        field = document.getElementById(selectId);
        // loop through all the options and try to match the option value (not option text)
        for (var i = 0; i < field.options.length; i++) {
            if (field.options[i].value == optionValue) {
                // if found, set the index
                selected = i;
            }
        }
        field.selectedIndex = selected;
    }
}

function changePrice(priceCell, regPrice, salePrice) {
    var cell = document.getElementById(priceCell);
    var priceText;

    //if (salePrice != regPrice) {
		if (salePrice > '') {
        priceText = '<span class="hasStrike">' + regPrice + '</span>&nbsp;&nbsp;<span class="redColor">' + salePrice + '</span>';
    } else {
        priceText = '<span class="blueColor">'  + regPrice + '</span>';
    }

    domSetInnerHTML(cell, priceText);
}

// Permite obtener un campo indicando su nombre
function getAll(FieldName)
{
	var i = 0;
	var form = document.forms[i];
	while (form != null)
	{
		if (eval("form." + FieldName) != null) {
			return (eval("form." + FieldName));
		}
		form = document.forms[i];
		i++;
	}
	
	if (document.getElementById(FieldName) != null)
	{
			return (document.getElementById(FieldName));
	}
	
	i = 0;
	var objImage = document.images[i];
	while (objImage != null)
	{
		if (eval("objImage." + FieldName) != null) {
			return (eval("objImage." + FieldName));
		}
		objImage = document.images[i];
		i++;
	}
	
	return null;
}  


function strlen (string)
{
	return (string+'').length;
}

// Permite ocultar un DIV
function hidediv()
{
	if (document.getElementById) { // DOM3 = IE5, NS6
		document.getElementById('hideShow').style.visibility = 'hidden';
	}
	else {
		if (document.layers) { // Netscape 4
			document.hideShow.visibility = 'hidden';
		}
		else { // IE 4
			document.all.hideShow.style.visibility = 'hidden';
		}
	}
}

// Permite mostrar un DIV oculto
function showdiv()
{
	if (document.getElementById) { // DOM3 = IE5, NS6
		document.getElementById('hideShow').style.visibility = 'visible';
	}
	else {
		if (document.layers) { // Netscape 4
			document.hideShow.visibility = 'visible';
		}
		else { // IE 4
			document.all.hideShow.style.visibility = 'visible';
		}
	}
}


// @@@ VCORREA 20090321 : Recibe una cadena con entidades HTML y las convierte al texto correspondiente
//                        para mostrar un mensaje, por ejemplo, con un alert().
function ReplaceHtmlEntities( txt )
{
	var result = txt;
	result = result.replace( /&ndash;/g,  '–' );
	result = result.replace( /&mdash;/g,  '—' );
	result = result.replace( /&iexcl;/g,  '¡' );
	result = result.replace( /&iquest;/g, '¿' );
	result = result.replace( /&quot;/g,   String.fromCharCode(34) );
	result = result.replace( /&ldquo;/g,  '“' );
	result = result.replace( /&rdquo;/g,  '”' );
	result = result.replace( /&lsquo;/g,  '‘' );
	result = result.replace( /&rsquo;/g,  '’' );
	result = result.replace( /&laquo;/g,  '«' );
	result = result.replace( /&raquo;/g,  '»' );
	result = result.replace( /&nbsp;/g,   ' ' );
	result = result.replace( /&amp;/g,    '&' );
	result = result.replace( /&cent;/g,   '¢' );
	result = result.replace( /&copy;/g,   '©' );
	result = result.replace( /&divide;/g, '÷' );
	result = result.replace( /&gt;/g,     '>' );
	result = result.replace( /&lt;/g,     '<' );
	result = result.replace( /&micro;/g,  'µ' );
	result = result.replace( /&middot;/g, '·' );
	result = result.replace( /&para;/g,   '¶' );
	result = result.replace( /&plusmn;/g, '±' );
	result = result.replace( /&euro;/g,   '€' );
	result = result.replace( /&pound;/g,  '£' );
	result = result.replace( /&reg;/g,    '®' );
	result = result.replace( /&sect;/g,   '§' );
	result = result.replace( /&yen;/g,    '¥' );
	result = result.replace( /&aacute;/g, 'á' );
	result = result.replace( /&agrave;/g, 'à' );
	result = result.replace( /&acirc;/g,  'â' );
	result = result.replace( /&aring;/g,  'å' );
	result = result.replace( /&atilde;/g, 'ã' );
	result = result.replace( /&auml;/g,   'ä' );
	result = result.replace( /&aelig;/g,  'æ' );
	result = result.replace( /&ccedil;/g, 'ç' );
	result = result.replace( /&eacute;/g, 'é' );
	result = result.replace( /&egrave;/g, 'è' );
	result = result.replace( /&ecirc;/g,  'ê' );
	result = result.replace( /&euml;/g,   'ë' );
	result = result.replace( /&iacute;/g, 'í' );
	result = result.replace( /&igrave;/g, 'ì' );
	result = result.replace( /&icirc;/g,  'î' );
	result = result.replace( /&iuml;/g,   'ï' );
	result = result.replace( /&ntilde;/g, 'ñ' );
	result = result.replace( /&oacute;/g, 'ó' );
	result = result.replace( /&ograve;/g, 'ò' );
	result = result.replace( /&ocirc;/g,  'ô' );
	result = result.replace( /&oslash;/g, 'ø' );
	result = result.replace( /&otilde;/g, 'õ' );
	result = result.replace( /&ouml;/g,   'ö' );
	result = result.replace( /&szlig;/g,  'ß' );
	result = result.replace( /&uacute;/g, 'ú' );
	result = result.replace( /&ugrave;/g, 'ù' );
	result = result.replace( /&ucirc;/g,  'û' );
	result = result.replace( /&uuml;/g,   'ü' );
	result = result.replace( /&yuml;/g,   'ÿ' );
	result = result.replace( /&Aacute;/g, 'Á' );
	result = result.replace( /&Agrave;/g, 'À' );
	result = result.replace( /&Acirc;/g,  'Â' );
	result = result.replace( /&Aring;/g,  'Å' );
	result = result.replace( /&Atilde;/g, 'Ã' );
	result = result.replace( /&Auml;/g,   'Ä' );
	result = result.replace( /&AElig;/g,  'Æ' );
	result = result.replace( /&Ccedil;/g, 'Ç' );
	result = result.replace( /&Eacute;/g, 'É' );
	result = result.replace( /&Egrave;/g, 'È' );
	result = result.replace( /&Ecirc;/g,  'Ê' );
	result = result.replace( /&Euml;/g,   'Ë' );
	result = result.replace( /&Iacute;/g, 'Í' );
	result = result.replace( /&Igrave;/g, 'Ì' );
	result = result.replace( /&Icirc;/g,  'Î' );
	result = result.replace( /&Iuml;/g,   'Ï' );
	result = result.replace( /&Ntilde;/g, 'Ñ' );
	result = result.replace( /&Oacute;/g, 'Ó' );
	result = result.replace( /&Ograve;/g, 'Ò' );
	result = result.replace( /&Ocirc;/g,  'Ô' );
	result = result.replace( /&Oslash;/g, 'Ø' );
	result = result.replace( /&Otilde;/g, 'Õ' );
	result = result.replace( /&Ouml;/g,   'Ö' );
	result = result.replace( /&Uacute;/g, 'Ú' );
	result = result.replace( /&Ugrave;/g, 'Ù' );
	result = result.replace( /&Ucirc;/g,  'Û' );
	result = result.replace( /&Uuml;/g,   'Ü' );

	return result;
}


// @@@ VCORREA 20090321 : Función 'trim', para eliminar los espacios anteriores y posteriores de una cadena.
//                        NOTA: Tomada de la función 'trim10' en: http://blog.stevenlevithan.com/archives/faster-trim-javascript
function trim( str )
{
	var whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
	for (var i = 0; i < str.length; i++) {
		if (whitespace.indexOf(str.charAt(i)) === -1) {
			str = str.substring(i);
			break;
		}
	}
	for (i = str.length - 1; i >= 0; i--) {
		if (whitespace.indexOf(str.charAt(i)) === -1) {
			str = str.substring(0, i + 1);
			break;
		}
	}
	return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}


// @@@ VCORREA 20090321 : Añadimos una función (que hemos copiado de otro sitio) que permite realizar una búsqueda binaria de un 
//                        elemento alfanumérico en un array ordenado, teniendo la opción de ignorar mayúsculas y minúsculas.
//
// Devuelve la posición dentro del array 'haystack' del elemento 'needle' encontrado o -1 si no lo encuentra.
// MUY IMPORTANTE: El array debe estar ordenado.
//
// @@@ VCORREA 20090926 : Renombrada la función 'typeOf' como 'LibTypeOf'.
//
function searchArrayText( needle, haystack, case_insensitive )
{
  if( LibTypeOf( haystack ) === 'undefined'  ||  !haystack.length )  { return -1; }

  case_insensitive = ( ( LibTypeOf( case_insensitive ) === 'undefined' || case_insensitive ) ? true : false );
  needle = ( case_insensitive ? needle.toLowerCase() : needle );

  var high = haystack.length - 1;
  var low = 0;

  while( low <= high ) {
    var mid = parseInt( ( low + high ) / 2 );
    element = ( case_insensitive ? haystack[ mid ].toLowerCase() : haystack[ mid ] );
    if( element > needle ) {
      high = mid - 1;
    } else if( element < needle ) {
      low = mid + 1;
    } else {
      return mid;
    }
  }

  return -1;
};


// @@@ VCORREA 20090927 : Nueva función.
//
// Devuelve la posición dentro del array 'haystack' del elemento con el valor 'needle' o 'false' si no lo encuentra.
// El valor de 'needle' debe ser de texto.
// NOTA 1: Admite arrays asociativos.
// NOTA 2: No es necesario que el array esté ordenado.
//
function searchArrayText2( needle, haystack, case_insensitive )
{
  if( LibTypeOf( haystack ) === 'undefined' )  { return false; }

  case_insensitive = ( ( LibTypeOf( case_insensitive ) === 'undefined' || case_insensitive ) ? true : false );
  needle = ( case_insensitive ? needle.toLowerCase() : String( needle ) );

  for( var Index in haystack ) {
    if( needle == ( case_insensitive ? haystack[ Index ].toLowerCase() : haystack[ Index ] ) )  { return Index; }
  }
  return false;
}


// Devuelve la posición dentro del array 'haystack' del elemento 'needle' encontrado o -1 si no lo encuentra.
// Si el array es multidimensional se buscará en la primera dimensión.
// MUY IMPORTANTE: El array debe estar ordenado.
//
// @@@ VCORREA 20090321 : Modificación sobre la función 'searchArrayText' para que busque un número entero en lugar de un texto.
// @@@ VCORREA 20090926 : Renombrada la función 'typeOf' como 'LibTypeOf'.
//
function searchArrayInt( needle, haystack )
{
  if( typeof( haystack ) === 'undefined'  ||  !haystack.length )  { return -1; }

  var high = haystack.length - 1;
  var low = 0;
  var multidimensional = ( LibTypeOf( haystack[0] ) === 'array' ? true : false );

  while( low <= high ) {
    var mid = parseInt( ( low + high ) / 2 );
		if( multidimensional ) {
    	element = haystack[ mid ][ 0 ];
		} else {
    	element = haystack[ mid ];
		}
    if( element > needle ) {
      high = mid - 1;
    } else if( element < needle ) {
      low = mid + 1;
    } else {
      return mid;
    }
  }

  return -1;
};


// @@@ VCORREA 20090927 : Nueva función.
//
// Devuelve la posición dentro del array 'haystack' del elemento con el valor 'needle' o 'false' si no lo encuentra.
// El valor de 'needle' debe ser numérico.
// NOTA 1: Admite arrays asociativos.
// NOTA 2: No es necesario que el array esté ordenado.
//
function searchArrayInt2( needle, haystack )
{
  if( LibTypeOf( haystack ) === 'undefined' )  { return false; }

  var multidimensional = ( LibTypeOf( haystack[0] ) === 'array' ? true : false );

  for( var Index in haystack ) {
    if( multidimensional ) {
      if( needle == haystack[ Index ][ 0 ] )  { return Index; }
    } else {
      if( needle == haystack[ Index ] )  { return Index; }
    }
  }
  return false;
}


// @@@ VCORREA 20090927 : Nueva función.
//
// Devuelve la posición dentro del array 'haystack' del elemento con el índice 'needle' encontrado o 'false' si no lo encuentra.
// NOTA: Admite arrays asociativos.
//
function searchArrayKey( needle, haystack, case_insensitive )
{
  if( LibTypeOf( haystack ) === 'undefined' )  { return false; }

  case_insensitive = ( ( LibTypeOf( case_insensitive ) === 'undefined' || case_insensitive ) ? true : false );
  
  if( LibTypeOf( needle ) == 'string' ) {
    needle = ( case_insensitive ? needle.toLowerCase() : String( needle ) );

    for( var Index in haystack ) {
      if( needle == ( case_insensitive ? String( Index ).toLowerCase() : String( Index ) ) )  { return Index; }
    }
  } else {
    for( var Index in haystack ) {
      if( needle == Index )  { return Index; }
    }
  }

  return false;
}


// @@@ VCORREA 20090321 : Comprueba si una fecha es válida. Puede recibir como argumento un texto o un objeto Textbox.
//
function isDate( dateStr )
{
  var datePat = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/;
  var matchArray = dateStr.match( datePat ); // is the format ok?
  if( matchArray == null )  { return false; }
  
  month = matchArray[1]; // parse date into variables
  day = matchArray[3];
  year = matchArray[5];
  
  if( month < 1  ||  month > 12 )  { return false; }
  if( day < 1  ||  day > 31 )  { return false; }
  if( ( month == 4  ||  month == 6  ||  month == 9  ||  month == 11 )  &&  day == 31 )  { return false; }
  if( month == 2 ) {
    //var isleap = ( year % 4 == 0  &&  ( year % 100 != 0  ||  year % 400 == 0 ) );
    var isleap = ( year % 4 == 0 );
    if( day > 29  ||  ( day == 29  &&  !isleap ) )  { return false; }
  }

  return true; // date is valid
}


// @@@ VCORREA 20090321 : Añadimos una función (que hemos copiado de otro sitio) que permite resolver los problemas del operador 'typeof',
//                        que devuelve 'object' cuando el argumento es un array o null.
//
// Devuelve lo mismo que el operador typeof salvo en el caso de los arrays que devuelve 'array' y de null, que devuelve 'null'.
//
// @@@ VCORREA 20090926 : Renombrada la función 'typeOf' como 'LibTypeOf'.
// @@@ VCORREA 20091118 : Se modifica para que sea compatible con IE 6 y 7.
//
//function typeOf( value )
function LibTypeOf( value )
{
  var s = typeof( value );
  if( s === 'object' ) {
    if( value ) {
      //if( typeof( value.length ) === 'number' && !( value.propertyIsEnumerable( 'length' ) ) && typeof( value.splice ) === 'function' ) {         
      if( value instanceof Array ) {
        s = 'array';
      }
    } else {
      s = 'null';
    }
  }
  return s;
}


// @@@ VCORREA 20090321 : Función que devuelve el valor de una variable recibida por parámetro.
//                        Si no la encuentra devuelve NULL.
//
function GetVar( a_var )
{
  var pos = String( window.location.href ).indexOf( '?' );
  var argumentos = ( pos >= 0 ) ? String( window.location.href ).substr( pos + 1 ) : String( '' );
  if( argumentos.charAt( argumentos.length - 1 ) != '&' )  { argumentos = argumentos.concat( '&' ); }

  while( true ) {
    pos = argumentos.indexOf( '&' );  // Busca el final de la variable.
    if( pos < 0 )  { break; }

    var varActual = argumentos.substring( 0, pos );   // Guardamos la variable encontrada junto con su valor.
    argumentos = argumentos.substr( pos + 1 );        // Eliminamos la variable actual para no volver a encontrarla.

    pos = varActual.indexOf( '=' );  if( pos < 0 )  { continue; }
    var nombreVar = varActual.substring( 0, pos );    // Extraemos el nombre de la variable.
    if( nombreVar == a_var )
    { // Encontrada!!
      return decodeURI( varActual.substr( pos + 1 ) );
    }
  }

  return null;
}


// @@@ VCORREA 20090812 : Exporta la página actual a Excel
//
function LibExportToExcel()  { return LibExportTo_Mode( 'excel' ); }
function LibExportToCSV()    { return LibExportTo_Mode( 'csv'   ); }
function LibExportTo_Mode( mode )
{
  var url = window.location.href;
  var pos = url.indexOf( '?' );
  if( pos >= 0 ) { // Si la url SÍ tiene parámetros...
    var url2 = url.substring( 0, pos ) + '&' + url.substr( pos + 1 ) + '&';
    var pos2 = url2.indexOf( '&ReportMode=' );
    if( pos2 >= 0 ) { // Si la url ya tiene el parámetro 'ReportMode' lo sustituimos.
      var pos3 = url2.indexOf( '&', pos2 + 1 );
      url = url.substring( 0, pos2 + 12 ) + mode + url.substr( pos3 );
    } else {  // Si la url NO tiene el parámetro 'ReportMode' lo añadimos.
      url += '&ReportMode=' + mode;
    }
  } else {  // Si la url NO tiene parámetros...
    url += '?ReportMode=' + mode;
  }

  LibWindowPopup( url, 'export', 800, 600 );
  return false;
}


// @@@ VCORREA 20090321 : Función que devuelve el nombre del script actual, tomándolo de la URL.
//                        El nombre del script sí tiene extensión pero no ruta.
//
function GetScriptName()
{
  var pos = String( window.location.href ).indexOf( '?' );
  if( pos >= 0 ) {
    return document.URL.substring( document.URL.lastIndexOf("\/") + 1, pos );
  } else {
    return document.URL.substring( document.URL.lastIndexOf("\/") + 1 );
  }
}


// @@@ VCORREA 20090426 : Nueva función para rellenar un listbox con los valores de un array.
//
// Parámetros:
//  - objListbox    : nombre u objeto de tipo Listbox.  Si es un texto se buscará el objeto por ID.
//  - aValues       : array de datos. Cada elemento es a su vez un array de dos elementos. El primero será el texto descriptivo de la opción y el segundo el ID.
//  - cSelectOption : texto de la opción 'Seleccionar valor...'.  Si está vacío no se añade esta opción.
//  - nOptionsWidth : ancho forzado de las opciones (no del propio listbox).  Si vale 0 o vacío se ignora.
//
// @@@ VCORREA 20090926 : Renombrada la función 'typeOf' como 'LibTypeOf'.
// @@@ VCORREA 20091030 : Damos la posibilidad de forzar el ancho de las opciones.
//                        No se mostraba correctamente el texto de la opción vacía.
//
function FillListbox( objListbox, aValues, cSelectOption, nOptionsWidth )
{
  if( LibTypeOf( nOptionsWidth ) === 'undefined' )  { nOptionsWidth = 0; }

  // Si no es un objeto suponemos que es un texto con el ID del objeto.
  if( 'object' != LibTypeOf( objListbox ) )  { objListbox = document.getElementById( objListbox ); }
  if( 'object' != LibTypeOf( objListbox ) )  { alert( 'Listbox object not found' );  return; }

  // Vaciamos el listbox.
  objListbox.options.length = 0;

  // Añadimos un elemento vacío (si se indica un texto).
  if( cSelectOption > '' ) {
    var newOption = new Option( cSelectOption, '' );
    if( nOptionsWidth > 0 )  { newOption.style.width = nOptionsWidth.toString() + 'px'; }
    objListbox.options[ objListbox.options.length ] = newOption;
  }

  // Añadimos las nuevas entradas al listbox.
  for( var n = 0; n < aValues.length; n++ ) {
    var newOption = new Option( aValues[ n ][ 0 ], aValues[ n ][ 1 ] );
    if( nOptionsWidth > 0 )  { newOption.style.width = nOptionsWidth.toString() + 'px'; }
    objListbox.options[ objListbox.options.length ] = newOption;
  }
}


// @@@ VCORREA 20090505 : Nueva función.
//
// Busca un Button por ID y copia varias propiedades en otro de destino ('href', 'onclick' y contenido).
//
// @@@ VCORREA 20090926 : Renombrada la función 'typeOf' como 'LibTypeOf'.
//
function LibCopyButton( SourceID, TargetID, CopyText, CopyImage )
{
  var objSource = document.getElementById( 'LibButtonLink_' + SourceID );
  var objTarget = document.getElementById( 'LibButtonLink_' + TargetID );
  if( 'object' == LibTypeOf( objSource )  &&  'object' == LibTypeOf( objTarget ) ) {
    objTarget.href = objSource.href;
    objTarget.onclick = objSource.onclick;
    
    var content = '';
    if( CopyImage  &&  CopyText ) {
      content = objSource.innerHTML;
    } else if( CopyImage ) {
      content += document.getElementById( 'LibButtonImg_' + SourceID ).innerHTML;
    } else if( CopyText ) {
      content += document.getElementById( 'LibButtonText_' + SourceID ).innerHTML;
    }
    objTarget.innerHTML = content;
  }
}


// @@@ VCORREA 20090514 : Nueva función.
//
// Devuelve el valor de la opción seleccionada.
//
function LibGetCheckedValue( radioObj )
{
  if( !radioObj )  { return ""; }
  
  var radioLength = radioObj.length;
  if( radioLength == undefined ) {
    if( radioObj.checked )  { return radioObj.value; }
    else                    { return ""; }
  }
  
  for( var i = 0; i < radioLength; i++ ) {
    if( radioObj[ i ].checked ) {
      return radioObj[ i ].value;
    }
  }
  return "";
}

function left( str, n )
{
	if( n <= 0 )                         { return ""; }
	else if( n > String( str ).length )  { return str; }
	else                                 { return String( str ).substring( 0, n ); }
}

function right( str, n )
{
  if( n <= 0 ) { return ""; }
  else if( n > String( str ).length )  { return str; }
  else {
    var iLen = String( str ).length;
    return String( str ).substring( iLen, iLen - n );
  }
}

// @@@ VCORREA 20090901 : Nueva función.
//
// Función que valida los datos introducidos en los campos de un formulario.
// NOTA: Hace uso de AJAX.
//
// @@@ VCORREA 20090919 : Hacemos que el ID del formulario y el idioma sean automáticos (se toman del propio formulario).
//
//function LibFormCheck( objForm, ContentID, LanguageID )
function LibFormCheck( objForm )
{
  var result = true;
  var CheckResult = ajaxRunDirect( 'LibPageClassFormCheck', LibGetFormFields( objForm ), objForm.elements[ 'SysContentID' ].value, objForm.elements[ 'SysLanguageID' ].value );
  if( CheckResult > '' ) { eval( CheckResult ); }
  return result;
}


// @@@ VCORREA 20090831 : Nueva función.
//
// Devuelve un array asociativo de los valores de los campos de un formulario. Los índices del array serán los nombres de los campos.
// Recibe el objeto 'form' del que se quieren obtener los campos.
//
// @@@ VCORREA 20091009 : Hacemos que los botones de tipo 'radio' tomen su valor correcto.
//
function LibGetFormFields( objForm )
{
  var result = new Array();
  var Radios = new Array();

  // Recorremos todos los controles del formulario, procesando todos salvo los de tipo 'radio' de los que sólo tomaremos nota.
  for( var n = 0; n < objForm.elements.length; n++ ) {
    var obj = objForm.elements[ n ];
    if( obj.type == 'checkbox' ) {
      result[ obj.name ] = ( obj.checked ? true : false );
    } else if( obj.type == 'radio' ) {
      Radios[ obj.name ] = '';  // Inicializamos el valor del radio.
    } else {
      result[ obj.name ] = obj.value;
    }
  }

  // Procesamos todos los 'radio' encontrados.
  for( RadioName in Radios ) {
    for( var n = 0; n < objForm.elements.length; n++ ) {
      var obj = objForm.elements[ n ];
      if( obj.type == 'radio'  &&  obj.checked ) {  // Si están marcados tomamos nota de su valor.
        Radios[ RadioName ] = obj.value;
      }
    }
    result[ RadioName ] = Radios[ RadioName ];
  }

  return result;
}


// @@@ VCORREA 20090831 : Nueva función.
//
// Devuelve un array con los nombres de los campos de un formulario.
// Recibe el objeto 'form' del que se quieren obtener los campos.
//
function LibGetFormFieldsNames( objForm )
{
  var result = new Array();
  for( var n = 0; n < objForm.elements.length; n++ ) {
    var obj = objForm.elements[ n ];
    result[ n ] = obj.name;
  }
  return result;
}

// @@@ VCORREA 20090831 : Nueva función.
//
// Devuelve un array con los valores de los campos de un formulario.
// Recibe el objeto 'form' del que se quieren obtener los campos.
//
function LibGetFormFieldsValues( objForm )
{
  var result = new Array();
  for( var n = 0; n < objForm.elements.length; n++ ) {
    var obj = objForm.elements[ n ];
    if( obj.type == 'checkbox' ) {
      result[ n ] = ( obj.checked ? true : false );
    } else {
      result[ n ] = obj.value;
    }
  }
  return result;
}

function get_html_translation_table (table, quote_style) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philip Peterson
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: noname
    // +   bugfixed by: Alex
    // +   bugfixed by: Marco
    // +   bugfixed by: madipta
    // +   improved by: KELAN
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Frank Forte
    // +   bugfixed by: T.Wild
    // +      input by: Ratheous
    // %          note: It has been decided that we're not going to add global
    // %          note: dependencies to php.js, meaning the constants are not
    // %          note: real constants, but strings instead. Integers are also supported if someone
    // %          note: chooses to create the constants themselves.
    // *     example 1: get_html_translation_table('HTML_SPECIALCHARS');
    // *     returns 1: {'"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;'}
    
    var entities = {}, hash_map = {}, decimal = 0, symbol = '';
    var constMappingTable = {}, constMappingQuoteStyle = {};
    var useTable = {}, useQuoteStyle = {};
    
    // Translate arguments
    constMappingTable[0]      = 'HTML_SPECIALCHARS';
    constMappingTable[1]      = 'HTML_ENTITIES';
    constMappingQuoteStyle[0] = 'ENT_NOQUOTES';
    constMappingQuoteStyle[2] = 'ENT_COMPAT';
    constMappingQuoteStyle[3] = 'ENT_QUOTES';
 
    useTable       = !isNaN(table) ? constMappingTable[table] : table ? table.toUpperCase() : 'HTML_SPECIALCHARS';
    useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT';
 
    if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
        throw new Error("Table: "+useTable+' not supported');
        // return false;
    }
 
    entities['38'] = '&amp;';
    if (useTable === 'HTML_ENTITIES') {
        entities['160'] = '&nbsp;';
        entities['161'] = '&iexcl;';
        entities['162'] = '&cent;';
        entities['163'] = '&pound;';
        entities['164'] = '&curren;';
        entities['165'] = '&yen;';
        entities['166'] = '&brvbar;';
        entities['167'] = '&sect;';
        entities['168'] = '&uml;';
        entities['169'] = '&copy;';
        entities['170'] = '&ordf;';
        entities['171'] = '&laquo;';
        entities['172'] = '&not;';
        entities['173'] = '&shy;';
        entities['174'] = '&reg;';
        entities['175'] = '&macr;';
        entities['176'] = '&deg;';
        entities['177'] = '&plusmn;';
        entities['178'] = '&sup2;';
        entities['179'] = '&sup3;';
        entities['180'] = '&acute;';
        entities['181'] = '&micro;';
        entities['182'] = '&para;';
        entities['183'] = '&middot;';
        entities['184'] = '&cedil;';
        entities['185'] = '&sup1;';
        entities['186'] = '&ordm;';
        entities['187'] = '&raquo;';
        entities['188'] = '&frac14;';
        entities['189'] = '&frac12;';
        entities['190'] = '&frac34;';
        entities['191'] = '&iquest;';
        entities['192'] = '&Agrave;';
        entities['193'] = '&Aacute;';
        entities['194'] = '&Acirc;';
        entities['195'] = '&Atilde;';
        entities['196'] = '&Auml;';
        entities['197'] = '&Aring;';
        entities['198'] = '&AElig;';
        entities['199'] = '&Ccedil;';
        entities['200'] = '&Egrave;';
        entities['201'] = '&Eacute;';
        entities['202'] = '&Ecirc;';
        entities['203'] = '&Euml;';
        entities['204'] = '&Igrave;';
        entities['205'] = '&Iacute;';
        entities['206'] = '&Icirc;';
        entities['207'] = '&Iuml;';
        entities['208'] = '&ETH;';
        entities['209'] = '&Ntilde;';
        entities['210'] = '&Ograve;';
        entities['211'] = '&Oacute;';
        entities['212'] = '&Ocirc;';
        entities['213'] = '&Otilde;';
        entities['214'] = '&Ouml;';
        entities['215'] = '&times;';
        entities['216'] = '&Oslash;';
        entities['217'] = '&Ugrave;';
        entities['218'] = '&Uacute;';
        entities['219'] = '&Ucirc;';
        entities['220'] = '&Uuml;';
        entities['221'] = '&Yacute;';
        entities['222'] = '&THORN;';
        entities['223'] = '&szlig;';
        entities['224'] = '&agrave;';
        entities['225'] = '&aacute;';
        entities['226'] = '&acirc;';
        entities['227'] = '&atilde;';
        entities['228'] = '&auml;';
        entities['229'] = '&aring;';
        entities['230'] = '&aelig;';
        entities['231'] = '&ccedil;';
        entities['232'] = '&egrave;';
        entities['233'] = '&eacute;';
        entities['234'] = '&ecirc;';
        entities['235'] = '&euml;';
        entities['236'] = '&igrave;';
        entities['237'] = '&iacute;';
        entities['238'] = '&icirc;';
        entities['239'] = '&iuml;';
        entities['240'] = '&eth;';
        entities['241'] = '&ntilde;';
        entities['242'] = '&ograve;';
        entities['243'] = '&oacute;';
        entities['244'] = '&ocirc;';
        entities['245'] = '&otilde;';
        entities['246'] = '&ouml;';
        entities['247'] = '&divide;';
        entities['248'] = '&oslash;';
        entities['249'] = '&ugrave;';
        entities['250'] = '&uacute;';
        entities['251'] = '&ucirc;';
        entities['252'] = '&uuml;';
        entities['253'] = '&yacute;';
        entities['254'] = '&thorn;';
        entities['255'] = '&yuml;';
    }
 
    if (useQuoteStyle !== 'ENT_NOQUOTES') {
        entities['34'] = '&quot;';
    }
    if (useQuoteStyle === 'ENT_QUOTES') {
        entities['39'] = '&#39;';
    }
    entities['60'] = '&lt;';
    entities['62'] = '&gt;';
 
 
    // ascii decimals to real symbols
    for (decimal in entities) {
        symbol = String.fromCharCode(decimal);
        hash_map[symbol] = entities[decimal];
    }
    
    return hash_map;
}

function htmlentities (string, quote_style) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: nobbler
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Ratheous
    // -    depends on: get_html_translation_table
    // *     example 1: htmlentities('Kevin & van Zonneveld');
    // *     returns 1: 'Kevin &amp; van Zonneveld'
    // *     example 2: htmlentities("foo'bar","ENT_QUOTES");
    // *     returns 2: 'foo&#039;bar'
 
    var hash_map = {}, symbol = '', tmp_str = '', entity = '';
    tmp_str = string.toString();
    
    if (false === (hash_map = this.get_html_translation_table('HTML_ENTITIES', quote_style))) {
        return false;
    }
    hash_map["'"] = '&#039;';
    for (symbol in hash_map) {
        entity = hash_map[symbol];
        tmp_str = tmp_str.split(symbol).join(entity);
    }
    
    return tmp_str;
}

function checkEnter()
{
  if( event.keyCode == 13 ) {
    document.forms[0].submit();
    return false;
  }
  return true;
}

function nl2br( str, is_xhtml )
{
  // Converts newlines to HTML line breaks  
  // 
  // version: 909.322
  // discuss at: http://phpjs.org/functions/nl2br
  // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // +   improved by: Philip Peterson
  // +   improved by: Onno Marsman
  // +   improved by: Atli Þór
  // +   bugfixed by: Onno Marsman
  // +      input by: Brett Zamir (http://brett-zamir.me)
  // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // *     example 1: nl2br('Kevin\nvan\nZonneveld');
  // *     returns 1: 'Kevin<br />\nvan<br />\nZonneveld'
  // *     example 2: nl2br("\nOne\nTwo\n\nThree\n", false);
  // *     returns 2: '<br>\nOne<br>\nTwo<br>\n<br>\nThree<br>\n'
  // *     example 3: nl2br("\nOne\nTwo\n\nThree\n", true);
  // *     returns 3: '<br />\nOne<br />\nTwo<br />\n<br />\nThree<br />\n'
  var breakTag = '<br />';
  if( typeof is_xhtml != 'undefined'  &&  !is_xhtml )  { breakTag = '<br>'; }
  return String( str ).replace(/([^>]?)\n/g, '$1' + breakTag + '\n' );
}

function str_repeat( input, multiplier )
{
  // Returns the input string repeat mult times  
  // 
  // version: 909.322
  // discuss at: http://phpjs.org/functions/str_repeat
  // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // +   improved by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  // *     example 1: str_repeat('-=', 10);
  // *     returns 1: '-=-=-=-=-=-=-=-=-=-='
  return new Array( multiplier + 1 ).join( input );
}

function str_replace( search, replace, subject, count )
{
  // Replaces all occurrences of search in haystack with replace  
  // 
  // version: 909.322
  // discuss at: http://phpjs.org/functions/str_replace
  // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // +   improved by: Gabriel Paderni
  // +   improved by: Philip Peterson
  // +   improved by: Simon Willison (http://simonwillison.net)
  // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  // +   bugfixed by: Anton Ongson
  // +      input by: Onno Marsman
  // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // +    tweaked by: Onno Marsman
  // +      input by: Brett Zamir (http://brett-zamir.me)
  // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // +   input by: Oleg Eremeev
  // +   improved by: Brett Zamir (http://brett-zamir.me)
  // +   bugfixed by: Oleg Eremeev
  // %          note 1: The count parameter must be passed as a string in order
  // %          note 1:  to find a global variable in which the result will be given
  // *     example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
  // *     returns 1: 'Kevin.van.Zonneveld'
  // *     example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
  // *     returns 2: 'hemmo, mars'
  var i = 0, j = 0, temp = '', repl = '', sl = 0, fl = 0,
      f = [].concat(search),
      r = [].concat(replace),
      s = subject,
      ra = r instanceof Array, sa = s instanceof Array;
  s = [].concat(s);
  if (count) {
    this.window[count] = 0;
  }

  for (i=0, sl=s.length; i < sl; i++) {
    if (s[i] === '') {
      continue;
    }
    for (j=0, fl=f.length; j < fl; j++) {
      temp = s[i]+'';
      repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
      s[i] = (temp).split(f[j]).join(repl);
      if (count && s[i] !== temp) {
        this.window[count] += (temp.length-s[i].length)/f[j].length;}
    }
  }
  return sa ? s : s[0];
}

function implode (glue, pieces) {
    // Joins array elements placing glue string between items and return one string  
    // 
    // version: 911.718
    // discuss at: http://phpjs.org/functions/implode
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Waldo Malqui Silva
    // +   improved by: Itsacon (http://www.itsacon.net/)
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // *     example 1: implode(' ', ['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: 'Kevin van Zonneveld'
    // *     example 2: implode(' ', {first:'Kevin', last: 'van Zonneveld'});
    // *     returns 2: 'Kevin van Zonneveld'
    var i = '', retVal='', tGlue='';
    if (arguments.length === 1) {
        pieces = glue;
        glue = '';
    }
    if (typeof(pieces) === 'object') {
        if (pieces instanceof Array) {
            return pieces.join(glue);
        }
        else {
            for (i in pieces) {
                retVal += tGlue + pieces[i];
                tGlue = glue;
            }
            return retVal;
        }
    }
    else {
        return pieces;
    }
}

function number_format( number, decimals, dec_point, thousands_sep )
{
  // Formats a number with grouped thousands
  //
  // version: 906.1806
  // discuss at: http://phpjs.org/functions/number_format
  // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // +     bugfix by: Michael White (http://getsprink.com)
  // +     bugfix by: Benjamin Lupton
  // +     bugfix by: Allan Jensen (http://www.winternet.no)
  // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  // +     bugfix by: Howard Yeend
  // +    revised by: Luke Smith (http://lucassmith.name)
  // +     bugfix by: Diogo Resende
  // +     bugfix by: Rival
  // +     input by: Kheang Hok Chin (http://www.distantia.ca/)
  // +     improved by: davook
  // +     improved by: Brett Zamir (http://brett-zamir.me)
  // +     input by: Jay Klehr
  // +     improved by: Brett Zamir (http://brett-zamir.me)
  // +     input by: Amir Habibi (http://www.residence-mixte.com/)
  // +     bugfix by: Brett Zamir (http://brett-zamir.me)
  // *     example 1: number_format(1234.56);
  // *     returns 1: '1,235'
  // *     example 2: number_format(1234.56, 2, ',', ' ');
  // *     returns 2: '1 234,56'
  // *     example 3: number_format(1234.5678, 2, '.', '');
  // *     returns 3: '1234.57'
  // *     example 4: number_format(67, 2, ',', '.');
  // *     returns 4: '67,00'
  // *     example 5: number_format(1000);
  // *     returns 5: '1,000'
  // *     example 6: number_format(67.311, 2);
  // *     returns 6: '67.31'
  // *     example 7: number_format(1000.55, 1);
  // *     returns 7: '1,000.6'
  // *     example 8: number_format(67000, 5, ',', '.');
  // *     returns 8: '67.000,00000'
  // *     example 9: number_format(0.9, 0);
  // *     returns 9: '1'
  // *     example 10: number_format('1.20', 2);
  // *     returns 10: '1.20'
  // *     example 11: number_format('1.20', 4);
  // *     returns 11: '1.2000'
  // *     example 12: number_format('1.2000', 3);
  // *     returns 12: '1.200'
  var n = number, prec = decimals;

  var toFixedFix = function( n, prec ) {
    var k = Math.pow( 10, prec );
    return ( Math.round( n * k ) / k ).toString();
  };

  n = !isFinite( +n ) ? 0 : +n;
  prec = !isFinite( +prec ) ? 0 : Math.abs( prec );
  var sep = ( typeof thousands_sep === 'undefined' ) ? ',' : thousands_sep;
  var dec = ( typeof dec_point === 'undefined' ) ? '.' : dec_point;

  var s = ( prec > 0 ) ? toFixedFix( n, prec ) : toFixedFix( Math.round( n ), prec ); //fix for IE parseFloat(0.55).toFixed(0) = 0;

  var abs = toFixedFix( Math.abs( n ), prec );
  var _, i;

  if( abs >= 1000 ) {
    _ = abs.split(/\D/);
    i = _[0].length % 3 || 3;
    _[0] = s.slice( 0, i + ( n < 0 ) ) + _[ 0 ].slice( i ).replace(/(\d{3})/g, sep + '$1' );
    s = _.join( dec );
  } else {
    s = s.replace( '.', dec );
  }

  var decPos = s.indexOf( dec );
  if( prec >= 1  &&  decPos !== -1  &&  ( s.length - decPos - 1 ) < prec ) {
    s += new Array( prec - ( s.length - decPos - 1 ) ).join( 0 ) + '0';
  } else if( prec >= 1  &&  decPos === -1 ) {
    s += dec + new Array( prec ).join( 0 ) + '0';
  }
  return s;
}

function LibFormatID( value, numChars )
{
  if( LibTypeOf( numChars ) === 'undefined' )  { numChars = 4; }  else  { numChars = Number( numChars ); }
  if( isNaN( numChars ) )  { numChars = 4; }

  var result = String( value );
  if( result.length > numChars )  { return result; }
  result = str_repeat( '0', numChars ) + result;
  return result.substr( result.length - numChars, numChars );
}

function LibFormatMoney( value, format )
{
  if( LibTypeOf( format ) === 'undefined' )  { format = "Normal"; }

	if( format == "Normal" ) {
		var result = number_format( value, 2, '.', ',' );
	} else {
		if( value >= 0 ) {
			var Color = "text_green";
		} else {
			var Color = "text_red";
    }
		result = "<span id='" + Color + "'>" + number_format( value, 2, '.', ',' ) + "</span>";
	}
	return result;
}

function LibFormatNum( value, decimals, format )
{
  if( LibTypeOf( decimals ) === 'undefined' )  { decimals = 0; }
  if( LibTypeOf( format   ) === 'undefined' )  { format   = "#ENG"; }

	if( format == "#ENG" ) {
		return number_format( value, decimals, '.', ',' );
	} else {
		return number_format( value, decimals, ',', '.' );
  }
}

function LibDateToday( Format )
{
  if( LibTypeOf( Format ) === 'undefined' )  { Format = 'ESP'; }

  var today = new Date();
  var Day   = today.getDate();          if( Day   < 10 )  { Day   = '0' + Day.toString();   }
  var Month = today.getMonth() + 1;     if( Month < 10 )  { Month = '0' + Month.toString(); }
  var Year  = today.getYear() + 1900;

  switch( Format.toUpperCase() ) {
    case 'ENG' :
      return Month.toString() + '/' + Day.toString() + '/' + Year.toString();

    case 'ESP' :
    case 'FRA' :
    default    :
      return Day.toString() + '/' + Month.toString() + '/' + Year.toString();
  }
}
