function AnnouncementHandler(){
	
	//hack for self-referancing timer
	this.id = "AnnouncementHandler" + AnnouncementHandlerIdNumb++;
	window[this.id] = this;
	//end hack
	
	this.divName;									//name of the element we are writing to
	this.fadeInTimer_id;					//id of the timer associated with when to do fadeIn step
	this.fadeOutTimer = 6;				//how long we show each announcement
	this.fadeOutTimer_id;					//id of the timer associated with fadeOut step
	this.fadeLength = 2;					//how long to fade (applies to both fade in and out
	this.announcement_title = "Error: Announcement Not Set!";		//announcement title
	this.announcement_id = "null";		//announcement id (for displaying an individual announcement from a link)
	this.announcementGetterFunction;	//function to run to get a new announcement
	this.action = "init";							//action to perform next (init not actually used)
	this.opacif = new Opacifier();		//opacifier object for private use
	
	/*html code to write to the element
		hooks can be inserted into the html in the format ":hookname"
		these hooks (if recognized) will be replaced by associated data
		recognized hooks:
			:title = replaced by announcement_title
			:id = replaced by announcement_id
			:encoded_id = replaced by the base64_encode()ed announcement_id
	*/
	
	this.html = "<a href=\"http://justanexample.com/?id=:id\">:title</a>";
	this.jscode = "onMouseOver=\"window."+this.id+".pause();\" onMouseOut=\"window."+this.id+".resume();\"";  //javascript code for div surrounding html
}
	
//set the html to be used for the element (for customizability's sake)
AnnouncementHandler.prototype.setHtml = function(html){
	this.html = html;
};

//set the javascript to be printed for the div surrounding the html code
AnnouncementHandler.prototype.setJScode = function(js_code){
	this.jscode = js_code;
};

//replace hooks in html with currently set data
//returning the resultant html
AnnouncementHandler.prototype.injectVars = function(){
	var html = this.html;
	html = html.replace(/:title/g, this.announcement_title);
	html = html.replace(/:id/g, this.announcement_id);
	html = html.replace(/:encoded_id/g, base64_encode(this.announcement_id));
	return html;
}

//write the current data to the element
AnnouncementHandler.prototype.writeElement = function(){
	document.getElementById(this.divName).innerHTML = "<div "+this.jscode+">"+this.injectVars()+"</div>";
};

//initialize object for normal operation and start program loop
AnnouncementHandler.prototype.init = function(){
	this.makeTrans();  //make element transparent
	this.getAnnouncement(); //send for first announcement
	this.setNextAction("fadeIn"); //set next program step to fadeIn
	//give fadeLength seconds to get information like everywhere else(ajax or other asynchronous method)
	this.fadeInTimer_id = setTimeout("window."+this.id+".doAction()", this.fadeLength*1000);
};

//pause the animation and stop all timers, make opaque
AnnouncementHandler.prototype.pause = function(){
	this.killTimers();
	this.makeOpaque();
};

//resume operation, switching to next immediately
AnnouncementHandler.prototype.resume = function(){
	this.startTimersShort();
}

//set Element to write html to
AnnouncementHandler.prototype.setElem = function(ElementId){
	this.divName = ElementId;		
};

//set next action announcements will perform
AnnouncementHandler.prototype.setNextAction = function(act){
	if(act.length > 0){
	 this.action = act;
	}
};

AnnouncementHandler.prototype.doAction = function(){
	switch(this.action){
	
		/* on the fadeOut step:
			get the next announcement
			fadeout
			set timer for fadeIn step after fadeout animation is complete
			set next action to be fadeIn step
		*/
		case "fadeOut":
			this.getAnnouncement();
			this.fadeOut();
			this.fadeInTimer_id = setTimeout("window."+this.id+".doAction()", this.fadeLength*1000);
			this.setNextAction("fadeIn");
			break;
			
		/* on fadeIn step 
		  run this.changeAnnouncement();
		*/	
		case "fadeIn":
			this.changeAnnouncement();
			break;
		case "init": //not currently used
			this.init();
			break;
		default: //if this is hit, something is pretty wrong
			this.killTimers();
	}
};	

//fades element in over a period of fadeLength seconds	
AnnouncementHandler.prototype.fadeIn = function(){
	this.opacif.transOpacity(this.divName, 0, 100, this.fadeLength*1000);
};

//fades element out over a period of fadeLenght seconds
AnnouncementHandler.prototype.fadeOut = function(){
	this.opacif.transOpacity(this.divName, 100, 5, this.fadeLength*1000);
};

//makes element opaque immediately	
AnnouncementHandler.prototype.makeOpaque = function(){
	this.opacif.opaque(this.divName);
};

//makes element transparent immediately
AnnouncementHandler.prototype.makeTrans = function(){
	this.opacif.transparent(this.divName);
}

//starts program loop at beginning after fadeOutTimer fires
AnnouncementHandler.prototype.startTimers = function(){
	this.setNextAction("fadeOut");
	this.fadeOutTimer_id = setTimeout( "window."+this.id+".doAction()", this.fadeLength+this.fadeOutTimer*1000);
};


//starts program loop at beginning immediately
AnnouncementHandler.prototype.startTimersShort = function(){
	this.setNextAction("fadeOut");
	this.doAction();
};

//stop timer that will change announcements
AnnouncementHandler.prototype.clearFadeInTimer = function(){
	clearTimeout(this.fadeInTimer_id);
}

