/* -----------------------------------------------------------------------------
	Template Name:	wordBreak-master.js
	Orig Author:	Courts
	Orig Date:		Feb 07
	Description:	creates an variable called wordBreaker, an object for splitting excessively long text.
	Note:				Please leave the version number here and in the actualy, compressed js file
	Inputs:			N/A
	Output:			N/A
* -------------------------------------------------------------------------------
		Here's a javascript compressor: http://www.creativyst.com/Prod/3/
* -------------------------------------------------------------------------------
Feb 07: Courts
.000 - brute-force version, very dumb about &-entities

Jun 07: Courts
.001 - rushed into produciont for MySpaceTV...
.006: - 12-Nov, Courts, HotFix to mangle URLs
.007: - 28-Nov, Courts, Fix to above hotfix. "too much recursion" error in firefox.
.008: - 21-Dev, Courts, mangle URLs ever more, single dots within urls: "." to " . "
.009: - 23-Jan, Courts, more with "more". Seeing very odd error in IE7 that suddenly stopped appearing, watch out:
				"Internet Exporer cannot open the Internet site ... Operation aborted"
.010: - 28-Jan, Courts here again. That error above didn't go away, it was how i was stupidly adding the CSS to avoid the document.write that bombed on Contest's prototype needs.
* -------------------------------------------------------------------------------
	To Do:
		1. [donish] handle & entities
		2. [done] rewrite URL's
		3. [done-ish] better break (<br>) handing, firefox bug and dumb approach.
		4. [done] differentiate link based on what it links to, jpeg versus site
		5. [done] favor even early breaks on punctuation (underscore)
		6. shit. already forgot.
		7. [done] allow dev's to change max character-block length (just need to build the regex)
		8. [done] put flag to prevent reduantant runs
		9. play with <wbr>
		-- 
* -------------------------------------------------------------------------------
	Implementation Notes:
	* Regular Expressions:
		All (most, actually) regexes defined in object for a couple of reasons:
		1. pre-compiling saves processor time
		2. when you compress this, as i know you will, make sure this does NOT get compressed. 
				put it back, exactly as is. debugging regex is too annoying to monkey about with.

	* HTML:
		I've tried again and again, but <wbr> doesn't seem to consistently work. Thus using this span ruse.

	* CSS:
		funny story actually, the definition uses margin 0 whereas I'd wanted, insofar as I'd wanted this
		span-approach in the first place, to have a left margin of -1px, but it doesn't work. At least, in IE.
		IE, for some reason, won't attempt to redraw the affected content. So, a permanent 0 instead of:
		
			span.enspacex{font-size:1px;padding:0;margin:0 0 0 -1px;}

		again: a shame. 

* ------------------------------------------------------------------------------- */
var wordBreaker = {

	// -------------------------------
	// #region Worker Fields
	_hasCSS : false,
	_maxLength : 12,// Max Number of Unbroken Characters
	// #endregion
	// -------------------------------


	// -------------------------------
	// #region Predefined Constants
	//_spacer : '<wbr>', // very, very touchy
	_spacer : '<span class="enspacex" wbr="true"> </span>', // ugly, but all browser-safe.
	re : {
		biggie: /\S{12,}/gi,
		nbsp: /&nbsp;/gi,
		gt: /&gt;/gi,
		lt: /&lt;/gi,
		amp: /&amp;/gi,
		spaces: /\s+/g,
		brk: /((&lt;|<)br\s*\/?(&gt;|>)|\n)/gi,
		excessbrk: /(<br>\s+){2,}/gi,
		piclnk: /\.(jpe?g|png|gif)$/gi,
		dot: /\./g,
		// Dec 20, 2007, Courts wrote:
		// adding two regexs to mangle dots WITHIN URLs... now, this could be done more elegantly, natch, but point is
		// ever second I spend on this my soul shrivels 1.37%, which will soon kill me... ya see, they keep asking for more
		// drakonian changes, to the point where I'd prefer double dotting the whole friggin thing. So, instead, I try to avoid 
		// mangling numbers "89.99" and instead, knowing that all TLDs are 2 or more chars, and that subdomains like "www." or "evil." all have letters
		// we'll let pass the first dot in "ww6.890.com" knowing will match on the second.  Oh, we're replacing, so don't want to be too greedy, as
		// would be {2,}
		mangleDot1: /([a-z]{2})\.([a-z0-9]{2})/gi,
		mangleDot2: /([a-z0-9]{2})\.([a-z]{2})/gi,
		lnk: /^(http:\/\/[^\s"]+)$/gi

 },
	// " // this comment is here just for editors, the regexes tend to mess-up script color-coding
	// #endregion
	// -------------------------------
	

	// -------------------------------
	// #region Properties
	isRewriteLinks : true,
	isPreserveBreaks : false,
	isDebug : false,
	resources : {
		normalLinkText: "[link]",
		imageLinkText: "[image link]",
		lessLinkText: "[less]",
		moreLinkText: "[more]"

 },

	setMaxLength : function(l) {
		if (this._maxLength == l) return;
		this._maxLength= l;
		this.re.biggie =new (RegExp)("\\S{"+l+",}","gi");
	}
	// #endregion
	// -------------------------------

} // wordbreaker object


// --------------------------------------------------------------- //
//	function: writeCSS
//	Scope: private
//	Does: adds required CSS to the page. Now does this without
//		document.write, instead adds a new CSS Stylesheet to the HEAD
//		or, just adds a new Rule to the last stylesheet (IE).
// --------------------------------------------------------------- //
wordBreaker.writeCSS = function() {
	var selector = 'span.enspacex';
	var rule = 'font-size:1px;padding:0;margin:0;'+((this.isDebug)?"background:#f00;padding-top:6px;":"");
	if (document.styleSheets[0].addRule){
		// We're in IE land
		var h =  _proxy_jslib_handle(document.styleSheets, (document.styleSheets.length - 1), 0, 0);
		h.addRule(selector, rule );
	} else {
		// Other browswers...
		var h=  _proxy_jslib_handle(document, 'getElementsByTagName', '', 1, 0)("head")[0];
		var newCSS = document.createElement("style");
		 _proxy_jslib_handle(newCSS, 'setAttribute', '', 1, 0)("type", "text/css");
		 _proxy_jslib_handle(newCSS, 'setAttribute', '', 1, 0)("media", "screen"); 
		 _proxy_jslib_assign('', newCSS, 'innerHTML', '=', ( selector+'{'+rule+'}'));
		h.appendChild(newCSS);
	}
	this._hasCSS = true;
}


// --------------------------------------------------------------- //
//	function: addSpacers
//	Scope: private
//	returns string with "fix-it HTML breaks" every [12] characters
//	notes: a few bits really complicated this:
//		1. url handler? actually not that hard
//		2. preserving >, <, &? still not sucha chore.
//		3. break early on underscore over between chars? ok, that really made this unreadable.
// --------------------------------------------------------------- //
wordBreaker.addSpacers = function(txt) {

	var s="";

	if (this.isRewriteLinks && this.re.lnk.test(txt)){

		var x = (this.re.piclnk.test(txt))?this.resources.imageLinkText:this.resources.normalLinkText;

		//s=txt.replace(this.re.lnk,"<a href=\"$1\" target=\"_blank\" title=\"$1\">" +x+ "</a>");		

		newlink= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.lnk,"$1");
		// Nov 13, Courts: no mor msplink:
		// s=txt.replace(this.re.lnk,"<a href=\"" + this.MSPLinksEncode(newlink) + "\" target=\"_blank\" title=\"$1\">" +x+ "</a>");	
		// replace msplink with mangler		
		s= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.lnk,this.mangle(newlink));

	} else {
		var x="";
		/* ok, temporarily put >, <, and & in as single characters, don't worry, i'll re-escape them afterward */
		// if (this.isPreserveBreaks) txt=txt.replace(this.re.brk,"\t");// hokey? sure. use tabs to represent our temp breaks
		txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.gt,">");
		txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.lt,"<");
		txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.amp,"&");

		/* done, back to norm stuff (this used to be a simple "for". darned underscores! */
		var i=0;
		while (i< txt.length){
			x=txt.substring(i,i+this._maxLength);
			d= x.lastIndexOf("_");
			if (d>=0){
				d++;
				x=txt.substring(i,i+d);
			} else {
				d=this._maxLength;
			}
			i+=d;

			/* re-escape */
			x= _proxy_jslib_handle(x, 'replace', '', 1, 0)( "&", "&amp;" );
			x= _proxy_jslib_handle(x, 'replace', '', 1, 0)( ">", "&gt;" );
			x= _proxy_jslib_handle(x, 'replace', '', 1, 0)( "<", "&lt;" );
			// if (this.isPreserveBreaks) x=x.replace("\t","<br />");

			/* push it on */
			s+=x+ (i<txt.length?this._spacer:"");
		}// while
	}
	return s;
}// addSpacers



