/**
 *  jQuery Plugin textgrad, version 0
 *  (c) 2007 Guillaume Andrieu, subtenante@yahoo.fr
 *  http://www.agencenp.net/textgrad/textgrad.html
 *  Licensed GPL licenses:
 *   http://www.gnu.org/licenses/gpl.html
 */
(function($){

/**
 * SPANIZE routine
 */
$.spanizeText = 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);
};

/**
 * spanize jquery function
 */
$.fn.spanize = function(spanClass,maxGroup){
	$(this).each(function(){$.spanizeText(this,spanClass,maxGroup);});
};

/**
 * UNSPANIZE routine
 */
$.unspanize = function(obj,spanClass){
	var text=$(obj).html();
  var reg = new RegExp ("<(?:span|SPAN)[^>]*"+(spanClass==''?'':' class=(?:"|\')?'+spanClass+'(?:"|\')?')+">([^<\\s]+)</(?:span|SPAN)>",'g');
  text=text.replace(reg,"$1");
  //alert($(obj).html()+"\n\n"+text);
  $(obj).html(text);
};

/**
 * unspanize jquery function
 */
$.fn.unspanize = function(spanClass){
	$(this).each(function(){$.unspanize(this,spanClass);});
}



$.str2color = function(str){
  if (str && str.constructor == Array && str.length == 3) return str;
  var res;
	if (str.match(/rgb\([0-9]{1,3},[0-9]{1,3},[0-9]{1,3}\)/)){
		str.replace("rgb(","");str.replace(")","");
		res=str.split(",");
		for(i=0;i<3;i++){if (res[i]>255) res[i]=255;}
		return res;}
	else if (str.match(/#?[0-9a-fA-F]{6}/)){
		if (str.length==7) str=str.substring(1);
		res = [parseInt(str.substring(0,2),16),
					 parseInt(str.substring(2,4),16),
					 parseInt(str.substring(4,6),16)];}
	else if(str.match(/#?[0-9a-fA-F]{3}/)){
		if (str.length==4) str=str.substring(1);
		res =  [parseInt(str.substring(0,1)+str.substring(0,1),16),
						parseInt(str.substring(1,2)+str.substring(1,2),16),
						parseInt(str.substring(2,3)+str.substring(2,3),16)];}
	else res = [0,0,0];
	return res;};

/**
 * DEFAULTS for textgrad
 */
$.textGrad = {};
$.textGrad.defaults = {
debut:'F00',
fin:'0FF',
maxGroup:3,
type:'',
spanClass:''
};

/**
 * textgrad jquery function
 */
$.fn.textgrad=function(settings){

	//+++++ FUNCTIONS
	var abspos = function(jobj){
		var curleft = 0;
		var curtop = 0;
		if (jobj.offsetParent) {
			curleft += jobj.offsetLeft;
			curtop += jobj.offsetTop;
			var obj=jobj;
			while (obj = obj.offsetParent) {
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;}}
		return [curleft,curtop];};
		
  var pos = function(jobj){
    var res=abspos(jobj);
    return [res[0]-0.5*jobj.offsetWidth,res[1]+0.5*jobj.offsetHeight];};
  
	var boxpos = function(jobj){
		var tpos = abspos(jobj);
    $(jobj).prepend('<span class="test">p</span>');
		var res = [tpos[0]+0.5*$('span.test',jobj).get(0).offsetWidth,
		tpos[1]+0.5*$('span.test',jobj).get(0).offsetHeight,
		jobj.offsetWidth-0.5*$('span.test',jobj).get(0).offsetWidth,
		jobj.offsetHeight-0.5*$('span.test',jobj).get(0).offsetHeight];
    $('span.test',jobj).slice(0, 1).remove();
		return res;};

  var spandim = function(span){
    var tpos = pos(span);
		var res = [tpos[0],tpos[1],0.5*span.offsetWidth,0.5*span.offsetHeight];
		return res;};

  var pickingrad = function(point){
    if (grad.length==0) return [0,0,0];
    if (grad.length==1) return grad[0]['col'];

    point=100*point;  
    if (point<=grad[0]['pc']) {
      //alert(point+" "+grad[0]['col']);
      return grad[0]['col'];}
    if (point>=grad[grad.length-1]['pc']) {
      //alert(point+" "+grad[0]['col']);
      return grad[grad.length-1]['col'];}

    var mins=0;var maxs=100;var minc=[0,0,0];var maxc=[0,0,0];
    var i=0;
    while(point>=grad[i]['pc'] && i<grad.length){mins=grad[i]['pc'];minc=grad[i]['col'];i++;}
    i=grad.length-1;
    while(point<=grad[i]['pc'] && i>=0){maxs=grad[i]['pc'];maxc=grad[i]['col'];i--;}
    var res=[0,0,0];
    var mult = (point-mins)/(maxs-mins);
    for(i=0;i<3;i++){res[i]=minc[i]+(maxc[i]-minc[i])*mult;}
    //alert(minc+"\n"+maxc+"\n"+point+"\n"+mult+"\n"+res);
    return res;
  };

	var getcolor = function(span,bp){
		var sp=spandim(span);
		var res=[0,0,0];
    if (type=='|'){
      var delta=(sp[1]-bp[1])/bp[3];
    }
    else if (type=='o'){
      Cx=bp[0]+bp[2]/2;Cy=bp[1]+bp[3]/2;
      r=Math.sqrt((Cx-sp[0])*(Cx-sp[0])+(Cy-sp[1])*(Cy-sp[1]));
      R=Math.sqrt((bp[2])*(bp[2])/4+(bp[3])*(bp[3])/4);
      var delta =r/R;
    }
    else if (type=='_' || 2.5*sp[3]>bp[3]){
      var delta=(sp[0]-bp[0])/bp[2];
    }
    else if (type=='/'){
      multx=(sp[0]-bp[0])/bp[2];
      multy=(bp[3]-sp[1]+bp[1])/bp[3];
      var delta = (multx+multy)/2;
    }
    else{
      multx=(sp[0]-bp[0])/bp[2];
      multy=(sp[1]-bp[1])/bp[3];
      var delta = (multx+multy)/2;
    }
    var res = pickingrad(delta);
    res = "rgb("+Math.round(res[0])+","+Math.round(res[1])+","+Math.round(res[2])+")";
    //alert(sp+"\n"+bp+"\n"+$(span).text()+"\n"+res);		
    return res;
	};

  var treatgrad=function(){
    for(i=0;i<opt['colgrad'].length;i++){
      opt['colgrad'][i]['col']=$.str2color(opt['colgrad'][i]['col']);}
    return opt['colgrad'];
  };
  //----- FUNCTIONS

	//+++++ PARAMS
  var opt = settings||{};
  var d = $.textGrad.defaults;
	var coldeb=$.str2color(opt['debut']||opt['begin']||d['debut']);
	var colfin=$.str2color(opt['fin']||opt['end']||d['fin']);
  var grad=opt['colgrad']?treatgrad():[{pc:0,col:coldeb},{pc:100,col:colfin}];
	var maxGroup = opt['maxGroup']||d['maxGroup'];
  var type = opt['type']||d['type'];
  var spanize = opt['spanize']||1;
  var spanClass = opt['spanClass']||d['spanClass'];
	//----- PARAMS
	
	$(this).each(function(){
		
    if (spanize>0) $.spanizeText(this,spanClass,maxGroup);

		var blockpos=boxpos(this);

		$("span"+(spanClass==''?'':'.'+spanClass),this).each(function(){$(this).css('color',getcolor(this,blockpos))});

		if (opt['cb'] && opt['cb'].constructor == Function) opt['cb'].call(this);

	});//EO $(this).each(...);
};//EO $.fn.textgrad

/**
 * textscan jquery function
 */
$.fn.textscan = function(settings){

  var opt = settings||{};
  var initColor = $.str2color(opt['initColor']||"000");  
  var endColor  = $.str2color(opt['endColor']||"F00");
  var transColor= $.str2color(opt['transColor']||"FFF");
  var spcl = opt['spanClass']||'animgradsp';
  var direction = opt['direction']||'->';
  var mg = opt['maxGroup']||2;
  var spnz = opt['spanize']||1;
  var unspnz = opt['unspanize']||1;
  var amplitude = opt['amplitude']||20;
  var step = opt['step']||5;
  
  $(this).each(function(){
    var timer;
    var steps = 100+2*amplitude;
    var currStep=(direction=='->'?0:100);
    var grad;
    var obj=this;
    $(this).textgrad({spanize:spnz,maxGroup:mg,spanClass:spcl,debut:initColor,fin:initColor});
  	timer = window.setInterval(function() {
      if(direction=='->'){
      currStep+=step;
      grad=[{pc:currStep-2*amplitude,col:endColor}
           ,{pc:currStep-amplitude,col:transColor}
           ,{pc:currStep,col:initColor}];}
      else{
      currStep-=step;
      grad=[{pc:currStep,col:initColor}
           ,{pc:currStep+amplitude,col:transColor}
           ,{pc:currStep+2*amplitude,col:endColor}];}
      $(obj).textgrad({spanize:-1,spanClass:spcl,colgrad:grad});
      // End the process
  		if (currStep >= steps+1 || currStep<=-2*amplitude-1) {
        if (unspnz>0){
          $.unspanize(obj,spcl);}        
  			window.clearInterval(timer);timer=null;
    		if (opt['cb'] && opt['cb'].constructor == Function) opt['cb'].call(obj);
  		}
  	},50);
  });//EO each
};//EO textscan*/


/*EOP*/
})(jQuery);



