/*! jCarousel - Riding carousels with jQuery */
(function(g){
    var q={
        vertical:!1,
        rtl:!1,
        start:1,
        offset:1,
        size:null,
        scroll:3,
        visible:null,
        animation:"normal",
        easing:"swing",
        auto:0,
        wrap:null,
        initCallback:null,
        setupCallback:null,
        reloadCallback:null,
        itemLoadCallback:null,
        itemFirstInCallback:null,
        itemFirstOutCallback:null,
        itemLastInCallback:null,
        itemLastOutCallback:null,
        itemVisibleInCallback:null,
        itemVisibleOutCallback:null,
        animationStepCallback:null,
        buttonNextHTML:"<div></div>",
        buttonPrevHTML:"<div></div>",
        buttonNextEvent:"click",
        buttonPrevEvent:"click", 
        buttonNextCallback:null,
        buttonPrevCallback:null,
        itemFallbackDimension:null
    },m=!1;
    g(window).bind("load.jcarousel",function(){
        m=!0
        });
    g.jcarousel=function(a,c){
        this.options=g.extend({},q,c||{});
        this.autoStopped=this.locked=!1;
        this.buttonPrevState=this.buttonNextState=this.buttonPrev=this.buttonNext=this.list=this.clip=this.container=null;
        if(!c||c.rtl===void 0)this.options.rtl=(g(a).attr("dir")||g("html").attr("dir")||"").toLowerCase()=="rtl";
        this.wh=!this.options.vertical?"width":"height";
        this.lt=!this.options.vertical? this.options.rtl?"right":"left":"top";
        for(var b="",d=a.className.split(" "),f=0;f<d.length;f++)if(d[f].indexOf("jcarousel-skin")!=-1){
            g(a).removeClass(d[f]);
            b=d[f];
            break
        }
        a.nodeName.toUpperCase()=="UL"||a.nodeName.toUpperCase()=="OL"?(this.list=g(a),this.clip=this.list.parents(".jcarousel-clip"),this.container=this.list.parents(".jcarousel-container")):(this.container=g(a),this.list=this.container.find("ul,ol").eq(0),this.clip=this.container.find(".jcarousel-clip"));
        if(this.clip.size()===0)this.clip= this.list.wrap("<div></div>").parent();
        if(this.container.size()===0)this.container=this.clip.wrap("<div></div>").parent();
        b!==""&&this.container.parent()[0].className.indexOf("jcarousel-skin")==-1&&this.container.wrap('<div class=" '+b+'"></div>');
        this.buttonPrev=g(".jcarousel-prev",this.container);
        if(this.buttonPrev.size()===0&&this.options.buttonPrevHTML!==null)this.buttonPrev=g(this.options.buttonPrevHTML).appendTo(this.container);
        this.buttonPrev.addClass(this.className("jcarousel-prev"));
        this.buttonNext= g(".jcarousel-next",this.container);
        if(this.buttonNext.size()===0&&this.options.buttonNextHTML!==null)this.buttonNext=g(this.options.buttonNextHTML).appendTo(this.container);
        this.buttonNext.addClass(this.className("jcarousel-next"));
        this.clip.addClass(this.className("jcarousel-clip")).css({
            position:"relative"
        });
        this.list.addClass(this.className("jcarousel-list")).css({
            overflow:"hidden",
            position:"relative",
            top:0,
            margin:0,
            padding:0
        }).css(this.options.rtl?"right":"left",0);
        this.container.addClass(this.className("jcarousel-container")).css({
            position:"relative"
        });
        !this.options.vertical&&this.options.rtl&&this.container.addClass("jcarousel-direction-rtl").attr("dir","rtl");
        var j=this.options.visible!==null?Math.ceil(this.clipping()/this.options.visible):null,b=this.list.children("li"),e=this;
        if(b.size()>0){
            var h=0,i=this.options.offset;
            b.each(function(){
                e.format(this,i++);
                h+=e.dimension(this,j)
                });
            this.list.css(this.wh,h+100+"px");
            if(!c||c.size===void 0)this.options.size=b.size()
                }
                this.container.css("display","block");
        this.buttonNext.css("display","block");
        this.buttonPrev.css("display", "block");
        this.funcNext=function(){
            e.next()
            };
            
        this.funcPrev=function(){
            e.prev()
            };
            
        this.funcResize=function(){
            e.resizeTimer&&clearTimeout(e.resizeTimer);
            e.resizeTimer=setTimeout(function(){
                e.reload()
                },100)
            };
            
        this.options.initCallback!==null&&this.options.initCallback(this,"init");
        !m&&g.browser.safari?(this.buttons(!1,!1),g(window).bind("load.jcarousel",function(){
            e.setup()
            })):this.setup()
        };
        
    var f=g.jcarousel;
    f.fn=f.prototype={
        jcarousel:"0.2.8"
    };
    
    f.fn.extend=f.extend=g.extend;
    f.fn.extend({
        setup:function(){
            this.prevLast= this.prevFirst=this.last=this.first=null;
            this.animating=!1;
            this.tail=this.resizeTimer=this.timer=null;
            this.inTail=!1;
            if(!this.locked){
                this.list.css(this.lt,this.pos(this.options.offset)+"px");
                var a=this.pos(this.options.start,!0);
                this.prevFirst=this.prevLast=null;
                this.animate(a,!1);
                g(window).unbind("resize.jcarousel",this.funcResize).bind("resize.jcarousel",this.funcResize);
                this.options.setupCallback!==null&&this.options.setupCallback(this)
                }
            },
    reset:function(){
        this.list.empty();
        this.list.css(this.lt, "0px");
        this.list.css(this.wh,"10px");
        this.options.initCallback!==null&&this.options.initCallback(this,"reset");
        this.setup()
        },
    reload:function(){
        this.tail!==null&&this.inTail&&this.list.css(this.lt,f.intval(this.list.css(this.lt))+this.tail);
        this.tail=null;
        this.inTail=!1;
        this.options.reloadCallback!==null&&this.options.reloadCallback(this);
        if(this.options.visible!==null){
            var a=this,c=Math.ceil(this.clipping()/this.options.visible),b=0,d=0;
            this.list.children("li").each(function(f){
                b+=a.dimension(this, c);
                f+1<a.first&&(d=b)
                });
            this.list.css(this.wh,b+"px");
            this.list.css(this.lt,-d+"px")
            }
            this.scroll(this.first,!1)
        },
    lock:function(){
        this.locked=!0;
        this.buttons()
        },
    unlock:function(){
        this.locked=!1;
        this.buttons()
        },
    size:function(a){
        if(a!==void 0)this.options.size=a,this.locked||this.buttons();
        return this.options.size
        },
    has:function(a,c){
        if(c===void 0||!c)c=a;
        if(this.options.size!==null&&c>this.options.size)c=this.options.size;
        for(var b=a;b<=c;b++){
            var d=this.get(b);
            if(!d.length||d.hasClass("jcarousel-item-placeholder"))return!1
                }
                return!0
        }, 
    get:function(a){
        return g(">.jcarousel-item-"+a,this.list)
        },
    add:function(a,c){
        var b=this.get(a),d=0,p=g(c);
        if(b.length===0)for(var j,e=f.intval(a),b=this.create(a);;){
            if(j=this.get(--e),e<=0||j.length){
                e<=0?this.list.prepend(b):j.after(b);
                break
            }
        }else d=this.dimension(b);
        p.get(0).nodeName.toUpperCase()=="LI"?(b.replaceWith(p),b=p):b.empty().append(c);
        this.format(b.removeClass(this.className("jcarousel-item-placeholder")),a);
        p=this.options.visible!==null?Math.ceil(this.clipping()/this.options.visible): null;
        d=this.dimension(b,p)-d;
        a>0&&a<this.first&&this.list.css(this.lt,f.intval(this.list.css(this.lt))-d+"px");
        this.list.css(this.wh,f.intval(this.list.css(this.wh))+d+"px");
        return b
        },
    remove:function(a){
        var c=this.get(a);
        if(c.length&&!(a>=this.first&&a<=this.last)){
            var b=this.dimension(c);
            a<this.first&&this.list.css(this.lt,f.intval(this.list.css(this.lt))+b+"px");
            c.remove();
            this.list.css(this.wh,f.intval(this.list.css(this.wh))-b+"px")
            }
        },
next:function(){
    this.tail!==null&&!this.inTail?this.scrollTail(!1): this.scroll((this.options.wrap=="both"||this.options.wrap=="last")&&this.options.size!==null&&this.last==this.options.size?1:this.first+this.options.scroll)
    },
prev:function(){
    this.tail!==null&&this.inTail?this.scrollTail(!0):this.scroll((this.options.wrap=="both"||this.options.wrap=="first")&&this.options.size!==null&&this.first==1?this.options.size:this.first-this.options.scroll)
    },
scrollTail:function(a){
    if(!this.locked&&!this.animating&&this.tail){
        this.pauseAuto();
        var c=f.intval(this.list.css(this.lt)), c=!a?c-this.tail:c+this.tail;
        this.inTail=!a;
        this.prevFirst=this.first;
        this.prevLast=this.last;
        this.animate(c)
        }
    },
scroll:function(a,c){
    !this.locked&&!this.animating&&(this.pauseAuto(),this.animate(this.pos(a),c))
    },
pos:function(a,c){
    var b=f.intval(this.list.css(this.lt));
    if(this.locked||this.animating)return b;
    this.options.wrap!="circular"&&(a=a<1?1:this.options.size&&a>this.options.size?this.options.size:a);
    for(var d=this.first>a,g=this.options.wrap!="circular"&&this.first<=1?1:this.first,j=d?this.get(g): this.get(this.last),e=d?g:g-1,h=null,i=0,k=!1,l=0;d?--e>=a:++e<a;){
        h=this.get(e);
        k=!h.length;
        if(h.length===0&&(h=this.create(e).addClass(this.className("jcarousel-item-placeholder")),j[d?"before":"after"](h),this.first!==null&&this.options.wrap=="circular"&&this.options.size!==null&&(e<=0||e>this.options.size)))j=this.get(this.index(e)),j.length&&(h=this.add(e,j.clone(!0)));
        j=h;
        l=this.dimension(h);
        k&&(i+=l);
        if(this.first!==null&&(this.options.wrap=="circular"||e>=1&&(this.options.size===null||e<= this.options.size)))b=d?b+l:b-l
            }
            for(var g=this.clipping(),m=[],o=0,n=0,j=this.get(a-1),e=a;++o;){
        h=this.get(e);
        k=!h.length;
        if(h.length===0){
            h=this.create(e).addClass(this.className("jcarousel-item-placeholder"));
            if(j.length===0)this.list.prepend(h);else j[d?"before":"after"](h);
            if(this.first!==null&&this.options.wrap=="circular"&&this.options.size!==null&&(e<=0||e>this.options.size))j=this.get(this.index(e)),j.length&&(h=this.add(e,j.clone(!0)))
                }
                j=h;
        l=this.dimension(h);
        if(l===0)throw Error("jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...");
        this.options.wrap!="circular"&&this.options.size!==null&&e>this.options.size?m.push(h):k&&(i+=l);
        n+=l;
        if(n>=g)break;
        e++
    }
    for(h=0;h<m.length;h++)m[h].remove();
    i>0&&(this.list.css(this.wh,this.dimension(this.list)+i+"px"),d&&(b-=i,this.list.css(this.lt,f.intval(this.list.css(this.lt))-i+"px")));
    i=a+o-1;
    if(this.options.wrap!="circular"&&this.options.size&&i>this.options.size)i=this.options.size;
    if(e>i){
        o=0;
        e=i;
        for(n=0;++o;){
            h=this.get(e--);
            if(!h.length)break;
            n+=this.dimension(h);
            if(n>=g)break
        }
        }
        e=i-o+ 1;
this.options.wrap!="circular"&&e<1&&(e=1);
    if(this.inTail&&d)b+=this.tail,this.inTail=!1;
    this.tail=null;
    if(this.options.wrap!="circular"&&i==this.options.size&&i-o+1>=1&&(d=f.intval(this.get(i).css(!this.options.vertical?"marginRight":"marginBottom")),n-d>g))this.tail=n-g-d;
    if(c&&a===this.options.size&&this.tail)b-=this.tail,this.inTail=!0;
    for(;a-- >e;)b+=this.dimension(this.get(a));
    this.prevFirst=this.first;
    this.prevLast=this.last;
    this.first=e;
    this.last=i;
    return b
    },
animate:function(a,c){
    if(!this.locked&& !this.animating){
        this.animating=!0;
        var b=this,d=function(){
            b.animating=!1;
            a===0&&b.list.css(b.lt,0);
            !b.autoStopped&&(b.options.wrap=="circular"||b.options.wrap=="both"||b.options.wrap=="last"||b.options.size===null||b.last<b.options.size||b.last==b.options.size&&b.tail!==null&&!b.inTail)&&b.startAuto();
            b.buttons();
            b.notify("onAfterAnimation");
            if(b.options.wrap=="circular"&&b.options.size!==null)for(var c=b.prevFirst;c<=b.prevLast;c++)c!==null&&!(c>=b.first&&c<=b.last)&&(c<1||c>b.options.size)&&b.remove(c)
                };                
        this.notify("onBeforeAnimation");
        if(!this.options.animation||c===!1)this.list.css(this.lt,a+"px"),d();
        else{
            var f=!this.options.vertical?this.options.rtl?{
                right:a
            }:{
                left:a
            }:{
                top:a
            },d={
                duration:this.options.animation,
                easing:this.options.easing,
                complete:d
            };
            
            if(g.isFunction(this.options.animationStepCallback))d.step=this.options.animationStepCallback;
            this.list.animate(f,d)
            }
        }
},
startAuto:function(a){
    if(a!==void 0)this.options.auto=a;
    if(this.options.auto===0)return this.stopAuto();
    if(this.timer===null){
        this.autoStopped= !1;
        var c=this;
        this.timer=window.setTimeout(function(){
            c.next()
            },this.options.auto*1E3)
        }
    },
stopAuto:function(){
    this.pauseAuto();
    this.autoStopped=!0
    },
pauseAuto:function(){
    if(this.timer!==null)window.clearTimeout(this.timer),this.timer=null
        },
buttons:function(a,c){
    if(a==null&&(a=!this.locked&&this.options.size!==0&&(this.options.wrap&&this.options.wrap!="first"||this.options.size===null||this.last<this.options.size),!this.locked&&(!this.options.wrap||this.options.wrap=="first")&&this.options.size!==null&& this.last>=this.options.size))a=this.tail!==null&&!this.inTail;
    if(c==null&&(c=!this.locked&&this.options.size!==0&&(this.options.wrap&&this.options.wrap!="last"||this.first>1),!this.locked&&(!this.options.wrap||this.options.wrap=="last")&&this.options.size!==null&&this.first==1))c=this.tail!==null&&this.inTail;
    var b=this;
    this.buttonNext.size()>0?(this.buttonNext.unbind(this.options.buttonNextEvent+".jcarousel",this.funcNext),a&&this.buttonNext.bind(this.options.buttonNextEvent+".jcarousel",this.funcNext), this.buttonNext[a?"removeClass":"addClass"](this.className("jcarousel-next-disabled")).attr("disabled",a?!1:!0),this.options.buttonNextCallback!==null&&this.buttonNext.data("jcarouselstate")!=a&&this.buttonNext.each(function(){
        b.options.buttonNextCallback(b,this,a)
        }).data("jcarouselstate",a)):this.options.buttonNextCallback!==null&&this.buttonNextState!=a&&this.options.buttonNextCallback(b,null,a);
    this.buttonPrev.size()>0?(this.buttonPrev.unbind(this.options.buttonPrevEvent+".jcarousel",this.funcPrev), c&&this.buttonPrev.bind(this.options.buttonPrevEvent+".jcarousel",this.funcPrev),this.buttonPrev[c?"removeClass":"addClass"](this.className("jcarousel-prev-disabled")).attr("disabled",c?!1:!0),this.options.buttonPrevCallback!==null&&this.buttonPrev.data("jcarouselstate")!=c&&this.buttonPrev.each(function(){
        b.options.buttonPrevCallback(b,this,c)
        }).data("jcarouselstate",c)):this.options.buttonPrevCallback!==null&&this.buttonPrevState!=c&&this.options.buttonPrevCallback(b,null,c);
    this.buttonNextState= a;
    this.buttonPrevState=c
    },
notify:function(a){
    var c=this.prevFirst===null?"init":this.prevFirst<this.first?"next":"prev";
    this.callback("itemLoadCallback",a,c);
    this.prevFirst!==this.first&&(this.callback("itemFirstInCallback",a,c,this.first),this.callback("itemFirstOutCallback",a,c,this.prevFirst));
    this.prevLast!==this.last&&(this.callback("itemLastInCallback",a,c,this.last),this.callback("itemLastOutCallback",a,c,this.prevLast));
    this.callback("itemVisibleInCallback",a,c,this.first,this.last,this.prevFirst, this.prevLast);
    this.callback("itemVisibleOutCallback",a,c,this.prevFirst,this.prevLast,this.first,this.last)
    },
callback:function(a,c,b,d,f,j,e){
    if(!(this.options[a]==null||typeof this.options[a]!="object"&&c!="onAfterAnimation")){
        var h=typeof this.options[a]=="object"?this.options[a][c]:this.options[a];
        if(g.isFunction(h)){
            var i=this;
            if(d===void 0)h(i,b,c);
            else if(f===void 0)this.get(d).each(function(){
                h(i,this,d,b,c)
                });else for(var a=function(a){
                i.get(a).each(function(){
                    h(i,this,a,b,c)
                    })
                },k=d;k<=f;k++)k!== null&&!(k>=j&&k<=e)&&a(k)
                }
            }
},
create:function(a){
    return this.format("<li></li>",a)
    },
format:function(a,c){
    for(var a=g(a),b=a.get(0).className.split(" "),d=0;d<b.length;d++)b[d].indexOf("jcarousel-")!=-1&&a.removeClass(b[d]);
    a.addClass(this.className("jcarousel-item")).addClass(this.className("jcarousel-item-"+c)).css({
        "float":this.options.rtl?"right":"left",
        "list-style":"none"
    }).attr("jcarouselindex",c);
    return a
    },
className:function(a){
    return a+" "+a+(!this.options.vertical?"-horizontal":"-vertical")
    }, 
dimension:function(a,c){
    var b=g(a);
    if(c==null)return!this.options.vertical?b.outerWidth(!0)||f.intval(this.options.itemFallbackDimension):b.outerHeight(!0)||f.intval(this.options.itemFallbackDimension);
    else{
        var d=!this.options.vertical?c-f.intval(b.css("marginLeft"))-f.intval(b.css("marginRight")):c-f.intval(b.css("marginTop"))-f.intval(b.css("marginBottom"));
        g(b).css(this.wh,d+"px");
        return this.dimension(b)
        }
    },
clipping:function(){
    return!this.options.vertical?this.clip[0].offsetWidth-f.intval(this.clip.css("borderLeftWidth"))- f.intval(this.clip.css("borderRightWidth")):this.clip[0].offsetHeight-f.intval(this.clip.css("borderTopWidth"))-f.intval(this.clip.css("borderBottomWidth"))
    },
index:function(a,c){
    if(c==null)c=this.options.size;
    return Math.round(((a-1)/c-Math.floor((a-1)/c))*c)+1
    }
});
f.extend({
    defaults:function(a){
        return g.extend(q,a||{})
        },
    intval:function(a){
        a=parseInt(a,10);
        return isNaN(a)?0:a
        },
    windowLoaded:function(){
        m=!0
        }
    });
g.fn.jcarousel=function(a){
    if(typeof a=="string"){
        var c=g(this).data("jcarousel"),b=Array.prototype.slice.call(arguments, 1);
        return c[a].apply(c,b)
        }else return this.each(function(){
        var b=g(this).data("jcarousel");
        b?(a&&g.extend(b.options,a),b.reload()):g(this).data("jcarousel",new f(this,a))
        })
    }
    })(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
 */

(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);


jQuery.validator.addMethod("defaultInvalid", function(value, element) 
{
    if (element.value == jQuery(element).prev('label:first').text())
    {
        return false;
    }
    return true;
},'Este campo é obrigatório.');
