/*
cpbutil.js
Javascript utility routines

(c)2001-2006 compuBase / Tech COM

@version 1.0.0
@date 01/11/15
@Author Christophe Dubourg

WARNING : contains some accents, MUST be saved as UTF8 !!!!


Last updates:
060929 - NEW SizeObject() to handle IFRAME height change using MouseOver controls
061002 - NEW CpbTab and CpbTabList objects to handle tabs
070403
- Moving duplicated function from SEL.JS and TREE.JS in CPBUTIL.JS,
  Since CPBUTIL.JS is now always included in pages where SEL.JS or TREE.JS are included
*/


var isIE = false;
var isOP = false;
var isNS = false;

try {
  isIE = (navigator.appName.indexOf("Microsoft")>-1);
  isOP = (navigator.appName.indexOf("Opera")>-1);
  isNS = (navigator.appName.indexOf("Netscape")>-1);
} catch (e) {
  ; // nothing special
}

/*
  <tr valign="top" class="mdllist" onMouseOver="this.className='mdlhl'" onMouseOut="this.className='mdllist'">
*/
var SHOW_DEBUG = true;  // show alert messages using debug("message")

var TOP_FRAME_NAME = "CpbTopFrame";
var LEFT_FRAME_NAME = "CpbLeftFrame";
var winNameHelpPopup = "CpbHelpPopup";
var winNameHelpPage = "CpbHelpPage";

var winNameCpyDetail = "cpydetail"; // must match java code
var winNameProdDetail = "cpyProduct"; // must match java code

var ceil = null;  // will be top or parent depending on current window name, to cope with interframe restrictions
/*
  ChD Log window constants and variables
  start lgging with logStart() - also opens the log window
  stop logging with logStop()
*/
trek = false; // NO VAR -

// nav uses isIE and other fields
var nav = new navObject();  // contains everything about the navigator
var isNS4 = (isNS && (nav.version<5));

var cpbSearchVersion = new Array(1,0,0);  // ChD version - can be updated by outer frames (guidedachat...)
var cpbTabs = null;

var CPBDOMAIN = "compubase.net";

//  var allSearchTabs = new Array("divCpbList","divCpbDetail");

/******* CONSTANTS *******/
//var toolWindowHelpPopup = "toolbar=no,titlebar=0,resizable=1,scrollbars=1,status=0,notitlebar,width=320,height=240";
var toolWindowHelpPopup = "toolbar=no,status=no,titlebar=no,resizable=1,scrollbars=1,width=320,height=200";
var toolWindowHelpPopupV = "toolbar=no,status=no,titlebar=no,resizable=1,scrollbars=1,width=320,height=512";
var toolWindowNoSize = "toolbar=no,resizable=1,scrollbars=1,status=1,titlebar=1";
var toolWindowDefParams = toolWindowNoSize + ",width=750,height=580";

/* doAlert() CONSTANTS */
var AL_NYI = "Not yet implemented";
var AL_NotAvailSession = "Not available with your sessions rights";

var CRLF = String.fromCharCode(13,10);
var SPLIT_SEP = ";";

// Placeholder stuff
var PH_PREFIX = "!!JS#";
var PH_PREFIX_LENGTH = PH_PREFIX.length;

var aZipStates = new Array("none","block"); // see zipUnzipLayerObj()
aZipStates[true] = "block";
aZipStates[false] = "none";

var aPlaceHolders = new Array();  // Empty placeholders array - caller page must fill it

rnd.today=new Date(); // Prepare SEED
rnd.seed=rnd.today.getTime(); // Prepare SEED

// consts for DirectSearch V2
var DSEARCH_HIDE_FORM = true;
var DSEARCH_HIDE_RESULTS = true;

var preloaded_images = new Array(); // @seealso preloadImages() below

var divPleaseWait = null;

var userSelClickXMLdoc = null;  // used for CpbList checkboxes

var switchLayerObjs = new Array();  // remember layers visible state - see switchLayer()


// ok I finally added this one (from prototype.js) since we assume navigators are all DOM compliant now
function $() {
    var elements = new Array();
    for (var i = 0; i < arguments.length; i++) {
        var element = arguments[i];
        if (typeof element == 'string')
            element = document.getElementById(element);
        if (arguments.length == 1)
            return element;
        elements.push(element);
    }
    return elements;
}



function getElementsByClass(searchClass,node,tag) {
    var classElements = new Array();
    if ( node == null )
        node = document;
    if ( tag == null )
        tag = '*';
    var els = node.getElementsByTagName(tag);
    var elsLen = els.length;
    var pattern = new RegExp('(^|\\s)'+searchClass+'(\\s|$)');
    for (i = 0, j = 0; i < elsLen; i++) {
        if ( pattern.test(els[i].className) ) {
            classElements[j] = els[i];
            j++;
        }
    }
    return classElements;
}


// Main object, instanciated in TOP level window (if frames are used)
// Properties are added when ready by different frames
var Cpb = function() {
  this.msg = new Array(); // association array of translated strings

  /**
  chd080220
  called from JSP, init an associative array of IDs and translated strings
  @seealso : getMsg(id)
  */
  this.initMsg = function() {
    var mc = arguments.length;
    for (var mi=0; mi<mc; mi++) {
      var mKey = arguments[mi++];
      var mText = arguments[mi];
      this.msg[mKey] = mText;
    }
  }

  this.getMsg = function(id) {
    return this.msg[id];
  }
}

// For optional multi-frame windows
// Create TOP object instance, if not yet initialized.
// Use like this : myCpb = getCpb();
// Then, myCpb.myGlobalvariable = xxxx;
function getCpb() {
 if (!top.cpbGlobal) {
   top.cpbGlobal = new(Cpb);
 }
 return top.cpbGlobal;
}


var Hashtable = function() {
  this.length = 0;
  this.items = new Array(); // WARNING: "associative" array !!

  // Constructor

  for (var i = 0; i < arguments.length; i += 2) {
    if (typeof(arguments[i + 1]) != 'undefined') {
      this.items[arguments[i]] = arguments[i + 1];
      this.length++;
    }
  }

  // methods

  //**chd080407 calc a associative key (Hashcode) for every type
  /*
  this.getHashKey = function(key) {
    if(typeof(key) == 'object') {
          if (key.getHashKey) {
        alert("getHashKey OK");
         return key.getHashKey();
      }
    } else {
      return key;
    }
  }
  */

  // remove and return associated item
  this.remove = function(key) {
    var tmp_value;
    if (typeof(this.items[key]) != 'undefined') {
      this.length--;
      var tmp_value = this.items[key];
      delete this.items[key];
    }
    return tmp_value;
  }

  // return item by index (in case of "for (var v in items)" loop)
  this.itemAt = function(index) {

    alert("not tested yet");

    var result=null;
    if ((index>=0) && (index<this.length)) {
      var i = -1; // start here
      for (var ai in this.items) {
        if (++i==index) {
          result=this.items[ai];  // return current item
          break;  // and break loop right now
        }
      }
    }
    return result;
  }


  this.get = function(key) {
    return this.items[key];
  }

  this.put = function(key, aValue) {
    if (typeof(aValue) != 'undefined') {
      if (typeof(this.items[key]) == 'undefined') {
        this.length++;
      }
      this.items[key] = aValue;
    }
    return aValue;
  }

  this.contains = function(key) {
    return typeof(this.items[key]) != 'undefined';
  }

  this.clear = function() {
    this.items.length = 0;
    this.length = 0;
  }

  /* return all items as standard indexed (zero-based) array */
  this.toArray = function() {
    var result = new Array();
    for (var ai in this.items) {
      result.push(this.items[ai]);
    }
    return result;
  }

  return this;
}

