// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function(){
  log.history = log.history || [];   // store logs to an array for reference
  log.history.push(arguments);
  if(this.console) {
    arguments.callee = arguments.callee.caller;
    var newarr = [].slice.call(arguments);
    (typeof console.log === 'object' ? log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr));
  }
};

// make it safe to use console.log always
(function(b){function c(){}for(var d="assert,clear,count,debug,dir,dirxml,error,exception,firebug,group,groupCollapsed,groupEnd,info,log,memoryProfile,memoryProfileEnd,profile,profileEnd,table,time,timeEnd,timeStamp,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try
{console.log();return window.console;}catch(err){return window.console={};}})());

/*
 * Blockquotes
 * @author Ianko Leite
 **/
$('blockquote').each(function (){
    $(this)
        .prepend('<span class="bq-open">“</span>')
        .append('<span class="bq-close">”</span>');
});

/*
 * Itens da etiqueta
 * @author Ianko Leite
 **/
$('.etiqueta:not(.links)').each(function (){
    var self = $(this),
        main = self.parents('#main'),
        anchors = main.find('a[name]'),
        ul = $('<ul>').insertAfter($('header', self));
        
        // ir para o topo no link de rodapé da etiqueta
        $('a.scrollTop', this).click(function (event){
            event.preventDefault();

            $('html,body').animate({scrollTop: 0});
        });

        // criar o corpo de links da etiqueta
        $(anchors).each(function (i, e){
            $('<li>').append(
                $('<a>')
                    .attr('href', '#' + e.name)
                    .text(e.name)
                    .click(function (event){
                        event.preventDefault();

                        $('html,body').animate({
                            scrollTop: $(e).offset().top - 20
                        }, 1500, 'easeOutQuint');
                    })
            )
            .toggleClass('first', i == 0)
            .toggleClass('last', i == anchors.length - 1)
            .appendTo(ul);
        });
        
        // animar a movimentação da etiqueta
        if (self.is('.scrollable')) {
            var defaultOffsetTop = self.offset().top,
                defaultCssTop = self.css('top');
            
            // guarda a posição original do sidebar
            self.data('offsetTop', defaultOffsetTop);
            self.data('cssTop', defaultCssTop);
            
            // atualiza a posição do sidebar
            $(window).scroll(function() {
                var totalHeight = self.height(),
                    headerHeight = $('header', self).outerHeight(),
                    limitBottom = $('#footer').offset().top - totalHeight,
                    scrollTop = $(this).scrollTop(),
                    scrollTo = defaultCssTop;
                    
                // topo da página
                if (scrollTop < defaultOffsetTop) {
                    scrollTo = defaultCssTop;
                }
                // fim da página
                else if (scrollTop > limitBottom) {
                    scrollTo = limitBottom - headerHeight;
                }
                // dentro do container #main
                else {
                    scrollTo = scrollTop - headerHeight;
                }
                
                self.stop(true).animate({top: scrollTo}, 500, 'easeOutQuint');
                
            });
        }
        
});

/*
 * Box slide
 * @author Ianko Leite
 **/
$('.box-slide').each(function (){
    var self    = $(this),
        lis     = self.find('li');
    
    if (lis.length > 1) {
        var next = $('<div class="next"><span>Próximo</span></div>'),
            prev = $('<div class="prev"><span>Anterior</span></div>');
        
        self.css({
            'padding-left': 30,
            'padding-right': 30
        })
        .prepend(next).prepend(prev);
            
        lis.not(':first').each(function (){
            $(this).hide();
        });
        
        prev.click(function (){
            lis.filter(':visible').stop(false, true).fadeOut('fast', function (){
                var _this = $(this),
                    next = (_this.index()  != 0) ? _this.index() - 1 : lis.length - 1;
                    
                    lis.eq(next).stop(false, true).fadeIn('fast');
            });
        });
        
        next.click(function (){
            lis.filter(':visible').stop(false, true).fadeOut('fast', function (){
                var _this = $(this),
                    next = (_this.index()  < lis.length - 1) ? _this.index() + 1 : 0;
                    
                    lis.eq(next).stop(false, true).fadeIn('fast');
            });
        });
        
    }
});




/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert(jQuery.easing.default);
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;if ((t/=d)==1) return b+c;if (!p) p=d*.3;
		if (a < Math.abs(c)) {a=c;var s=p/4;}
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;if ((t/=d)==1) return b+c;if (!p) p=d*.3;
		if (a < Math.abs(c)) {a=c;var s=p/4;}
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;if ((t/=d/2)==2) return b+c;if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) {a=c;var s=p/4;}
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158; 
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});




/**
* hoverIntent r6 // 2011.02.26 // jQuery 1.5.1+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* @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
*/
(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev])}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev])};var handleHover=function(e){var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t)}if(e.type=="mouseenter"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob)},cfg.timeout)}}};return this.bind('mouseenter',handleHover).bind('mouseleave',handleHover)}})(jQuery);