// --------------------------------------------------------------- //
//	function: addMoreLink
//	Does:	Two flavors -- 
//					addMoreLink( TagName, Classname, MaxLength );
//					addMoreLink( Element, MaxLength );
//	Params: TagName
//					Classname
//					(optional) MaxLength, default 140 characters
// --------------------------------------------------------------- //
wordBreaker.addMoreLink = function() {
	// "maxLength" -- descriptions over this get chopped and a More link added.
	if (typeof(arguments[0]) == "string"){
		var tag = arguments[0];
		var cls = arguments[1];
		var maxLength = (arguments.length > 2)?arguments[2]:140;
		var e = this.getElementsByClass(tag,cls);
		for (var i=0; i < e.length; i++){
			this._doAddMoreLink( _proxy_jslib_handle(e, (i), 0, 0),maxLength);
		}
	} else {
		var maxLength = (arguments.length > 1)?arguments[1]:140;
		this._doAddMoreLink(arguments[0],maxLength);
	}
} // addMoreLink


// this actually does the work on ONE element
wordBreaker._doAddMoreLink = function(e,maxLength) {
	// return;
	if(e.getAttribute("wbr") == null){ //todo: || (e.getAttribute("wbr") != "wbr")){
		if ( _proxy_jslib_handle(e, 'innerHTML', '', 0, 0).length <= maxLength){
			 _proxy_jslib_assign('', e, 'innerHTML', '=', ( wordBreaker.fix( _proxy_jslib_handle(e, 'innerHTML', '', 0, 0))));
		} else {
			 _proxy_jslib_handle(e, 'setAttribute', '', 1, 0)("wbr_swap", wordBreaker.fix( _proxy_jslib_handle(e, 'innerHTML', '', 0, 0))+ ' <a href="#" onclick="return wordBreaker.doMoreSwap(this)">' +this.resources.lessLinkText+'</a> ');
			// let's shoot for a space to break upon
			var s =  _proxy_jslib_handle(e, 'innerHTML', '', 0, 0).substr( 0, maxLength );
			var m = s.lastIndexOf(' ');
			//	what I'm shooting for is a convenient place to break the text. We'll add the "more" link after the break
			//	so we'll try for the largest "word" at least 30 characters in, but no more than maxLength:
			if (m > 30)
				s =  _proxy_jslib_handle(e, 'innerHTML', '', 0, 0).substr( 0, m );
			 _proxy_jslib_assign('', e, 'innerHTML', '=', ( this.fix(s)));
			 _proxy_jslib_assign('', e, 'innerHTML', '+=', ( ' ... <a href="#" onclick="return wordBreaker.doMoreSwap(this)">' +this.resources.moreLinkText+'</a> '));
		}
		 _proxy_jslib_handle(e, 'setAttribute', '', 1, 0)('wbr', 'true');
	}
}