/**
 * jQuery.ScrollTo
 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com
 * Licensed under GPL license (http://www.opensource.org/licenses/gpl-license.php).
 * Date: 1/2/2008
 *
 * @projectDescription Easy element scrolling using jQuery.
 * Tested with jQuery 1.2.1. On FF 2.0.0.11, IE 6, Opera 9.22 and Safari 3 beta. on Windows.
 *
 * @author Ariel Flesler
 * @version 1.3
 *
 * @id jQuery.scrollTo
 * @id jQuery.fn.scrollTo
 * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
 *	  The different options for target are:
 *		- A number position (will be applied to all axes).
 *		- A string position ('44', '100px', '+=90', etc ) will be applied to all axes
 *		- A jQuery/DOM element ( logically, child of the element to scroll )
 *		- A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
 *		- A hash { top:x, left:y }, x and y can be any kind of number/string like above.
 * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
 * @param {Object} settings Hash of settings, optional.
 *	 @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
 *	 @option {Number} duration The OVERALL length of the animation.
 *	 @option {String} easing The easing method for the animation.
 *	 @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
 *	 @option {Object, Number} offset Add/deduct from the end position. One number for both axis or { top:x, left:y }
 *	 @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
 *	 @option {Function} onAfter Function to be called after the scrolling ends. 
 *	 @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @example $('div').scrollTo( 340 );
 *
 * @example $('div').scrollTo( '+=340px', { axis:'y' } );
 *
 * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
 *
 * @example var second_child = document.getElementById('container').firstChild.nextSibling;
 *			$('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
 *				alert('scrolled!!');																   
 *			}});
 *
 * @example $('div').scrollTo( { top: 300, left:'+=200' }, { offset:-20 } );
 *
 * Notes:
 *  - jQuery.scrollTo will make the whole window scroll, it accepts the same parameters as jQuery.fn.scrollTo.
 *  - The plugin no longer requires Dimensions.
 *	- If you are interested in animated anchor navigation, check http://jquery.com/plugins/project/LocalScroll.
 *	- The option 'margin' won't be valid, if the target is not a jQuery object or a DOM element.
 *	- The option 'queue' won't be taken into account, if only 1 axis is given.
 */