/**
  OBJECT ChD
  misc useful functions inside ;)
*/
var ChD = function(aOwner) {
  this.aOwner = aOwner; // ref to owner tab list
  this.showAlerts = false;  // default
  this.queryParams = null;  // Query string parameters parsed and stored here
  this.rndseed=new Date().getTime();  // init for rnd and rand() member functions
  this.globals = new Array(1024); // array of globals JS objects searchable by name

  // member functions

  // log(format, param, param....)
  try {
      this.log = console.log;
  } catch (e) {
    this.log = function() {
      ; // do nothing
    }
  }

  // show or hide tab and associated layers
  this.alert = function(s) {
    if (this.showAlerts) {
      alert(s);
    }
  } // end alert

  // Returns the class name of the argument or undefined if
    // it's not a valid JavaScript object.
    // NOTE: objects must be written this way : "function XXX(params) {...}"
    /*
  this.getNameOfClass = function(obj) {
      if (obj && obj.constructor && obj.constructor.toString) {
          var a = obj.constructor.toString().match("/function\s*(\w+)/");
          if (a && a.length == 2) {
              return a[1];
          }
      }
      return undefined;
  }
  */

  /* remove any DOM element from document */
  this.removeElement = function(id)  {
    var node = document.getElementById(id);
    if ((node) && (node.parentNode)) {
      node.parentNode.removeChild(node);
    }
  }

  /*
    display user message centered on screen (40% width)
    call with just ID to clear it
    @param duration not yet implemented
    if DIV exists, just change its properties. Else create/delete one as needed
  */
  this.messageDlg = function(id,text,duration) {
    if (!text) {
      hideLayer(id);
      this.removeElement("chdmsg_"+id);
    } else {
      var tmpDiv = MM_findObj(id);
      if (tmpDiv==null) { // not found -- create one with default style
        var txt = document.createTextNode(text);

        var y = 128;
        if (window.innerHeight) {
          y = window.innerHeight / 3; // top 1/3 of screen
        }

        var div = document.createElement('div');
        div.setAttribute("id" ,"chdmsg_"+id);
        div.setAttribute("style","position:absolute;top:"+y+"px;padding:8px 32px 8px 32px"
          +";left:30%;right:30%;text-align:center"
          +";background-color:white;color:orange;border:1px solid green;font-size:13pt");
        div.appendChild(txt);

        var body = document.getElementsByTagName('body')[0];
        body.appendChild(div);
      } else {  // div found -- fill its "msg" tag if present else just fill DIV itself

        tmpDiv.innerHTML = text;

        //chd.log(tmpDiv);

        showHideLayerObj(tmpDiv,true);
      }
    } // endif text defined
  }


  // params = caller, msg [other arguments if msg is a format string]
  this.error = function(caller) {
    var msg = "";
    if (caller.classId) {
      msg = "["+caller.classId+"] ";
    }
    alert(msg + arguments[1]);
    /*
    if (arguments.length>1) {
      var fmt = arguments[0];
      arguments.delete(0);
    var msg = this.format(fmt,arguments);
    }
    */
  }

  this.dump = function(obj) {
    var sResult = "Object properties: "+CRLF;
    if (obj) {
      if (obj.attributes) {
        for (var oi=0; oi<obj.attributes.length; oi++) {
          sResult+="attr."+obj.attributes[oi].name+" = "+obj.attributes[oi].value+CRLF;
        }
/*
      } else if (obj.elements) {
        for (var oi=0; oi<obj.elements.length; oi++) {
          sResult+="element."+obj.elements[oi].name+" = "+obj.elements[oi].value+CRLF;
        }
*/
      } else {
        sResult+="(no attributes)"+CRLF;
      }
    } else {
      sResult+="(object is undefined)"+CRLF;
    }
    return sResult;
  } // end dump()


  this.parseQueryString = function() {
    this.queryParams = new Array();
    var query = window.location.search.substring(1);
    var params = query.split('&');
    for (var i=0; i<params.length; i++) {
      var p = params[i].indexOf('=');
      if (p > 0) {
        var key = params[i].substring(0,p);
        var val = params[i].substring(p+1);
        this.queryParams[key] = val;
      }
    }
  }

  /* parse query string (if not done yet) and return requested param (or null) */
  this.getParam = function(key) {
    if (this.queryParams==null) {
      this.parseQueryString();
    }
    return this.queryParams[key];
  }

  // String.right
  this.right = function(s,n) {
    var L = s.length;
    var r = L-n;
    if (r<0) {
      r = 0;
    }
    return s.substr(r);
  }

  // String.left
  this.left = function(s,n) {
    return s.substr(0,n);
  }

  // String.endsWith
  this.endsWith = function(s,sub) {
    return this.right(s,sub.length)==sub;
  }

  // String.endsWithIgnoreCase
  this.endsWithIgnoreCase = function(s,sub) {
    return this.right(s,sub.length).toUpperCase==sub.toUpperCase;
  }

  // String.startsWith
  this.startsWith = function(s,sub) {
    return this.left(s,sub.length)==sub;
  }

  // String.startsWithIgnoreCase
  this.startsWithIgnoreCase = function(s,sub) {
    return this.left(s,sub.length).toUpperCase==sub.toUpperCase;
  }

  // replace all s1 by s2 in s
  // TO CHECK !! (not tested yet)
  this.replaceAll = function(s,s1,s2) {
    var re = new RegExp(s1,"g");
    return s.replace(re,s2);
  }



// Format a string passing parameters values in an array
  // Format is like "string %0 and %1 and %2", where %X is the index of param in array
  // example : myText = chd.format("%0 files read in directory %1",[123,"c:\temp"]);
  this.format = function(f,aParams) {
    var result = "";
    var cStart = 0;
    var c,cl;
    for (ci=0; ci<f.length; ci++) {
      if (f.substr(ci,1)=="%") {
        c=f.substr(ci+1,1); // get num code after "%"
        if ((c >= "0") && (c <= "9")) {
          cl = ci-cStart; // chunk length
          result = result + f.substr(cStart,cl) + aParams[c];
          cStart+=(cl+2);
          ci++;
        }
      }
    }
    return result + f.substr(cStart,999);
  }

  // split string into array
  // workaround BUG in JS - if empty string, returns an array with 1 empty item
  this.split = function(s, sep) {
    if ((s==null) || (s=="") || (s==sep)) {
    return [];
    } else {
      return s.split(sep);
    }
  }


  this.arraySwap = function(a, i, j) {
    var tmp=a[i];
    a[i]=a[j];
    a[j]=tmp;
    return a;
  }

  this.arrayIndexOf = function(a,v) {
    var i = a.length-1;
    while (i>=0) {
      if (a[i] == v) {
        break;
      } else {
        i--;
      }
    }
    return(i);
  }

  // compare 2 objects
  // objects can be null (a and/or b)
  // objects MUST implement compareTo().
  // If objects are simple types (integer, string) just compare normally
  this.compareObjects = function(a,b) {
    if (b==null) {
      if (a==null) {
        return 0; // null==null!
      } else {
        return +1; // invert : null always BEFORE the rest
      }
    } else if (a!=null) {  // obj2 not null (we tested it just above)
      if (a.compareTo) {
        return a.compareTo(b);  // complex object comparison (must implement compareTo)
      } else {
        return (a<b ? -1 : (a>b ? +1 : 0)); // native comparison
      }
    }
  }


  /**
   * quickSorts a region of an Array
   * @PARAM lo the lower index
   * @PARAM hi the upper index
   * @RESULT the # of comparisons to sort the region
   */
  this.quickSort = function(a, lo, hi) {
    var i=lo;
    var j=hi;
    var nbComparisons = 0;  // for benchmarking purpose

    var midObj = a[(lo+hi) >> 1]; // object in the middle of range

    //  divide into partitions for simplest comparison
    do {
      //  while (a[i] < midObj) {
      nbComparisons++;
      while ((i < hi) && (this.compareObjects(a[i], midObj)<0)) {
        i++;  // increase LO index
        nbComparisons++;
      }
      nbComparisons++;
      while ((j > lo) && (this.compareObjects(a[j], midObj)>0)) {
        j--;    // decrease HIGH index
        nbComparisons++;
      }
      if (i<=j) { // not reached middle of sub-block
        this.arraySwap(a,i++,j--);
      }
    } while (i<=j);

    //  sort sub-regions if regions are too big (lo and hi)
    if (lo<j) {
      nbComparisons += this.quickSort(a, lo, j);
    }
    if (i<hi) {
      nbComparisons += this.quickSort(a, i, hi);
    }

    return nbComparisons;
  }


  /*
    QuickSorts an array of objects, each object must implement "compareTo", like Java ;)
  */
  this.arraySort = function(a) {
    if (a.length>1) {
      return this.quickSort(a, 0, a.length-1);
    } else {
      return 0;
    }
  }



  // return string S with char C changed at position p
  this.setCharAt = function(s,p,c) {
    return s.substr(0,p) + c + s.substr(p+1);
  }

  // get filename from FullURL/Filename
  this.extractFileName = function(s) {
    if (s==null) {
      return("");
    }
    var L = s.length;
    var p = L;
    if (L>0) {
      var c = s.charAt(L-1);  // get last char
      while ((L>0) && (c!="/") && (c!="\\") && (c != ":")) {
        p--;
        L--;
        c = s.charAt(L-1);  // get last char
      }
      return (s.substr(p,99));
    } else {
      return(s);
    }
  }


  // get filename extension from FullURL/Filename
  this.extractFileExt = function(s) {
    var result = "";
    if (s!=null) {
      var L = s.length;
      if (L>0) {
        var p = L-1;
        var c = s.charAt(p);  // get last char
        while ((p>0) && (c!='.') && (c!="/") && (c!="\\") && (c != ":")) {
          p--;
          c = s.charAt(p);  // get last char
        }
        if (c=='.') {
          result = s.substring(p);
        }
      }
    }
    return result;
  }

  this.rnd = function() {
    this.rndseed = (this.rndseed*9301+49297) % 233280;
    return this.rndseed/(233280.0);
  }

  this.rand = function(n) {
    return Math.ceil(this.rnd()*n);
  }

  // Return an unique param to avoid cache mechanism
  // "&nocache="+rand(10000)
  this.getUniqueParam = function(sep) {
    if (arguments.length>0) {
      return sep+"nocache="+this.rand(10000);
    } else {
      return "&nocache="+this.rand(10000);
    }
  }

  // XML DOM functions
  this.getField = function(node,fieldName) {
    return node.getElementsByTagName(fieldName)[0].firstChild;
  }

  // XML DOM functions
  this.getFieldValue = function(node,fieldName,defaultValue) {
    var node = this.getField(node,fieldName);
    if (node==null) {
      return defaultValue;
    } else {
      return node.nodeValue;
    }
  }

  // XML DOM functions
  // return array of all values for specified field
  this.getFieldValues = function(node,fieldName,defaultValue) {
    var result = new Array();
    var fields = node.getElementsByTagName(fieldName); // case sensitive
    for (var vi=0; vi<fields.length; vi++) {
      result.push(fields[vi].firstChild.nodeValue);
      //result.push(fields[vi].nodeValue);
    }
    return result;
  }

/*
  this.clone = function(obj) {
      if(obj == null || typeof(obj) != 'object') {
      return obj;
      }
      var tmp = new obj.constructor();
      for(var key in obj) {
        tmp[key] = clone(obj[key]);
      }
      return tmp;
  }
*/
  // this clones any array (not objects inside, just the array)
  // including problematic "arguments" array that don't copy well
  // across callback functions, and don't accept
  // the "for (var v in array)" loop in FF2
  this.cloneArray = function(a) {
      var aClone = new Array();
      for(var ai=0; ai<a.length; ai++) {
        aClone.push(a[ai]);
      }
      return aClone;
  }

  // this function is to be used as-is by objects who need to be registered
  // This is useful for objects that have a HTML representation and actions
  // ex: tab objects or buttons
  //this.getUUID = function() {return this.classId + "_" + this.id;}

  // add global object to list of globals. Object must have
  // these 2 fields : classId and Id
  this.registerGlobal = function(obj) {
    if (!obj.getUUID) {
      alert("registerGlobal() : object have no getUUID function");
    }
    var key = obj.getUUID();
    if (key==null) {
      alert("registerGlobal() : object have no 'Id' field or Id field not set");
    }
    this.globals[key] = obj;

//    alert("registerGlobal() : object "+key+" registered");
  }

  this.dumpGlobals = function() {
    var tmp = "List of registered global objects:";
    for (var gi in this.globals) {
      var obj = this.globals[gi];
      tmp = tmp + CRLF + obj.getUUID();
    }
    return tmp;
  }

  // retrieve a global by its fullname (classId + instance id)
  this.findGlobal = function(uuid) {
    if (arguments.length>1) { // search for classname and id
      return this.globals[arguments[0] + "_" + arguments[1]];
    } else {
      return this.globals[uuid];
      }
  }

  // HTML objects can call click passing themself as sender, and the uuid that
  // generated this object
  this.click = function(sender,uuid) {
//    var self = this; // NEW: Fix loss-of-scope in inner function
    var obj = this.findGlobal(uuid);

//    alert("chd.click(): sender.id="+sender.id+", uuid="+uuid);

    if (obj!=null) {
    if (obj.onClick) {
        obj.onClick(arguments); // pass arguments pseudo ARRAY as only param of this function
      } else {
      alert("ChD.click(): UUID has no onClick() handler: "+uuid);
    }
    } else {
      alert("ChD.click(): UUID not found: "+uuid);
    }
  }


  // set HTML object style, depending on navigator.
  /*
  this.setStyle = function(HTMLObj,styleName,styleValue) {
    if (HTMLObj) {
      var style = HTMLObj.style ? HTMLObj.style : HTMLObj;
      style.attributes(styleName) = styleValue; // TO CHECK !!
    }
  }
  */

  this.setClassName = function(HTMLObj, aClassName) {
    this.className = aClassName;
  }

  /*
    div.style["height"] = (selBVisible ? "50%" : "100%");
  */
  this.setStyle = function(obj,styleName,styleValue) {
    if (obj.style) {
      obj=obj.style;
    }
    obj[styleName] = styleValue;
  }

  return this;
}


function getAjaxRequest() {
  try {
//alert("try 1");
    return new XMLHttpRequest();  // native object (newest navigators only)
  } catch(e) {}

  try {
//alert("try 2");
    return new ActiveXObject('Msxml2.XMLHTTP');
  } catch(e) {}

  try {
//alert("try 3");
  return new ActiveXObject('Microsoft.XMLHTTP');
  } catch(e) {}

  return null;  // nothing worked -- give up
}

/*
  Portable Ajax tool by ChD
*/
function ChDAjax(aOwner) {

  // members

  this.xhr = null;
  this.docXML = null;

  // init
  this.owner = aOwner;

  // member functions
  this.callback = function() {
    if (this.owner.callback) {  // forward XML doc to owner callback function
      this.owner.callback(this.docXML);
    }
  }

  this.fetch = function(url) {
    this.xhr = getAjaxRequest();

    if (this.xhr==null) {
      if (document.implementation && document.implementation.createDocument) {
      this.docXML = document.implementation.createDocument("","doc",null);
        this.docXML.onload = this.callback;
    }
    } else {

    // FireFox 2, IE7

    var self = this; // NEW: Fix loss-of-scope in inner function

      this.xhr.onreadystatechange = function() {
          if (self.xhr.readyState == 4) {
      if (self.xhr.status == 200) {
        self.docXML = self.xhr.responseXML;
        self.callback(self.docXML);
      } else {
        self.callback(null);  // inform callback of the error
        //alert("error");
        // error in request response
      }
      }
    }
    }

    if (this.xhr==null) {
    alert('Your browser can\'t handle this AJAX script');
    return;
    }

//    this.xmlHttp.load(url);
    this.xhr.open("GET",url,true);  // simply get and quit
    this.xhr.send(null);  // new
  }

  return this;
}





function ajaxClass(url, refObj, mName)
{
  var tabXhr = new Array();

  var xhr_object = null;
  tabXhr.push(xhr_object);

  var isLink = false;
  this.cname = mName;
  this.mUrl = url;
  var mObj = refObj;



  this.execute = function()
  {
    this.SendGetRequestSearch(this.url,mObj);

  }

  this.SendGetRequestSearch = function(URL,objectID){


    if (window.XMLHttpRequest){

      xhr_object = new XMLHttpRequest();

      if (xhr_object.overrideMimeType)
      {

        //xhr_object.overrideMimeType('text/xml');
        xhr_object.overrideMimeType('text/html; charset=ISO-8859-1');
      }

    } else if (window.ActiveXObject){
      //this.xhr_object = new ActiveXObject('Microsoft.XMLHTTP');
      xhr_object = new ActiveXObject('Msxml6.XMLHTTP');
    } else {
      alert("votre nagigateur ne prend pas en compte XMLHTTPRequest");
      return;
    }

    xhr_object.open('GET',this.mUrl,true);

    xhr_object.setRequestHeader("Content-Type", "text/html; charset=UTF-8");
    //xhr_object.overrideMimeType('text/xml');

    //xhr_object.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    if (mObj != "")
    {

      xhr_object.onreadystatechange = this.CallBackRequest;
      xhr_object.WaitForResponse;
    }

    var miSoap='<?xml version="1.0" encoding="UTF-8"?> \n' +

    xhr_object.send(miSoap);
  }

  this.CallBackRequest = function(){
    //
    if (xhr_object.readyState == 4){

      if (isLink)
      {
        document.location = mObj;
      } else
      {
        switch (mObj)
        {
        case "_close":
          self.close();
          break;
        case null:
          isLink = false;
          break;
        default:
          mObj.innerHTML = " ";
          mObj.style.display = "block";
          //alert(xhr_object.responseText);

          mObj.innerHTML = xhr_object.responseText;
        }
      }
      isLink = false;

    }
  }

}











// **chd0610 - Replace window/frame/iframe url -- both Mozilla and IE compatible
function setLocation(w,url) {
  if (w.location) {
//    alert("setLocation (location) to "+url);
    w.location.replace(url);
  } else {
//    alert("setLocation (src) to "+url);
    w.src=url;
  }
}


function getCopyright() {
  var d = new Date();
  var y = "200X";
  if (d.getFullYear) {
    y = d.getFullYear();
  }
  return " compuBase online (c)2000-"+y+" compuBase";
}




function addBookmark(title,url) {
  try {
    if (window.sidebar) { // firefox first
      window.sidebar.addPanel(title, url, "");
    } else if (window.external) {
      window.external.AddFavorite(url, title);
    } else if (window.opera && window.print) {  // opera part from www.dynamicdrive.com
      var elem = document.createElement('a');
      elem.setAttribute('href',url);
      elem.setAttribute('title',title);
      elem.setAttribute('rel','sidebar');
      elem.click();
    }
  } catch (e) {
  ; // nothing special
  }
}