// Diapo slideshow v1.0.1 - a jQuery slideshow with many effects, transitions, easy to customize, using canvas and mobile ready, based on jQuery 1.4+
// Copyright (c) 2011 by Manuel Masia - www.pixedelic.com
// Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
;(function($){$.fn.diapo = function(opts, callback) {
	
	var defaults = {
		selector			: 'div',	//target element
		
		fx					: 'random',
//'random','simpleFade','curtainTopLeft','curtainTopRight','curtainBottomLeft','curtainBottomRight','curtainSliceLeft','curtainSliceRight','blindCurtainTopLeft','blindCurtainTopRight','blindCurtainBottomLeft','blindCurtainBottomRight','blindCurtainSliceBottom','blindCurtainSliceTop','stampede','mosaic','mosaicReverse','mosaicRandom','mosaicSpiral','mosaicSpiralReverse','topLeftBottomRight','bottomRightTopLeft','bottomLeftTopRight','bottomLeftTopRight','scrollLeft','scrollRight','scrollTop','scrollBottom','scrollHorz'
		
//you can also use more than one effect: 'curtainTopLeft, mosaic, bottomLeftTopRight'

		mobileFx			: '',	//leave empty if you want to display the same effect on mobile devices and on desktop etc.

		slideOn				: 'random',	//next, prev, random: decide if the transition effect will be applied to the current (prev) or the next slide
				
		gridDifference		: 250,	//to make the grid blocks slower than the slices, this value must be smaller than transPeriod
		
		easing				: 'easeInOutExpo',	//for the complete list http://jqueryui.com/demos/effect/easing.html
		
		mobileEasing		: '',	//leave empty if you want to display the same easing on mobile devices and on desktop etc.
		
		loader				: 'pie',	//pie, bar, none (even if you choose "pie", old browsers like IE8- can't display it... they will display always a loading bar)
		
		loaderOpacity		: .8,	//0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1
		
		loaderColor			: '#ffff00', 
		
		loaderBgColor		: '#222222', 
		
		pieDiameter			: 50,
		
		piePosition			: 'top:5px; right:5px',	//this option accepts any CSS value
		
		pieStroke			: 8,
		
		barPosition			: 'bottom',	//bottom, top
		
		barStroke			: 5,
		
		navigation			: true,	//true, false. It enables the previous and the next buttons, their IDs are #pix_prev and #pix_next
		
		mobileNavigation	: true,	//true, false. It enables the previous and the next buttons on mobile devices
		
		navigationHover		: true,	//true, false. If true navigation will be visible only on hover state
		
		mobileNavHover		: true,	//true, false. If true navigation will be visible only on hover state for mobile devices
		
		commands			: true,	//true, false. It enables stop and play buttons
		
		mobileCommands		: true,	//true, false. It enables stop and play buttons on mobile devices
				
		pagination			: true,	//true, false. It enables the pagination numbers. This is the appended code: 
									//<div id="pix_pag">
										//<ul id="pix_pag_ul">
											//<li id="pag_nav_0"><span><span>0</span></span></li>
											//<li id="pag_nav_1"><span><span>1</span></span></li>
											//<li id="pag_nav_2"><span><span>2</span></span></li>
											//...etc.
										//</ul>
									//</div>
		
		mobilePagination	: true,	//true, false. It enables the pagination numbers on mobile devices
		
		thumbs				: true,	//true, false. It shows the thumbnails (if available) when the mouse is on the pagination buttons. Not available for mobile devices
		
		hover				: true,	//true, false. Puase on state hover. Not available for mobile devices
		
		pauseOnClick		: true,	//true, false. It stops the slideshow when you click the sliders.
		
		rows				: 4,
		
		cols				: 6,
		
		slicedRows			: 8,	//if 0 the same value of rows
		
		slicedCols			: 12,	//if 0 the same value of cols
		
		time				: 3000,	//milliseconds between the end of the sliding effect and the start of the nex one
		
		transPeriod			: 1500,	//lenght of the sliding effect in milliseconds
		
		autoAdvance			: true,	//true, false
		
		mobileAutoAdvance	: true, //truem false. Auto-advancing for mobile devices
		
		onStartLoading		: function() {  },
		
		onLoaded			: function() {  },
		
		onEnterSlide		: function() {  },
		
		onStartTransition	: function() {  }
    };
	
	
	function isMobile() {	//sniff a mobile browser
		if( navigator.userAgent.match(/Android/i) ||
			navigator.userAgent.match(/webOS/i) ||
			navigator.userAgent.match(/iPad/i) ||
			navigator.userAgent.match(/iPhone/i) ||
			navigator.userAgent.match(/iPod/i)
			){
				return true;
		}	
	}
	
	var opts = $.extend({}, defaults, opts);
	
	var elem = this;
	
	var h = elem.height();
	var w = elem.width();
	
	var u;

//Define some difference if is a mobile device or not
	var clickEv,
		autoAdv,
		navigation,
		navHover,
		commands,
		pagination;

	if (isMobile()) {
		clickEv = 'tap';
	} else {
		clickEv = 'click';
	}
	
	if(isMobile()){
		autoAdv = opts.mobileAutoAdvance;
	} else {
		autoAdv = opts.autoAdvance;
	}
	
	if(autoAdv==false){
		elem.addClass('stopped');
	}

	if(isMobile()){
		navigation = opts.mobileNavigation;
	} else {
		navigation = opts.navigation;
	}

	if(isMobile()){
		navHover = opts.mobileNavHover;
	} else {
		navHover = opts.navigationHover;
	}

	if(isMobile()){
		commands = opts.mobileCommands;
	} else {
		commands = opts.commands;
	}

	if(isMobile()){
		pagination = opts.mobilePagination;
	} else {
		pagination = opts.pagination;
	}

//The slideshow starts when all the images are loaded
	function loadimages(imgArr,callback) {
		if (!$.browser.msie || ($.browser.msie && $.browser.version == 9)) {
			var imagesLoaded = 0;
			opts.onStartLoading.call(this);
			$.each(imgArr, function(i, image) {
	
			   var img = new Image();
			
			   img.onload = function() {
				   imagesLoaded++;
				   if (imagesLoaded == imgArr.length) {
						opts.onLoaded.call(this);
					   callback();
				   }
			   };
			
			   img.src = image;
	
			});
		} else {
		   callback();
		}
	}



	if(elem.length!=0){
			
		var selector = $('> '+ opts.selector, elem).not('#pix_canvas').not('#pix_canvas_wrap').not('#pix_next').not('#pix_prev').not('#pix_commands');
		selector.wrapInner('<div class="pix_relativize" style="width:'+w+'px; height:'+h+'px" />');	//wrap a div for the position of absolute elements
		var amountSlide = selector.length;    //how many sliders
		
		var nav;	//nextSlide(nav)
		
		function imgFake() {	//this function replace elements such as iframes or objects with an image stored in data-fake attribute
			$('*[data-fake]',elem).each(function(){
				var t = $(this);
				var imgFakeUrl = t.attr('data-fake');
				var imgFake = new Image();
				imgFake.src = imgFakeUrl;
				t.after($(imgFake).attr('class','imgFake'));	//the image has class imgFake
				var clone = t.clone();
				t.remove();	//I remove the element after cloning so it is initialized only when it appears
				$('.elemToHide').show();
				$(imgFake)[clickEv](function(){
					$(this).hide().after(clone);
					$('.elemToHide').hide();
				});
			});
		}
		
		imgFake();
		
		
		if(opts.hover==true){	//if the option "hover" is true I stop the slideshow on mouse over and I resume it on mouse out
			if(!isMobile()){
				elem.hoverIntent({	
					over: function(){
							elem.addClass('stopped');
						},
					out: function(){
							if(autoAdv!=false){
								elem.removeClass('stopped');
							}									
						},
					timeout: 0
				});
			}
		}

		if(navHover==true){	//if the option is true I show the next and prev button only on mouse over
			if(isMobile()){
				elem.live('vmouseover',function(){
					$('#pix_prev, #pix_next').animate({opacity:1},200);
				});
				elem.live('vmouseout',function(){
					$('#pix_prev, #pix_next').delay(500).animate({opacity:0},200);
				});
			} else {
				elem.hover(function(){
					$('#pix_prev, #pix_next').stop(true,false).animate({opacity:1},200);
				},function(){
					$('#pix_prev, #pix_next').stop(true,false).animate({opacity:0},200);
				});
			}
		}
	
	
		$.fn.diapoStop = function() {
			autoAdv = false;
			elem.addClass('stopped');
			if($('#pix_stop').length){
				$('#pix_stop').fadeOut(100,function(){
					$('#pix_play').fadeIn(100);
					if(opts.loader!='none'){
						$('#pix_canvas').fadeOut(100);
					}
				});
			} else {
				if(opts.loader!='none'){
					$('#pix_canvas').fadeOut(100);
				}
			}
		}

		$('#pix_stop').live('click',function(){	//stop function
			elem.diapoStop();
		});
	
		$.fn.diapoPlay = function() {
			autoAdv = true;
			elem.removeClass('stopped');
			if($('#pix_play').length){
				$('#pix_play').fadeOut(100,function(){
					$('#pix_stop').fadeIn(100);
					if(opts.loader!='none'){
						$('#pix_canvas').fadeIn(100);
					}
				});
			} else {
				if(opts.loader!='none'){
					$('#pix_canvas').fadeIn(100);
				}
			}
		}

		$('#pix_play').live('click',function(){	//play function
			elem.diapoPlay();
		});
	
		if(opts.pauseOnClick==true){	//if option is true I stop the slideshow if the user clicks on the slider
			selector[clickEv](function(){
				autoAdv = false;
				elem.addClass('stopped');
				$('#pix_stop').fadeOut(100,function(){
					$('#pix_play').fadeIn(100);
					$('#pix_canvas').fadeOut(100);
				});
			});
		}
		
		
		var allImg = new Array();	//I create an array for the images of the slideshow
		$('img', elem).each( function() { 
			allImg.push($(this).attr('src'));	//all the images are pushed in the array
		});
		if (!$.browser.msie) {	//sorry IE8- has some problem with this
			$('div, span, a', elem).each(function(){	//I check all the background images in the sliders and I push them into the array
				var bG = $(this).css('background');
				var bG2 = $(this).attr('style');
				if(typeof bG !== 'undefined' && bG !== false && bG.indexOf("url") != -1) {
					var bGstart = bG.lastIndexOf('url(')+4;
					var bGfinish = bG.lastIndexOf(')');
					bG = bG.substring(bGstart,bGfinish);
					bG = bG.replace(/'/g,'');
					bG = bG.replace(/"/g,'');
					allImg.push(bG);
				} else if (typeof bG2 !== 'undefined' && bG2 !== false && bG2.indexOf("url") != -1) {
					var bG2start = bG2.lastIndexOf('url(')+4;
					var bG2finish = bG2.lastIndexOf(')');
					bG2 = bG2.substring(bG2start,bG2finish);
					bG2 = bG2.replace(/'/g,'');
					bG2 = bG2.replace(/"/g,'');
					allImg.push(bG2);
				}
			});
		}
				
	
		loadimages(allImg,nextSlide);	//when all the images in the array are loaded nextSlide function starts
		
	}
	
	
		function shuffle(arr) {	//to randomize the effect
			for(
			  var j, x, i = arr.length; i;
			  j = parseInt(Math.random() * i),
			  x = arr[--i], arr[i] = arr[j], arr[j] = x
			);
			return arr;
		}
	
		function isInteger(s) {	//to check if a number is integer
			return Math.ceil(s) == Math.floor(s);
		}	
	
		if (($.browser.msie && $.browser.version < 9) || opts.loader == 'bar') {	//IE8- has some problems with canvas, I prefer to use a simple loading bar in CSS
			elem.append('<span id="pix_canvas" />');
			var canvas = $("#pix_canvas");
			if(opts.barPosition=='top'){
				canvas.css({'top':0});
			} else {
				canvas.css({'bottom':0});
			}
			canvas.css({'position':'absolute', 'left':0, 'z-index':1001, 'height':opts.barStroke, 'width':0, 'background-color':opts.loaderColor});
		} else {
			elem.append('<canvas id="pix_canvas"></canvas>');
			var G_vmlCanvasManager;
			var canvas = document.getElementById("pix_canvas");
			canvas.setAttribute("width", opts.pieDiameter);
			canvas.setAttribute("height", opts.pieDiameter);
			canvas.setAttribute("style", "position:absolute; z-index:1002; "+opts.piePosition);
			var rad;
			var radNew;
	
			if (canvas && canvas.getContext) {
				var ctx = canvas.getContext("2d");
				ctx.rotate(Math.PI*(3/2));
				ctx.translate(-opts.pieDiameter,0);
			}
		
		}
		if(opts.loader=='none' || autoAdv==false) {	//hide the loader if you want
			$('#pix_canvas, #pix_canvas_wrap').hide();
		}
		
		if(navigation==true) {	//I create the next/prev buttons
			elem.append('<div id="pix_prev" />').append('<div id="pix_next" />');
			$('#pix_prev').animate({opacity:0},200);
		}
			
		elem.after('<div id="pix_pag" />');	//I create a div that will contain the play/stop button and the pagination buttons
		if(pagination==true) {
			$('#pix_pag').append('<ul id="pix_pag_ul" />');
			var li;
			for (li = 1; li <= amountSlide; li++){
				$('#pix_pag_ul').append('<li id="pag_nav_'+li+'" style="position:relative; z-index:1002"><span><span>'+li+'</span></span></li>');
				if(opts.thumbs==true) {
					var dataThumb = selector.eq(li).attr('data-thumb');
					var newImg = new Image();
					newImg.src = dataThumb;
					$('li#pag_nav_'+li).append($(newImg).attr('class','pix_thumb').css('position','absolute').animate({opacity:0},0));
					$('li#pag_nav_'+li+' > img').after('<div class="thumb_arrow" />');
					$('li#pag_nav_'+li+' > .thumb_arrow').animate({opacity:0},0);
					
					if(!isMobile()){
						$('#pix_pag li').hover(function(){
							$('.pix_thumb, .thumb_arrow',this).addClass('visible').stop(true,false).animate({'margin-top':-15, opacity: 1},300,'easeOutQuad');					
						},function(){
							$('.pix_thumb, .thumb_arrow',this).removeClass('visible').stop(true,false).animate({'margin-top':0, opacity: 0},150);					
						});
					}
				}
			}
		}
			
		if(commands==true) {
			$('#pix_pag').append('<div id="pix_commands" />');
			$('#pix_pag').find('#pix_commands').append('<div id="pix_play" />').append('<div id="pix_stop" />');
			if(autoAdv==true){
				$('#pix_play').hide();
				$('#pix_stop').show();
			} else {
				$('#pix_stop').hide();
				$('#pix_play').show();
			}
		}
			
		if(navHover==true){
			$('#pix_prev, #pix_next').animate({opacity:0},0);
		}
			
		function canvasLoader() {
			opts.onStartTransition.call(this);
			rad = 0;
			if (($.browser.msie && $.browser.version < 9) || opts.loader == 'bar') {
				$('#pix_canvas').css({'width':0});
			} else {
				ctx.clearRect(0,0,opts.pieDiameter,opts.pieDiameter); // clear canvas
			}
		}
		
		
		canvasLoader();
		
		
		$('.fromLeft, .fromRight, .fromTop, .fromBottom, .fadeIn').each(function(){
			$(this).css('visibility','hidden');
		});
		
	
	/*************************** FUNCTION nextSlide() ***************************/
	
	function nextSlide(nav){    //funzione per il fading delle immagini
		elem.addClass('diaposliding');	//aggiunge una classe che mi dice che il fading è in corso
		
		var vis = parseFloat($('> '+opts.selector +'.diapocurrent',elem).not('#pix_canvas').not('#pix_canvas_wrap').not('#pix_next').not('#pix_prev').not('#pix_commands').index());    //la variabile è il numero del div partendo da 0

		if(nav>0){    //se siamo all'ultimo div o se ancora non ho creato nessun div
			var i = nav-1;
		} else if (vis == amountSlide-1) { 
			var i = 0;
		} else {    //altrimenti l'indice è l'id corrent più uno, quindi il div successivo
			var i = vis+1;
		}
				
		

		var rows = opts.rows,
			cols = opts.cols,
			couples = 1,
			difference = 0,
			dataSlideOn,
			time,
			fx,
			easing,
			randomFx = new Array('simpleFade','curtainTopLeft','curtainTopRight','curtainBottomLeft','curtainBottomRight','curtainSliceLeft','curtainSliceRight','blindCurtainTopLeft','blindCurtainTopRight','blindCurtainBottomLeft','blindCurtainBottomRight','blindCurtainSliceBottom','blindCurtainSliceTop','stampede','mosaic','mosaicReverse','mosaicRandom','mosaicSpiral','mosaicSpiralReverse','topLeftBottomRight','bottomRightTopLeft','bottomLeftTopRight','bottomLeftTopRight','scrollLeft','scrollRight','scrollTop','scrollBottom','scrollHorz');
			marginLeft = 0,
			marginTop = 0;
		
		
		if(isMobile()){
			var dataFx = selector.eq(i).attr('data-fx');
		} else {
			var dataFx = selector.eq(i).attr('data-mobileFx');
		}
		if(typeof dataFx !== 'undefined' && dataFx!== false){
			fx = dataFx;
		} else {
			if(isMobile()&&opts.mobileFx!=''){
				fx = opts.mobileFx;
			} else {
				fx = opts.fx;
			}
			if(fx=='random') {
				fx = shuffle(randomFx);
				fx = fx[0];
			} else {
				fx = fx;
				if(fx.indexOf(',')>0){
					fx = fx.replace(/ /g,'');
					fx = fx.split(',');
					fx = shuffle(fx);
					fx = fx[0];
				}
			}
		}
		
		if(isMobile()&&opts.mobileEasing!=''){
			easing = opts.mobileEasing;
		} else {
			easing = opts.easing;
		}

		dataSlideOn = selector.eq(i).attr('data-slideOn');
		if(typeof dataSlideOn !== 'undefined' && dataSlideOn!== false){
			slideOn = dataSlideOn;
		} else {
			if(opts.slideOn=='random'){
				var slideOn = new Array('next','prev');
				slideOn = shuffle(slideOn);
				slideOn = slideOn[0];
			} else {
				slideOn = opts.slideOn;
			}
		}
			
		time = selector.eq(i).attr('data-time');
		if(typeof time !== 'undefined' && time!== false){
			time = time;
		} else {
			time = opts.time;
		}
			
		if(!$(elem).hasClass('diapostarted')){
			fx = 'simpleFade';
			slideOn = 'next';
			$(elem).addClass('diapostarted')
		}

		switch(fx){
			case 'simpleFade':
				cols = 1;
				rows = 1;
					break;
			case 'curtainTopLeft':
				if(opts.slicedCols == 0) {
					cols = opts.cols;
				} else {
					cols = opts.slicedCols;
				}
				rows = 1;
					break;
			case 'curtainTopRight':
				if(opts.slicedCols == 0) {
					cols = opts.cols;
				} else {
					cols = opts.slicedCols;
				}
				rows = 1;
					break;
			case 'curtainBottomLeft':
				if(opts.slicedCols == 0) {
					cols = opts.cols;
				} else {
					cols = opts.slicedCols;
				}
				rows = 1;
					break;
			case 'curtainBottomRight':
				if(opts.slicedCols == 0) {
					cols = opts.cols;
				} else {
					cols = opts.slicedCols;
				}
				rows = 1;
					break;
			case 'curtainSliceLeft':
				if(opts.slicedCols == 0) {
					cols = opts.cols;
				} else {
					cols = opts.slicedCols;
				}
				rows = 1;
					break;
			case 'curtainSliceRight':
				if(opts.slicedCols == 0) {
					cols = opts.cols;
				} else {
					cols = opts.slicedCols;
				}
				rows = 1;
					break;
			case 'blindCurtainTopLeft':
				if(opts.slicedRows == 0) {
					rows = opts.rows;
				} else {
					rows = opts.slicedRows;
				}
				cols = 1;
					break;
			case 'blindCurtainTopRight':
				if(opts.slicedRows == 0) {
					rows = opts.rows;
				} else {
					rows = opts.slicedRows;
				}
				cols = 1;
					break;
			case 'blindCurtainBottomLeft':
				if(opts.slicedRows == 0) {
					rows = opts.rows;
				} else {
					rows = opts.slicedRows;
				}
				cols = 1;
					break;
			case 'blindCurtainBottomRight':
				if(opts.slicedRows == 0) {
					rows = opts.rows;
				} else {
					rows = opts.slicedRows;
				}
				cols = 1;
					break;
			case 'blindCurtainSliceTop':
				if(opts.slicedRows == 0) {
					rows = opts.rows;
				} else {
					rows = opts.slicedRows;
				}
				cols = 1;
					break;
			case 'blindCurtainSliceBottom':
				if(opts.slicedRows == 0) {
					rows = opts.rows;
				} else {
					rows = opts.slicedRows;
				}
				cols = 1;
					break;
			case 'stampede':
				difference = '-'+opts.transPeriod;
					break;
			case 'mosaic':
				difference = opts.gridDifference;
					break;
			case 'mosaicReverse':
				difference = opts.gridDifference;
					break;
			case 'mosaicRandom':
					break;
			case 'mosaicSpiral':
				difference = opts.gridDifference;
				couples = 1.7;
					break;
			case 'mosaicSpiralReverse':
				difference = opts.gridDifference;
				couples = 1.7;
					break;
			case 'topLeftBottomRight':
				difference = opts.gridDifference;
				couples = 6;
					break;
			case 'bottomRightTopLeft':
				difference = opts.gridDifference;
				couples = 6;
					break;
			case 'bottomLeftTopRight':
				difference = opts.gridDifference;
				couples = 6;
					break;
			case 'topRightBottomLeft':
				difference = opts.gridDifference;
				couples = 6;
					break;
			case 'scrollLeft':
				cols = 1;
				rows = 1;
					break;
			case 'scrollRight':
				cols = 1;
				rows = 1;
					break;
			case 'scrollTop':
				cols = 1;
				rows = 1;
					break;
			case 'scrollBottom':
				cols = 1;
				rows = 1;
					break;
			case 'scrollHorz':
				cols = 1;
				rows = 1;
					break;
		}
			
			var cycle = 0;
			var blocks = rows*cols;	//number of squares
			var leftScrap = w-(Math.floor(w/cols)*cols);	//difference between rounded widths and total width
			var topScrap = h-(Math.floor(h/rows)*rows);	//difference between rounded heights and total height
			var addLeft;	//1 optional pixel to the widths
			var addTop;	//1 optional pixel to the heights
			var tAppW = 0;	//I need it to calculate the margin left for the widths
			var tAppH = 0;	//I need it to calculate the margin right for the widths
			var arr = new Array();
			var delay = new Array();
			var order = new Array();
			while(cycle < blocks){
				arr.push(cycle);
				delay.push(cycle);
				elem.append('<div class="diapoappended" style="display:none; overflow:hidden; position:absolute; z-index:1000" />');
				var tApp = $('.diapoappended:eq('+cycle+')');
				tApp.find('iframe').remove();
				if(fx=='scrollLeft' || fx=='scrollRight' || fx=='scrollTop' || fx=='scrollBottom' || fx=='scrollHorz'){
					selector.eq(i).clone().show().appendTo(tApp);
				} else {
					if(slideOn=='next'){
						selector.eq(i).clone().show().appendTo(tApp);
					} else {
						selector.eq(vis).clone().show().appendTo(tApp);
					}
				}

				if(cycle%cols<leftScrap){
					addLeft = 1;
				} else {
					addLeft = 0;
				}
				if(cycle%cols==0){
					tAppW = 0;
				}
				if(Math.floor(cycle/cols)<topScrap){
					addTop = 1;
				} else {
					addTop = 0;
				}
				tApp.css({
					'height': Math.floor((h/rows)+addTop+1),
					'left': tAppW,
					'top': tAppH,
					'width': Math.floor((w/cols)+addLeft+1)
				});
				$('> '+opts.selector, tApp).not('#pix_canvas').not('#pix_canvas_wrap').not('#pix_next').not('#pix_prev').not('#pix_commands').css({
					'height': h,
					'margin-left': '-'+tAppW+'px',
					'margin-top': '-'+tAppH+'px',
					'width': w
				});
				tAppW = tAppW+tApp.width()-1;
				if(cycle%cols==cols-1){
					tAppH = tAppH + tApp.height() - 1;
				}
				cycle++;
			}
			

			
			switch(fx){
				case 'curtainTopLeft':
						break;
				case 'curtainBottomLeft':
						break;
				case 'curtainSliceLeft':
						break;
				case 'curtainTopRight':
					arr = arr.reverse();
						break;
				case 'curtainBottomRight':
					arr = arr.reverse();
						break;
				case 'curtainSliceRight':
					arr = arr.reverse();
						break;
				case 'blindCurtainTopLeft':
						break;
				case 'blindCurtainBottomLeft':
					arr = arr.reverse();
						break;
				case 'blindCurtainSliceTop':
						break;
				case 'blindCurtainTopRight':
						break;
				case 'blindCurtainBottomRight':
					arr = arr.reverse();
						break;
				case 'blindCurtainSliceBottom':
					arr = arr.reverse();
						break;
				case 'stampede':
					arr = shuffle(arr);
						break;
				case 'mosaic':
						break;
				case 'mosaicReverse':
					arr = arr.reverse();
						break;
				case 'mosaicRandom':
					arr = shuffle(arr);
						break;
				case 'mosaicSpiral':
					var rows2 = rows/2, x, y, z, n=0;
						for (z = 0; z < rows2; z++){
							y = z;
							for (x = z; x < cols - z - 1; x++) {
								order[n++] = y * cols + x;
							}
							x = cols - z - 1;
							for (y = z; y < rows - z - 1; y++) {
								order[n++] = y * cols + x;
							}
							y = rows - z - 1;
							for (x = cols - z - 1; x > z; x--) {
								order[n++] = y * cols + x;
							}
							x = z;
							for (y = rows - z - 1; y > z; y--) {
								order[n++] = y * cols + x;
							}
						}
						
						arr = order;

						break;
				case 'mosaicSpiralReverse':
					var rows2 = rows/2, x, y, z, n=blocks-1;
						for (z = 0; z < rows2; z++){
							y = z;
							for (x = z; x < cols - z - 1; x++) {
								order[n--] = y * cols + x;
							}
							x = cols - z - 1;
							for (y = z; y < rows - z - 1; y++) {
								order[n--] = y * cols + x;
							}
							y = rows - z - 1;
							for (x = cols - z - 1; x > z; x--) {
								order[n--] = y * cols + x;
							}
							x = z;
							for (y = rows - z - 1; y > z; y--) {
								order[n--] = y * cols + x;
							}
						}

						arr = order;
						
						break;
				case 'topLeftBottomRight':
					for (var y = 0; y < rows; y++)
					for (var x = 0; x < cols; x++) {
						order.push(x + y);
					}
						delay = order;
						break;
				case 'bottomRightTopLeft':
					for (var y = 0; y < rows; y++)
					for (var x = 0; x < cols; x++) {
						order.push(x + y);
					}
						delay = order.reverse();
						break;
				case 'bottomLeftTopRight':
					for (var y = rows; y > 0; y--)
					for (var x = 0; x < cols; x++) {
						order.push(x + y);
					}
						delay = order;
						break;
				case 'topRightBottomLeft':
					for (var y = 0; y < rows; y++)
					for (var x = cols; x > 0; x--) {
						order.push(x + y);
					}
						delay = order;
						break;
			}
			
			
						
			$.each(arr, function(index, value) {

				if(value%cols<leftScrap){
					addLeft = 1;
				} else {
					addLeft = 0;
				}
				if(value%cols==0){
					tAppW = 0;
				}
				if(Math.floor(value/cols)<topScrap){
					addTop = 1;
				} else {
					addTop = 0;
				}
				
				$('.interval').text(fx);
			
				switch(fx){
					case 'simpleFade':
						height = h;
						width = w;
							break;
					case 'curtainTopLeft':
						height = 0,
						width = Math.floor((w/cols)+addLeft+1),
						marginTop = '-'+Math.floor((h/rows)+addTop+1)+'px';
							break;
					case 'curtainTopRight':
						height = 0,
						width = Math.floor((w/cols)+addLeft+1),
						marginTop = '-'+Math.floor((h/rows)+addTop+1)+'px';
							break;
					case 'curtainBottomLeft':
						height = 0,
						width = Math.floor((w/cols)+addLeft+1),
						marginTop = Math.floor((h/rows)+addTop+1)+'px';
							break;
					case 'curtainBottomRight':
						height = 0,
						width = Math.floor((w/cols)+addLeft+1),
						marginTop = Math.floor((h/rows)+addTop+1)+'px';
							break;
					case 'curtainSliceLeft':
						height = 0,
						width = Math.floor((w/cols)+addLeft+1);
						if(value%2==0){
							marginTop = Math.floor((h/rows)+addTop+1)+'px';					
						} else {
							marginTop = '-'+Math.floor((h/rows)+addTop+1)+'px';					
						}
							break;
					case 'curtainSliceRight':
						height = 0,
						width = Math.floor((w/cols)+addLeft+1);
						if(value%2==0){
							marginTop = Math.floor((h/rows)+addTop+1)+'px';					
						} else {
							marginTop = '-'+Math.floor((h/rows)+addTop+1)+'px';					
						}
							break;
					case 'blindCurtainTopLeft':
						height = Math.floor((h/rows)+addTop+1),
						width = 0,
						marginLeft = '-'+Math.floor((w/cols)+addLeft+1)+'px';
							break;
					case 'blindCurtainTopRight':
						height = Math.floor((h/rows)+addTop+1),
						width = 0,
						marginLeft = Math.floor((w/cols)+addLeft+1)+'px';
							break;
					case 'blindCurtainBottomLeft':
						height = Math.floor((h/rows)+addTop+1),
						width = 0,
						marginLeft = '-'+Math.floor((w/cols)+addLeft+1)+'px';
							break;
					case 'blindCurtainBottomRight':
						height = Math.floor((h/rows)+addTop+1),
						width = 0,
						marginLeft = Math.floor((w/cols)+addLeft+1)+'px';
							break;
					case 'blindCurtainSliceBottom':
						height = Math.floor((h/rows)+addTop+1),
						width = 0;
						if(value%2==0){
							marginLeft = '-'+Math.floor((w/cols)+addLeft+1)+'px';
						} else {
							marginLeft = Math.floor((w/cols)+addLeft+1)+'px';
						}
							break;
					case 'blindCurtainSliceTop':
						height = Math.floor((h/rows)+addTop+1),
						width = 0;
						if(value%2==0){
							marginLeft = '-'+Math.floor((w/cols)+addLeft+1)+'px';
						} else {
							marginLeft = Math.floor((w/cols)+addLeft+1)+'px';
						}
							break;
					case 'stampede':
						height = 0;
						width = 0;					
						marginLeft = (w*0.2)*(((index)%cols)-(cols-(Math.floor(cols/2))))+'px';					
						marginTop = (h*0.2)*((Math.floor(index/cols)+1)-(rows-(Math.floor(rows/2))))+'px';	
							break;
					case 'mosaic':
						height = 0;
						width = 0;					
							break;
					case 'mosaicReverse':
						height = 0;
						width = 0;					
						marginLeft = Math.floor((w/cols)+addLeft+1)+'px';					
						marginTop = Math.floor((h/rows)+addTop+1)+'px';					
							break;
					case 'mosaicRandom':
						height = 0;
						width = 0;					
						marginLeft = Math.floor((w/cols)+addLeft+1)*0.5+'px';					
						marginTop = Math.floor((h/rows)+addTop+1)*0.5+'px';					
							break;
					case 'mosaicSpiral':
						height = 0;
						width = 0;
						marginLeft = Math.floor((w/cols)+addLeft+1)*0.5+'px';					
						marginTop = Math.floor((h/rows)+addTop+1)*0.5+'px';					
							break;
					case 'mosaicSpiralReverse':
						height = 0;
						width = 0;
						marginLeft = Math.floor((w/cols)+addLeft+1)*0.5+'px';					
						marginTop = Math.floor((h/rows)+addTop+1)*0.5+'px';					
							break;
					case 'topLeftBottomRight':
						height = 0;
						width = 0;					
							break;
					case 'bottomRightTopLeft':
						height = 0;
						width = 0;					
						marginLeft = Math.floor((w/cols)+addLeft+1)+'px';					
						marginTop = Math.floor((h/rows)+addTop+1)+'px';					
							break;
					case 'bottomLeftTopRight':
						height = 0;
						width = 0;					
						marginLeft = 0;					
						marginTop = Math.floor((h/rows)+addTop+1)+'px';					
							break;
					case 'topRightBottomLeft':
						height = 0;
						width = 0;					
						marginLeft = Math.floor((w/cols)+addLeft+1)+'px';					
						marginTop = '-'+Math.floor((h/rows)+addTop+1)+'px';					
							break;
					case 'scrollRight':
						height = h;
						width = w;
						marginLeft = -w;					
							break;
					case 'scrollLeft':
						height = h;
						width = w;
						marginLeft = w;					
							break;
					case 'scrollTop':
						height = h;
						width = w;
						marginTop = h;					
							break;
					case 'scrollBottom':
						height = h;
						width = w;
						marginTop = -h;					
							break;
					case 'scrollHorz':
						height = h;
						width = w;
						if(vis==0 && i==amountSlide-1) {
							marginLeft = -w;	
						} else if(vis<i  || (vis==amountSlide-1 && i==0)) {
							marginLeft = w;	
						} else {
							marginLeft = -w;	
						}
							break;
					}
					
			
				var tApp = $('.diapoappended:eq('+value+')');
								
				start = new Date().valueOf()+(opts.transPeriod+difference);
				
				if(typeof u !== 'undefined'){
					clearInterval(u);
					setTimeout(canvasLoader,opts.transPeriod+difference);
				}
				
				
				function diapoeased() {
					$(this).addClass('diapoeased');
					if($('.diapoeased').length==blocks){
						opts.onEnterSlide.call(this);
						
						$('.fromLeft, .fromRight, .fromTop, .fromBottom, .fadeIn').each(function(){
							$(this).css('visibility','hidden');
						});
		
						selector.eq(i).show().css('z-index','999').addClass('diapocurrent');
						selector.eq(vis).css('z-index','1').removeClass('diapocurrent');
						var lMoveIn = selector.eq(i).find('.fromLeft, .fromRight, .fromTop, .fromBottom, .fadeIn').length;
						
						if (lMoveIn!=0){
							$('.diapocurrent .fromLeft, .diapocurrent .fromRight, .diapocurrent .fromTop, .diapocurrent .fromBottom, .diapocurrent .fadeIn').each(function(){
								if($(this).attr('data-easing')!=''){
									var easeMove = $(this).attr('data-easing');
								} else {
									var easeMove = easing;
								}
								var t = $(this);
								var wMoveIn = t.width();
								var hMoveIn = t.outerHeight();
								t.css('width',wMoveIn);
								var pos = t.position();
								var left = pos.left;
								var top = pos.top;
								var tClass = t.attr('class');
								var ind = t.index();
								var hRel = t.parents('.pix_relativize').height();
								var wRel = t.parents('.pix_relativize').width();
								if(tClass.indexOf("fromLeft") != -1) {
									t.css({'left':'-'+wRel+'px','right':'auto'});
									t.css('visibility','visible').delay((time/lMoveIn)*(0.1*(ind-1))).animate({'left':pos.left},(time/lMoveIn)*0.2,easeMove);
								} else if(tClass.indexOf("fromRight") != -1) {
									t.css({'left':wRel+'px','right':'auto'});
									t.css('visibility','visible').delay((time/lMoveIn)*(0.1*(ind-1))).animate({'left':pos.left},(time/lMoveIn)*0.2,easeMove);
								} else if(tClass.indexOf("fromTop") != -1) {
									t.css({'top':'-'+hRel+'px','bottom':'auto'});
									t.css('visibility','visible').delay((time/lMoveIn)*(0.1*(ind-1))).animate({'top':pos.top},(time/lMoveIn)*0.2,easeMove);
								} else if(tClass.indexOf("fromBottom") != -1) {
									t.css({'top':hRel+'px','bottom':'auto'});
									t.css('visibility','visible').delay((time/lMoveIn)*(0.1*(ind-1))).animate({'top':pos.top},(time/lMoveIn)*0.2,easeMove);
								} else if(tClass.indexOf("fadeIn") != -1) {
									t.animate({opacity:0},0).css('visibility','visible').delay((time/lMoveIn)*(0.1*(ind-1))).animate({opacity:1},(time/lMoveIn)*0.2,easeMove);
								}
							});
						}

						
						if(pagination==true){
							$('#pix_pag li').removeClass('diapocurrent');
							$('#pix_pag li').eq(i).addClass('diapocurrent');
						}
						
						$('.diapoappended').remove();
						elem.removeClass('diaposliding');	//I remove this class, that means the effect is finished
							selector.eq(vis).hide();

							$('#pix_canvas').animate({opacity:opts.loaderOpacity},400);
							u = setInterval(
								function(){
									if (($.browser.msie && $.browser.version < 9) || opts.loader == 'bar') {
										if(rad<=1 && !elem.hasClass('stopped')){
											rad = rad+0.01;
										} else if (rad<=1 && (elem.hasClass('stopped'))){
											rad = rad;
										} else {
											if(!elem.hasClass('stopped'))
												imgFake();
												clearInterval(u);
												$('#pix_canvas').animate({opacity:0},200,function(){
													setTimeout(canvasLoader,opts.transPeriod+difference);
													nextSlide();
												});
										}
										canvas.css({'width':(w*rad)});
									} else {
										radNew = rad;
										ctx.clearRect(0,0,opts.pieDiameter,opts.pieDiameter);
										ctx.globalCompositeOperation = 'destination-over';
										ctx.beginPath();
										ctx.arc((opts.pieDiameter)/2, (opts.pieDiameter)/2, (opts.pieDiameter)/2-opts.pieStroke,0,Math.PI*2,false);
										ctx.lineWidth = opts.pieStroke;
										ctx.strokeStyle = opts.loaderBgColor;
										ctx.stroke();
										ctx.closePath();
										ctx.globalCompositeOperation = 'source-over';
										ctx.beginPath();
										ctx.arc((opts.pieDiameter)/2, (opts.pieDiameter)/2, (opts.pieDiameter)/2-opts.pieStroke,0,Math.PI*2*radNew,false);
										ctx.lineWidth = opts.pieStroke-4;
										ctx.strokeStyle = opts.loaderColor;
										ctx.stroke();
										ctx.closePath();
												
										if(rad<=1 && !elem.hasClass('stopped')){
											rad = rad+0.01;
										} else if (rad<=1 && (elem.hasClass('stopped'))){
											rad = rad;
										} else {
											if(!elem.hasClass('stopped'))
												imgFake();
												clearInterval(u);
												$('#pix_canvas, #pix_canvas_wrap').animate({opacity:0},200,function(){
													setTimeout(canvasLoader,opts.transPeriod+difference);
													nextSlide(); 
												});
										}
									}
								},(time)*0.01
							);
						}

				}


				if(fx=='scrollLeft' || fx=='scrollRight' || fx=='scrollTop' || fx=='scrollBottom' || fx=='scrollHorz'){
					tApp.delay((((opts.transPeriod+difference)/blocks)*delay[index]*couples)*0.5).css({
							'display' : 'block',
							'height': height,
							'margin-left': marginLeft,
							'margin-top': marginTop,
							'width': width
						}).animate({
							'height': Math.floor((h/rows)+addTop+1),
							'margin-top' : 0,
							'margin-left' : 0,
							'width' : Math.floor((w/cols)+addLeft+1)
						},(opts.transPeriod-difference),easing,diapoeased);
					selector.eq(vis).delay((((opts.transPeriod+difference)/blocks)*delay[index]*couples)*0.5).animate({
							'margin-left': marginLeft*(-1),
							'margin-top': marginTop*(-1)
						},(opts.transPeriod-difference),easing,function(){
							jQuery(this).css({'margin-top' : 0,'margin-left' : 0});
						});
				} else {
					if(slideOn=='next'){
						tApp.delay((((opts.transPeriod+difference)/blocks)*delay[index]*couples)*0.5).css({
								'display' : 'block',
								'height': height,
								'margin-left': marginLeft,
								'margin-top': marginTop,
								'width': width,
								'opacity' : 0
							}).animate({
								'height': Math.floor((h/rows)+addTop+1),
								'margin-top' : 0,
								'margin-left' : 0,
								'opacity' : 1,
								'width' : Math.floor((w/cols)+addLeft+1)
							},(opts.transPeriod-difference),easing,diapoeased);
					} else {
						selector.eq(i).show().css('z-index','999').addClass('diapocurrent');
						selector.eq(vis).css('z-index','1').removeClass('diapocurrent');
						tApp.delay((((opts.transPeriod+difference)/blocks)*delay[index]*couples)*0.5).css({
								'display' : 'block',
								'height': Math.floor((h/rows)+addTop+1),
								'margin-top' : 0,
								'margin-left' : 0,
								'opacity' : 1,
								'width' : Math.floor((w/cols)+addLeft+1)
							}).animate({
								'height': height,
								'margin-left': marginLeft,
								'margin-top': marginTop,
								'width': width,
								'opacity' : 0
							},(opts.transPeriod-difference),easing,diapoeased);
					}
				}



				if(navigation==true){
					$('#pix_prev')[clickEv](function(){
						if(!elem.hasClass('diaposliding')){
							var idNum = parseFloat($('.diapocurrent').index());
							clearInterval(u);
							imgFake();
							$('#pix_canvas, #pix_canvas_wrap').animate({opacity:0},0);
							canvasLoader();
							if(idNum!=0){
								nextSlide(idNum);
							} else {
								nextSlide(amountSlide);
						   }
						}
					});
			
					$('#pix_next')[clickEv](function(){
						if(!elem.hasClass('diaposliding')){
							var idNum = parseFloat($('.diapocurrent').index()); 
							clearInterval(u);
							imgFake();
							$('#pix_canvas, #pix_canvas_wrap').animate({opacity:0},0);
							canvasLoader();
							if(idNum==amountSlide-1){
								nextSlide(1);
							} else {
								nextSlide(idNum+2);
						   }
						}
					});
				}


				if(isMobile()){
					elem.live('swipeleft',function(event){
						if(!elem.hasClass('diaposliding')){
							var idNum = parseFloat($('.diapocurrent').index()); 
							clearInterval(u);
							imgFake();
							$('#pix_canvas, #pix_canvas_wrap').animate({opacity:0},0);
							canvasLoader();
							if(idNum==amountSlide-1){
								nextSlide(1);
							} else {
								nextSlide(idNum+2);
						   }
						}
					});
					elem.live('swiperight',function(event){
						if(!elem.hasClass('diaposliding')){
							var idNum = parseFloat($('.diapocurrent').index());
							clearInterval(u);
							imgFake();
							$('#pix_canvas, #pix_canvas_wrap').animate({opacity:0},0);
							canvasLoader();
							if(idNum!=0){
								nextSlide(idNum);
							} else {
								nextSlide(amountSlide);
						   }
						}
					});
				}

				if(pagination==true){
					$('#pix_pag li')[clickEv](function(){
						if(!elem.hasClass('diaposliding')){
							var idNum = parseFloat($(this).index());
							var curNum = parseFloat($('.diapocurrent').index());
							if(idNum!=curNum) {
								clearInterval(u);
								imgFake();
								$('#pix_canvas, #pix_canvas_wrap').animate({opacity:0},0);
								canvasLoader();
								nextSlide(idNum+1);
							}
						}
					});
				}

				if(opts.thumbs==true){

					$('#pix_pag li .pix_thumb')[clickEv](function(){
						if(!elem.hasClass('diaposliding')){
							var idNum = parseFloat($(this).parents('li').index());
							var curNum = parseFloat($('.diapocurrent').index());
							if(idNum!=curNum) {
								clearInterval(u);
								imgFake();
								$('#pix_canvas, #pix_canvas_wrap').animate({opacity:0},0);
								canvasLoader();
								nextSlide(idNum+1);
							}
						}
					});
				}



			});
	}
}

})(jQuery);





/**
 * jquery.meio.mask.js
 * @author: fabiomcosta
 * @version: 1.1.3
 *
 * Created by Fabio M. Costa on 2008-09-16. Please report any bug at http://www.meiocodigo.com
 *
 * Copyright (c) 2008 Fabio M. Costa http://www.meiocodigo.com
 *
 * The MIT License (http://www.opensource.org/licenses/mit-license.php)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

(function($){
		
	var isIphone = (window.orientation != undefined),
		// browsers like firefox2 and before and opera doenst have the onPaste event, but the paste feature can be done with the onInput event.
		pasteEvent = (($.browser.opera || ($.browser.mozilla && parseFloat($.browser.version.substr(0,3)) < 1.9 ))? 'input': 'paste');
		
	$.event.special.paste = {
		setup: function() {
	    	if(this.addEventListener)
	        	this.addEventListener(pasteEvent, pasteHandler, false);
   			else if (this.attachEvent)
				this.attachEvent(pasteEvent, pasteHandler);
		},

		teardown: function() {
			if(this.removeEventListener)
	        	this.removeEventListener(pasteEvent, pasteHandler, false);
   			else if (this.detachEvent)
				this.detachEvent(pasteEvent, pasteHandler);
		}
	};
	
	// the timeout is set because we can't get the value from the input without it
	function pasteHandler(e){
		var self = this;
		e = $.event.fix(e || window.e);
		e.type = 'paste';
		// Execute the right handlers by setting the event type to paste
		setTimeout(function(){ $.event.handle.call(self, e); }, 1);
	};

	$.extend({
		mask : {
			
			// the mask rules. You may add yours!
			// number rules will be overwritten
			rules : {
				'z': /[a-z]/,
				'Z': /[A-Z]/,
				'a': /[a-zA-Z]/,
				'*': /[0-9a-zA-Z]/,
				'@': /[0-9a-zA-ZçÇáàãâéèêíìóòôõúùü]/
			},
			
			// these keys will be ignored by the mask.
			// all these numbers where obtained on the keydown event
			keyRepresentation : {
				8	: 'backspace',
				9	: 'tab',
				13	: 'enter',
				16	: 'shift',
				17	: 'control',
				18	: 'alt',
				27	: 'esc',
				33	: 'page up',
				34	: 'page down',
				35	: 'end',
				36	: 'home',
				37	: 'left',
				38	: 'up',
				39	: 'right',
				40	: 'down',
				45	: 'insert',
				46	: 'delete',
				116	: 'f5',
				123 : 'f12',
				224	: 'command'
			},
			
			iphoneKeyRepresentation : {
				10	: 'go',
				127	: 'delete'
			},
			
			signals : {
				'+' : '',
				'-' : '-'
			},
			
			// default settings for the plugin
			options : {
				attr: 'alt', // an attr to look for the mask name or the mask itself
				mask: null, // the mask to be used on the input
				type: 'fixed', // the mask of this mask
				maxLength: -1, // the maxLength of the mask
				defaultValue: '', // the default value for this input
				signal: false, // this should not be set, to use signal at masks put the signal you want ('-' or '+') at the default value of this mask.
							   // See the defined masks for a better understanding.
				
				textAlign: true, // use false to not use text-align on any mask (at least not by the plugin, you may apply it using css)
				selectCharsOnFocus: true, // select all chars from input on its focus
				autoTab: true, // auto focus the next form element when you type the mask completely
				setSize: false, // sets the input size based on the length of the mask (work with fixed and reverse masks only)
				fixedChars : '[(),.:/ -]', // fixed chars to be used on the masks. You may change it for your needs!
				
				onInvalid : function(){},
				onValid : function(){},
				onOverflow : function(){}
			},
			
			// masks. You may add yours!
			// Ex: $.fn.setMask.masks.msk = {mask: '999'}
			// and then if the 'attr' options value is 'alt', your input should look like:
			// <input type="text" name="some_name" id="some_name" alt="msk" />
			masks : {
				'phone'				: { mask : '(99) 9999-9999' },
				'phone-us'			: { mask : '(999) 999-9999' },
				'cpf'				: { mask : '999.999.999-99' }, // cadastro nacional de pessoa fisica
				'cnpj'				: { mask : '99.999.999/9999-99' },
				'date'				: { mask : '39/19/9999' }, //uk date
				'date-us'			: { mask : '19/39/9999' },
				'cep'				: { mask : '99999-999' },
				'time'				: { mask : '29:59' },
				'cc'				: { mask : '9999 9999 9999 9999' }, //credit card mask
				'integer'			: { mask : '999.999.999.999', type : 'reverse' },				
				'decimal'			: { mask : '99,999.999.999.999', type : 'reverse', defaultValue : '000' },
				'decimal-us'		: { mask : '99.999,999,999,999', type : 'reverse', defaultValue : '000' },
				'signed-decimal'	: { mask : '99,999.999.999.999', type : 'reverse', defaultValue : '+000' },
				'signed-decimal-us' : { mask : '99,999.999.999.999', type : 'reverse', defaultValue : '+000' }
			},
			
			init : function(){
				// if has not inited...
				if( !this.hasInit ){

					var self = this, i,
						keyRep = (isIphone)? this.iphoneKeyRepresentation: this.keyRepresentation;
						
					this.ignore = false;
			
					// constructs number rules
					for(i=0; i<=9; i++) this.rules[i] = new RegExp('[0-'+i+']');
				
					this.keyRep = keyRep;
					// ignore keys array creation for iphone or the normal ones
					this.ignoreKeys = [];
					$.each(keyRep,function(key){
						self.ignoreKeys.push( parseInt(key) );
					});
					
					this.hasInit = true;
				}
			},
			
			set: function(el,options){
				
				var maskObj = this,
					$el = $(el),
					mlStr = 'maxLength';
				
				options = options || {};
				this.init();
				
				return $el.each(function(){
					
					if(options.attr) maskObj.options.attr = options.attr;
					
					var $this = $(this),
						o = $.extend({}, maskObj.options),
						attrValue = $this.attr(o.attr),
						tmpMask = '';
						
					// then we look for the 'attr' option
					tmpMask = (typeof options == 'string')? options: (attrValue != '')? attrValue: null;
					if(tmpMask) o.mask = tmpMask;
					
					// then we see if it's a defined mask
					if(maskObj.masks[tmpMask]) o = $.extend(o, maskObj.masks[tmpMask]);
					
					// then it looks if the options is an object, if it is we will overwrite the actual options
					if(typeof options == 'object' && options.constructor != Array) o = $.extend(o, options);
					
					//then we look for some metadata on the input
					if($.metadata) o = $.extend(o, $this.metadata());
					
					if(o.mask != null){
						
						if($this.data('mask')) maskObj.unset($this);
						
						var defaultValue = o.defaultValue,
							reverse = (o.type=='reverse'),
							fixedCharsRegG = new RegExp(o.fixedChars, 'g');
						
						if(o.maxLength == -1) o.maxLength = $this.attr(mlStr);
						
						o = $.extend({}, o,{
							fixedCharsReg: new RegExp(o.fixedChars),
							fixedCharsRegG: fixedCharsRegG,
							maskArray: o.mask.split(''),
							maskNonFixedCharsArray: o.mask.replace(fixedCharsRegG, '').split('')
						});
						
						//setSize option (this is not removed from the input (while removing the mask) since this would be kind of funky)
						if((o.type=='fixed' || reverse) && o.setSize && !$this.attr('size')) $this.attr('size', o.mask.length);
						
						//sets text-align right for reverse masks
						if(reverse && o.textAlign) $this.css('text-align', 'right');
						
						if(this.value!='' || defaultValue!=''){
							// apply mask to the current value of the input or to the default value
							var val = maskObj.string((this.value!='')? this.value: defaultValue, o);
							//setting defaultValue fixes the reset button from the form
							this.defaultValue = val;
							$this.val(val);
						}
						
						// compatibility patch for infinite mask, that is now repeat
						if(o.type=='infinite') o.type = 'repeat';
						
						$this.data('mask', o);
						
						// removes the maxLength attribute (it will be set again if you use the unset method)
						$this.removeAttr(mlStr);
						
						// setting the input events
						$this.bind('keydown.mask', {func:maskObj._onKeyDown, thisObj:maskObj}, maskObj._onMask)
							.bind('keypress.mask', {func:maskObj._onKeyPress, thisObj:maskObj}, maskObj._onMask)
							.bind('keyup.mask', {func:maskObj._onKeyUp, thisObj:maskObj}, maskObj._onMask)
							.bind('paste.mask', {func:maskObj._onPaste, thisObj:maskObj}, maskObj._onMask)
							.bind('focus.mask', maskObj._onFocus)
							.bind('blur.mask', maskObj._onBlur)
							.bind('change.mask', maskObj._onChange);
					}
				});
			},
			
			//unsets the mask from el
			unset : function(el){
				var $el = $(el);
				
				return $el.each(function(){
					var $this = $(this);
					if($this.data('mask')){
						var maxLength = $this.data('mask').maxLength;
						if(maxLength != -1) $this.attr('maxLength', maxLength);
						$this.unbind('.mask')
							.removeData('mask');
					}
				});
			},
			
			//masks a string
			string : function(str, options){
				this.init();
				var o={};
				if(typeof str != 'string') str = String(str);
				switch(typeof options){
					case 'string':
						// then we see if it's a defined mask	
						if(this.masks[options]) o = $.extend(o, this.masks[options]);
						else o.mask = options;
						break;
					case 'object':
						o = options;
				}
				if(!o.fixedChars) o.fixedChars = this.options.fixedChars;

				var fixedCharsReg = new RegExp(o.fixedChars),
					fixedCharsRegG = new RegExp(o.fixedChars, 'g');
					
				// insert signal if any
				if( (o.type=='reverse') && o.defaultValue ){
					if( typeof this.signals[o.defaultValue.charAt(0)] != 'undefined' ){
						var maybeASignal = str.charAt(0);
						o.signal = (typeof this.signals[maybeASignal] != 'undefined') ? this.signals[maybeASignal] : this.signals[o.defaultValue.charAt(0)];
						o.defaultValue = o.defaultValue.substring(1);
					}
				}
				
				return this.__maskArray(str.split(''),
							o.mask.replace(fixedCharsRegG, '').split(''),
							o.mask.split(''),
							o.type,
							o.maxLength,
							o.defaultValue,
							fixedCharsReg,
							o.signal);
			},
			
			// all the 3 events below are here just to fix the change event on reversed masks.
			// It isn't fired in cases that the keypress event returns false (needed).
			_onFocus: function(e){
				var $this = $(this), dataObj = $this.data('mask');
				dataObj.inputFocusValue = $this.val();
				dataObj.changed = false;
				if(dataObj.selectCharsOnFocus) $this.select();
			},
			
			_onBlur: function(e){
				var $this = $(this), dataObj = $this.data('mask');
				if(dataObj.inputFocusValue != $this.val() && !dataObj.changed)
					$this.trigger('change');
			},
			
			_onChange: function(e){
				$(this).data('mask').changed = true;
			},
			
			_onMask : function(e){
				var thisObj = e.data.thisObj,
					o = {};
				o._this = e.target;
				o.$this = $(o._this);
				// if the input is readonly it does nothing
				if(o.$this.attr('readonly')) return true;
				o.data = o.$this.data('mask');
				o[o.data.type] = true;
				o.value = o.$this.val();
				o.nKey = thisObj.__getKeyNumber(e);
				o.range = thisObj.__getRange(o._this);
				o.valueArray = o.value.split('');
				return e.data.func.call(thisObj, e, o);
			},
			
			_onKeyDown : function(e,o){
				// lets say keypress at desktop == keydown at iphone (theres no keypress at iphone)
				this.ignore = $.inArray(o.nKey, this.ignoreKeys) > -1 || e.ctrlKey || e.metaKey || e.altKey;
				if(this.ignore){
					var rep = this.keyRep[o.nKey];
					o.data.onValid.call(o._this, rep? rep: '', o.nKey);
				}
				return isIphone ? this._keyPress(e, o) : true;
			},
			
			_onKeyUp : function(e, o){
				//9=TAB_KEY 16=SHIFT_KEY
				//this is a little bug, when you go to an input with tab key
				//it would remove the range selected by default, and that's not a desired behavior
				if(o.nKey==9 || o.nKey==16) return true;
				
				if(o.data.type=='repeat'){
					this.__autoTab(o);
					return true;
				}

				return this._onPaste(e, o);
			},
			
			_onPaste : function(e,o){
				// changes the signal at the data obj from the input
				if(o.reverse) this.__changeSignal(e.type, o);
				
				var $thisVal = this.__maskArray(
					o.valueArray,
					o.data.maskNonFixedCharsArray,
					o.data.maskArray,
					o.data.type,
					o.data.maxLength,
					o.data.defaultValue,
					o.data.fixedCharsReg,
					o.data.signal
				);
				
				o.$this.val( $thisVal );
				// this makes the caret stay at first position when 
				// the user removes all values in an input and the plugin adds the default value to it (if it haves one).
				if( !o.reverse && o.data.defaultValue.length && (o.range.start==o.range.end) )
					this.__setRange(o._this, o.range.start, o.range.end);
					
				//fix so ie's and safari's caret won't go to the end of the input value.
				if( ($.browser.msie || $.browser.safari) && !o.reverse)
					this.__setRange(o._this,o.range.start,o.range.end);
				
				if(this.ignore) return true;
				
				this.__autoTab(o);
				return true;
			},
			
			_onKeyPress: function(e, o){
				
				if(this.ignore) return true;
				
				// changes the signal at the data obj from the input
				if(o.reverse) this.__changeSignal(e.type, o);
				
				var c = String.fromCharCode(o.nKey),
					rangeStart = o.range.start,
					rawValue = o.value,
					maskArray = o.data.maskArray;
				
				if(o.reverse){
					 	// the input value from the range start to the value start
					var valueStart = rawValue.substr(0, rangeStart),
						// the input value from the range end to the value end
						valueEnd = rawValue.substr(o.range.end, rawValue.length);
					
					rawValue = valueStart+c+valueEnd;
					//necessary, if not decremented you will be able to input just the mask.length-1 if signal!=''
					//ex: mask:99,999.999.999 you will be able to input 99,999.999.99
					if(o.data.signal && (rangeStart-o.data.signal.length > 0)) rangeStart-=o.data.signal.length;
				}

				var valueArray = rawValue.replace(o.data.fixedCharsRegG, '').split(''),
					// searches for fixed chars begining from the range start position, till it finds a non fixed
					extraPos = this.__extraPositionsTill(rangeStart, maskArray, o.data.fixedCharsReg);
				
				o.rsEp = rangeStart+extraPos;
				
				if(o.repeat) o.rsEp = 0;
				
				// if the rule for this character doesnt exist (value.length is bigger than mask.length)
				// added a verification for maxLength in the case of the repeat type mask
				if( !this.rules[maskArray[o.rsEp]] || (o.data.maxLength != -1 && valueArray.length >= o.data.maxLength && o.repeat)){
					// auto focus on the next input of the current form
					o.data.onOverflow.call(o._this, c, o.nKey);
					return false;
				}
				
				// if the new character is not obeying the law... :P
				else if( !this.rules[maskArray[o.rsEp]].test( c ) ){
					o.data.onInvalid.call(o._this, c, o.nKey);
					return false;
				}
				
				else o.data.onValid.call(o._this, c, o.nKey);
				
				var $thisVal = this.__maskArray(
					valueArray,
					o.data.maskNonFixedCharsArray,
					maskArray,
					o.data.type,
					o.data.maxLength,
					o.data.defaultValue,
					o.data.fixedCharsReg,
					o.data.signal,
					extraPos
				);
				
				o.$this.val( $thisVal );
				
				return (o.reverse)? this._keyPressReverse(e, o): (o.fixed)? this._keyPressFixed(e, o): true;
			},
			
			_keyPressFixed: function(e, o){

				if(o.range.start==o.range.end){
					// the 0 thing is cause theres a particular behavior i wasnt liking when you put a default
					// value on a fixed mask and you select the value from the input the range would go to the
					// end of the string when you enter a char. with this it will overwrite the first char wich is a better behavior.
					// opera fix, cant have range value bigger than value length, i think it loops thought the input value...
					if((o.rsEp==0 && o.value.length==0) || o.rsEp < o.value.length)
						this.__setRange(o._this, o.rsEp, o.rsEp+1);	
				}
				else
					this.__setRange(o._this, o.range.start, o.range.end);
					
				return true;
			},
			
			_keyPressReverse: function(e, o){
				//fix for ie
				//this bug was pointed by Pedro Martins
				//it fixes a strange behavior that ie was having after a char was inputted in a text input that
				//had its content selected by any range 
				if($.browser.msie && ((o.range.start==0 && o.range.end==0) || o.range.start != o.range.end ))
					this.__setRange(o._this, o.value.length);
				return false;
			},
			
			__autoTab: function(o){
				if(o.data.autoTab
					&& (
						(
							o.$this.val().length >= o.data.maskArray.length 
							&& !o.repeat 
						) || (
							o.data.maxLength != -1
							&& o.valueArray.length >= o.data.maxLength
							&& o.repeat
						)
					)
				){
					var nextEl = this.__getNextInput(o._this, o.data.autoTab);
					if(nextEl){
						o.$this.trigger('blur');
						nextEl.focus().select();
					}
				}
			},
			
			// changes the signal at the data obj from the input			
			__changeSignal : function(eventType,o){
				if(o.data.signal!==false){
					var inputChar = (eventType=='paste')? o.value.charAt(0): String.fromCharCode(o.nKey);
					if( this.signals && (typeof this.signals[inputChar] != 'undefined') ){
						o.data.signal = this.signals[inputChar];
					}
				}
			},
			
			__getKeyNumber : function(e){
				return (e.charCode||e.keyCode||e.which);
			},
			
			// this function is totaly specific to be used with this plugin, youll never need it
			// it gets the array representing an unmasked string and masks it depending on the type of the mask
			__maskArray : function(valueArray, maskNonFixedCharsArray, maskArray, type, maxlength, defaultValue, fixedCharsReg, signal, extraPos){
				if(type == 'reverse') valueArray.reverse();
				valueArray = this.__removeInvalidChars(valueArray, maskNonFixedCharsArray, type=='repeat'||type=='infinite');
				if(defaultValue) valueArray = this.__applyDefaultValue.call(valueArray, defaultValue);
				valueArray = this.__applyMask(valueArray, maskArray, extraPos, fixedCharsReg);
				switch(type){
					case 'reverse':
						valueArray.reverse();
						return (signal || '')+valueArray.join('').substring(valueArray.length-maskArray.length);
					case 'infinite': case 'repeat':
						var joinedValue = valueArray.join('');
						return (maxlength != -1 && valueArray.length >= maxlength)? joinedValue.substring(0, maxlength): joinedValue;
					default:
						return valueArray.join('').substring(0, maskArray.length);
				}
				return '';
			},
			
			// applyes the default value to the result string
			__applyDefaultValue : function(defaultValue){
				var defLen = defaultValue.length,thisLen = this.length,i;
				//removes the leading chars
				for(i=thisLen-1;i>=0;i--){
					if(this[i]==defaultValue.charAt(0)) this.pop();
					else break;
				}
				// apply the default value
				for(i=0;i<defLen;i++) if(!this[i])
					this[i] = defaultValue.charAt(i);
					
				return this;
			},
			
			// Removes values that doesnt match the mask from the valueArray
			// Returns the array without the invalid chars.
			__removeInvalidChars : function(valueArray, maskNonFixedCharsArray, repeatType){
				// removes invalid chars
				for(var i=0, y=0; i<valueArray.length; i++ ){
					if( maskNonFixedCharsArray[y] &&
						this.rules[maskNonFixedCharsArray[y]] &&
						!this.rules[maskNonFixedCharsArray[y]].test(valueArray[i]) ){
							valueArray.splice(i,1);
							if(!repeatType) y--;
							i--;
					}
					if(!repeatType) y++;
				}
				return valueArray;
			},
			
			// Apply the current input mask to the valueArray and returns it. 
			__applyMask : function(valueArray, maskArray, plus, fixedCharsReg){
				if( typeof plus == 'undefined' ) plus = 0;
				// apply the current mask to the array of chars
				for(var i=0; i<valueArray.length+plus; i++ ){
					if( maskArray[i] && fixedCharsReg.test(maskArray[i]) )
						valueArray.splice(i, 0, maskArray[i]);
				}
				return valueArray;
			},
			
			// searches for fixed chars begining from the range start position, till it finds a non fixed
			__extraPositionsTill : function(rangeStart, maskArray, fixedCharsReg){
				var extraPos = 0;
				while(fixedCharsReg.test(maskArray[rangeStart++])){
					extraPos++;
				}
				return extraPos;
			},
			
			__getNextInput: function(input, selector){
				var formEls = input.form.elements,
					initialInputIndex = $.inArray(input, formEls) + 1,
					$input = null,
					i;
				// look for next input on the form of the pased input
				for(i = initialInputIndex; i < formEls.length; i++){
					$input = $(formEls[i]);
					if(this.__isNextInput($input, selector))
						return $input;
				}
					
				var forms = document.forms,
					initialFormIndex = $.inArray(input.form, forms) + 1,
					y, tmpFormEls = null;
				// look for the next forms for the next input
				for(y = initialFormIndex; y < forms.length; y++){
					tmpFormEls = forms[y].elements;
					for(i = 0; i < tmpFormEls.length; i++){
						$input = $(tmpFormEls[i]);
						if(this.__isNextInput($input, selector))
							return $input;
					}
				}
				return null;
			},
			
			__isNextInput: function($formEl, selector){
				var formEl = $formEl.get(0);
				return formEl
					&& (formEl.offsetWidth > 0 || formEl.offsetHeight > 0)
					&& formEl.nodeName != 'FIELDSET'
					&& (selector === true || (typeof selector == 'string' && $formEl.is(selector)));
			},
			
			// http://www.bazon.net/mishoo/articles.epl?art_id=1292
			__setRange : function(input, start, end) {
				if(typeof end == 'undefined') end = start;
				if (input.setSelectionRange){
					input.setSelectionRange(start, end);
				}
				else{
					// assumed IE
					var range = input.createTextRange();
					range.collapse();
					range.moveStart('character', start);
					range.moveEnd('character', end - start);
					range.select();
				}
			},
			
			// adaptation from http://digitarald.de/project/autocompleter/
			__getRange : function(input){
				if (!$.browser.msie) return {start: input.selectionStart, end: input.selectionEnd};
				var pos = {start: 0, end: 0},
					range = document.selection.createRange();
				pos.start = 0 - range.duplicate().moveStart('character', -100000);
				pos.end = pos.start + range.text.length;
				return pos;
			},
			
			//deprecated
			unmaskedVal : function(el){
				return $(el).val().replace($.mask.fixedCharsRegG, '');
			}
			
		}
	});
	
	$.fn.extend({
		setMask : function(options){
			return $.mask.set(this, options);
		},
		unsetMask : function(){
			return $.mask.unset(this);
		},
		//deprecated
		unmaskedVal : function(){
			return $.mask.unmaskedVal(this[0]);
		}
	});
})(jQuery);


