Skip to content

Instantly share code, notes, and snippets.

@JustLikeIcarus
Created September 16, 2009 05:43
Show Gist options
  • Save JustLikeIcarus/187892 to your computer and use it in GitHub Desktop.
Save JustLikeIcarus/187892 to your computer and use it in GitHub Desktop.
/**
* 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 : '9999/19/39' }, //mysql date
'date-us' : { mask : '19/39/9999' },
'cep' : { mask : '99999-999' },
'time' : { mask : '29:59' },
'datetime' : { mask : '9999/19/39 29:59' }, //datetime field
'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%5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment