//<SCRIPT LANGUAGE="javascript" TYPE="text/javascript">
/******************** Global Functions *********************************************/

// Usable client window width, (NOT Screen width!)
function windWidth() {
   if (document.body.clientWidth >= 0) { // IE
      return (document.body.clientWidth - 10) ;
   }else if (window.innerWidth >= 0) { // Netscape
      return (window.innerWidth - 30) ;
   }
   return 750 ; // Effective width of client area for full screen window in 800x600 resolution
}
// Usable client window height, (NOT Screen height!)
function windHeight() {
   if (document.body.clientHeight >= 0) { // IE
      return (document.body.clientHeight - 10) ;
   }else if (window.innerHeight >= 0) { // Netscape
	  return (window.innerHeight - 20) ;
   }
   return 450 ; // Effective height of client area for full screen window in 800x600 resolution
}
// Amount of vertical scrolling
function docYScroll() {	 
   if (document.body.scrollTop >= 0) { // IE
	  return document.body.scrollTop ;
   }else if (window.pageYOffset >= 0) { // Netscape
      return  window.pageYOffset ;
   }
   return 0 ;
}
// Amount of horizontal scrolling
function docXScroll() {	 
   if (document.body.scrollLeft >= 0) { // IE
	  return document.body.scrollLeft ;
   }else if (window.pageXOffset >= 0) { // Netscape
	  return window.pageXOffset ;
   } 
   return 0 ;
}
// Mouse Pointer Coordinates
var MouseX = 0 ;
var MouseY = 0 ;
function mouseEventHandler (ev) {
  if (ev) { 
     if (ev.clientX) { // IE and Netscape 
        MouseX = ev.clientX ; 
	    MouseY = ev.clientY ;
	 }else if (ev.x) { // IE
        MouseX = ev.x ;
        MouseY = ev.y ;
	 }else if (ev.pageX) { // Netscape
	    MouseX = ev.pageX - docXScroll() ; 
	    MouseY = ev.pageY - docYScroll() ;
	 } 
  }
}  
// Find the object in the document
function getObjByID(divID, layID) {
   var obj ;
   if (document.getElementById) { // Modern browsers come here
      obj = document.getElementById(divID) ;
      if (obj) obj.isLayer = 0 ;
   }else if (document.all) { // IE browsers support this
      obj = document.all(divID)
      if (obj) obj.isLayer = 0 ;
   }else if (document.layers) { // Old Netscape browsers support this
      obj = document.layers(layID) ; 
      if (obj) obj.isLayer = 1 ;
   }
   return obj ;
}
// Changes the html content(s) of given DIV (actualy any html tag) or 
// LAYER (for compatibility with older netscape browsers) tags.  
function putContent(obj, cont) {
   if (obj) {
      if (obj.isLayer) { // Layer objects have special formats
	     obj.document.write(cont) ;
         obj.document.close() ;
      }else {
         obj.innerHTML = cont ;
      }
   }
}
/******************** Global Cookie Helper functions ***************************/
// Parse the cookies in memory in name value pairs in an array
function deleteCookie (cname) {
   var expires = new Date(0) ;
   document.cookie = cname + "=; path=/; expires=" + expires.toGMTString() ;
}
// Search the cookies for a name, and return its value if found
function getCookieValue (cname) {
   var prefix = cname + "=" ; 
   var rcookie = document.cookie ;
   var sti = rcookie.indexOf(prefix) ; 
   if (sti == -1) return null ;
   sti += prefix.length ; 
   var endi = rcookie.indexOf("; ", sti) ; 
   if (endi == -1) endi = rcookie.length ; 
   return rcookie.substring(sti, endi) ; 
}
// Parse the cookies in memory in name value pairs in an array
function parseCookie () {
   var acookie = new Array() ;
   var rcookie = document.cookie ;
   var cindex = 0, line, sti = 0, endi = 0, eqi ;
   while (endi >= 0) {
     endi = rcookie.indexOf ("; ", sti) ;
     if (endi < 0) { 
	    line = rcookie.substring(sti, rcookie.length) ;
	 }else {
	    line = rcookie.substring(sti, endi) ;
     }
	 // Here we have a cookie in line
	 sti = endi + 2 ;
	 eqi = line.indexOf ("=", 0) ;
	 if (eqi >= 0) { 
	    acookie [cindex] = new Array(2) ;
	    acookie [cindex][0] = line.substring(0, eqi) ; // name
	    acookie [cindex][1] = line.substring(eqi+1, line.length) ; // value
		cindex ++ ;
	 }
   }
   return acookie ; 
}
// Parse the value section of a cookie into pieces in an array 
function parseCookieValue (val) {
     var aval = new Array() ;
	 var sti=0, endi=0, str ;
	 while (endi >= 0) {
	    endi = val.indexOf ("&", sti) ;
        if (endi < 0) { 
	       str = val.substring(sti, val.length) ;
	    }else {
	       str = val.substring(sti, endi) ;
        }
	    sti = endi + 1 ;
		aval[aval.length] = unescape(str) ;
	 }
	 return aval ;
}
/******************** Ad object *********************************************/
// The Original Html of Ad
function Ad_Html () {
   return this.hhtml + this.link + this.fhtml ;
}
// Redirected Html of Ad
function Ad_RedHtml () {
   return this.hhtml + this.rlink + this.fhtml ;
}
// Ad object constructor
function Ad (category, name, hhtml, fhtml, link, rlink, weight) {
   // Methods
   this.Html = Ad_Html ;
   this.RedHtml = Ad_RedHtml ;

   // Properties
   // Test this property to identify Ad objects
   this.isAd = true ;
   // If category is an Ad object, initialize from that object
   if (category && category.isAd) {
      this.category = category.category ;
      this.name = category.name ;
   	  this.hhtml = category.hhtml ;
   	  this.fhtml = category.fhtml ;
   	  this.link = category.link ;
   	  this.rlink = category.rlink ;
   	  this.weight = category.weight ;
   }else {
      // Name of the category
      this.category = category ? category : "" ;
      // Name of the Ad
      this.name = name ? name : "" ;
      // Header Html
   	  this.hhtml = hhtml ? hhtml : "" ;
   	  // Footer Html
   	  this.fhtml = fhtml ? fhtml : "" ;
   	  // Original Link
   	  this.link = link ? link : "" ;
   	  // Redirected Link
   	  this.rlink = rlink ? rlink : "" ;
   	  // Weight of the Ad
   	  this.weight = weight ? weight : "" ;
   }
}
/******************** Ad Group object ***************************************/
// Create a new Ad and append it to the ad list
function AdGrp_NewAd (category, name, hhtml, fhtml, link, rlink, weight) {
   this.ads[this.length] = new Ad(category, name, hhtml, fhtml, link, rlink, weight) ;
   this.length ++ ;
}
// Generate a uniform random index
function AdGrp_RandIndex () {
   return Math.floor(Math.random() * this.length)  ;
}
// Generate a weighted random index (A roulette wheel approach)
function AdGrp_WRandIndex () {
   var indx ;
   // Find the total sum of the weights
   var sw = 0 ;
   for (indx = 0 ; indx < this.length ; ++indx) {
      sw += this.ads[indx].weight ;
   } 
   // Generate a random number in the range 0 to sum of weights
   var num = Math.random() * sw ;
   // Find which index is addressed?
   for (indx = 0 ; indx < this.length ; ++indx) {
	  num -= this.ads[indx].weight ;
      if (num <= 0) {
	     return indx ;
	  }
   }
   // Normaly this statement will never get executed
   return this.length-1 ;
}
// Get a uniformly random selected Ad from the list
function AdGrp_RandAd () {
   return this.ads[this.RandIndex()] ;
}
// Get a weighted random selected Ad from the list
function AdGrp_WRandAd () {
   return this.ads[this.WRandIndex()] ;
}
// AdGrp Object constructor
function AdGrp (ag) {
  // Methods
  this.NewAd = AdGrp_NewAd ;
  this.RandIndex = AdGrp_RandIndex ;
  this.WRandIndex = AdGrp_WRandIndex ;
  this.RandAd = AdGrp_RandAd ;
  this.WRandAd = AdGrp_WRandAd ;

  // Properties
  // Test this property to identify AdGrp objects
  this.isAdGrp = true ;
  if (ag && ag.isAdGrp) {
     this.length = 0 ;
	 this.ads = new Array() ;
	 for (var i=0 ; i < ag.length ; ++i) {
	    this.NewAd(ag.ads[i]) ;
	 }
  }else {
     // Number of ads in this group
     this.length = 0 ;
     // Ads array
     this.ads = new Array() ;
  }
}
/******************** Display Ad Group Object ***************************************/
function DAG_GetAdsFromCookie (name, append) {
  if (!name) name = this.name ;
  // Get the length of the data, if it exists
  var adcount = parseInt(unescape(getCookieValue(name + "Len"))) ; 
  if (!adcount) return false ;
  deleteCookie(name + "Len") ; 
  var changed = false ;
  // Retrieve the ads one by one
  for (var i=0 ; i < adcount ; ++i) {
	 var val = getCookieValue(name + "Ad" + i) ;
     if (val) {
  	    deleteCookie(name + "Ad" + i) ; 
	    var ad = new Ad() ;
        var aval = parseCookieValue(val) ;
		for (var j=0 ; j < aval.length ; j += 2) {
           if (j == aval.length-1)  break ;
		   switch(aval[j]) {
             case ("Category"): ad.category = aval[j+1] ; break ;
             case ("AdName"): ad.name = aval[j+1] ; break ;
             case ("Html1"): ad.hhtml = aval[j+1] ; break ;
             case ("Html2"): ad.fhtml = aval[j+1] ; break ;
             case ("Link"): ad.link = aval[j+1] ; break ;
             case ("RLink"): ad.rlink = aval[j+1] ; break ;
             case ("Weight"): ad.weight = aval[j+1] ; break ;
		  }
	   }
  	   if (!i && !append) this.ag = new AdGrp () ;
	   this.ag.NewAd(ad) ;
  	   changed = true ;
	 }
  }
  return changed ;
}
// Receive a requested cookie 
function DAG_ReceiveAdCookie(cname, append, vname, cnt) {
   if (!cname) cname = this.name ;
   if (!vname) vname = this.VarName() ;
   if (this.GetAdsFromCookie(cname, append)) { // Cookie is retrieved and deleted
      if (this.cc_task) eval(this.cc_task) ;
      this.cc_received = true ;
   }else { // Cookie is not found
      cnt = cnt ? parseInt(cnt) : 100 ;
	  if (--cnt > 0)
         setTimeout(vname + ".ReceiveAdCookie(\""+cname+"\", "+append+", \""+
		            vname+"\", \""+cnt+"\")", 250) ;
   }
}
// Request an Ad through cookie 
function DAG_ReqAdCookie(urlqstr) {
   if (!this.cc_obj) {// If no communication IMG element was found
      this.cc_obj = getObjByID(this.CCId(), "") ;  // Try searching the doc
   	  if (!this.cc_obj) { // Not created yet. ==> Create one
	      if (!document.createElement)  return false ;
	      var tmpimg = document.createElement('img') ;
    	  tmpimg.setAttribute('id', this.CCId()) ;
    	  tmpimg.setAttribute('width', "1") ;
    	  tmpimg.setAttribute('height', "1") ;
    	  this.cc_obj = document.body.appendChild(tmpimg);
          if (!this.cc_obj) return false ;
	  }
   }
   // cc_obj is OK, Make the src update
   if (!urlqstr)  urlqstr = this.cc_url ;
   this.cc_obj.src = "" ;
   this.cc_obj.src = urlqstr + "&dummy=" + Math.floor(Math.random() * 10000) ;
   this.cc_received = false ;
   return true ;
}
// Write the IMG element for cookie communication 
function DAG_WriteCCElem() {
   document.write("<IMG ID=\"" + this.CCId() + 
                  "\" BORDER=\"0\" WIDTH=\"1\" HEIGHT=\"1\" SRC=\"\" >") ;
   this.cc_obj = getObjByID(this.CCId(), "") ;
}
// Generate the ID of cookie image 
function DAG_CCId() {
   return "cimg" + this.name ;
}
// Generate the div ID (name of container in the browser) associated with this Display Ad Group
function DAG_DivId() {
   return "div" + this.name ;
}
// Generate the layer ID (name of container in the browser) associated with this Display Ad Group
function DAG_LayerId() {
   return "lay" + this.name ;
}
// Generate the variable name of the DAG object ?? only a guess 
function DAG_VarName() {
   return "dag" + this.name ;
}
// Write the container and an initial html content to the document of browser for interpretation.
function DAG_WriteContainer(cont) {
   document.write("<layer name=\"" + this.LayerId() + "\" >") ;
   document.write("<DIV ID=\"" + this.DivId() + "\" >") ;
   if (cont)  document.write(cont) ;
   document.write("</div></layer>") ;
   this.put_obj = getObjByID(this.DivId(), this.LayerId()) ;
}
// Get the html object
function DAG_Object () {
   if (!this.put_obj)
      this.put_obj = getObjByID(this.DivId(), this.LayerId()) ;
   return  this.put_obj ;
}
// Put the given content to this Display Group's container
function DAG_PutContent(cont) {
   putContent(this.Object(), cont) ;
}
// Get the html content of ad at the given index
function DAG_GetSelAd(adi, oh) {
	return (this.put_head + 
	        ((oh) ? this.ag.ads[adi].Html() : this.ag.ads[adi].RedHtml()) + 
		    this.put_foot ) ;
}
// Display Ad Group put_mode values 
var DAG_PUT_MODE_FSEQ = 0 ;
var DAG_PUT_MODE_WRAND = 1 ;
var DAG_PUT_MODE_URAND = 2 ;
var DAG_PUT_MODE_ALL = 3 ;
var DAG_PUT_MODE_BSEQ = 4 ;