// --------------------------------------------------------------- //
//	function: doMoreSwap
//	Does:	
// --------------------------------------------------------------- //
wordBreaker.doMoreSwap = function(me) {
	me = me.parentNode;
	var s = me.getAttribute("wbr_swap");
	 _proxy_jslib_handle(me, 'setAttribute', '', 1, 0)("wbr_swap",  _proxy_jslib_handle(me, 'innerHTML', '', 0, 0) );
	 _proxy_jslib_assign('', me, 'innerHTML', '=', ( s));
	return false;
}

// --------------------------------------------------------------- //
//	function: mangle
//	Does:	
// --------------------------------------------------------------- //
wordBreaker.mangle = function(u) {
	u =  _proxy_jslib_handle(u, 'replace', '', 1, 0)( this.re.dot, ". ");
	return u;
	// return this.addSpacers(u);
}

wordBreaker.mangleDots = function(txt) {
	txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.mangleDot1, "$1 . $2" );
	txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.mangleDot2, "$1 . $2" );
	/*
	if (this.re.mangleDot1.test(txt)){
		results = txt.match(this.re.mangleDot1);
		console.log( "dot 1 found "+ results.length+" matches");
		for (var i=0; i < results.length; i++){
			console.log( (i+1)+". "+results[i]);
		}
		txt=txt.replace(this.re.mangleDot1, "$1 . $2" );
	}
	if (this.re.mangleDot2.test(txt)){
		results = txt.match(this.re.mangleDot2);
		console.log( "dot 2 found "+ results.length+" matches");
		for (var i=0; i < results.length; i++){
			console.log( (i+1)+". "+results[i]);
		}
		txt=txt.replace(this.re.mangleDot2, "$1 . $2" );
	}
	*/
	return txt;
}