;(function( $ ){
		  
	$.scrollTo = function( target, duration, settings ){
		$( $.browser.safari ? 'body' : 'html' ).scrollTo( target, duration, settings );
	};
	
	$.scrollTo.defaults = {
		axis:'y',
		duration:1
	};
	
	$.fn.scrollTo = function( target, duration, settings ){
		if( typeof duration == 'object' ){
			settings = duration;
			duration = 0;
		}
		settings = $.extend( {}, $.scrollTo.defaults, settings );
		if( !duration )
			duration = settings.speed || settings.duration;//backward compatibility fix
		settings.queue = settings.queue && settings.axis.length == 2;//make sure the settings are given right
		if( settings.queue )
			duration = Math.ceil( duration / 2 );//let's keep the overall speed, the same.
		if( typeof settings.offset == 'number' )
			settings.offset = { left: settings.offset, top: settings.offset };
		
		return this.each(function(){
			var elem = this, $elem = $(elem),
				t = target, toff, attr = {},
				win = $elem.is('html,body');
			switch( typeof t ){
				case 'number'://will pass the regex
				case 'string':
					if( /^([+-]=)?\d+(px)?$/.test(t) ){
						t = { top:t, left:t };
						break;//we are done
					}
					t = $(t,this);// relative selector, no break!
				case 'object':
					if( t.is || t.style )//DOM/jQuery
						toff = (t = $(t)).offset();//get the real position of the target 
			}
			$.each( settings.axis.split(''), parse );			
			animate( settings.onAfter );			
			
			function parse( i, axis ){
				var Pos	= axis == 'x' ? 'Left' : 'Top',
					pos = Pos.toLowerCase(),
					key = 'scroll' + Pos,
					act = elem[key];
					
				if( toff ){//jQuery/DOM
					attr[key] = toff[pos] + ( win ? 0 : act - $elem.offset()[pos] );
					
					if( settings.margin ){//if it's a dom element, reduce the margin
						attr[key] -= parseInt(t.css('margin'+Pos)) || 0;
						attr[key] -= parseInt(t.css('border'+Pos+'Width')) || 0;
					}
					
					if( settings.offset && settings.offset[pos] )
						attr[key] += settings.offset[pos];
				}else{
					attr[key] = t[pos];
				}				
				
				if( /^\d+$/.test(attr[key]) )
					attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(axis) );//check the limits
				
				if( !i && settings.queue ){//queueing each axis is required					
					if( act != attr[key] )//don't waste time animating, if there's no need.
						animate( settings.onAfterFirst );//intermediate animation
					delete attr[key];//don't animate this axis again in the next iteration.
				}
			};
			
			function animate( callback ){
				$elem.animate( attr, duration, settings.easing, function(){
					if( callback )
						callback.call(this, $elem, attr, t );
				});
			};
			function max( axis ){
				var el = win ? $.browser.opera ? document.body : document.documentElement : elem,
					Dim = axis == 'x' ? 'Width' : 'Height';
				return el['scroll'+Dim] - el['client'+Dim];
			};
		});
	};

})( jQuery );
