// =========================================================================================
// 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'.
//
function LibWindowPopup(url_page, window_name, w, h)
{
  LibWindowPopupW(url_page, window_name, w, h);
  return false;
}

// Abre una ventana emergente
//@@@ VCORREA 20090417 : Devuelve el nuevo objeto 'window' creado.
//
function LibWindowPopupW(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=no,menubar=no,toolbar=no,resizable=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
//@@@ VCORREA 20090417 : Devuelve 'false'.
//
function LibWindowPopupScroll(url_page, window_name, w, h)
{
  LibWindowPopupScrollW(url_page, window_name, w, h);
  return false;
}

// Abre una ventana emergente con scroll
//@@@ VCORREA 20090417 : Devuelve el nuevo objeto 'window' creado.
//
function LibWindowPopupScrollW(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=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 == "" );
}

// 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.
//
function searchArrayText( needle, haystack, case_insensitive )
{
  if( typeof( haystack ) === 'undefined'  ||  !haystack.length )  { return -1; }

  var high = haystack.length - 1;
  var low = 0;
  case_insensitive = ( ( typeof( case_insensitive ) === 'undefined' || case_insensitive ) ? true : false );
  needle = ( case_insensitive ? needle.toLowerCase() : needle );

  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 20090321 : Modificación sobre la función 'searchArrayText' para que busque un número entero en lugar de un texto.
//
// 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.
//
function searchArrayInt( needle, haystack )
{
  if( typeof( haystack ) === 'undefined'  ||  !haystack.length )  { return -1; }

  var high = haystack.length - 1;
  var low = 0;
  multidimensional = ( typeOf( 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 20090321 : Comprueba si una fecha es válida. Puede recibir como argumento un texto o un objeto Textbox.
//
function isDate( dateStr )
{
	alert( typeof( 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'.
//
function typeOf( value )
{
  var s = typeof value;
  if( s === 'object' ) {
    if( value ) {
      if( typeof value.length === 'number' && 
          !( value.propertyIsEnumerable( 'length' ) ) &&
          typeof value.splice === 'function' ) {         
        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.
//
function FillListbox( objListbox, aValues, cSelectOption )
{
  // Si no es un objeto suponemos que es un texto con el ID del objeto.
  if( 'object' != typeOf( objListbox ) )  { objListbox = document.getElementById( objListbox ); }
  if( 'object' != typeOf( 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 > '' )  { objListbox.options[ objListbox.options.length ] = new Option( '', '' ); }

  // Añadimos las nuevas entradas al listbox.
  for( var n = 0; n < aValues.length; n++ ) {
    objListbox.options[ objListbox.options.length ] = new Option( aValues[ n ][ 0 ], aValues[ n ][ 1 ] );
  }
}


//@@@ VCORREA 20090505 : Nueva función.
//
// Busca un Button por ID y copia varias propiedades en otro de destino ('href', 'onclick' y contenido).
//
function LibCopyButton( SourceID, TargetID, CopyText, CopyImage )
{
  var objSource = document.getElementById( 'LibButtonLink_' + SourceID );
  var objTarget = document.getElementById( 'LibButtonLink_' + TargetID );
  if( 'object' == typeOf( objSource )  &&  'object' == typeOf( 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 "";
}


//@@@ 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.
//
function LibGetFormFields( objForm )
{
  var result = new Array();
  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 {
      result[ obj.name ] = obj.value;
    }
  }
  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;
}

