/**********************************************************************************
   Timers
 **********************************************************************************/
var waitLastAction = (function() {
	var wtimers = {};
	return function (callback, ms, uniqueId) {
		if (!uniqueId) {
			uniqueId = "juste pour le fun, utilsez autre chose";
		}
		if (wtimers[uniqueId]) {
			clearTimeout (wtimers[uniqueId]);
		}
		wtimers[uniqueId] = setTimeout(callback, ms);
	};
})();

/* objectsArraysStrings.js */
/*
     Example File From "JavaScript and DHTML Cookbook"
     Published by O'Reilly & Associates
     Copyright 2003 Danny Goodman
*/
function object2String(obj) {
    var val, output = "";
    if (obj) {    
        output += "{";
        for (var i in obj) {
            val = obj[i];
            switch (typeof val) {
                case ("object"):
                    if (val[0]) {
                        output += i + ":" + array2String(val) + ",";
                    } else {
                        output += i + ":" + object2String(val) + ",";
                    }
                    break;
                case ("string"):
                    output += i + ":'" + escape(val) + "',";
                    break;
                default:
                    output += i + ":" + val + ",";
            }
        }
        output = output.substring(0, output.length-1) + "}";
    }
    return output;
}

function array2String(array) {
    var output = "";
    if (array) {
        output += "[";
        for (var i in array) {
            val = array[i];
            switch (typeof val) {
                case ("object"):
                    if (val[0]) {
                        output += array2String(val) + ",";
                    } else {
                        output += object2String(val) + ",";
                    }
                    break;
                case ("string"):
                    output += "'" + escape(val) + "',";
                    break;
                default:
                    output += val + ",";
            }
        }
        output = output.substring(0, output.length-1) + "]";
    }
    return output;
}


function string2Object(string) {
	eval("var result = " + string);
	return result;
}

function string2Array(string) {
	eval("var result = " + string);
	return result;
}

function inArray(array, p_val) {
    var l = array.length;
    for(var i = 0; i < l; i++) {
        if(array[i] == p_val) {
            return true;
        }
    }
    return false;
}

function randOrd(){ return (Math.round(Math.random())-0.5); }

function createRandArray( arr, notrand ) {
	var arrRet = new Array();
	for( var i=0; i<arr.length; i++ ) {
		arrRet.push(i);
	};
	if(!notrand) arrRet.sort( randOrd );
	return( arrRet );
};


/**
 * Function : dump()
 * Arguments: The data - array,hash(associative array),object
 *    The level - OPTIONAL
 * Returns  : The textual representation of the array.
 * This function was inspired by the print_r function of PHP.
 * This will accept some data as the argument and return a
 * text that will be a more readable version of the
 * array/hash/object that is given.
 * Docs: http://www.openjs.com/scripts/others/dump_function_php_print_r.php
 */
function dump(arr,level) {
	var dumped_text = "";
	if(!level) level = 0;
	
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";
	
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			var value = arr[item];
			
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}

function dumpbr(arr,level,intlev) {
	var dumped_text = "";
	if(!intlev) intlev = 0;
	if( typeof(level)=='undefined' ) level = -1;
	
	//The padding given at the beginning of the line.
	var level_padding = "<span>", numel = 0;
	if( intlev>0 ) for(var j=0;j<intlev;j++) level_padding += "&nbsp;&nbsp;&nbsp;"; //"&middot;&nbsp;&nbsp;";
	level_padding += "</span>";
	
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			var value = arr[item];
			
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "<span>" + numel + "<em> "+typeof(value)+"</em>&gt;</span> " + item + " &not;<br>";
				numel++;
				if( ( level==-1 || intlev<level ) && item.search('canvas')==-1 )
					dumped_text += dumpbr(value,level,intlev+1);
			} else {
				dumped_text += level_padding + "<span>" + numel + "<em> "+typeof(value)+"</em>&gt;</span> " + item + " => \"" + value + "\"<br>";
				numel++;
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===<em> "+typeof(arr)+"</em><br>";
	}
	return dumped_text;
}

function getKey(arr,key) {
	var retobj = false;
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			if( item==key ) {
				var nobj = new Object();
				nobj[item] = arr[item];
				return nobj;
			}
			if( typeof(arr[item]) == 'object' && item.search('canvas')==-1 ) {
				retobj = getKey(arr[item],key);
			}
			if( retobj ) break;
		}
	}
	return retobj;
}

String.prototype.addSlashes = function()
{return this.replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0');};
 
String.prototype.stripSlashes = function()
{return this.replace(/\\(.?)/g, function (s, n1){switch (n1){case '\\':return '\\';case '0':return '\u0000';case '':return '';default:return n1;}});};

function string_to_slug(str) {
  str = str.replace(/^\s+|\s+$/g, ''); // trim
  str = str.toLowerCase();
  
  // remove accents, swap ñ for n, etc
  var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;";
  var to   = "aaaaeeeeiiiioooouuuunc------";
  for (var i=0, l=from.length ; i<l ; i++) {
    str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
  }

  str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
    .replace(/\s+/g, '-') // collapse whitespace and replace by -
    .replace(/-+/g, '-'); // collapse dashes

  return str;
}

(function($) {
/**
* hoverIntent is similar to jQuery's built-in "hover" function except that
* instead of firing the onMouseOver event immediately, hoverIntent checks
* to see if the user's mouse has slowed down (beneath the sensitivity
* threshold) before firing the onMouseOver event.
* 
* hoverIntent r6 // 2011.02.26 // jQuery 1.5.1+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* hoverIntent is currently available for use in all personal or commercial 
* projects under both MIT and GPL licenses. This means that you can choose 
* the license that best suits your project, and use it accordingly.
* 
* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
* $("ul li").hoverIntent( showNav , hideNav );
* 
* // advanced usage receives configuration object only
* $("ul li").hoverIntent({
*	sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
*	interval: 100,   // number = milliseconds of polling interval
*	over: showNav,  // function = onMouseOver callback (required)
*	timeout: 0,   // number = milliseconds delay before onMouseOut function call
*	out: hideNav    // function = onMouseOut callback (required)
* });
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne brian(at)cherne(dot)net
*/
	$.fn.hoverIntent = function(f,g) {
		//var spanHv = $.add('span');
		
		// default configuration options
		var cfg = {
			sensitivity: 7,
			interval: 100,
			timeout: 0
		};
		// override configuration options with user supplied object
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// instantiate variables
		// cX, cY = current X and Y position of mouse, updated by mousemove event
		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
		var cX, cY, pX, pY;

		// A private function for getting mouse position
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// A private function for comparing current and previous mouse position
		var compare = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			// compare mouse positions to see if they've crossed the threshold
			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove",track);
				// set hoverIntent state to true (so mouseOut can be called)
				ob.hoverIntent_s = 1;
				return cfg.over.apply(ob,[ev]);
			} else {
				// set previous coordinates for next time
				pX = cX; pY = cY;
				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
			}
		};

		// A private function for delaying the mouseOut function
		var delay = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			ob.hoverIntent_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// A private function for handling mouse 'hovering'
		var handleHover = function(e) {
			// copy objects to be passed into t (required for event object to be passed in IE)
			var ev = jQuery.extend({},e);
			var ob = this;

			// cancel hoverIntent timer if it exists
			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

			// if e.type == "mouseenter"
			if (e.type == "mouseenter" || e.type == "mouseover") {
				// set "previous" X and Y position based on initial entry point
				pX = ev.pageX; pY = ev.pageY;
				// update "current" X and Y position based on mousemove
				$(ob).bind("mousemove",track);
				// start polling interval (self-calling timeout) to compare mouse coordinates over time
				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );};
			// else e.type == "mouseleave"
			} else {
				// unbind expensive mousemove event
				$(ob).unbind("mousemove",track);
				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );};
			};
		};

		// bind the function to the two event listeners
		//return this.bind('mouseenter',handleHover).bind('mouseleave',handleHover);
		return this.bind('mouseenter',handleHover).bind('mouseover',handleHover).bind('mouseleave',handleHover);
	};


/*
* jQuery.fn.rand();
*
* Return a random, but defined numbers of elements from a jQuery Object.
* $('element').rand(); // returns one element from the jQuery Object.
* $('element').rand(4); // returns four elements from the jQuery Object.
*
* Version 0.8.5
* www.labs.skengdon.com/rand
* www.labs.skengdon.com/rand/js/rand.min.js
*/
	$.fn.rand = function( number ) {
		var array_rand = function (input, num_req) {
			// http://kevin.vanzonneveld.net
			// +   original by: Waldo Malqui Silva
			// *	 example 1: array_rand( ['Kevin'], 1 );
			// *	 returns 1: 0
			// FROM: http://phpjs.org/functions/array_rand:332
			var indexes = [];
			var ticks = num_req || 1;
			var checkDuplicate = function (input, value) {
				var exist = false,
				index = 0;
				while (index < input.length) {
					if (input[index] === value) {
						exist = true;
						break;
					};
					index++;
				};
				return exist;
			};
			while (true) {
				var rand = Math.floor((Math.random() * input.length));
				if (indexes.length === ticks) {
					break;
				};
				if (!checkDuplicate(indexes, rand)) {
					indexes.push(rand);
				}
	   		};
			return ((ticks == 1) ? indexes.join() : indexes);
		};

		if ( typeof number !== 'number' ) var number = 1;
		
		if ( number > this.length ) number = this.length;
		
		var numbers = array_rand( this, number );
		
		var $return = [];
		for ( var i = 0; i < number; i++ ) {
			$return[i] = this.get( numbers[i] );
		};
		return $( $return );
		
	};

})(jQuery);