/*
Internal Navigator object with super fields inside !

Field description:
- version,majorVersion  : 5 for IE 5.5, 5 for Netscape 6.2
- minorVersion (not implemented yet) : 5 for IE5.5, 2 for Netscape 6.2
- id  : Short name like IE, NS, OP, XX
- lang : FR, ES, etc
- shortName : id+version+lang = IE5FR
- screenInfo : width,height,bitsPerPixel = 1024,768,24
- info : shortName+screenInfo = IE5FR,1024,768,24
*/
function navObject() {
  this.version = parseInt(navigator.appVersion);  // get 3, 4, 5...

//  alert("version="+this.version);

  if (isIE) {
    var p = navigator.appVersion.indexOf("MSIE");
    if (p>=0) {
      this.version = parseInt(navigator.appVersion.substr(p+4,99)); // get 3, 4, 5... after MSIE
      //alert(ver);
    }
  }

  this.majorVersion = this.version; // version si an alias for majorVersion

  // set id (2 letters)
  if (isIE) {
    this.id = "IE";
  } else if (isNS) {
    this.id = "NS";
  } else if (isOP) {
    this.id = "OP";
  } else {
    this.id = "XX"; // needed for shortName
  }

  // set language
  this.lang = "";
  if (navigator.systemLanguage) {
    this.lang = navigator.systemLanguage.substr(0,2).toUpperCase();
  } else  if (navigator.language) {
    this.lang = navigator.language.substr(0,2).toUpperCase();
  }
/*
  if (isIE) {
    this.lang = navigator.systemLanguage.substr(0,2).toUpperCase();
  } else if (isNS) {
    this.lang = navigator.language.substr(0,2).toUpperCase();
  }
*/
  this.shortName = this.id + this.majorVersion + this.lang; // XXNLL
  this.screenInfo = "";

/*
 if (self.screen) {
  sr=screen.width+"x"+screen.height;
  sc=screen.colorDepth+"-bit";
 }
*/
  //screen.width+"_"+screen.height+"_"+screen.colorDepth;
  this.info = this.shortName+"_"+this.screenInfo;

  return this;
}

/**
  OBJECT CpbTab
  @param aIndex index in list of tabs
  @param aId div id of tab?
  @param list of associated DIV to show/hide upon selection/deselection of tab
*/
function CpbTab(aOwner,aIndex,aId) {
  this.aOwner = aOwner; // ref to owner tab list
  this.index = aIndex;
  this.id = aId;


  var ceil = getCeil();

  //alert("aId="+aId);  // ex: "divSearchTab0"

  this.obj = MM_findObj(aId,ceil);

  if (this.obj) {
    // Constructor
    this.layers = new Array(arguments.length-2);
    for (var ai=2; ai<arguments.length; ai++) {
      this.layers[ai-2] = MM_findObj(arguments[ai],ceil);
    }
  } else {
    alert("can't find specified CpbTab : "+aId);
  }

  // member functions

  // show or hide tab and associated layers
  this.showHide = function(state) {
    zipUnzipLayerObj(this.obj,state);
    for (var li=0; li<this.layers.length; li++) {
      zipUnzipLayerObj(this.layers[li],state);
    }
  }

  this.clear = function() {
/*
    for (var li=0; li<this.layers.length; li++) {
      var aDiv = this.layers[li];
      aFrames = aDiv.getElementsByTagName("iframe");
      if (aFrames.length>0) {
        var aFrame = aFrames[0];
//        alert("aFrame="+aFrame.id);
        setLocation(aFrame,"about:blank");
      }
    }
*/
  }

  return this;
}

function CpbTabList() {
  this.items = null;

  // member functions
  this.init = function() {
    this.items = new Array(arguments.length);
    for (var ai=0; ai<arguments.length; ai++) {
      this.items[ai] = arguments[ai];
    }
  }

  this.itemAt = function(index,subIndex) {
    return this.items[index];
  }

  // show selected tab and objects, hide others
  this.select = function(aIndex) {
    for (var ti=0; ti<this.items.length; ti++) {
      this.items[ti].showHide(ti==aIndex);
    }
  }

    // clear selected tab objects
  this.clear = function(aIndex) {
//    this.items[aIndex].clear();
  }

  return this;
}


/* MacroMedia standard functions */
function MM_callJS(jsStr) { //v2.0
  return eval(jsStr)
}

function MM_reloadPage(init) {  //reloads the window if Nav4 resized
  if (init==true) { // 1st call - save sizes
    if (isNS4) {
      document.MM_pgW=innerWidth;
      document.MM_pgH=innerHeight;
      onresize=MM_reloadPage;
    }
  } else if (innerWidth!=document.MM_pgW || innerHeight!=document.MM_pgH) {
    location.reload();
  }
}

function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}


/*
function MM_findObj(n, d) { //v4.01
  var p,i,x;
  if(!d)
    d=document;
  if((p=n.indexOf("?"))>0 && parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document;
    n=n.substring(0,p);
  }
  if(!(x=d[n]) && d.all)
    x=d.all[n];
  for (i=0;!x && i<d.forms.length;i++)
    x=d.forms[i][n];
  for(i=0;!x && d.layers && i<d.layers.length;i++)
    x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById)
    x=d.getElementById(n);
  return x;
}
*/

//Copyright 2000, 2001, 2002, 2003 Macromedia, Inc. All rights reserved.
//Given a unique object name, finds the object in the DOM. dom is used for recursion
//and is not normally passed in. For example:
//    obj = MM_findObj("image1");
//obj will point to the image object. It can be in layers, frames etc.
//To look in other frames, use objName?frameName. For example:
//    obj = MM_findObj("image1?topFrame");
//will only search frame "topFrame".
//Now works for Netscape 6 as well!
//
// ChD enhancements:
// -----------------
// - now find objects inside forms
// - 2nd param can be a WINDOW object (ex: top, parent..), not just a DOCUMENT object
//
function MM_findObj(n, d) { //v4.50++ -- ChD version
  var p,i,x;

  if (d) {  // chd now 2nd param can be a window object instead of a document
//    var paramType=typeof(d);
//  alert("MM_findObj(). typeof d="+paramType);
//    if ((paramType=="window") || (paramType=="frame")) {
    if (d.document) {
      d = d.document;
    }
  } else {
    d = document;
  }

  //**chd061211 now search frames in current document (if script is in frameset)
  if((p=n.indexOf("?"))>0) {  // sometime I have a "indexOf is not a function" bug!!
    var frameName = n.substring(p+1); // extract frameName
    n=n.substring(0,p); // keep only object name

//    alert("frameName="+frameName+", object name="+n);
    var aFrame=null;
  if (frames && frames.length) {  // search current frameset first
//    alert("MM_findObj(): searching frame in current document: "+frameName);
    aFrame=frames[frameName];
    }
    if (!aFrame && parent && parent.frames && parent.frames.length) { // search parent frameset
    aFrame=parent.frames[frameName];
//    alert("MM_findObj(): searching frame in parent document: "+frameName);
  }
  if (aFrame!=null)  {

/*
    if (frameName=="tsBotFrame") {
        alert("frame "+frameName+" searched. stop 1.");// aFrame="+aFrame.name);  // CANT ACCESS NAME !!

    }
*/
    d=aFrame.document;
//      x=d.getElementById(n);
//      alert("x="+x.id);
  }
  }

/*
if((p=n.indexOf("?"))>0 && parent.frames && parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document;
    n=n.substring(0,p);
  }
*/

  if(!(x=d[n]) && d.all)
    x=d.all[n];
  for (i=0; !x && d.forms && i<d.forms.length; i++) // chd added
    x=d.forms[i][n];
  for (i=0; !x && d.layers && i<d.layers.length; i++)
    x=MM_findObj(n,d.layers[i].document);
  if (!x && d.getElementById)
    x=d.getElementById(n);
  return x;
}


function MM_showHideLayers() { //v3.0
  var i,p,v,obj,args=MM_showHideLayers.arguments;
  for (i=0; i<(args.length-2); i+=3) if ((obj=MM_findObj(args[i]))!=null) { v=args[i+2];
    if (obj.style) { obj=obj.style; v=(v=='show')?'visible':(v='hide')?'hidden':v; }
    obj.visibility=v; }
}

/* END MacroMedia standard functions */


/*
  A few prototype changes for some JavaScript objects
  NOTE: for arrays, if a property is added to the prototype,
  then the code "for (var x in myArray) will include this new property... strange...
*/


function Array_swap(a, b) {
  var tmp=this[a];
  this[a]=this[b];
  this[b]=tmp;
  return this;
}


/**
  chd080407 NEW optional param, inherit
*/
function showHideLayerObj(obj,visible,inherit) {
  if (obj.style) {
    obj=obj.style;
  }
  if (visible!=false) { // check visibility level
    if (inherit) {
    visible = "inherit";  // use inherit visiblity
  } else {
    visible = "visible";  // force visibility
  }
  }
  obj.visibility = (visible==false) ? 'hidden' : visible;
}

function showHideLayer(layerName,visible) {
  var obj=null;
  if ((obj=MM_findObj(layerName))!=null) {
    showHideLayerObj(obj,visible);
  }
}

function showLayer(layerName) {
  var obj=null;
  if ((obj=MM_findObj(layerName))!=null) {
    showHideLayerObj(obj,true);
  }
}

// Just display a layer, leave blank in place
function hideLayer(layerName) {
  var obj=null;
  if ((obj=MM_findObj(layerName))!=null) {
    showHideLayerObj(obj,false);
  }
}

/*
  zip or unzip a layer object
  PARAM obj the layer object
  PARAM state 0=zipped, 1=unzipped, no param = switch state
*/
function zipUnzipLayerObj(obj,state) {
  if (obj.style) {
    obj=obj.style;
  }
  if (state!=null) {
    if (state==1) state=true;
    if (state==0) state=false;
    obj.display=aZipStates[state];
  } else {
    if (obj.display==aZipStates[true]) {
      obj.display=aZipStates[false]
    } else {
      obj.display=aZipStates[true];
    }
  }
}

function zipUnzipLayer(layerName,state) {
  if ((obj=MM_findObj(layerName))!=null) {
    zipUnzipLayerObj(obj,state);
  }
}


function unzipLayer(layerName) {
  zipUnzipLayer(layerName,1);
}

function zipLayer(layerName) {
  zipUnzipLayer(layerName,0);
}

/*
chd080211 NEW
pass a layername, a initial state and this proc will switch its visibility
and remember last state
*/
function switchLayer(layerName, defaultState) {
  var obj = switchLayerObjs[layerName]; // retrieve maybe stored layer info
  if (!obj) {
    obj = new Array();    // 1st call - create object
    obj.state=defaultState; // with initial state
    switchLayerObjs[layerName]=obj; // store new layer info
  }
  obj.state=!obj.state;   // switch
  zipUnzipLayer(layerName,obj.state); // and apply
}


// Return X left chars from string
function left(s,n) {
  alert("left() DEPRECATED. Please use cpbutil.chd.left() instead.");
  return substr(s,0,n);
}

/* NOTE: this freeze the navigator (single thread) */
function sleep1(ms) {
  var now = new Date();
  var endTime = now.getTime() + ms;
  while ((now=getTime()) < endTime) {
    ; // wait
  }
}

/* NOTE: this freeze the navigator (single thread) */
function sleep(ms) {
  var date = new Date();
  var now = null;

  do {
    now = new Date();
  } while (now-date < ms);
}

function ChDLog() {
  this.winObj = null;
  this.divLog = null;
  this.winCreating = false;
  this.winName = "ChDConsole";
  this.winWidth = 280;
  this.winHeight = 500;

  this.makeWindow = ChDLog_makeWindow;
  this.add = ChDLog_add;
}

function ChDLog_makeWindow() {
  if (!this.winCreating) {  // not already started window creation

    this.winCreating = true;

    var x = screen.width - this.winWidth;
    var y = screen.height - this.winHeight - 128;

    this.winObj = window.open("", this.winName,"toolbar=no,width="+this.winWidth+",height="+this.winHeight+",left="+x+",top="+y+",resizable=1,scrollbars=1,status=1,titlebar=1");

    var w = this.winObj;  // shortcut for window
    var d = w.document;   // shortcut for document

    d.open();
    d.writeln("<html><head><title>Javascript console by ChD v1.0.0</title>");
    d.writeln("<script src='/seltree/cpbutil.js'></script>");
    d.writeln("</head>");
    d.writeln("<body style='font-size:8pt'><NOBR>");
    d.writeln("<div id='divLog' name='divLog' style='position:absolute' width='100%' height='100%'>Log started</div>");
    d.writeln("</NOBR>");
    d.writeln("<script>");
//        d.writeln("  alert('opener='+opener);");
//        d.writeln("  alert('opener.top='+opener.top);");
//        d.writeln("  alert('opener.top.chdLog='+opener.top.chdLog);");

    d.writeln("  opener.top.chdLog.divLog = document.getElementById('divLog');");

//        d.writeln("  alert('opener.top.chdLog.divLog='+opener.top.chdLog.divLog);");
    d.writeln("</script>");
    d.writeln("</body></html>");
    d.close();

//        alert("BEFORE divLog="+divLog);

//        this.divLog = MM_findObj("divLog",d);

//        alert("AFTER divLog="+divLog);

    w.focus();

    this.winCreating = false;
  //      alert("log created");
  }
}

