﻿/*
 * 
 */

/**
 * 
 */

(function($){

$.extend({

/**
 * SPANIZE routine
 */
spanize:function(obj,spanClass,maxGroup){
	var text=$(obj).html();
	var res = "";
	var tag="";
	var spanlength=1;
	var reg = new RegExp ("^([^\\s<&]|&[a-z]*;){1,"+maxGroup+"}");
	while (text.length>0){
		if (tag=text.match(/^(\s|(<[^>]*>))+\s*/)){
			if (tag.length>0){
			text = text.substr(tag[0].length);
			res+=tag[0];}}
		if (tag=text.match(reg)){spanlength=tag[0].length;}
    else spanlength=1;
		res+="<span"+(spanClass==''?'':' class="'+spanClass+'"')+">"+text.substring(0,spanlength)+"</span>";
		text=text.substring(spanlength);
	}
	$(obj).html(res);
},

/**
 * Function that returns an array of integers where 
 * the word passed as argument can be hyphened.
 * ---
 * 1. between two consonants if they are not at the end of the word,
 * no list contains a 'h' : you do not want to cut neither ch,sh,ph,th,...
 * [bcdfgjklmnpqrstvwxz][bcdfgjklmnpqrstvwxz]
 * ---
 * 2. after the first voyel in : voyel + consonant + h? + voyel
 * [aeiouàâäéèêëîïôöùûüœæýÿ][bcçdfghjklmnpqrstvwxz]h?[^bcdfgjklmnpqrstvwxz]
 * ---
 * In case 1., you want to have other things before and after the match : 
 * you don't cut s-phyn-x, but possibly as-phyxie, an-xieux.
 */
decoupe:function(word){//w:word
	var wcopy = word;
	var res = [];
	var regexp = /([bcdfgjklmnpqrstvwxz][bcdfgjklmnpqrstvwxz][aeiouyàáâäèéêëìíîïòóôöùúûüœæýÿ]|[aeiouyàáâäèéêëìíîïòóôöùúûüœæýÿ][çbcdfghjklmnpqrstvwxz]h?([àáâäèéêëìíîïòóôöùúûüœæýÿ]|[^bcdfgjklmnpqrstvwxz\W])|[aeiouàáâäèéêëìíîïòóôöùúûüœæ]y([àáâäèéêëìíîïòóôöùúûüœæ]|[^bcdfgjklmnpqrstvwxz\W]))/i;
	var found = 1;
	var last = 0;
	while(found>-1){
		found = wcopy.search(regexp);
		//alert(wcopy+' '+found)
		if (found>=0){
			if ((last>0&&found>=0)||(last==0&&found>=1)) res.push(last+found+1);
			last+=found+1;
			wcopy = wcopy.substr(found+1);}}
	/*// Debugging
	var str="<h3>Results for "+word+":</h3>\n";
	for(var i in res){str+=''+res[i]+'/'+word.length+':'+word.substring(0,res[i])+'-'+word.substring(res[i])+'<br/>\n';}
	$('<div/>').html(str).appendTo($('div#results'));
	// */
	return res;
}

});// $.extend

$.fn.extend({

spanize:function(spanClass,maxGroup){
	return this.each(function(){$.spanize(this,spanClass,maxGroup);});
},
unspanize:function(spanClass){
	return this.each(function(){
		$('span.'+spanClass,this).each(function(){$(this).before($(this).html());}).remove();
	});
},

ponctuation:function(){
	var thinnbsp='<span class="thinnbsp">&nbsp;</span>';
	return this.each(function(){
		$(this).spanize('ponctumots',2000);
		$(this).find('span.ponctumots').each(function(){
			var text = $(this).text();
			text=text.replace(/(&nbsp;|\s)*;/g,thinnbsp+';');
			text=text.replace(/(&nbsp;|\s)*\?/g,thinnbsp+'?');
			text=text.replace(/(&nbsp;|\s)*!/g,thinnbsp+'!');
			text=text.replace(/(&nbsp;|\s)*:/g,thinnbsp+':');
			text=text.replace(/«(&nbsp;|\s)*/g,'«'+thinnbsp);
			text=text.replace(/(&nbsp;|\s)*»/g,thinnbsp+'»');
			$(this).html(text);
		});
		$(this).unspanize('ponctumots');
	});
},

lettrine:function(){
	var reg = /^(\W*)([a-zàáâäèéêëìíîïòóôöùúûüœæýÿç]|[0-9]+)/i;
	var fc = false;	//fc : foundcharacter
	var m;
	var p; // p for parent of the textNode
	var wrapLettr = function(n,spannc){ //n : node
		//alert('node type : '+n.nodeType+', children :'+n.childNodes.length);
		if (fc) return;
		children:for (var i=0;i<n.childNodes.length;i++){
			m = n.childNodes.item(i);
			//alert(m.nodeName);
			if (m.nodeName.match(/h[1-6]/i)){continue children;}
			//alert('child type : '+m.nodeType);
			if (m.nodeType==1){// NodeType==1 : element node
				wrapLettr(m,spannc);
				if (fc) {
					//n.normalize();
					break children;}}
			else if (m.nodeType==3){// NodeType==3 : text node
				//alert(m.nodeValue);
				if (str = m.nodeValue.match(reg)){
					if (str[0].length<=5 || spannc.text().length>0){
						if (spannc.text().length==0){
							//alert('Parent:'+n.nodeName);
							p=n;}
						m.nodeValue=m.nodeValue.substr(str[0].length);
						$(n).css({textIndent:0});
						spannc.append(str[0]);}
					fc=true;
					break children;}
				else if(!m.nodeValue.match(/^\s*$/)){
					if (spannc.text().length==0){
						//alert('Parent:'+n.nodeName);
						p=n;}
					spannc.append(m.nodeValue);
					$(n).css({textIndent:0});
					m.nodeValue='';}}}
	
	};//EOF wrapLettr

	return this.each(function(){
		fc=false;
		$(this).css({clear:'both',textIndent:0});
		var spannc = $('<span class="lettrine" style="display:block;float:left;font-size:1em; text-transform:uppercase;"/>');
		wrapLettr(this,spannc);
		spannc.prependTo(p);
	});
},

// if (!confirm('')) break;
cesure:function(){
	return this.each(function(){

		var filter = function(n) {
			if (n.nodeName.match(/span/i) && n.className == "cesuremot")
				return NodeFilter.FILTER_ACCEPT;
			return NodeFilter.FILTER_SKIP;}
		
		var tw = document.createTreeWalker(this,NodeFilter.SHOW_ELEMENT,filter,false);
		
		// fil : first in line
		// lil : last in line;
		// fal : first after line;
		var cptline=0,line,fil,lil,fal,filoff,liloff,faloff,problem,
			spacewidth,linespacewidth,hyphenwidth,exwidth,overspace,
			linewidth,lineheight,
			parentwidth,parentoff,
			wordswidth,wordsnum,bckp,dlw,l,
			checksel,checkwidth,span;

		var falNextWord = function(){
			liloff = lil.offset();
			tmp=tw.nextNode();
			if (tmp==null) return false;
			else fal = $(tmp);
			faloff = fal.offset();
			return true;
		};

		var getLine = function(){	
			var tmp,line;
			cptline++;
			fil = fal;
			if (fil==null || fil.length==0) return null;
			filoff = fil.offset();
			line = fil; 
			lil = fil; 
			tw.currentNode = fil.get(0);
			//if (!confirm('Line '+cptline+' fil : '+tw.currentNode.firstChild.nodeValue)) return false;
			if (!falNextWord()) return null;
			while (faloff.left > liloff.left && faloff.top <= liloff.top+lineheight){
				line = line.add(fal);
				lil = fal;
				if (!falNextWord()) return null;}
			return line;
		};

		// Splitting the words
		$(this).spanize('cesuremot',2000);
		$('span.lettrine',this).unspanize('cesuremot');

		// Setting lengths
		parentwidth = $(this).width();
		parentoff = $(this).offset();
		parentoff.right = parentoff.left+parentwidth;
		span=$('<span id="newcesure"/>').appendTo($(this));
		span.html('-');hyphenwidth = span.width();
		span.html('x'); exwidth = span.width();
		span.html('&nbsp;');spacewidth = span.width();
		lineheight = span.height();
		span.remove();

		// Finding first line 
		fal = $(tw.nextNode());
		line = getLine(fil);
		
		// Doing the computation of lengths
		while (line!=null && line.length>0){
			// Setting line-lengths

			linewidth = parentoff.right - filoff.left;
			wordsnum = line.length;
			wordswidth=0;
			line.each(function(){wordswidth+=$(this).width();});

			linespacewidth = (linewidth-wordswidth)/(wordsnum-1);
			overspace = linewidth - (wordswidth+(wordsnum-1)*spacewidth);

			// if words too long for the line : trying to cut the last word 
			// (which surely may be the only one...)
			if (liloff.left+lil.width()>parentoff.right){
				problem = true;
				bckp = lil.text();
				dlw = $.decoupe(bckp);
				if (dlw.length>0){
					span = $('<span id="newcesure"/>').insertBefore(lil);
					l = dlw.length;
					while (problem && l>0){
						l--;
						span.text(bckp.substring(0,dlw[l])+'- ');
						lil.text(bckp.substring(dlw[l]));
						problem = (span.offset().left+span.width() > parentoff.right);}
					if (problem){
						span.remove();
						lil.text(bckp);}
					else{
						span.removeAttr('id').addClass('cesuremot');
						fal=lil;}
				}
			}

			// if there is enough space for a cut, 
			// cut the first word of the next line, if this line exists.
			// TODO : better 2nd conditional and checking for text-indent on first line...
			else if (linespacewidth/spacewidth>1.3 && overspace>=3*exwidth){
				problem = true;
				if (fal.length==0) break;
				bckp = fal.text();
				dlw = $.decoupe(bckp);
				if (dlw.length>0){
					span = $('<span id="newcesure"/>').insertBefore(fal);
					l = dlw.length;
					while (problem && l>0){
						l--;
						span.text(bckp.substring(0,dlw[l])+'- ');
						problem = span.offset().top-faloff.top>=0;}
					if (problem){
						span.remove();}
					else{
						span.removeAttr('id').addClass('cesuremot');
						fal.text(bckp.substring(dlw[l]));}
				}
			}

			line = getLine(fal);
			
		}//EO while
		$(this).unspanize('cesuremot').find('[id=newcesure]').remove();
	});
}

});// $.fn.extend

})(jQuery);