// --------------------------------------------------------------- //
//	function: fix
//	Does:	if string (txt) contains any block larger than [12] consecutive non-whitepace 
//		characters this returns the string with "fix-it HTML breaks" embedded every [12] chars.
//		Note: this always compresses string's whitespace by stripping embedded <br> and &nbsp;
// --------------------------------------------------------------- //
wordBreaker.fix = function(txt) {
	if (!this._hasCSS) this.writeCSS();
	txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.nbsp," ");// sorry, no "non-breaking spaces"
	txt=this.mangleDots(txt);
	if (this.isPreserveBreaks){
		txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.brk," <br> ");// pack breaks (spaces will break);
		txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.excessbrk," <br><br> ");// excessive line breaks get clobbered (need to stay under maxlength)
	}	else {
		txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.brk," ");// no line-breaks? <br>
	}
	//if (this.re.biggie.test(txt)){ // there is some problem, both IE and Firefox, with this on me demo page. no clue. thus:
	if (txt.match(this.re.biggie)){
		txt= _proxy_jslib_handle(txt, 'replace', '', 1, 0)(this.re.spaces," ");// compress whitespace
		var t=txt.split(" ");
		var s="";
		for (var i=0; i < t.length; i++){
			if ( _proxy_jslib_handle(t, (i), 0, 0).length > this._maxLength)
				s+=" "+this.addSpacers( _proxy_jslib_handle(t, (i), 0, 0));
			else
				s+=" "+ _proxy_jslib_handle(t, (i), 0, 0);
		} // for
		return s.substring(1,s.length);
	} else {
		return txt;
	}// if
}// fix


// --------------------------------------------------------------- //
// Function: getElementsByClass
//	Two variations:
//		getElementsByClass( ClassName )
//		getElementsByClass( TagName, ClassName )
// Notes: I don't like stuffing these in there, but so be it. Should be general function
// --------------------------------------------------------------- //
wordBreaker.getElementsByClass = function() {
	if (arguments.length > 1){
		var tag = arguments[0];
		var cls= arguments[1];
	} else {
		var tag = "*";
		var cls= arguments[0];
	}
	var rtn = new (Array)();
	var e =  _proxy_jslib_handle(document, 'getElementsByTagName', '', 1, 0)(tag);
	var	re=new (RegExp)("(^|\\b|\\s)"+cls+"(\\s|\\b|$)","gi"); // let's drop the \b
	for(var i = 0;i < e.length;i++){
		if ( _proxy_jslib_handle( _proxy_jslib_handle(e, (i), 0, 0).className, 'search', '', 1, 0)(re)>-1)
			 _proxy_jslib_assign('', rtn, (rtn.length), '=', ( _proxy_jslib_handle(e, (i), 0, 0)));
	}
	return rtn;
}

// --------------------------------------------------------------- //
// Function: getElementsByAttribute
//	Two variations:
//		getElementsByAttribute( Attribute )
//		getElementsByAttribute( TagName, Attribute )
// Notes: I don't like stuffing these in there, but so be it. Should be general function
// --------------------------------------------------------------- //
wordBreaker.getElementsByAttribute = function () {
	if (arguments.length > 1){
		var tag = arguments[0];
		var attr= arguments[1];
	} else {
		var tag = "*";
		var attr= arguments[0];
	}
	var e =  _proxy_jslib_handle(document, 'getElementsByTagName', '', 1, 0)(tag);
	var rtn = new (Array)();
	for(var i=0;i < e.length; i++){
		if( _proxy_jslib_handle(e, (i), 0, 0).getAttribute(attr) != null)
			 _proxy_jslib_assign('', rtn, (rtn.length), '=', (  _proxy_jslib_handle(e, (i), 0, 0)

 ))}
	return rtn;
} 