/*
  2DO:
  1. Create window if not shown, and wait until a special variable is set to true.
  2. inside window, create script to initialize this variable one the page is rendered

  REM:
  1. If the caller page reload, the ChDLogWin variable is cleared, but the window may be still visible
     in this case the var=win.open is made again to initialize the var
*/
function ChDLog_add(s) {
  if ((!this.winObj) || (this.winObj.closed)) { // window not yet created or closed
    this.makeWindow();
  }

  if (this.divLog) {
//    this.divLog.innerHTML += (s + "<br>");
    this.divLog.innerHTML = (s + "<br>") + this.divLog.innerHTML;
  } else {
    alert("divLog not found");
  }
}

function log(s) {
  if (trek) {
    if (!top.chdLog) {
      top.chdLog = new ChDLog();
    }
    top.chdLog.add(s);
  }
}

function logStart(s) {
  trek = true;  // enable log() function calls
  if (!s) {
    s = "";
  }
  if (!top.chdLog) {
    top.chdLog = new ChDLog();
  }

  log("ChD Log (c)compuBase, started !"
    +"<br>Window name: "+(this.name==null?"(unknown)":this.name)
    +"<br>Location: "+(this.location==null?"(unknown":this.location)
    +"<br>"+s+"<br>");
}

function logStop() {
  trek = false;
}

// Format a string passing parameters values in an array
// Format is like "string %0 and %1 and %2", where %X is the index of param in array
// DEPRECATED
function chdFormat(f,aParams) {
  alert("cpbutil.js.chdFormat() DEPRECATED. Use cpbutil.js.chd.format() instead");

  var result = "";
  var cStart = 0;
  var c,cl;

  for (ci=0; ci<f.length; ci++) {
    if (f.substr(ci,1)=="%") {
      c=f.substr(ci+1,1); // get num code after "%"
      if ((c >= "0") && (c <= "9")) {
        cl = ci-cStart; // chunk length
        result = result + f.substr(cStart,cl) + aParams[c];
        cStart+=(cl+2);
        ci++;
      }
    }
  }
  return result + f.substr(cStart,1024);
}

// split string into array
// workaround BUG in JS - if empty string, returns an array with 1 empty item
// DEPRECATED
function mySplit(s, SPLIT_SEP) {

  alert("cpbutil.js.mySplit() DEPRECATED. Use cpbutil.js.chd.split() instead");

  if ((s==null) || (s=="") || (s==SPLIT_SEP)) {
    return [];
  } else {
    return s.split(SPLIT_SEP);
  }
}


// DEBUG: Show contents of an array
// DEPRECATED see chd.showArray()
/*
function showArray(a) {
  var s = a.length+" items in array:\n\n";
  var ci;
  for (ci=0; ci<a.length; ci++) {
    s+=a[ci]+"\n";
  }
  alert(s);
}
*/


/**
  Force RELOAD of specified window or frame
*/
/*
function refreshWindow(w) {
  w.location.replace(w.location.href);
  //w.location.reload();
}
*/

/**
  return index of selected item in SELECT object
  @param selectName the SELECT object name
*/
function getSelectIndex(selectName) {
  var result = -1;
  var selectObj = MM_findObj(selectName);
  if (selectObj!=null) {
    for (var i=0; (i<selectObj.length) && (result<0); i++) {
      if (selectObj.options[i].selected == true) {
        result=i;
      }
    }
  }
  return result;
}

/**
  return value of selected item in SELECT object
  @param selectName the SELECT object name
*/
function getSelectValue(selectName) {
  var result = null;
  var selectObj = MM_findObj(selectName);
  if (selectObj!=null) {
    for (var i=0; (i<selectObj.length) && (result==null); i++) {
      if (selectObj.options[i].selected == true) {
        result=selectObj.options[i].text;
      }
    }
  }
  return result;
}


/*
Update main window top frame
so that the company name or logo is displayed
@PARAM (optional) can provide an URL to this function
*/
function updateTopFrame(url) {

  log("updateTopFrame");

  if ((top.frames) && (top.frames.length)) {
    var topFrame = top.frames[TOP_FRAME_NAME];
    if (topFrame!=null) {
      if (!url) {
        url = topFrame.location.href;
        var p = url.indexOf("?ff");
        if (p>-1) {
          url = url.substring(0,p);
        }
      }
      //topFrame.location.replace(url);
      setLocation(topFrame,url);
    }
  }
}

/*
Update left frame, containing main menus
so that the menu uses the choosen language
*/
function updateLeftFrame(counter) {

  if (!counter) {
    counter = 1;
  }

  log("updateLeftFrame-"+counter);

  if ((top.frames) && (top.frames.length)) {

    log("updateLeftFrame - step 3");

    var leftFrame = top.frames[LEFT_FRAME_NAME];

    log("updateLeftFrame - step 4");

    if (leftFrame!=null) {
      var url = leftFrame.location.href;
      var p = url.indexOf("?ff");
      if (p>-1) {
        url = url.substring(0,p);
      }
      //leftFrame.location.replace(url);
      setLocation(leftFrame,url);
    } else {
      counter++;
      log("left frame not found, trying attempt "+counter);
      if (counter<5) {
        setTimeout("updateLeftFrame("+counter+")",500);
      }
    }
  }
}

/*
openToolWindow opens a window without navigation buttons, nor url.
The window is NAMED, FOCUSED and PUT TO FRONT.
NEW 011004 : Optional arguments are : WIDTH and HEIGHT
*/
function openToolWindow(winName,URL) {
  var w;
  if (arguments.length>3) {
    w=window.open(URL,winName,toolWindowNoSize + ",width="+arguments[2]+",height="+arguments[3]);
  } else {
    w=window.open(URL,winName,toolWindowDefParams);
  }
  w.focus();
}

/*
openWindow opens a normal navigator window.
The window is NAMED, FOCUSED and PUT TO FRONT.
*/
function openWindow(winName,URL) {
  var w=window.open(URL,winName);
  w.focus();
}

/*
refreshWindow brings named window to front
and refresh its URL (if avail)
WARNING : If the window doesn't have an URL it may crash the browser
(looping forever)
*/
function refreshWindowName(winName) {
  var w=window.open("javascript:if (location!=null)location=location;",winName);
  w.focus();
}

function refreshWindow(w) {
  if (w.location) {
    w.location.replace(w.location.href);
  } else if (w.src) {
    w.src=w.src;
  }
  //w.location.reload();
}

/*
  ChD 030602 force refresh or repoen of given window and URL
*/
function refreshWindowURL(winName,URL,doFocus) {
  var w=window.open("javascript:location='"+URL+"';",winName);
  if (doFocus) {
    w.focus();
  }
}

/*
openWindow opens a normal navigator window.
The window is NAMED, FOCUSED and PUT TO FRONT.
*/
function openWindowParams(winName,URL,params) {
  var w;
  if (params==null) {
    w=window.open(URL,winName);
  } else {
    w=window.open(URL,winName,params);
  }
  w.focus();
}


function printFrame(frameName) {
  if (CpbMainFrame.frames[frameName].print) {
    CpbMainFrame.frames[frameName].print();
   } else {
    alert('Function not supported by your Navigator. Please use your navigator Print button or menu');
  }
}


function printDoc() {
  if (CpbMainFrame.print) {
    CpbMainFrame.print();
  } else {
    alert('Function not supported by your Navigator. Please use your navigator Print button or menu');
  }
}

function openerFocus() {
  var w=opener;
  if ((w==null) || (w.closed)) {
    alert('The parent window has been closed !');
  } else {
    w.focus();
  }
}

function openerRefresh() {
  var w=opener;
  if ((w==null) || (w.closed)) {
    alert('The parent window has been closed !');
  } else {
    alert("Now replacing opener with: "+  w.location.href);
    w.location.replace(w.location.href);
  }
}

function openerName() {
  var w=opener;
  if ((w==null) || (w.closed)) {
    return '';
  } else {
    return w.name;
  }
}

// Set a cookie value with long validity
function setCookie(name, value, expire) {
   document.cookie = name + "=" + escape(value)
   + ((expire == null) ? "" : ("; expires=" + expire.toGMTString()))
}

// Return cookie value, or "" if error or not found
function getCookie(Name) {
   var search = Name + "=";
   var result = "";
   if (document.cookie.length > 0) { // if there are any cookies
      offset = document.cookie.indexOf(search);
      if (offset != -1) { // if cookie exists
         offset += search.length; // set index of beginning of value
         end = document.cookie.indexOf(";", offset); // set index of end of cookie value
         if (end == -1)
            end = document.cookie.length;
         result=unescape(document.cookie.substring(offset, end));
      }
   }
   return result;
}

// JDM
function rnd() {
  rnd.seed = (rnd.seed*9301+49297) % 233280;
  return rnd.seed/(233280.0);
}

function rand(number) {
  return Math.ceil(rnd()*number);
}

// Return an unique param to avoid cache mechanism
// "&nocache="+rand(10000)
function getUniqueParam(sep) {
  if (arguments.length>0) {
    return sep+"nocache="+rand(10000);
  } else {
    return "&nocache="+rand(10000);
  }
//  return "&milli=" + (new Date()).getMilliseconds();
}

// returns index of value in array (this)
// Usage : myArray.indexOf = indexOf;
function indexOf(v) {
  var i = this.length-1;
  while (i>=0) {
    if (this[i] == v) {
      break;
    } else {
      i--;
    }
  }
  return(i);
}

// DEBUG: Show contents of an array
function dumpArray(a) {
  var s = a.length+" items in array:\n\n";
  var ci;
  for (ci=0; ci<a.length; ci++) {
    s+=a[ci]+"\n";
  }
  alert(s);
}

function helpPopup(URL) {
  var w = window.open(URL,winNameHelpPopup,toolWindowHelpPopup);
  w.focus();
}

function helpPopupV(URL) {
  var w = window.open(URL,winNameHelpPopup,toolWindowHelpPopupV);
  w.focus();
}

function helpPage(URL) {
  openWindow(winNameHelpPage,URL);
}


/**
  generate a HTML TABLE with X columns,
  provided logo, links, target, etc

  @PARAMS:
  1. # of columns per row (3)
  2. Target window name (or "_blank")

  Then,for each row :
  1. Logo
  3. Languages (one letter for each)
  5. URL
  2. Text 1 (short)
  4. Text 2 (long)
*/
function getPartnersTableRows() {
  var DIR_LOGO = "logo/";
  var FLAG_PREFIX = "img/flag_";
  var FLAG_SUFFIX = ".gif";

  var FIXEDPARMCOUNT = 2;

  var args = arguments;
  var argc = args.length;

  var itemCount = argc - FIXEDPARMCOUNT;

  var nCols = args[0];
  var nRows = Math.floor(itemCount / nCols);

  var target = args[1]; // target window name

  //alert("nCols="+nCols+", nRows="+nRows+", itemCount="+itemCount+", fixed="+FIXEDPARMCOUNT);

  //alert("itemCount="+itemCount+", nCols="+nCols+", nRows="+nRows);

  var result = "";  //  "<table border=0 cellpadding=0 cellspacing='16px'>";


  var ai = FIXEDPARMCOUNT;  // start index in argument array
  var imgName,text1,text2,langs,langsHTML;
  var URL,aHREF;

  for (var ri=0; ri<nRows; ri++) {
    result += "<tr><td height='32px' colspan="+nCols+">&nbsp;</td></tr><tr>";

    imgName = DIR_LOGO + args[ai++];
    langs = args[ai++];
    URL  = args[ai++];
    text1 = args[ai++];
    text2 = args[ai++];

    // Make list of flag bitmaps
    langsHTML = "";
    if (langs.length>0) {
      var aLangs = chd.split(langs,",");
      for (var li=0; li<aLangs.length; li++) {
        langsHTML += "<img src='"+FLAG_PREFIX + aLangs[li] + FLAG_SUFFIX+"'>";
      }
    } else {
      langsHTML = "&nbsp;"; // avoid empty cells for ns4
    }

    aHREF = "<a href='"+URL+"' target='"+target+"'><img src='"+imgName+"' border=0></a>";
    result += "<td align='center' valign='top'>"+aHREF+"</td>";
    result += "<td align='center' valign='top'>"+text1+"</td>";
    result += "<td width='36px' align='center' valign='top'>"+langsHTML+"</td>";
    result += "<td align='center' valign='top'>"+text2+"</td>";
    aHREF = "<a href='"+URL+"' class='action' target='"+target+"'>"+URL+"</a>";
    result += "<td align='center' valign='top'>"+aHREF+"</td>";

//    alert(ri+"="+imgName+" / " + langs + " / "+text1);

    result += "</tr>"+CRLF;

  }

  return result;  //+"</table>";
}

function setPlaceHolder(key,value) {
  if (!aPlaceHolders) {
    alert("You must first add : aPlaceHolders = new Array();");
  } else {
    aPlaceHolders[key] = value;
  }
}

function applyPlaceHolders(s) {

  if ((aPlaceHolders) /* && (aPlaceHolders.length>0) */) {
    var p0,p1,L;
    var phCode,phReplacer;
    var p = -1; // start before 0
    while ((p=s.indexOf(PH_PREFIX,++p))>=0) {

      L = s.length;
      p0=p+PH_PREFIX_LENGTH;
      p1=p0;
      while ((p1<L) && ((c=s.charAt(p1))>='A') && (c<='Z')) {
        p1++;
      }
  //    if (p1==L) {
        //p1++;
      //}
      phCode = s.substr(p0,p1-p0);
      phReplacer = aPlaceHolders[phCode];
//      if (phReplacer) {
        s = s.substr(0,p) + phReplacer + s.substr(p1);
//      }
    }
  }

  return s;
}