//stop timer that will load announcements
AnnouncementHandler.prototype.clearFadeOutTimer = function(){
	clearTimeout(this.fadeOutTimer_id);
}

//stops and clears all timers
AnnouncementHandler.prototype.killTimers = function(){
	this.opacif.stop(this.divName);
	this.opacif.clearTimers(this.divName);
	this.clearFadeOutTimer();
	this.clearFadeInTimer();
};

/*sets the function that is fired when AnnouncementsHandler needs to
get the next announcement*/
AnnouncementHandler.prototype.setAnnouncementFunction = function(fnName){
	this.announcementGetterFunction = fnName;
};

/*uses function to send for the next announcement*/
AnnouncementHandler.prototype.getAnnouncement = function(){
	var func = this.announcementGetterFunction;
	func(); //runs the function to get a new announcement 
};

/* depreciated! */
AnnouncementHandler.prototype.getVarsFromString = function(resp){
	return resp.split(this.delimiter);
};

//sets title and id for the announcement to be displayed	
AnnouncementHandler.prototype.setAnnouncement = function(ann_title, ann_id){
	this.announcement_id = ann_id;
	this.announcement_title = ann_title.replace("'", "&#39;");
}

//render the currently set announcement & restart loop
AnnouncementHandler.prototype.changeAnnouncement = function(){
	this.killTimers(); //make sure nothing fires while we are waiting
	//this.makeTrans();
	this.writeElement(); //write html with new data to the element
	
	//this.fadeIn(); //fade the element in
	this.makeOpaque();
	this.startTimers(); //restart timers
};			

function base64_encode( benc_data ) {
	//return benc_data;
    // http://kevin.vanzonneveld.net
    // +   original by: Tyler Akins (http://rumkin.com)
    // +   improved by: Bayron Guevara
    // +   improved by: Thunder.m
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)        
    // -    depends on: utf8_encode
    // *     example 1: base64_encode('Kevin van Zonneveld');
    // *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
 
    // mozilla has this native
    // - but breaks in 2.0.0.12!
    //if (typeof window['atob'] == 'function') {
    //    return atob(data);
    //}
        
    var benc_b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var benc_o1, benc_o2, benc_o3, benc_h1, benc_h2, benc_h3, benc_h4, benc_bits, benc_i = benc_ac = 0, benc_enc="", benc_tmp_arr = [];
    benc_data = benc_utf8_encode(benc_data);
    
    do { // pack three octets into four hexets
        benc_o1 = benc_data.charCodeAt(benc_i++);
        benc_o2 = benc_data.charCodeAt(benc_i++);
        benc_o3 = benc_data.charCodeAt(benc_i++);
 
        benc_bits = benc_o1<<16 | benc_o2<<8 | benc_o3;
 
        benc_h1 = benc_bits>>18 & 0x3f;
        benc_h2 = benc_bits>>12 & 0x3f;
        benc_h3 = benc_bits>>6 & 0x3f;
        benc_h4 = benc_bits & 0x3f;
 
        // use hexets to index into b64, and append result to encoded string
        benc_tmp_arr[benc_ac++] = benc_b64.charAt(benc_h1) + benc_b64.charAt(benc_h2) + benc_b64.charAt(benc_h3) + benc_b64.charAt(benc_h4);
    } while (benc_i < benc_data.length);
    
    benc_enc = benc_tmp_arr.join('');
    
    switch( benc_data.length % 3 ){
        case 1:
            benc_enc = benc_enc.slice(0, -2) + '==';
        break;
        case 2:
            benc_enc = benc_enc.slice(0, -1) + '=';
        break;
    }
 
    return benc_enc;
} // END function base64_encode

function benc_utf8_encode ( u8_string ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: sowberry
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // +   improved by: Yves Sucaet
    // +   bugfixed by: Onno Marsman
    // *     example 1: utf8_encode('Kevin van Zonneveld');
    // *     returns 1: 'Kevin van Zonneveld'
 
    u8_string = (u8_string+'').replace(/\r\n/g, "\n").replace(/\r/g, "\n");
 
    var u8_utftext = "";
    var u8_start, u8_end;
    var u8_stringl = 0;
 
    u8_start = u8_end = 0;
    u8_stringl = u8_string.length;
    for (var u8_n = 0; u8_n < u8_stringl; u8_n++) {
        var u8_c1 = u8_string.charCodeAt(u8_n);
        var u8_enc = null;
 
        if (u8_c1 < 128) {
            u8_end++;
        } else if((u8_c1 > 127) && (u8_c1 < 2048)) {
            u8_enc = String.fromCharCode((u8_c1 >> 6) | 192) + String.fromCharCode((u8_c1 & 63) | 128);
        } else {
            u8_enc = String.fromCharCode((u8_c1 >> 12) | 224) + String.fromCharCode(((u8_c1 >> 6) & 63) | 128) + String.fromCharCode((u8_c1 & 63) | 128);
        }
        if (u8_enc != null) {
            if (u8_end > u8_start) {
                u8_utftext += u8_string.substring(u8_start, u8_end);
            }
            u8_utftext += u8_enc;
            u8_start = u8_end = u8_n+1;
        }
    }
 
    if (u8_end > u8_start) {
        u8_utftext += u8_string.substring(u8_start, u8_string.length);
    }
 
    return u8_utftext;
} // end function benc_utf8_encode

includeJS("/javascript/Opacifier.js");
var AnnouncementHandlerIdNumb = 0;

