
// 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/




var nullOver = function() {
		if( this.className=='null' ){ 
			this.style.color=zColor;
			this.style.backgroundColor=zColor;
		}
	},

	nullOut = function() {
		if( this.className=='null' ){ 
			this.style.color="#000";
			this.style.backgroundColor="#000";
		}
	},

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

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

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

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

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

	// Top bar and info displays, highlights, and color changes
	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
	disableSelection = function(element) {
	    element.onselectstart 		= function() { return false; };
	    element.unselectable 		= "on";
	    element.style.MozUserSelect = "none";
	    element.style.cursor 		= "default";
	},
	
	
	
	
	

	/////////////
	// fade in //
	/////////////


	// Counters used for fade in
	c  = 0,
	cx = 0,	
	
	// Counters used for colors and word quantities over time
	d  = 1, 
	dx = 2,
		
	// State of initial fade
	complete = false,
	
	

	// Initialization: runs on domready
	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 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);
		
	},
	


	// Attach recall observers when initial fade is almost completed
	checkAllAppeared = function(){
		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
	initializeRecall = function(){
		var w, id, word;

		for (w = 0; w <= 365; w++) {
			id = ("m" + w);
			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
	appear = function(id, w) {
		var n, col, word;
	
		// Generate a target shade	
		n = (Math.floor(Math.random()*50))+50;
		col = 'rgb('+n+','+n+','+n+');';
		word = $(id);
	
		// Start fade
		new Effect.Morph($(id), {
			style: 'color: ' + col,
			duration: (((Math.floor(Math.random()*220))/30)+3),
			afterFinish: function () {
				checkAllAppeared();
			}
		});
	},






	////////////
	// colors //
	////////////


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


	// Update palette to reflect current conditions
	processColor = function() {
		var cDec, cRed, col;

		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*0.8) + ',' + Math.floor(cDec*0.8) + ')';
		mColor3 = 'rgb(48,'  + Math.floor(cDec*0.6) + ',' + Math.floor(cDec*0.6) + ')';
		mColor2 = 'rgb(32,'  + Math.floor(cDec*0.4) + ',' + Math.floor(cDec*0.4) + ')';
		mColor1 = 'rgb(16,'  + Math.floor(cDec*0.2) + ',' + Math.floor(cDec*0.2) + ')';
		
		if(cDec < 16) {
			cDec = "00";
			cRed = Math.floor(90 - (d * (dx / 18)));
			dx ++;
			
			if(cRed < 16){ cRed = 16;}
			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;
		});
	
	
	},






	////////////////////////////
	// interactivity/response //
	////////////////////////////

	nullClick = function() {
	
		var col,
			forgets = [],
			recalls = [],
			x 		= 0,
			tNumber,
			target,
			rNumber,
			rWeight;

		// 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();
			col = 'color: ' + zColor + ';';
			new Effect.Morph(this.id, {
				style: col,
				duration: 2.0
			});
		
			// Get new forget targets
			while ((forgets.length*6) < (d-20) && x < 365){	
				tNumber = Math.floor(Math.random()*365);
				if($('m'+tNumber)){
					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 ){	
				rNumber = Math.floor(Math.random()*365);
				rWeight = Math.floor(Math.random()*365);
				if($('m' + rNumber)){
					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
	forgetWords = function(forgets) { 
		var k, word, after;
		for (k = 0; k < forgets.length; k++) {
			word = forgets[k];
			if(!(word.className=='influx')){
			
				// Add "null" class to the word
				word.className = "null";

				// Generate a target shade
				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)
				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
	recallWords = function(recalls) { 
		var k, word, n, col, rNumber;
	
		for (k = 0; k < recalls.length; k++) {
			word = recalls[k];
			if(!(word.className == 'influx')){	
			
				// Generate a target shade
				n = (Math.floor(Math.random() * 50)) + 50;	
				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
				rNumber = ((Math.floor(Math.random()*580)) / 100) + 1;
			
				// Fade in the word
				new Effect.Morph(word.id, {
					style: 'color: ' + col,
					duration: rNumber
				});
			}
		}	
	};


Event.onReady(remember);