// Display an Ad
function DAG_PutAd(adi, oh) {
   var html = "" ;
   if ((adi != null) && (adi >= 0)) {
	  // adi is assumed to be an index to the array, this.ag.ads[adi]
	  this.put_lasti = adi ;
	  html = this.GetSelAd(adi, oh) ;
   }else if (this.put_mode == DAG_PUT_MODE_FSEQ) { // Forward Sequential display Mode
	  this.put_lasti = (this.put_lasti + 1) % this.ag.length ;
	  html = this.GetSelAd(this.put_lasti, oh) ;
   }else if (this.put_mode == DAG_PUT_MODE_WRAND) { // Weighted random display
      this.put_lasti = this.ag.WRandIndex() ;
	  html = this.GetSelAd(this.put_lasti, oh) ;
   }else if (this.put_mode == DAG_PUT_MODE_URAND) { // Uniform random display
      this.put_lasti = this.ag.RandIndex() ;
	  html = this.GetSelAd(this.put_lasti, oh) ;
   }else if (this.put_mode == DAG_PUT_MODE_ALL) { // Display All ads
      var html = "" ;
	  for (var i=0 ; i < this.ag.length ; ++i) {
	     html = html + this.GetSelAd(i, oh) ;
	  }
   }else if (this.put_mode == DAG_PUT_MODE_BSEQ) { // Backward Sequential display Mode
	  this.put_lasti = this.put_lasti ? (this.put_lasti-1) : (this.ag.length - 1) ;
	  html = this.GetSelAd(this.put_lasti, oh) ;
   }
   this.PutContent(html) ;
}
// Periodically put the ads of this DAG
function DAG_PutAdPer (varname, adi, oh) {
   if (!adi) adi = null ;
   if (!oh) oh = false ;
   this.PutAd(adi, oh) ;
   if (!varname) varname = this.VarName() ;
   if (this.put_period > 0) 
       this.timer[0] = setTimeout(varname+".PutAdPer(\""+varname+"\","+adi+","+oh+")", 
	                              this.put_period) ;
}
// Stop the timer
function DAG_StopTimer (timerno) {
   if (!timerno) timerno = 0 ;
   clearTimeout(this.timer[timerno]) ;
}
// Update the visual properties of this object
function DAG_RefreshVisual () {
   var obj = this.Object() ;
   if (!obj) return ;
   if (obj.isLayer) { // Layer object
      obj.left = parseInt(this.left) ;
      obj.top = parseInt(this.top) ;
	  obj.width = parseInt(this.width) ;
	  obj.height = parseInt(this.height) ;
	  obj.visibility = this.visible ? "show" : "hide" ;
   }else { // Div object
      obj.style.left = this.left ;
      obj.style.top = this.top ;
	  obj.style.width = this.width ;
	  obj.style.height = this.height ;
	  obj.style.visibility = this.visible ? "visible" : "hidden" ;
   }
}
// Calculate the left position of this object
function DAG_LeftPosition () {
   var w = this.Object().isLayer ? NaN : this.Object().offsetWidth ;
   w = isNaN(w) ? parseInt(this.width) : w ;
   return (docXScroll() * this.sxr + windWidth() * this.wxr + MouseX * this.mxr -
           (isNaN(w) ? 0 : w) * this.axr + this.xoff ) ;
}
// Calculate the top position of this object
function DAG_TopPosition () {
   var h = this.Object().isLayer ? NaN : this.Object().offsetHeight ;
   h = isNaN(h) ? parseInt(this.height) : h ;
   return (docYScroll() * this.syr + windHeight() * this.wyr + MouseY * this.myr - 
           (isNaN(h) ? 0 : h) * this.ayr + this.yoff ) ;
}
// Update the display position of this object
function DAG_RefreshPosition () {
   if (this.pos_pause_refresh) return ;
   var left = this.LeftPosition() ;
   var top  = this.TopPosition() ;
   if ((left != parseInt(this.left)) || (top != parseInt(this.top))) {
      this.left = left ;
	  this.top = top ;
	  this.RefreshVisual () ;
   } 
}
// Periodically refresh the position
function DAG_RefreshPositionPer (varname) {
   this.RefreshPosition() ;
   if (!varname) varname = this.VarName() ;
   if (this.pos_period > 0)
       this.timer[1] = setTimeout(varname+".RefreshPositionPer(\""+varname+"\")", this.pos_period) ;
}
// Predefined position ratios
var DAG_POS_LEFT = 0 ;
var DAG_POS_TOP = 0 ;
var DAG_POS_QUART = 0.25 ;
var DAG_POS_CENTER = 0.5 ;
var DAG_POS_3QUART = 0.75 ;
var DAG_POS_RIGHT = 1 ;
var DAG_POS_BOTTOM = 1 ;
var DAG_POS_NOSCROLL = 1 ;
var DAG_POS_SCROLL = 0 ;
var DAG_POS_NOMOUSE = 0 ;
var DAG_POS_MOUSE = 1 ;
// Set the reference point of ad box : enter null, if you want a parameter unchanged
function DAG_AdBoxRefPoint (xr, yr) {
  if (xr != null) this.axr = xr ;  // Horizontal reference ratio
  if (yr != null) this.ayr = yr ;  // Vertical reference ratio
}
// Set the anchor point on window : enter null, if you want a parameter unchanged
function DAG_WindAnchorPoint (wxr, mxr, xoff, wyr, myr, yoff) {
  if (wxr != null) this.wxr = wxr ; // Horizontal window anchor point ratio
  if (mxr != null) this.mxr = mxr ; // Horizontal mouse anchor point ratio
  if (xoff != null) this.xoff = xoff ; // Horizontal window anchor point offset in pixels
  if (wyr != null) this.wyr = wyr ; // Vertical window anchor point ratio
  if (myr != null) this.myr = myr ; // Vertical mouse anchor point ratio
  if (yoff != null) this.yoff = yoff ;// Vertical window anchor point offset in pixels
}
// Set the scroll compensation ratios
function DAG_ScrollCompensate(xr, yr) {  
  if (xr != null) this.sxr = xr ; // Horizontal scroll compensation ratio
  if (yr != null) this.syr = yr ; // Vertical scroll compensation ratio
}
// Change the anchor point without changing the position of the ad box
function DAG_ChangeAnchorPoint (wxr, mxr, xoff, axr, wyr, myr, yoff, ayr) {
  // calculate the last left and top positions
  var old_left = this.LeftPosition() ;
  var old_top = this.TopPosition() ;
  // set the new variables 
  this.WindAnchorPoint (wxr, mxr, xoff, wyr, myr, yoff) ;
  this.AdBoxRefPoint (axr, ayr) ;
  // recalculate left and top positions
  var new_left = this.LeftPosition() ;
  var new_top = this.TopPosition() ;
  // Compansate the difference in positions
  this.xoff += old_left - new_left ;
  this.yoff += old_top - new_top ;
}
// Drag and Drop Mouse Down function
function DAG_DDMouseDown () {
  if (this.dd_handshake) return true ;
  this.ChangeAnchorPoint(null,DAG_POS_MOUSE,null,null, null,DAG_POS_MOUSE,null,null) ;
  this.dd_handshake = true ;
  return true ;
}
// Drag and Drop Mouse Up function
function DAG_DDMouseUp () {
  if (!this.dd_handshake) return true ;
  this.ChangeAnchorPoint(null,DAG_POS_NOMOUSE,null,null, null,DAG_POS_NOMOUSE,null,null) ;
  this.dd_handshake = false ;
  return true ;
}
// Enable or Disable Drag and Drop on the ad box
function DAG_DDStatus (enable, varname) {
   if (!varname) varname = this.VarName() ;
   if (enable) { // Enable drag and drop
      var mdfnc = varname + "_MouseDown"  ; 
      var mdfstr = "function " + mdfnc + "(){ " + varname + ".DDMouseDown() ; } \n" +
                   "this.Object().onmousedown = " + mdfnc + " ;" ;
      eval(mdfstr) ;
   	  var mufnc = varname + "_MouseUp"  ; 
   	  var mufstr = "function " + mufnc + "(){ " + varname + ".DDMouseUp() ; } \n" +
                   "this.Object().onmouseup = " + mufnc + " ;" ;
      eval(mufstr) ;
   }else { // Disable drag and drop
      this.Object().onmousedown = null ;
      this.Object().onmouseup = null ;
   }
}
// Display Ad Group object constructor
function DAG (name, ag) {
   // Methods
   this.GetAdsFromCookie = DAG_GetAdsFromCookie ;
   this.ReceiveAdCookie = DAG_ReceiveAdCookie ;
   this.ReqAdCookie = DAG_ReqAdCookie ;
   this.WriteCCElem = DAG_WriteCCElem ;
   this.CCId = DAG_CCId ;
   this.DivId = DAG_DivId ;
   this.LayerId = DAG_LayerId ;
   this.VarName = DAG_VarName ;
   this.WriteContainer = DAG_WriteContainer ;   
   this.Object = DAG_Object ;
   this.PutContent = DAG_PutContent ;
   this.GetSelAd = DAG_GetSelAd ;
   this.PutAd = DAG_PutAd ;
   this.PutAdPer = DAG_PutAdPer ;
   this.StopTimer = DAG_StopTimer ;
   this.RefreshVisual = DAG_RefreshVisual ;
   this.LeftPosition = DAG_LeftPosition ;
   this.TopPosition = DAG_TopPosition ;
   this.RefreshPosition = DAG_RefreshPosition ;
   this.RefreshPositionPer = DAG_RefreshPositionPer ;
   this.AdBoxRefPoint = DAG_AdBoxRefPoint ;
   this.WindAnchorPoint = DAG_WindAnchorPoint ;
   this.ScrollCompensate = DAG_ScrollCompensate ;
   this.ChangeAnchorPoint = DAG_ChangeAnchorPoint ;

   this.DDMouseDown = DAG_DDMouseDown ;
   this.DDMouseUp = DAG_DDMouseUp ;
   this.DDStatus = DAG_DDStatus ;
   
   // Test this property to identify DAG objects
   this.isDAG = true ;
   
   // Name of this Display Group. Prefer it as the name of display position name.
   this.name = name ? name : "Unknown" +  Math.floor(Math.random() * 10000) ;
   // The Ads of the group.
   this.ag = ag ? new AdGrp(ag) : new AdGrp() ;

   // Properties related to content putting.
   // Container Object of this dag.
   this.put_obj = null ;   
   // Period of the periodic content put.
   this.put_period = 0 ;   
   // Mode of putting 
   this.put_mode = DAG_PUT_MODE_WRAND ;   
   // Prepend this to the content: PutAd, GetSelAd methods
   this.put_head = "" ;
   // Append this to the content: PutAd, GetSelAd method
   this.put_foot = "" ;
   // The index of last put ad
   this.put_lasti = 0 ;
   // Timer IDs are set by periodic events, and used to stop that event later
   // index 0: PutAdPer, index 1: RefreshPositionPer
   this.timer = new Array(2) ;
   
   // Properties related to Ad displaying
   // Ad display properties
   this.left = null ;
   this.top = null ;
   this.width = "auto" ;
   this.height = "auto" ;
   this.visible = 1 ;   
   // AdLeftPos = Xscroll * sxr + windWidth * wxr + MouseX * mxr - AdWidth * axr + xoff
   this.sxr = 0 ;  // Horizontal sroll ratio, 0: no follow (scroll), 1.0: follow (No scroll)
   this.wxr = 0 ;  // Horizontal window Align ratio, 0: Left, 0.5: Center, 1.0: Right
   this.mxr = 0 ;  // Horizontal Mouse Align, 0: No, 1.0: Align to Mouse pointer
   this.axr = 0 ;  // Horizontal alignment point on the ad, 0: Left, 0.5: Center, 1.0: Right
   this.xoff = 0 ; // Horizontal offset in pixels between window reference and ad reference
   // AdTopPos = Yscroll * syr + windHeight * wyr + MouseY * myr - AdHeight * ayr + yoff
   this.syr = 0 ;  // Vertical sroll ratio, 0: no follow (scroll), 1.0: follow (No scroll)
   this.wyr = 0 ;  // Vertical window Align ratio, 0: Top, 0.5: Center, 1.0: Bottom
   this.myr = 0 ;  // Vertical Mouse Align, 0: No, 1.0: Align to Mouse pointer
   this.ayr = 0 ;  // Vertical alignment point on the ad, 0: Top, 0.5: Center, 1.0: Bottom
   this.yoff = 0 ; // Vertical offset in pixels between window reference and ad reference
   // 
   this.pos_period = 0 ;
   this.pos_pause_refresh = 0 ;

   // Ad cookie related variables
   this.cc_obj = null ; // Object of the IMG element for cookie communication
   this.cc_url = "" ; // URL+query string to invoke cookie ad
   this.cc_received = false ; // false: No cookie is received. true: a cookie is received
   this.cc_task = null ; // Task to be executed when a cookie is received.
}
/******************** Global Event Handlers *********************************/
function GEH_NewHandler(str) {
   var i ;
   for (i=0 ; i < this.tasks.length ; ++i) {
      if (this.tasks[i] == null) {
	     this.tasks[i] = str ;
		 return i ;
	  }
   }
   i = this.tasks.length ;
   this.tasks[i] = str ;
   return i ;
}
function GEH_RemoveHandler(i) {
   if (i < this.tasks.length)  this.tasks[i] = null ;
}
function GEH_CallHandlers (ev) {
   if (!ev && window.event) { // IE
      ev = window.event ;
   }
   for (var i=0 ; i < this.tasks.length ; ++i) {
      if (this.tasks[i]) {
         eval(this.tasks[i]) ;
	  }
   }
}
function GEH () {
   this.NewHandler = GEH_NewHandler ;
   this.RemoveHandler = GEH_RemoveHandler ;
   this.CallHandlers = GEH_CallHandlers ;
  
   this.tasks = new Array() ;
}
//------ Initialize some Global Event Handlers -------

// document.onmousemove Global Event Handler
var gehMMove = new GEH() ;
function gehMMoveHandler (ev) { gehMMove.CallHandlers(ev) ; }
document.onmousemove = gehMMoveHandler ;
gehMMove.NewHandler ("mouseEventHandler (ev)") ;

// window.onresize Global Event Handler
var gehResize = new GEH() ;
function gehResizeHandler (ev) { gehResize.CallHandlers(ev) ; }
window.onresize = gehResizeHandler ;

// window.onscroll Global Event Handler
var gehScroll = new GEH() ;
function gehScrollHandler (ev) { gehScroll.CallHandlers(ev) ; }
window.onscroll = gehScrollHandler ;