// ChD050901 easily add a "rfrshxxxxx" string to any URL
function saltURL(url) {
  var saltPrefix="ChDSalt";
  var L = url.length;

  if (url[L-1]=='#') {
   url=url.substr(0,L-1);
  }

  var sL = 15;
  var s = (saltPrefix+rand(99999999)+"ChDChDChDChDChD").substr(0,sL);

  var p = url.indexOf(saltPrefix);
  if (p<0) { // not salted yet
    if (url.indexOf('?')<0) {
      url = url + "?" + s;  // no param yet
    } else {
      url = url + "&" + s;  // existing param found, add another
    }
  } else { // replace existing salt string - fixed length
    url = url.substr(0,p) + s + url.substr(p+sL,999);
  }

//  alert("salted url = "+url);

  return url;
}

/**
 * **chd071115 NEW
 * Filter specified string from string
 */
function filter(s,filter) {
  var p = s.indexOf(filter);
  if (p<0) { // not found
    return s;
  } else { // filter out
    return s.substr(0,p) + s.substr(p+filter.length,9999);
  }
}


//alert("filter test 1: " + filter("abcdef[&ff]&ghijkl","&ff"));
//alert("filter test 2: " + filter("abcdef[&ff]&ghijkl","XX"));
//alert("filter test 2: " + filter("abcdef[&ff]&ghijkl","abc"));

/**
 * Called by WelcomeUser.jsp and WelcomeDemo.jsp to
 * show Top frame and left frame with personalized colors,
 * styles, and menus
 *
 * **chd071115 FIX removes "&ff" if present
 */
function updateTopAndLeftFrames() {
  if ((top.frames) && (top.frames.length) && (top.frames.length>0)) {
    var aFrame;
    aFrame = top.frames["CpbTopFrame"];
    if (aFrame!=null) {
     setLocation(aFrame,saltURL(filter(aFrame.location.href,"&ff")));
//     aFrame.location.replace(saltURL(aFrame.location.href));
    }
    aFrame = top.frames["CpbLeftFrame"];
    if (aFrame!=null) {
     setLocation(aFrame,saltURL(filter(aFrame.location.href,"&ff")));
//     aFrame.location.replace(saltURL(aFrame.location.href));
    }
  }
}


/*
  Portable Ajax request (c)ChD !
*/
function ajaxLoad(url, callbackfunction) {
  var xmlhttp = false;
  if (window.XMLHttpRequest) {  // DOM = Mozilla, Safari, Conqueror...
//    alert("XMLHttpRequest");
    xmlhttp = new XMLHttpRequest();
  } else if (window.ActiveXObject) { // MSXML ActiveX
    try {
//      alert("ActiveXObject1");
      xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
//      alert("ActiveXObject2");
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); // MSXML ActiveX (alt version)
      } catch (e) {
      }
    }
  }

  if (xmlhttp) {  // ok we have a XML REQUEST object instanciated

     // Add inline event handler to XMLRequest object
     xmlhttp.onreadystatechange=function()  {
        if (xmlhttp.readyState == 4) { // 4 = page complete
           if (xmlhttp.status == 200) { // 200 = HTTP OK (no server error)
//              alert("response = "+xmlhttp.responseText);
              if (callbackfunction) {
                callbackfunction(xmlhttp.responseText);
              }
           }
        }
     }
    xmlhttp.open('GET', url, true)
    xmlhttp.send(null)
  }

  return xmlhttp; // caller must check FALSE/NULL for error (ex: if ajaxLoad()...)
}


/*
  Portable Ajax request (c)ChD !

  NOTE: we can be in domain "compubase.net" here.... caution with cross sub-domain stuff
*/
function ajaxLoadXML(url, callbackfunction) {

  var xmlDoc = null;

  if (document.implementation && document.implementation.createDocument) {
    xmlDoc = document.implementation.createDocument("","doc",null);
    xmlDoc.onload = callbackfunction;
  } else if (window.ActiveXObject) {
    xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.onreadystatechange = function () {
      if (xmlDoc.readyState == 4) {
        if (callbackfunction) {
          callbackfunction(xmlDoc);
        }
      }
    };
  } else {
    alert('Your browser can\'t handle this AJAX script');
    return;
  }

//  alert("ajaxLoadXML: url="+url);

  xmlDoc.load(url);
  return xmlDoc;
}

/*
function ajaxLoadXMLWithOwnerCallback(url, aOwner) {
  aOwner.callback();  // call generic callback in owner
}
*/

function ajaxLoadXML2(url, callbackfunction) {

  var xmlDoc = null;

  if (document.implementation && document.implementation.createDocument) {

    var objXMLHTTP = new XMLHttpRequest();
    objXMLHTTP.open("GET", url, false);
    objXMLHTTP.send(null);
    xmlDoc = objXMLHTTP.responseXML;
    //xmlDoc.domain = document.domain;

    userSelClickXMLdoc = objXMLHTTP;

    callbackfunction();

    alert("DEBUG step 003");


  } else if (window.ActiveXObject) {
    xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.onreadystatechange = function () {
      if (xmlDoc.readyState == 4) {
        if (callbackfunction) {
          callbackfunction(xmlDoc);
        }
      }
    };
  } else {
    alert('Your browser can\'t handle this script');
    return;
  }
  xmlDoc.load(url);
  return xmlDoc;
}


function ajaxLoadXML3(url, callbackfunction) {

  var xmlDoc = null;

  if (document.implementation && document.implementation.createDocument) {
    xmlDoc = document.implementation.createDocument("","doc",null);
    xmlDoc.onload = callbackfunction;
  } else if (window.ActiveXObject) {
    xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.onreadystatechange = function () {
      if (xmlDoc.readyState == 4) {
        if (callbackfunction) {
          callbackfunction(xmlDoc);
        }
      }
    };
  } else {
    alert('Your browser can\'t handle this script');
    return;
  }
  xmlDoc.load(url);
  return xmlDoc;
}








/*
  Return selected (checked) radio button value
*/
function getRadioValue(rb){
  var result=-1;
  var L=rb.length;
  if (L==1){
    result=rb.value;
  } else {
    for (i=0;i<L;i++){
      if (rb[i].checked==true) {
    result=rb[i].value;
      }
    }
  }
  return result;
}

function openInFrame(frameNameOrObj,url) {
  /*
  var sDebug = "parent="+parent.name+", top="+top.name+", top.frames.length="+top.frames.length;
  sDebug+=", top.frames[1]="+top.frames[1].name;
  alert(sDebug);
  */
  var f = ((typeof frameNameOrObj=="string") ? MM_findObj(frameNameOrObj,getCeil()) : frameNameOrObj);
  if (f==null) {
//    alert("frame "+frameName+" not found for "+url);
    openWindow(url);
  } else {
//    alert("frame "+frameName+" found for "+url+". location="+f.location);
    setLocation(f,url);
    /*
    if (f.location) {
      f.location.replace(url);  // works with IE6, not FireFox 1.0.7
    } else {
      f.src=url;  // works for FireFox 1.0.7, not IE6
    }
    */
  }
}

// return version of something specified (stored in TOP window)
//**chd 2do: store "what" in generic version container (use associative array)
function getVersion(what) {
//  return 2;

  var version = 0;
  if (what=="cpbSearch") {
    if (top.cpbSearchVersion) { // version array defined in top window
      version = top.cpbSearchVersion[0];  // get version number
    }
//    var obj=MM_findObj("cpbSearchVersion",top);
  }
//  alert("getVersion() return "+version);
  return version;
}

// set version of something specified (stored in TOP window)
function setVersion(what,v,s,r) {
  if (what=="cpbSearch") {
    if (top.cpbSearchVersion) { // version array defined in top window
      top.cpbSearchVersion[0]=v;  // version
      top.cpbSearchVersion[1]=s;  // sub-version
      top.cpbSearchVersion[2]=r;  // revision
    }
  }
}


/**
  returns the ceil for MM_findObj().
  Since security restrictions with IE6+, we can't access objects across
  frames when parent is in a different domain.
*/
function getCeil() {
  return getCeil2();
/*
//alert("getCeil(). ceil="+ceil+", window.name="+window.name);
  if (ceil==null) {
//alert("ceil was null. window.name="+window.name+", URL="+document.location.href);
    if ((window.name=="cpblist") || (window.name=="cpbdetail")
       //|| (window.name=="cpbframe")
       ) {
      ceil = parent;  // and start searching only from here
//alert("ceil=parent");
    } else if (window.name=="tsBotFrame") {
      if (parent.name=="cpblist") {
      ceil = parent.parent; // and start searching only from here
//alert("ceil=parent.parent");
      } else {
      ceil = parent;  //**chd061207
//alert("not in cpbList frame");
      }
    } else if (window!=top) { //(window.name=="cpbframe") ||
      ceil = window;  // no rights above current window !!
//alert("ceil=window");
    } else {
      ceil = top; // regular (no frameset)
//alert("ceil=top");
    }
  }
//alert("ceil="+ceil+", name="+ceil.name);
  return ceil;
*/
}

// alt method : go up until error or top found
function getCeil2(w) {
  var MAX_DEPTH = 32; // avoid infinite loop
  var distance = 0;
  if (!w) {
    w = this; // default = current window
  }
  try {
    while ((w!=top) && w.parent && (w.parent.name!=null) && (distance<MAX_DEPTH)) { // still can access NAME property
      w = w.parent;
      distance++;
    }
  } catch (e) {
    ; // nothing special -- just return last good result
  }

//  alert("getCeil2(). w.name="+w.name+", distance="+distance);
  return w;
}

// obtain depth of current window (in FRAMESET or IFRAME scheme)
function getWindowDepth(w) {
  var MAX_DEPTH = 32; // avoid infinite loop
  var result = 0; // start with root level
  if (!w) {
    w = this; // default = current window
  }

  try {
    while ((w!=top) && (w.parent) && (result<MAX_DEPTH)) {  // still can access a parent -- go up !
      result++;
      w = w.parent;
    }
  } catch (e) {
    ; // nothing special -- just return last good result
  }

  return result;
}

// setCpbDomain() if necessary, and return findRoot (ceil)
function checkCpbDomain() {
  var findRoot = null;

  if ((window.name=="cpblist") || (window.name=="cpbdetail")) {
    // we are in directsearch resultlist or proddetaiol or cpydetail
    setCpbDomain(); // we are in a cross-domain strategy -- adjust domain
    findRoot = getCeil();
  } else if (window.name=="tsBotFrame") {

    var parentName = "";
    try {
      parentName = parent.name;
    } catch (error) {
      parentName = "cpblist";
    }

//  alert("click from tsBotFrame: parentName="+parentName+"   parent.parent="+(parent.parent ? "YES" : "NO"));


//    alert("parent="+parent);



    if (parentName=="cpblist") {
//    parent.document.domain=CPBDOMAIN;
//    parent.frames["tsTopFrame"].document.domain=CPBDOMAIN;
//    parent.frames["tsMidFrame"].document.domain=CPBDOMAIN;
    setCpbDomain(); // we are in a cross-domain strategy -- adjust domain

//    alert("domains. parent="+parent.domain
    findRoot = getCeil();
    }
  } else {
    findRoot = getCeil();
  }

  //BUG above -- no more access to parent when tsBotFrame

  return findRoot;
}

function cpbLink(what,url) {

  var findRoot = checkCpbDomain();

//  alert("cpbLink(). document.domain="+document.domain);


//  alert("findRoot="+findRoot);
//  alert("domain="+document.domain+", findRoot.name="+findRoot.name);

  var frameCpbList = MM_findObj("cpblist",findRoot);
  var frameCpbDetail = MM_findObj("cpbdetail",findRoot);

    if (what=="C") {
      if (frameCpbList!=null) {
        openInFrame(frameCpbDetail,url);
//        showSearchTab(cpbSearchTabIds[1]);
        findRoot.cpbTabs.select(1);
      } else {
        openWindow('cpydetail',url);
      }
    } else if (what=="P") {
      if (frameCpbList!=null) {
  //      alert("open in frame cpbdetail : "+url);
        openInFrame(frameCpbDetail,url);
        findRoot.cpbTabs.select(1);
      } else {
        openWindow('cpbProduct',url);
      }
    } else if (what=="PT") {
  //    if (window.name=="cpblist") { // iframed stuff - find right iframe
      if (frameCpbList!=null) {
        openInFrame(frameCpbList,url);
        findRoot.cpbTabs.select(0);

//        refreshWindow(findRoot.cpblist);

      } else {
        openWindow('CpbMainFrame',url);
      }
    } else {
      openWindow(what,url);
    }
}




/* (c)ChD timed mouseover size control */

// utility object to add to sized element as a new property
// optional params = minHeight, maxHeight
function SizeObject(objName) {
  this.minHeight = (arguments.length>1) ? arguments[1] : 0;
  this.maxHeight = (arguments.length>2) ? arguments[2] : 768;
  this.qty = 0;
  this.elementName = objName;
  this.element = MM_findObj(objName); // attached div or span element

  this.doSizing = SizeObject_doSizing;
  this.prepare = SizeObject_prepare;
//  this.stop = SizeObject_stop;
  this.setMaxHeight = SizeObject_setMaxHeight;
  this.setMinHeight = SizeObject_setMinHeight;
  this.show = SizeObject_show;
  this.hide = SizeObject_hide;
  this.getSize = SizeObject_getSize;
  this.setSize = SizeObject_setSize;
  this.switchHeight = SizeObject_switchHeight;
  this.showHide = SizeObject_showHide;

  this.element.sizeObject = this; // attach a reference to self into target object

  return this;
}

