
function BrowserUtilities () {
    var versionSearchString;
    var dataBrowser = [
        { string: navigator.userAgent, subString: "Chrome", identity: "Chrome" },
        { string: navigator.userAgent, subString: "OmniWeb", identity: "OmniWeb", versionSearch: "OmniWeb/" },
        { string: navigator.vendor, subString: "Apple", identity: "Safari", versionSearch: "Version" },
        { prop: window.opera, identity: "Opera" },
        { string: navigator.vendor, subString: "iCab", identity: "iCab" },
        { string: navigator.vendor, subString: "KDE", identity: "Konqueror" },
        { string: navigator.userAgent, subString: "Firefox", identity: "Firefox" },
        { string: navigator.vendor, subString: "Camino", identity: "Camino" },
        { string: navigator.userAgent, subString: "Netscape", identity: "Netscape" }, // for newer Netscapes (6+)
        { string: navigator.userAgent, subString: "MSIE", identity: "Explorer", versionSearch: "MSIE" },
        { string: navigator.userAgent, subString: "Gecko", identity: "Mozilla", versionSearch: "rv" },
        { string: navigator.userAgent, subString: "Mozilla", identity: "Netscape", versionSearch: "Mozilla" }
    ];
    var dataOS = [
        { string: navigator.platform, subString: "Win", identity: "Windows" },
        { string: navigator.platform, subString: "Mac", identity: "Mac" },
        { string: navigator.userAgent, subString: "iPhone", identity: "iPhone/iPod" },
        { string: navigator.platform, subString: "Linux", identity: "Linux" }
    ];
    
    function searchString (data) {
        for ( var i = 0; i < data.length; i++ ) {
            var dataString = data[i].string;
            var dataProp = data[i].prop;
            versionSearchString = data[i].versionSearch || data[i].identity;
            if ( dataString ) {
                if ( dataString.indexOf(data[i].subString) != -1 ) return data[i].identity;
            }
            else if ( dataProp ) {
                return data[i].identity;
            }
        }
    }
    function searchVersion (dataString) {
        var index = dataString.indexOf(versionSearchString);
        if ( index == -1 ) return;
        return parseFloat(dataString.substring(index + versionSearchString.length + 1));
    }
    
    /* 
    * getBrowserName
    * description:        Use to retrieve browser name of end user
    * Return:            String "browser-version"
    */
    this.getBrowserName = function () {
        var name = searchString(dataBrowser) || "An unknown browser";
        return name;
    }
    
    /* 
    * getBrowserVersion
    * description:         Use to retrieve browser version of end user
    * Return:                String "browser-version"
    */
    this.getBrowserVersion = function () {
        if ( ! versionSearchString ) {
            searchString(dataBrowser);
        }
        var version = searchVersion(navigator.userAgent) || searchVersion(navigator.appVersion) || "an unknown version";
        return version;
    }
    
    /* 
    * getOS
    * description:    Use to retrieve OS of end user
    * Return:        String "OS"
    */
    this.getOS = function () {
        var OS = searchString(dataOS) || "an unknown OS";
        return OS;
    }
    
    /* 
    * getBrowser
    * description: Use to retrieve browser name, browser version, and OS of end user
    * Return:         String "browser-name browser-version OS"
    */
    this.getBrowser = function () {
        var browser = this.getBrowserName();
        var version = this.getBrowserVersion();
        var OS = this.getOS();
        return browser + ' ' + version + ' ' + OS;
    }
}
function PageUtilities () {
    /* 
    * getObject
    * description:    Use to access objects in DOM
    * Parameters:     ID of object - value of 'id' attribute
    * Return:         Requested object or undefined
    */
   this.getObject = function (obj) {
      if ( typeof obj != 'string') {
         return obj;
      }
      var newObj;
      if ( document.getElementById ) {
         newObj = document.getElementById(obj);
      }
      else if ( document.all ) {
         newObj = document.all(obj);
      }
      return newObj;
   }
   
    /* 
    * getQuery
    * description:    Use to access query string in main browser window
    * Return:         Associative array containing query string in name/value pairs
    */
    this.getQuery = function () {
      var qs = location.search.substring(1);
      var nv = qs.split('&');
      var url = new Object();
      for(i = 0; i < nv.length; i++) {
         eq = nv[i].indexOf('=');
         url[nv[i].substring(0,eq).toLowerCase()] = unescape(nv[i].substring(eq + 1));
      }
      return url;
   }
   
    /* 
    * getQueryField
    * description:     Use to access specific field in query string
    * Parameters:         Name of field in query string
    * Return:             Value of requested field or empty string
    */
    this.getQueryField = function (field) {
      var url = this.getQuery();
      if ( url[field] ) {
         return url[field];
      }
      return '';
   }
   
    /* 
    * getLongestObject    
    * description:         Use to find object with greatest height
    * Parameters:             Numeric array containing ids of objects to compare
    * Return:                 Object with greatest height
    */
   this.getLongestObject = function (objs) {
      var longest = new Object;
      longest.offsetHeight = '0';
      for ( i = 0; i < objs.length; i++ ) {
         var obj = this.getObject(objs[i]);
         if ( obj && obj.offsetHeight && (obj.offsetHeight > longest.offsetHeight) ) {
            longest = obj;
         }
      }
      return longest;
   }
    /* 
    * equalizeObjectHeight
    * description:                Use to find object with greatest height
    * Parameters:                 Numeric array containing ids of objects whose heights are to be made equal
    */
   this.equalizeObjectHeight = function (objs) {
      if ( objs.length == '0' ) {
         return;
      }
      var longest = this.getLongestObject(objs);
      for ( i = 0; i < objs.length; i++ ) {
         var obj = this.getObject(objs[i]);
         if ( obj && ('offsetHeight' in obj) ) {
            obj.style.height = longest.offsetHeight;
         }
      }
   }
   
    /* 
    * getLinks
    * description: Use to retrieve array of links (all 'A' tags with href value of at least one char) in a specific container and its descendents in DOM
    * Parameters:     ID of container to search for links
    * Return:         Numeric array of link objects
    */
    this.getLinks = function (containerID) {
      var container = this.getObject(containerID);
      var links = container.getElementsByTagName('A');
      var selected = new Array;
      for ( i in links ) {
         if ( links[i].href && links[i].href.length > 0 ) {
            selected.push(links[i]);
         }
      }
      return selected;
   }
    
    /* 
    * addPixels
    * description: Use to programmatically add two pixel measurements. Parses two integer values, adds them and appends 'px' to the return string
    * Parameters:     Two values containing integers. Trailing non-integer string parts will be stripped off.
    * Return:         String with sum of two integers and appended 'px'
    */
    this.addPixels = function (d1, d2) {
        d1 = parseInt(d1);
        d2 = parseInt(d2);
        var sum = d1 + d2;
        sum = sum + 'px';
        return sum; 
    }
    /* 
    * contains 
    * decription:     Use to test if a dom element is contained within another dom element
    * Parameters:     Two DOM elements (objects). The first element is the container, the second is the containee
    * Return:         Boolean value - true if container element contains containee. Will test false if elements are the same
    */
    this.contains = function (containerObj, obj) {
        var parentNode;
        if ( obj.parentNode ) {
            parentNode = obj.parentNode;
        }
        else if ( obj.parentElement ) {
            parentNode = obj.parentElement;
        }
        else {
            return false;
        }
    
        if ( containerObj.id == parentNode.id ) {
                return true;
        }
        if ( this.contains(containerObj, parentNode) ) {
            return true;
        }
        else {
            return false;
        }
    }
    /* 
    * getAbsoluteX
    * description: Use to find the absolute X co-ordinate of an HTML element
    * Parameters:    DOM Element (object)
    * Return:         Absolute X co-ordinate of HTML element 
    */
    this.getAbsoluteX = function (obj) {
        var curleft = 0;
        if ( obj.offsetParent ) {
            while ( true ) {
                curleft += obj.offsetLeft;
                if ( ! obj.offsetParent ) {
                    break;
                }
                obj = obj.offsetParent;
            }
        }
        else if ( obj.x ) {
            curleft += obj.x;
        }
        return curleft;
    }
    /* 
    * getAbsoluteY
    * description: Use to find the absolute Y co-ordinate of an HTML element
    * Parameters:    DOM Element (object)
    * Return:         Absolute Y co-ordinate of HTML element 
    */
    this.getAbsoluteY = function (obj) {
        var curtop = 0;
        if ( obj.offsetParent ) {
            while ( true ) {
                curtop += obj.offsetTop;
                if ( ! obj.offsetParent ) {
                    break;
                }
                obj = obj.offsetParent;
            }
        }
        else if ( obj.y ) {
            curtop += obj.y;
        }
        return curtop;
    }
}
function Widget (obj) {
    this.id = obj.id;
    this.offsetTop = obj.offsetTop;
    this.offsetLeft = obj.offsetLeft;
   this.transition = obj.transition;
    this.pageutilities = new PageUtilities;
   this.obj = this.pageutilities.getObject(obj.id);
    this.obj.style.top = obj.top;
    this.obj.style.left = obj.left;
    if ( obj.width ) { this.obj.style.width = obj.width; }
   this.obj.style.position = 'absolute';
   this.obj.style.visibility = 'hidden';
    this.toggle = function () {
      if ( this.obj.style.visibility == 'hidden' ) {
         this.show();
         return;
      }
      this.hide();
    }
   this.show = function () {
      var dx = 30, dy = 30, dt = 5;
      var dir = -1;
      if ( this.obj.style.visibility == 'visible' ) {
         dir = 1;
      }
      switch ( this.transition ) {
         case 't':
            var lpos = 0;
            var tpos = 0;
            var rpos = this.obj.offsetWidth;
            var bpos = 0;
            break;
         case 'b':
            var lpos = 0;
            var tpos = this.obj.offsetHeight;
            var rpos = this.obj.offsetWidth;
            var bpos = this.obj.offsetHeight;
            break;
         case 'tr':
            var lpos = this.obj.offsetWidth;
            var tpos = 0;
            var rpos = this.obj.offsetWidth;
            var bpos = 0;
            break;
      }
      var count = 0;
      var obj = this.obj;
      var transition = this.transition;
      var tmr = setInterval(
         function () {
            switch ( transition ) {
               case 't':
                  if ( bpos - tpos > 0 || bpos - tpos < obj.offsetHeight ) {
                     bpos -= (dir * dy);
                     if ( bpos - tpos < 0 ) {
                        bpos = tpos;
                     }
                     if ( bpos - tpos > obj.offsetHeight ) {
                        bpos = obj.offsetHeight;
                     }
                  }
                  break;
               case 'b':
                  if ( bpos - tpos > 0 || bpos - tpos < obj.offsetHeight ) {
                     tpos += (dir * dy);
                     if ( bpos - tpos < 0 ) {
                        bpos = tpos;
                     }
                     if ( bpos - tpos > obj.offsetHeight ) {
                        tpos = 0;
                     }
                  }
                  break;
               case 'tr':
                  if ( rpos - lpos > 0 || rpos - lpos < obj.offsetWidth ) {
                     lpos += (dir * dx);
                     if ( rpos - lpos < 0 ) {
                        lpos = rpos;
                     }
                     if ( rpos - lpos > obj.offsetWidth ) {
                        lpos = 0;
                     }
                  }
                  if ( bpos - tpos > 0 || bpos - tpos < obj.offsetHeight ) {
                     bpos -= (dir * dy);
                     if ( bpos - tpos < 0 ) {
                        bpos = tpos;
                     }
                     if ( bpos - tpos > obj.offsetHeight ) {
                        bpos = obj.offsetHeight;
                     }
                  }
                  break;
            }
            var clipstring = 'rect('+ tpos +'px,'+ rpos +'px,'+ bpos + 'px,'+ lpos + 'px)';
            obj.style.clip = clipstring;
            obj.style.visibility = 'visible';
            if ( rpos - lpos <= 0 && bpos - tpos <= 0 ) {
               obj.style.visibility = 'hidden';
               clearInterval(tmr);
            }
            else if ( rpos - lpos >= obj.offsetWidth && bpos - tpos >= obj.offsetHeight ) {
               clearInterval(tmr);
            }
         }, dt
      );
    }
   this.hide = function () {
      this.obj.style.visibility = 'hidden';
   }
}
function UNICEFBanner (ns) {
    this.anc;
   this.widget;
   this.ns = ns;
    this.pageutilities = new PageUtilities;
    this.browserutilities = new BrowserUtilities;
    this.addentry = function (obj) {
        var inst  = "<span id='" + obj.aid + "' style='position: relative;'><a href='#' onclick=\"" + this.ns + ".toggle(); return false\">" + obj.anc + "</a></span>";
        document.write(inst);
        this.anc = this.pageutilities.getObject(obj.aid);
        this.setXPos(obj);
        this.setYPos(obj);
        this.setWidth(obj);
        this.widget = new Widget(obj);
    }
    this.setXPos = function (obj) {
        var left = parseInt(this.anc.offsetLeft) + parseInt(obj.offsetLeft);
        var browser = this.browserutilities.getBrowser();
        if ( browser == 'Explorer 6 Windows' || browser == 'Explorer 7 Windows' ) {
            left += 1;
        }
        obj.left = left + 'px';
    }
    this.setYPos = function (obj) {
        var top = parseInt(this.anc.offsetTop) + parseInt(obj.offsetTop);
        obj.top = top + 'px';
    }
    this.setWidth = function (obj) {
        var width = '147px';
        if ( this.browserutilities.getBrowser() == 'Explorer 6 Windows') {
            width = '165px';
        }
        obj.width = width;
    }
    this.mouseOut = function (obj, event) {
        var relatedTarget;
        if ( event.relatedTarget ) {
            relatedTarget = event.relatedTarget;
        }
        else if ( event.toElement ) {
            relatedTarget = event.toElement;
        }
        else {
            obj.style.visibility = 'hidden';
        }
        if ( relatedTarget && obj.id != relatedTarget.id ) {
            if ( ! this.pageutilities.contains(obj, relatedTarget) ) {
                obj.style.visibility = 'hidden';            }
        }
    }
    this.toggle = function (id) {
      this.widget.toggle();
    }
}
eval("var UNICEFBANNER = new UNICEFBanner('UNICEFBANNER')");