// --------------------------------------------------------------- //
//	functions: fixElemArray, fixByClass, fixByAttribute
//	Notes:	I'm just gonna lump these three functions together, they all
//		loop over an array of elements running the fixer, just that two of
//		these functions actually create the arrays for ya.
// --------------------------------------------------------------- //
wordBreaker.fixElemArray = function(e) {
	for(var i=0;i<e.length;i++){
		if( _proxy_jslib_handle(e, (i), 0, 0).getAttribute("wbr") == null){////todo:  || (e[i].getAttribute("wbr") != "wbr")){
			 _proxy_jslib_assign('',  _proxy_jslib_handle(e, (i), 0, 0), 'innerHTML', '=', ( this.fix( _proxy_jslib_handle( _proxy_jslib_handle(e, (i), 0, 0), 'innerHTML', '', 0, 0))));
			 _proxy_jslib_handle( _proxy_jslib_handle(e, (i), 0, 0), 'setAttribute', '', 1, 0)('wbr', 'true');
		}
	}
}

wordBreaker.fixByTag = function(tagName) {
	this.fixElemArray( _proxy_jslib_handle(document, 'getElementsByTagName', '', 1, 0)(tagName));
}

// 	fixByClass( className );
// 	fixByClass( className, tagName );
wordBreaker.fixByClass = function(className) {
	var tag = (arguments.length > 1)?arguments[1]:"*";
	this.fixElemArray(this.getElementsByClass(tag,className));
}

// 	fixByAttribute( attr );
// 	fixByAttribute( attr, tagName );
wordBreaker.fixByAttribute = function(attr) {
	var tag = (arguments.length > 1)?arguments[1]:"*";
	this.fixElemArray(this.getElementsByAttribute(tag,attr))

}

wordBreaker.fixById = function(id) {
	var h =  _proxy_jslib_handle(document, 'getElementById', '', 1, 0)( id );
	if (!h) return;
	 _proxy_jslib_assign('', h, 'innerHTML', '=', ( this.fix( _proxy_jslib_handle(h, 'innerHTML', '', 0, 0))));
}

// --------------------------------------------------------------- //
//	function: fixNested
//	Description: Quickie one-off I rushed out for our 2nd demo, but kept around
//	because it seems to work well.
//	Does:	
//		Works on stuff like this:
//			<div class="boogers">Stuff we don't care about <a href="">Stuff_we_want_fixed_cuz_its_long<a> other crud</div>
//
//		Would be fixed by:
//			wordBreaker.fixNested( "boogers", "div", "a" );
// --------------------------------------------------------------- //
wordBreaker.fixNested = function( classname, tagname, nestedTagName ) {
	var e = new (Array)();
	var m = this.getElementsByClass(tagname,classname);
	if (!m) return ;
	var subs = null;
	for (var i=0; i < m.length; i++ ){
		subs= _proxy_jslib_handle( _proxy_jslib_handle(m, (i), 0, 0), 'getElementsByTagName', '', 1, 0)(nestedTagName);
		if (subs && (subs.length>0))
		  _proxy_jslib_assign('', e, (e.length), '=', ( subs[0]));
	}
	this.fixElemArray(e)

}

wordBreaker.MSPLinksEncode = function( input ) {
	var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

	var output = "";
	var chr1, chr2, chr3;
	var enc1, enc2, enc3, enc4;
	var i = 0;
	
	input = "01" + input;

	do {
		chr1 = input.charCodeAt(i++);
		chr2 = input.charCodeAt(i++);
		chr3 = input.charCodeAt(i++);

		enc1 = chr1 >> 2;
		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
		enc4 = chr3 & 63;

		if (isNaN(chr2)) {
			enc3 = enc4 = 64;
		} else if (isNaN(chr3)) {
			enc4 = 64;
		}

		output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + 
			keyStr.charAt(enc3) + keyStr.charAt(enc4);
	} while (i < input.length);

	output = "http://www.msplinks.com/" + output;
	
	return output;
} ;
_proxy_jslib_flush_write_buffers() ;