function SizeObject_getSize() {
  return parseInt(this.element.style.height)
}

function SizeObject_setSize(what,a) {
  this.doSizing(1);
}

function SizeObject_setMaxHeight() {
  this.element.style.height = this.maxHeight+"px";
}

function SizeObject_setMinHeight() {
  this.element.style.height = this.minHeight+"px";
}

function SizeObject_show() {
  zipUnzipLayerObj(this.element,true);
}

function SizeObject_hide() {
  zipUnzipLayerObj(this.element,false);
}


function SizeObject_switchHeight() {
  if (this.getSize()==this.minHeight) {
    this.setMaxHeight();
  } else {
    this.setMinHeight();
  }
}

function SizeObject_showHide() {
//  alert("showHide()");
  zipUnzipLayerObj(this.element);
}

// timer function
function SizeObject_doSizing() {
  var sizeCurrent = this.getSize();

  if (sizeCurrent<this.minHeight) {
      sizeCurrent=this.minHeight;
      this.element.style.height = sizeCurrent + "px";
      return false;
    } else if (sizeCurrent>this.maxHeight) {
      sizeCurrent=this.maxHeight;
      this.element.style.height = sizeCurrent + "px";
      return false
    } else if ((sizeCurrent+this.qty>this.minHeight) && (sizeCurrent+this.qty<this.maxHeight)) {
      sizeCurrent+=this.qty;
      this.element.style.height = sizeCurrent + "px";
      return true;
    } // else quit timer loop
}

function SizeObject_prepare(speed) {
  this.qty =(Math.abs(speed)==1 ? 10 : 30);
  if (speed<0) {
    this.qty=-this.qty;
  }
}

var sizeObjects = new Array();
var sizeObjectIndex = -1; // none used yet

// timeout (recursive loop) function
function doSizing() {
  if (sizeObjectIndex>=0) { // global variable in caller window
    if (sizeObjects[sizeObjectIndex].doSizing()) {
      setTimeout("doSizing();",100);
    } else {
      sizeObjectIndex = -1; // stop sizing loop
    }
  }
}

// the one to call from mouseEnter() event, etc
function enterSize(elementIndex, speed) {
//    alert("enterSize()");
  sizeObjectIndex = elementIndex;
  var el = sizeObjects[elementIndex];
  el.prepare(speed);
  setTimeout("doSizing();",333);  // delay before starting sizing (so mouseOut event can cancel it before starting)
}

function quitSize(elementIndex) {
  sizeObjectIndex = -1; // stop sizing loop
}

function setSize(elementIndex,what) {
  if (what==0) {
    sizeObjects[elementIndex].setMinHeight();
  } else if (what==1) {
    sizeObjects[elementIndex].setMaxHeight();
  } else {
    sizeObjects[elementIndex].switchHeight();
  }
}

function switchSize(elementIndex) {
  sizeObjects[elementIndex].switchHeight();
}

function showHide(elementIndex) {
  sizeObjects[elementIndex].showHide();
}

function showSearchTab(tabName,subTabName) {

  var tabList = top.document.getElementsByTagName("div");
  var state;
//  var tab = MM_findObj(tabName,top);

//  zipUnzipLayer("divTabList",true); // show tabs if not yet shown

  if (tabList.length>0) {
    for (var ti=0; ti<tabList.length; ti++) {
      aTab = tabList[ti];

//      alert("tab.name="+aTab.id+". indexOf="+allSearchTabs.indexOf(aTab.id));

      if (cpbSearchTabIds.indexOf(aTab.id)>=0) {  // found in defined list
        if (aTab.id==tabName) {
          state=true;
        } else {
          state=false;
        }
//        alert("DEBUG: "+aTab.id+", state="+state);
        zipUnzipLayerObj(aTab,state);
      }
    }

  } else {
    alert("tab ["+tabName+"] not found -- elementsByTagName() returned no results");
  }

}

// V1 : updates sender FORM action before regular POST
function cpbSearchSubmit(sender) {

  var senderForm = (sender.form ? sender.form : sender);

  var topdomain = "online";
  try {
    if (MM_findObj("cpbsearchdebug",sender.document)) {
      topdomain = "devsrv3";
    } else {
      topdomain=(document.location.href.indexOf("devsrv")>0 ? "devsrv3" : "online");
      }
    } catch (e) {
      topdomain=(document.location.href.indexOf("devsrv")>0 ? "devsrv3" : "online");
  }
  sender.action="http://"+topdomain+".compubase.net/webcpx/redir";

  toggleSearchVerbose(false);

  if (cpbTabs) {
    cpbTabs.select(0);  // show first tab (cpbList)
  }

  return true;
}


/*
  Utility function to make a queryString from FORM parameters
  Useful to make a url from a form action
*/
function getFormQueryString(sender) {
  var qs = "";
  var fields = (sender.form ? sender.form.elements : sender.elements);

  var sep="?";
  for (var eli=0; eli<fields.length; eli++) {
      var el = fields[eli];
      if (el.name && (el.name.length>0)) {
        if ((el.type=="text") || (el.type=="hidden") || (el.type=="password")
         || ((el.type=="option") && (el.selected))
         || (((el.type=="radio") || (el.type=="checkbox")) && (el.checked))
       ) {
          qs+=(sep+el.name+"="+el.value);
          sep = "&";  // sep for next params
    }
    }
  } // endfor eli
  return qs;
}

// V2 : uses FORM fields and constructs a new URL (no POST)
// "sender" may be either a FORM, either a FIELD (which has a parent form)
function cpbSearchSubmit2(sender) {

  var topdomain;

  try {
    if (MM_findObj("cpbsearchdebug",sender.document)) {
      topdomain = "devsrv3";
    } else {
      topdomain=(document.location.href.indexOf("devsrv")>0 ? "devsrv3" : "online");
      }
    } catch (e) {
      topdomain=(document.location.href.indexOf("devsrv")>0 ? "devsrv3" : "online");
  }

  cpbTabs.clear(0);

  toggleSearchVerbose(false);

  cpbTabs.select(0);  // show first tab (cpbList)

  var aFrame = MM_findObj("cpblist",getCeil());
  var url = "http://"+topdomain+".compubase.net/webcpx/redir" + getFormQueryString(sender);

  setLocation(aFrame,url);

  return true;
}

// called by SmartLine search forms
function cpbSearchSubmitOld() {
  if (getVersion("cpbSearch")>=3) {
    toggleSearchVerbose(false);
    cpbTabs.select(0);  // show first tab (cpbList)
  } else if (getVersion("cpbSearch")>=2) {
    toggleSearchVerbose(false);
    showSearchTab("divCpbList");
  } else {

  //  alert("submit !");
    var obj = MM_findObj("divCpbList");
    if (obj && (obj.sizeObject)) {
      obj.sizeObject.show();
    }
  }
  return true;
}





//**chd081013
var PartnerSearch = function(partnerName,params) {

  this.redirURL="http://online.compubase.net/webcpx/redir";

  this.mods = new Array();

  this.searchType = null;
  this.searchValue = null;

  this.searchTypeMain = null; // left part of searchType
  this.searchTypeOption = null; // right part of searchType

  this.direct = 1;  // default
  this.partner = (partnerName==null ? "itindex3" : partnerName);
  this.target = MM_findObj("cpblist"); // replace with target object (iframe, frame...)

  this.mod = null;  // param overridden
  this.lang = null; // param overridden
  this.root = null; // param overridden
  this.xbase = null; // param overridden

  // member functions

  // optional params : target frame object (default = current window)
  this.execute = function() {

    unzipLayer("divTabList");
    unzipLayer("divCpbList");

    toggleSearchVerbose(false);
    if (cpbTabs) {
      cpbTabs.select(0);  // show first tab (cpbList)
    }

    // check a few params
    this.searchType = this.aParams["type"]; // syntax: location.tree (ex: hwcat.cpy)
    this.searchValue = this.aParams["val"];
    this.mod = this.aParams["mod"];
    this.lang = this.aParams["lang"];
    this.root = this.aParams["root"];
    this.xbase = this.aParams["xbase"];


    // analyze searchType variations (.prod, .cpy)


    if (this.searchType) {  // avoid error if searchType not specified
      var aSearchType = this.searchType.split(".");
      this.searchTypeMain = aSearchType[0];
      if (aSearchType.length>1) {
        this.searchTypeOption = aSearchType[1];
      }
    }


    if (!this.searchValue) {
      var formFieldName = this.aParams["formfield"];
      if (formFieldName) {
        alert("formfield = "+formFieldName);
        var ed = MM_findObj(formFieldName);
        if (ed) {
          this.searchValue=ed.value;
        } else {
          alert("form field not found : "+formFieldName);
        }
      } else {  // no search value, and no formFieldName : use defaults
        if (this.searchTypeMain=="itcat") {
          this.searchValue=1; // nodecode for "itcat" - all IT tree
        }
        if (this.searchTypeMain=="hwcat") {
          this.searchValue=2; // nodecode for "hwcat" - Hardware stuff
        }
        if (this.searchTypeMain=="prodcat") {
          this.searchValue=478; // nodecode for "hwcat" - Software stuff
        }
      }
    }

    if (!this.searchValue) {
      return -1;
    }


    this.mod = this.mods[this.searchType];  // get MOD matching searchType

    if (this.mod!=null) { // OK, searchType exists (else error)

       if (this.searchTypeOption=="cpy") {
         this.xbase=1;
       }

       if (this.searchTypeMain=="hwcat") {
          this.root=2;  // set default root for hwcat
       }


    // construct final URL

      var URL = this.redirURL + "?part="+this.partner
        + ((this.direct==null) ? "" : "&direct="+this.direct)
        + ((this.mod==null) ? "" : "&mod="+this.mod)
        + ((this.searchValue==null) ? "" : (this.mod=="NSEARCH" ? "&nc=" : "&val=") +this.searchValue)
        + ((this.xbase==null) ? "" : "&xbase="+this.xbase)
        + ((this.lang==null) ? "" : "&lang="+this.lang)
        + ((this.root==null) ? "" : "&root="+this.root);

//      alert("searchType="+this.searchType+", URL = " + URL);

      if (this.target==null) {
        location.replace(URL);
      } else {
        setLocation(this.target,URL);
      }

    } else {
       alert("Invalid search type");
    }


  }

  // constructor start ----------------------------

  initGuideAchat();

  // init search types and associated mods
  this.mods["cpyname"] = "DSEARCH.CPYNAME";
  this.mods["postcode"] = "DSEARCH.POSTCODE";
  this.mods["prodkw"] = "DSEARCH.PRODKW";
  this.mods["prodname"] = "DSEARCH.PRODNAME";
  this.mods["selcpy"] = "DSEARCH.SELCPY";  // xbase 1
  this.mods["selprod"] = "DSEARCH.SELPROD";  // xbase 2

  this.mods["itcat"] = "NSEARCH";  // nomenclature (default root = IT, results=products)
  this.mods["itcat.cpy"] = "NSEARCH";  // nomenclature (default root = IT, results=companies)
  this.mods["prodcat"] = "NSEARCH";  // nomenclature (default root = software, results=products)
  this.mods["hwcat"] = "NSEARCH";  // nomenclature (default root = hardware, results=products)
  this.mods["prodcat.cpy"] = "NSEARCH";  // nomenclature (default root = software, results=companies)
  this.mods["hwcat.cpy"] = "NSEARCH";  // nomenclature (default root = hardware, results=companies)


  // parse params
  this.aParams = new Array();
  if (params.substring(0,1)=="?") { // remove first "?"
    params = params.substring(1);
  }

  var args = chd.split(params,'&');
  for (var i=0; i<args.length; i++) {
    var p = args[i].indexOf('=');
    if (p > 0) {
      var key = args[i].substring(0,p);
      var val = args[i].substring(p+1);
      this.aParams[key] = val;
    }
  }


  return this;
}






/**
  toggle Smartline verbose search form
*/
function toggleSearchVerbose(state) {
  if (DSEARCH_HIDE_FORM) {
    zipUnzipLayer("divCpbSearchVerbose0",state);
    zipUnzipLayer("divCpbSearchVerbose1",state);
  }
//  zipUnzipLayer("divToggleSearchVerbose",!state);
  if (DSEARCH_HIDE_RESULTS) {
    zipUnzipLayer("divSearchTabs",!state);  // optional : show/hide tab list and results
  } else {
    zipUnzipLayer("divSearchTabs",true);  // optional : show/hide tab list and results
  }
}

// Force all frames to same (sub) domain
// so I can access objects across frames, even when coming from smartline pages
function setCpbDomain() {
  chd.alert("setCpbDomain("+CPBDOMAIN+")");
  document.domain = CPBDOMAIN;
}

/*
function checkCpbDomain() {
 chd.alert("domain="+document.domain);
 chd.alert("top domain="+top.document.domain);

  if (document.domain != top.document.domain) {
//  alert("topdomain="+window.topdomain);

//if (document.domain != topdomain) {
    document.domain = top.document.domain;
//    setCpbDomain();
  }
}
*/

