
// Null Method v1.2

// Written + coded by Ian Hatcher         http://clearblock.net
// for publication by Counterpath Press   http://counterpathpress.org

// License: Attribution-Noncommercial-Share Alike 3.0 United States
// http://creativecommons.org/licenses/by-nc-sa/3.0/us/



// +---------+
// | Globals | 
// +---------+

var c = 0; var cx = 0;	// Counters used in initial fade
var d = 1; var dx = 2;	// Counters used to determine colors and word quantities over time
var complete = false;	// Whether initial fade has completed



// +--------------------------+
// | Event observers and init |
// +--------------------------+

// Initialization: runs on domready
var remember = function() {
		
	// Attach observers to top bar buttons
	$$('.bar').each(function(s) {
		Event.observe(s, 'mouseover', barOver);
		Event.observe(s, 'mouseout', barOut);
		disableSelection(s);
	})

	Event.observe( ($('bar_restart')), 'click', restart);
	Event.observe( ($('bar_info')), 'click', barInfo);

	// Attach observers to info box 'x' 
	Event.observe( ($('x')), 'click', barInfo);	
	Event.observe( ($('x')), 'mouseover', xOver);	
	Event.observe( ($('x')), 'mouseout', xOut);	

	// Attach observers to info box link to my site
	Event.observe( ($('link')), 'click', clearblock);	
	Event.observe( ($('link')), 'mouseover', linkOver);	
	Event.observe( ($('link')), 'mouseout', linkOut);	
	
	// A function to disable text selection in various places.  This is set with javascript
	// and not CSS in order to be more effective in Opera and older versions of IE
	disableSelection($('context').parentNode);
	disableSelection($('context'));
	disableSelection($('topbar'));
	
	// Begin to fade words in after 2 seconds
	setTimeout("initializeRecall();", 2);
		
}
Event.onReady(remember);



// Attach recall observers when initial fade is almost completed
function checkAllAppeared(){
	c++;
	if(c == (cx-3) && complete==false){
		$$('.null').each(function(s) {
			Event.observe(s, 'mouseover', nullOver);
			Event.observe(s, 'mouseout', nullOut);
			Event.observe(s, 'click', nullClick);
			disableSelection(s);
		})
		complete = true;
	}	
}

// Create initial fade delays
function initializeRecall(){
	for (var w = 0; w <= 365; w++) {
		var id = ("m" + w);
		var word = $(id);
		
		// Only fade in non-"null" words
		if(!(word.className=='null')){
			setTimeout("appear('"+id+"',"+w+")", (Math.floor(Math.random()*2600))); 
			cx++;
		}
	}
}

// Fade in top text
function appear(id, w) {
	
	// Generate a target shade	
	var n = (Math.floor(Math.random()*50))+50;
	var col = 'rgb('+n+','+n+','+n+');';
	var word = $(id);
	
	// Start fade
	new Effect.Morph($(id), {
		style: 'color: ' + col,
		duration: (((Math.floor(Math.random()*220))/30)+3),
		afterFinish: function () {
			checkAllAppeared();
		}
	});
}



// +--------+
// | Colors |
// +--------+

// Initialize palette variables
var zColor = '#555';
var mColor7 = 'rgb(112,112,112)';
var mColor5 = 'rgb(80,80,80)';
var mColor4 = 'rgb(64,64,64)';
var mColor3 = 'rgb(48,48,48)';
var mColor2 = 'rgb(32,32,32)';
var mColor1 = 'rgb(16,16,16)';

// Update palette to reflect current conditions
function processColor() {
	var cDec = 80 - Math.floor(d*1);
	if(cDec < 1) { cDec = 0; }

	mColor7 = 'rgb(112,'+Math.floor(cDec*1.4)+ ','+Math.floor(cDec*1.4)+')';
	mColor5 = 'rgb(80,'+cDec+ ','+cDec+')';
	mColor4 = 'rgb(64,'+Math.floor(cDec*.8)+ ','+Math.floor(cDec*.8)+')';
	mColor3 = 'rgb(48,'+Math.floor(cDec*.6)+ ','+Math.floor(cDec*.6)+')';
	mColor2 = 'rgb(32,'+Math.floor(cDec*.4)+ ','+Math.floor(cDec*.4)+')';
	mColor1 = 'rgb(16,'+Math.floor(cDec*.2)+ ','+Math.floor(cDec*.2)+')';
		
	if(cDec < 16) {
		cDec = "00";
		var cRed = (Math.floor(90 - (d*(dx/18))));
		dx++;
		if(cRed<16){ cRed = 16;}
		var col = 'rgb('+cRed+','+cDec+','+cDec+')';
		zColor = col;
	} else {
		zColor = mColor5;
	}
	
	// Update the colors of various elements
	$('context').style.borderColor = zColor;
	$('info').style.backgroundColor = mColor1;
	$('info').style.borderColor = mColor4;
	$('innerPopBar').style.backgroundColor = mColor2;
	$('innerPopBar2').style.backgroundColor = mColor2;
	$('innerPopBody').style.backgroundColor = mColor1;
	$('x').style.color = mColor5;
	$$('.bar').each(function(s) {
		s.style.color = mColor3;
		s.style.borderColor = mColor3;
	});
	
	
}



// +-----------------------------------+
// | Reader interactivity and response |
// +-----------------------------------+