function insideTabs() {
  chd.alert("insideTabs(): name="+name);
  var parentName = "";
  try {
  parentName = parent.name;
  } catch (error) {
    parentName = "cpblist";
  }
  chd.alert("insideTabs(): parentName="+parentName);
  return (parentName=="cpblist");
}

// Called from GuideAchat to setup a few specific behaviours
function initGuideAchat() {

  var okDomains = new Array("guideachat.compubase.net",
        "guidedachat.compubase.net",
        "online.compubase.net",
        "itindex.compubase.net",
        "searchict.compubase.net",
        "static.compubase.net",
        "devsrvx.compubase.net",
        "guidedachat.econumerique.compubase.net",
        "devsrv3.compubase.net",
        "compubase.net" //**chd081010 NEW for 01Net (reload 2 times same frame)
        );
  okDomains.indexOf = indexOf;  // add my function to this prototype
  if (okDomains.indexOf(document.domain)<0) {
    alert("Remarque: cette page ne fonctionnera pas correctement depuis ce domaine : "+document.domain);
  }

  setCpbDomain(); // allow inter-frame DOM object access

//  setVersion("cpbSearch",3,0,0);  // differ from compuBase-online behaviour

  cpbTabs = new CpbTabList();
  cpbTabs.init(
    new CpbTab(cpbTabs,0,"divSearchTab0","divCpbList"),
    new CpbTab(cpbTabs,1,"divSearchTab1","divCpbDetail")
  );

  cpbTabs.clear(0);
}




//**chd081010 easy to integrate for partners -- links to cpb search (see demo)
function doPartnerSearch(partnerName) {
  var frm = MM_findObj("cpbframe");
  var URL = "http://static.compubase.net/cpbol/cpbsearch/"+partnerName+".html";

  frm.src = URL + "?" + arguments[1];
}



function setDept(dept) {
  alert("dept="+dept);
}


/*
  cpbsearch.js -- CpbSearch CLASS

  Author Christophe DUBOURG 2006.01.01

  (c) 2006-2007 compuBase / TECH COM

  NOTE: uses cpbutil.js

  USAGE:

  1. cpbSearch.direct(params);
  2. cpbSearch.nomenclature(params);

*/

function cpbSearchCallBack() {
  return; //**chd070718

  if (name=="tsBotFrame") { // called from bottom frame of nomenclature
//    alert(document.domain);
//    alert("parent="+parent);
//    alert(parent.tsMidFrame.name);
    parent.searchCallBack();
  }
}

function CpbSearch() {

  this.partnerITIndex = "itindex3"; // Partner code for ITIndex V3

  // different HTML templates available
  this.templates = new Object();
  this.aCaptions = new Object();
  this.aCaptions.keys = new Object();
  this.params = new Object(); // open params (can be user overriden)

  this.params["captionStyle"] = "";
  this.params["buttonStyle"] = "";

  this.templates["direct.full"] = "<!-- CpbSearch gadget by ChD [Direct] -->"
    +"<form  name=\"%0\" method=\"get\" target=\"%1\" onsubmit=\"cpbSearchSubmit(this);\">"
    +"  <input type=\"hidden\" name=\"part\" value=\"%2\">"
    +"  <input type=\"hidden\" name=\"direct\" value=\"1\">"
    +"  <input type=\"hidden\" name=\"lang\" value=\"%3\">"
    +"  <input type=\"hidden\" name=\"mod\" value=\"%4\">"
    +"  <div id=\"debug\" style=\"display:none\">&nbsp;</div>"
    +"  <div class=\"searchgadget\">"
    +"    <div class=\"searchtitle\">%5</div>"
    +"    <div class=\"searchedit\"><input type=\"text\" name=\"val\" value=\"%6\"></div>"
    +"    <div class=\"searchbtn\"><input type=\"submit\" style=\"width:160px\" value=\"%7\"></div>"
    +"  </div>"
    +"</form>"
    ;

  this.templates["direct.nocaption"] = "<!-- CpbSearch gadget by ChD [Direct] -->"
    +"<form  name=\"%0\" method=\"get\" target=\"%1\" onsubmit=\"cpbSearchSubmit(this);\">"
    +"  <input type=\"hidden\" name=\"part\" value=\"%2\">"
    +"  <input type=\"hidden\" name=\"direct\" value=\"1\">"
    +"  <input type=\"hidden\" name=\"lang\" value=\"%3\">"
    +"  <input type=\"hidden\" name=\"mod\" value=\"%4\">"
    +"  <div id=\"debug\" style=\"display:none\">&nbsp;</div>"
    +"  <div class=\"searchgadget\">"
    +"    <div class=\"searchedit\"><input type=\"text\" name=\"val\" value=\"%6\"></div>"
    +"    <div class=\"searchbtn\"><input type=\"submit\" style=\"width:160px\" value=\"%7\"></div>"
    +"  </div>"
    +"</form>"
    ;

  this.templates["nomenclature.full"] = "<!-- CpbSearch gadget by ChD [Nomenclature] -->"
    +"<form  name=\"%0\" method=\"get\" target=\"%1\" onsubmit=\"cpbSearchSubmit(this);\">"
    +"  <input type=\"hidden\" name=\"part\" value=\"%2\">"
    +"  <input type=\"hidden\" name=\"direct\" value=\"1\">"
    +"  <input type=\"hidden\" name=\"lang\" value=\"%3\">"
    +"  <input type=\"hidden\" name=\"mod\" value=\"%4\">"
    +"  <div id=\"debug\" style=\"display:none\">&nbsp;</div>"
    +"  <div class=\"searchgadget\">"
    +"    <div class=\"searchtitle\">%5</div>"
    +"    <div class=\"searchedit\"><input type=\"text\" name=\"val\" value=\"%6\"></div>"
    +"    <div class=\"searchbtn\"><input type=\"submit\" value=\"%7\"></div>"
    +"  </div>"
    +"</form>"
    ;

  this.templates["nomenclature.nocaption"] = "<!-- CpbSearch gadget by ChD [Nomenclature] -->"
    +"<form  name=\"%0\" method=\"get\" target=\"%1\" onsubmit=\"cpbSearchSubmit(this);\">"
    +"  <input type=\"hidden\" name=\"part\" value=\"%2\">"
    +"  <input type=\"hidden\" name=\"direct\" value=\"1\">"
    +"  <input type=\"hidden\" name=\"lang\" value=\"%3\">"
    +"  <input type=\"hidden\" name=\"mod\" value=\"%4\">"
//    +"  <input type=\"hidden\" name=\"root\" value=\"65456\">"
//    +"  <input type=\"hidden\" name=\"chdtest\" value=\"1\">"
    +"  <div id=\"debug\" style=\"display:none\">&nbsp;</div>"
//    +"  <div name=\"divSearchButton\" class=\"searchButton\" onclick=\"cpbSearchSubmit(%0);\">%7</div>"
    +"  <input type=\"submit\" value=\"%7\">"
    +"</form>"
    ;

  this.templates["nomenclature.hidden.nocaption"] = "<!-- CpbSearch gadget by ChD [Nomenclature] -->"
    +"<form  name=\"%0\" method=\"get\" target=\"%1\" onsubmit=\"cpbSearchSubmit(this);\">"
    +"  <input type=\"hidden\" name=\"part\" value=\"%2\">"
    +"  <input type=\"hidden\" name=\"direct\" value=\"1\">"
    +"  <input type=\"hidden\" name=\"lang\" value=\"%3\">"
    +"  <input type=\"hidden\" name=\"mod\" value=\"%4\">"
    +"  <input type=\"hidden\" name=\"root\" value=\"%8\">"
    +"  <input type=\"hidden\" name=\"xbase\" value=\"%9\">"
    +"  <div id=\"debug\" style=\"display:none\">&nbsp;</div>"
    +"  <input type=\"submit\" value=\"Nomenclature (%9.%8)\">"
    +"</form>"
    ;

  // chd070402 added .SEL direct search for companies and products
  /*
  this.templates["sel.nocaption"] = "<!-- CpbSearch gadget by ChD [Selection] -->"
    +"<form  name=\"%0\" method=\"get\" target=\"%1\" onsubmit=\"cpbSearchSubmit(this);\">"
    +"  <input type=\"hidden\" name=\"part\" value=\"%2\">"
    +"  <input type=\"hidden\" name=\"direct\" value=\"1\">"
    +"  <input type=\"hidden\" name=\"lang\" value=\"%3\">"
    +"  <input type=\"hidden\" name=\"mod\" value=\"%4\">"
    +"  <input type=\"hidden\" name=\"value\" value=\"%5\">"
    +"  <input type=\"hidden\" name=\"xbase\" value=\"%9\">"
    +"  <div id=\"debug\" style=\"display:none\">&nbsp;</div>"
    +"  <input type=\"submit\" value=\"Selection (%9.%8)\">"
    +"</form>"
    ;
  */


  // chd070402 added .SEL direct search for companies and products
  // value indices in template must match these params order

  //%0=formName, %1=target,%2=sPartner,%3=lang,%4=mod,
  //%5=sLabelCaption,%6=sValue,%7=sOkCaption,%8=sRoot,%9=xBase

  this.templates["sel.hidden.nocaption"] = "<!-- CpbSearch gadget by ChD [Selection] -->"
    +"<form  name=\"%0\" method=\"get\" target=\"%1\" onsubmit=\"cpbSearchSubmit(this);\">"
    +"  <input type=\"hidden\" name=\"part\" value=\"%2\">"
    +"  <input type=\"hidden\" name=\"direct\" value=\"1\">"
    +"  <input type=\"hidden\" name=\"lang\" value=\"%3\">"
    +"  <input type=\"hidden\" name=\"mod\" value=\"%4\">"
    +"  <input type=\"hidden\" name=\"val\" value=\"%6\">"
    +"  <input type=\"hidden\" name=\"xbase\" value=\"%9\">"
    +"  <input type=\"submit\" value=\"Selection (%9.%8)\">"
    +"</form>"
    ;
  //("sel.hidden",formName,target,mod,lang,value,partner,null,null,null,xBase));


  this.makeCaptions = function(a) {
    for (var ai=0; ai<a.length; ai++) {
      var aKey=a[ai++];
      var aLang=a[ai++];
      var aLabelCaption=a[ai++];
      var aOkCaption=a[ai];

//      alert("makeCaptions:"+aKey+"."+aLang+"="+aLabelCaption+","+aOkCaption);

      var captionKey = this.aCaptions.keys[aKey];
      if (captionKey==null) {
        captionKey = (this.aCaptions.keys[aKey] = new Object());
        captionKey.labels = new Object();
        captionKey.buttons = new Object();
      }
      captionKey.labels[aLang] = aLabelCaption;
      captionKey.buttons[aLang] = aOkCaption;
    }
  }

  this.getLabelCaption = function(mod,lang) {
  var captionObj = this.aCaptions.keys[mod];
  if (captionObj==null) {
    alert("this module is not available: "+mod);
    return "n/a";
  }
    var sLabel = captionObj.labels[lang];
    if (sLabel==null) {
//    sLabel = "caption not available for this lang: "+mod+"/"+lang;  // not labelCaption could be found for this module
      sLabel = null;
  }
  return sLabel;
  }


  this.getButtonCaption = function(mod,lang) {
  var captionObj = this.aCaptions.keys[mod];
  if (captionObj==null) {
    alert("thid module doesn't exist : "+mod);
    return "n/a";
  }
    var sLabel = captionObj.buttons[lang];
    if (sLabel==null) {
    sLabel = "button label not avail for this lang: "+mod+"/"+lang; // not labelCaption could be found for this module
  }
  return sLabel;
  }



  //getHTML("nomenclature.hidden",formName,target,mod,lang,value,partner,null,null,root));
           //.getHTML("sel.hidden",formName,target,mod,lang,value,partner,null,null,null,xBase));


  this.getHTML = function(template,formName,target,mod,lang,value,partner,labelCaption,okCaption,root,xBase) {
    var sPartner = (partner==null ? this.partnerITIndex : partner);
    var sLabelCaption = (labelCaption==null ? this.getLabelCaption(mod,lang) : labelCaption);
    var sOkCaption = (okCaption==null ? this.getButtonCaption(mod,lang) : okCaption);
    var sValue = (value==null ? "" : value);
    var sRoot = (root==null ? "" : root);
    var xBase = (xBase==null ? "" : xBase);

    var templateSuffix = ".full";
    if (sLabelCaption==null) {
    templateSuffix = ".nocaption";
    }

    var templateName = template+templateSuffix;

  //  alert("templateName="+templateName);

    // value indices in template must match these params order
    var result = chd.format(this.templates[templateName],[
        formName,target,sPartner,lang,mod,
        sLabelCaption,sValue,sOkCaption,sRoot,xBase]);

//  alert(result);

    return result;
  } // end getHTML()


  // constructor 2DO: make this LATIN AND UTF8 compatible (no accents here)
  this.makeCaptions([
    "DSEARCH.CPYNAME","F","Soci&eacute;t&eacute;","Chercher une soci&eacute;t&eacute;",
    "DSEARCH.POSTCODE","F","Code postal","Chercher code postal",
    "DSEARCH.PRODKW","F","Mot cl&eacute;","Chercher par mot cl&eacute;",
    "DSEARCH.PRODNAME","F","Nom produit","Chercher un produit",
    "DSEARCH.SELCPY","F",null,"Afficher une s&eacute;lection de soci&eacute;t&eacute;s",
    "DSEARCH.SELPROD","F",null,"Afficher une s&eacute;lection de produits",
    "NSEARCH","F",null,"Nomenclature logicielle", // No label caption

    "DSEARCH.CPYNAME","E","Company","Search a company",
    "DSEARCH.POSTCODE","E","PostCode","Search PostCode",
    "DSEARCH.PRODKW","E","Keyword","Keyword search",
    "DSEARCH.PRODNAME","E","Product","Search product",
    "DSEARCH.SELCPY","E",null,"Show selection of companies",
    "DSEARCH.SELPROD","E",null,"Show selection of products",
    "NSEARCH","E",null,"Software directory"  // No label caption
  ]);

  // public functions

  // direct search
  this.direct = function(formName,target,mod,lang,value,partner,labelCaption,okCaption,xBase) {
  if (this.params["debug.html"]=="1") {
    alert(this.getHTML("direct",formName,target,mod,lang,value,partner,labelCaption,okCaption,null,xBase));
  } else {
    document.writeln(this.getHTML("direct",formName,target,mod,lang,value,partner,labelCaption,okCaption,null,xBase));
  }
  }

  // nomenclature search
  this.nomenclature = function(formName,target,mod,lang,value,partner,labelCaption,okCaption,root,xBase) {
  if (this.params["debug.html"]=="1") {
//    alert(this.getHTML("nomenclature",formName,target,mod,lang,value,partner,labelCaption,okCaption));
    document.writeln("<textarea cols=50 rows=8>"+this.getHTML("nomenclature",formName,target,mod,lang,value,partner,labelCaption,okCaption,root,xBase)+"</textarea>");
  } else {
    document.writeln(this.getHTML("nomenclature",formName,target,mod,lang,value,partner,labelCaption,okCaption,root,xBase));
  }
  }

  // nomenclature hidden **chd070306 NEW NEW NEW for Joomla nomenclature (MOSETS)
  //nomenclatureHidden("frmNomenclatureSoft","cpblist","NSEARCH","F",value,null,null,null,root);
  this.nomenclatureHidden = function(formName,target,mod,lang,value,partner,root,xBase) {
  //alert("nomenclatureHidden: root="+root);

  if (this.params["debug.html"]=="1") {
//    alert(this.getHTML("nomenclature",formName,target,mod,lang,value,partner,labelCaption,okCaption));
    document.writeln("<textarea cols=50 rows=8>"+this.getHTML("nomenclature.hidden",formName,target,mod,lang,value,partner,null,null,root,xBase)+"</textarea>");
  } else {
    document.writeln(this.getHTML("nomenclature.hidden",formName,target,mod,lang,value,partner,null,null,root,xBase));
  }
  }

  this.selHidden = function(formName,target,lang,value,partner,xBase) {
  //alert("nomenclatureHidden: root="+root);

  if (xBase==null) {
    xBase = 1;  // default = companies
  }
  var mod = "DSEARCH." + (xBase==1 ? "SELCPY" : "SELPROD");

/*
  if (chd.extractFileExt(value).length==0) {
    value+=".sel";
  }
*/

  if (this.params["debug.html"]=="1") {
//    alert(this.getHTML("nomenclature",formName,target,mod,lang,value,partner,labelCaption,okCaption));
    document.writeln("<textarea cols=50 rows=8>"+this.getHTML("nomenclature.hidden",formName,target,mod,lang,value,partner,null,null,null,xBase)+"</textarea>");
  } else {

    //var sDebug = "formName="+formName+", target="+target+", mod="+mod+", lang="+lang+", value="+value;
    //alert(sDebug);

    document.writeln(this.getHTML("sel.hidden",formName,target,mod,lang,value,partner,null,null,null,xBase));
  }
  }

  // set misc params
  // usage: setParams("param","value","param2","value2",.../...);
  this.setParams = function() {
    for (var pi=0; pi<arguments.length; pi++) {
      var key=arguments[pi++];
      var val=arguments[pi];
      this.params[key]=val;
    }
  }

  /*
  this.post = function(formName) {
    document.writeln("cpbSearchSubmit2(MM_findObj('"+formName+"'));");
  }
  */


  return this;
}


/*
  adjust IFRAME height to actual content
  should be called from a onload event
*/
function iFrameHeight(senderName) {
  var h = 0;
  if ( !document.all ) {
    h = document.getElementById(senderName).contentDocument.height;
    document.getElementById(senderName).style.height = h + 60 + 'px';
  } else if( document.all ) {
    h = document.frames(senderName).document.body.scrollHeight;
    document.all[senderName].style.height = h + 20 + 'px';
  }
}

/* simple preload images in an array using DOM, so thay are displayed instantly */
function preload_images() {
  for (var i = 0; i < arguments.length; i++) {
    preloaded_images[i] = document.createElement('img');
    preloaded_images[i].setAttribute('src',arguments[i]);
  }
}




/**
  cpbList : checkbox onclick event
  selKind = xBaseCode (currently)
*/
function userSelClick(row,selKind,code) {
  var url;
  if (row<0) {  // clear user selection
    url = "/webcpx/webserv?actn=userselection&xml=0&replace=1&kind="+selKind+"&values=";
  } else {
    url = "/webcpx/webserv?actn=userselection&xml=0&changed=1&x=1&kind="+selKind+"&values="+code;
  }

//  userSelClickXMLdoc.load(url);

//  alert("URL would be : "+url);
  userSelClickXMLdoc = ajaxLoad(url,userSelClickCallback);

//    userSelClickXMLdoc = ajaxLoadXML3(url,userSelClickCallback);
/*
//  userSelClickXMLrequest.addEventListener("load", userSelClickCallback, false);
  userSelClickXMLrequest = new XMLHttpRequest();
//  userSelClickXMLrequest.onload = userSelClickCallback;
  userSelClickXMLrequest.open("GET", url, true);
  userSelClickXMLrequest.send(null);

  userSelClickCallback();
*/
/*
    var objXMLHTTP = new XMLHttpRequest();
    objXMLHTTP.open("GET", url, false);
    objXMLHTTP.send(null);
    userSelClickXMLdoc = objXMLHTTP.responseXML;
    userSelClickCallback();
*/
}

/**
  cpbList : user clicked on "compare"
*/
function compareProducts(flags) {
  var URL = "/webcpx/redir?actn=prodcompare&f="+flags;
  openWindow("cpbCompare",URL);
}

/**
  AjaxCombo object
  (c) ChD 2007
  Link an HTML combo to an Ajax webservice, so it can be updated automagically
*/
function AjaxCombo(_targetName, queryID, _valueColumn, _labelColumn) {

    // members
    this.docXML = null; // changed by ajaxLoad()
    this.sortAttr = null;
    this.sortDirection = +1;

    this.baseUrl = "/webcpx/webserv?actn=ajax&q="+queryID;

  this.target = $(_targetName); // target HTML object (combo, list...)

    this.valueCol = _valueColumn; // ex: retrieve column "ID" as "value" field
  this.labelCol = _labelColumn; // ex: retrieve column "NAME" as label field

  this.aDiv = null; // new. set contents using innerHTML

    // set target comboBox or list
    this.setTarget = function(id) {
      this.target = MM_findObj(id);
    }

    this.getTarget = function() {
      return this.target;
    }

    this.setDiv = function(divName) {
    this.aDiv = MM_findObj(divName);
  }

  // clear combo options
    this.clear = function() {
//    alert("clearing");
    while (this.target.options.length>0) {
      this.target.options[this.target.options.length-1]=null;
    }
  }

  // call webservice to get new contents
    this.fetch = function(aParams, callback) {
      var url = this.baseUrl;
      for (var pi=0; pi<aParams.length; pi++) {
      url+= "&q0p"+pi+"=" + aParams[pi];
      }
//      alert("url = "+url);
      this.docXML = ajaxLoadXML(url,callback);
    }

  this.add = function(text,value) {
    var item = new Option(text,value);
    this.target.options[this.target.options.length] = item;
  }

  this.setItemAt = function(index,text,value) {
    var item = new Option(text,value);
    this.target.options[index] = item;
  }

  this.setLength = function(length) {
    this.target.options.length = length;
  }

  this.getLength = function(length) {
    return this.target.options.length;
  }

  this.draw2 = function() {
    this.clear(); // clear options

    var valueList = this.docXML.getElementsByTagName(this.valueCol);
    var labelList = this.docXML.getElementsByTagName(this.labelCol);

//alert("valueList.length="+valueList.length);

    this.setLength(valueList.length);

//alert("internal list length ="+this.getLength());

    for (var ri=0; ri<valueList.length; ri++) {
      var sValue = valueList[ri].firstChild.nodeValue;
      var sLabel = labelList[ri].firstChild.nodeValue;

//      this.add(sLabel,sValue);
    this.setItemAt(ri,sLabel,sValue);
    }

    return this;
    }

  this.draw = function() {
    var valueList = this.docXML.getElementsByTagName(this.valueCol);
    var labelList = this.docXML.getElementsByTagName(this.labelCol);

//alert("valueList.length="+valueList.length);

//    this.clear(); // clear options - no more necessary since we set length directly

    this.setLength(valueList.length);

    var opts = this.target.options;

    for (var ri=0, n=valueList.length; ri<n; ri++) {
      var sValue = valueList[ri].firstChild.nodeValue;
      var sLabel = labelList[ri].firstChild.nodeValue;

      var item = new Option(sLabel,sValue);

/*
    var item = document.createElement('option');
      item.value = sValue;
      item.text = sLabel;
*/
      opts[ri]=item;
    }
    return this;
    }

  this.draw4html = function() {

    var valueList = this.docXML.getElementsByTagName(this.valueCol);
    var labelList = this.docXML.getElementsByTagName(this.labelCol);

      var html = "<select id='prod' name='prod' size='16' style='width:100%' onChange='productChange()'>";

    for (var ri=0, n=valueList.length; ri<n; ri++) {
      var sValue = valueList[ri].firstChild.nodeValue;
      var sLabel = labelList[ri].firstChild.nodeValue;

    html+="<option value='"+sValue+"'>"+sLabel+"</option>";
    }

    html+="</select>";

    this.aDiv.innerHTML = html;

    return this;
    }
}

function pleaseWait(msg,parent) {
  if (divPleaseWait==null) {

    if (!parent) {
      parent = document.body;
      //alert("parent is body");
    }

    divPleaseWait = document.createElement('div');

    // Note: need to set EACH style one by one coz IE6 still don't use STYLE property (FF does) !!!!!!
    divPleaseWait.style.position = 'absolute';
    divPleaseWait.style.visible = "visible";
      divPleaseWait.style.top = "16px";
    divPleaseWait.style.left = "128px";
      divPleaseWait.style.backgroundColor = "yellow";
      divPleaseWait.style.color="blue";
      divPleaseWait.style.border="1px solid red";
      divPleaseWait.style.textalign="center";
      divPleaseWait.style.padding="8px";
//      divPleaseWait.style.zindex="0";

//    var msgObj=document.createTextNode("Dummy message text");
//      divPleaseWait.appendChild(msgObj);
    parent.appendChild(divPleaseWait);
    //document.insertBefore(divPleaseWait,parent);
  }
  if (msg!=null) {
    divPleaseWait.innerHTML = msg;
  }
  showHideLayerObj(divPleaseWait,msg!=null);
}

/**
  return value for an attribute in a CPBWEBSERV stream (not XML)
  ex: selcount=3 in [DATASET] section
*/
function getDatasetAttributeValue(aData,attributeName) {
  var result = null;
  var L = aData.length;
  var li = 0;
  var attrEq = attributeName+"=";
  while ((li<L) && (aData[li].indexOf("[DATASET]")<0)) { // search data rows start line
    li++;
  }
  // if found (li<L)
  while ((li<L) && (aData[li].indexOf(attrEq)<0)) { // search data rows start line
    li++;
  }
  if (li<L) { // found attributename
    result = aData[li].substr(attrEq.length); // take what is after the "=" sign
  }
  return result;
}

/**
  get ISO2 equivalent to cpb codes
*/
function cpbLangToISO2(lang) {
  var aCodes = new Array(6);
  aCodes["E"]="en";
  aCodes["F"]="fr";
  aCodes["G"]="de";
  aCodes["I"]="it";
  aCodes["S"]="es";

  var result=aCodes[lang];
  if (result==null) {
    result = "en";
  }
  return result;
}

/**
  return compuBase.net URL, using ISO2 langcode
*/
function getCompuBaseURL(langISO2) {
  return "http://"+langISO2+".compubase.net";
}

/**
  return compuBase.net ARTICLE URL, using ISO2 langcode and article number
*/
function getCompuBaseArticle(article,langISO2) {
  return getCompuBaseURL(langISO2) + "/index.php?action=article&numero="+article;
}

/**
  chd071026
  NEW now accepts a context parameter to display help
*/
function cpbHelp(pageName,params) {
  if (pageName=="GFK") {
      helpPopupV("/webcpx/help/gfk.jsp");
  } else if (pageName=="RANKING") {
    var iso2 = cpbLangToISO2(params);
    helpPage(getCompuBaseArticle(133,iso2));
  } else if (pageName=="SCORING") {
    var iso2 = cpbLangToISO2(params);
    helpPage(getCompuBaseArticle(134,iso2));
  }
}

// replace main compuBase window with URL
function replaceOpener(url) {
  var target = getCeil(opener);
  setLocation(target,url);
}


// misc initializations
var chd = new ChD(this);
var cpbSearch = new CpbSearch();