var nullClick = function() {
	
	// Update click counter
	d++;
	
	// Check to ensure the target span is fair game
	if( this.className=='null' ){ 
	
		// Reset clicked word to black
		this.style.color="#000";
		this.style.backgroundColor="#000";
		
		// Determine color of recalled word, initialize fade
		processColor();
		var col = 'color: ' + zColor + ';';
		new Effect.Morph(this.id, {
			style: col,
			duration: 2.0
		});

		// Reinitialize arrays
		var forgets = [];
		var recalls = [];
		var x = 0;
		
		// Get new forget targets
		while ((forgets.length*6) < (d-20) && x < 365){	
			var tNumber = Math.floor(Math.random()*365);
			if($('m'+tNumber)){
				var target = $('m'+tNumber);
				if(!(target.className=='null')) {
					forgets.push(target);
				}
				x++;
			}
		}

		// Get new recall targets
		while ( ((recalls.length) < 10) && ((recalls.length * d) < 55)  && d < 55 ){	
			var rNumber = Math.floor(Math.random()*365);
			var rWeight = Math.floor(Math.random()*365);
			if($('m'+rNumber)){
				var target = $('m'+rNumber);
				if( rNumber < rWeight  && !(target.className=='influx') ){ 
					recalls.push(target);
				}
			}
		}
		
		// Remove "null" class designation
		this.className='';
		this.style.cursor="default";

		// Run forget/recall functions
		forgetWords(forgets);
		recallWords(recalls);
			
	}
}

// Forget words
function forgetWords(forgets) { 
	for (var k = 0; k < forgets.length; k++) {
		var word = forgets[k];
		if(!(word.className=='influx')){
			
			// Add "null" class to the word
			word.className = "null";

			// Generate a target shade
			var rNumber = ((Math.floor(Math.random()*580))/100)+1;
						
			// Fade out the word
			new Effect.Morph(word.id, {
				style: 'color: #000;',
				duration: rNumber
			});
			
			// Add "null" observers after fade out is completed
			// (not using Scriptaculous "afterFinish" because it doesn't work consistently)
			var after = function () {
				Event.observe(word, 'mouseover', nullOver);
				Event.observe(word, 'mouseout', nullOut);
				Event.observe(word, 'click', nullClick);
				
				// Add "null" class to the word (redundant but necessary to address a cross-browser bug)
				word.className = "null";
			}
			setTimeout(after, rNumber+1);	

		}
	}
}

// Recall words
function recallWords(recalls) { 
	for (var k = 0; k < recalls.length; k++) {
		var word = recalls[k];
		if(!(word.className=='influx')){	
			
			// Generate a target shade
			var n = (Math.floor(Math.random()*50))+50;	
			var col = 'rgb('+n+','+n+','+n+');';

			// Remove observers from the no-longer-"null" word
			Event.stopObserving(word, 'mouseover', nullOver);
			Event.stopObserving(word, 'mouseout', nullOut);
			Event.stopObserving(word, 'click', nullClick);
			word.style.cursor = "";
			word.className = ' ';

			// Generate a duration
			var rNumber = ((Math.floor(Math.random()*580))/100)+1;
			
			// Fade in the word
			new Effect.Morph(word.id, {
				style: 'color: ' + col,
				duration: rNumber
			});
		}
	}	
}

// Null span rollovers
var nullOver = function() {
	if( this.className=='null' ){ 
		this.style.color=zColor;
		this.style.backgroundColor=zColor;
	}
}
var nullOut = function( ) {
	if( this.className=='null' ){ 
		this.style.color="#000";
		this.style.backgroundColor="#000";
	}
}



// +---------------------------------+
// | Top bar & info window functions |
// +---------------------------------+

var restart = function() { window.location.reload(); }

var linkOver = function() { this.style.color="#777"; }
var linkOut = function() { this.style.color="#555"; }
var clearblock = function() { window.open('http://clearblock.net','_blank'); }

var xOver = function() { this.style.color=mColor7; }
var xOut = function() { this.style.color=mColor5; }

var barOver = function() {
	if(!(this.title=='highlight')){
		this.style.backgroundColor=mColor1;
		this.style.color=mColor5;
	}
}

var barOut = function() {
	if(!(this.title=='highlight')){
		this.style.color = mColor3;
	}
}

// Top bar and info displays, highlights, and color changes
var barInfo = function() {
	if($('bar_info').title=='highlight' && !($('bar_info').alt=='influx') ) {
		$('bar_info').alt='influx';
		new Effect.Opacity('info', { from: 0.86, to: 0.0, duration: 0.8, afterFinish: function () {$('info').style.display='none'; $('bar_info').alt='';} });
		new Effect.Opacity('infoBody', { from: 1.0, to: 0.0, duration: 0.3 });
		$('bar_info').style.backgroundColor="#000";
		$('bar_info').style.color=mColor3;
		$('bar_info').title='';
	} else {
		if(!($('bar_info').alt=='influx') ){
			$('bar_info').alt='influx';
			$('info').style.display="block";
			new Effect.Opacity('info', { from: 0.0, to: 0.86, duration: 0.5 });
			new Effect.Opacity('infoBody', { from: 0.0, to: 1.0, duration: 1.2, afterFinish: function (){ $('bar_info').alt=''; } });
			$('infoBody').style.backgroundColor=mColor1;
			$('bar_info').style.backgroundColor=mColor2;
			$('bar_info').style.color=mColor7;
			$('bar_info').title='highlight';
		}
	}	
}

// Prevent the user from selecting the text
function disableSelection(element) {
    element.onselectstart = function() {
        return false;
    };
    element.unselectable = "on";
    element.style.MozUserSelect = "none";
    element.style.cursor = "default";
}



