CC-2917: Adding show, when inputting time and specifying a bogus
time (like 55555), then Nan-Nan-Nan shows up(possibly when tabbing) - fixed by implementing masking on the fields - used meioMask jquery plugin
This commit is contained in:
parent
79519e25c2
commit
0e29dfa617
|
@ -47,6 +47,7 @@ class ScheduleController extends Zend_Controller_Action
|
|||
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/schedule/full-calendar-functions.js','text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/schedule/add-show.js','text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/schedule/schedule.js','text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'/js/meioMask/jquery.meio.mask.js','text/javascript');
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'/css/jquery-ui-timepicker.css');
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'/css/fullcalendar.css');
|
||||
|
|
|
@ -20,6 +20,7 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
|
|||
'ViewHelper',
|
||||
'Description',
|
||||
array('Label', array('tag' =>'dt'))));
|
||||
$startDate->setAttrib('alt', 'date');
|
||||
$this->addElement($startDate);
|
||||
|
||||
// Add start time element
|
||||
|
@ -36,6 +37,7 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
|
|||
'ViewHelper',
|
||||
'Errors',
|
||||
array(array('close'=>'HtmlTag'), array('tag' => 'dd', 'closeOnly'=>true))));
|
||||
$startTime->setAttrib('alt', 'time');
|
||||
$this->addElement($startTime);
|
||||
|
||||
// Add end date element
|
||||
|
@ -53,6 +55,7 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
|
|||
'ViewHelper',
|
||||
'Description',
|
||||
array('Label', array('tag' =>'dt'))));
|
||||
$endDate->setAttrib('alt', 'date');
|
||||
$this->addElement($endDate);
|
||||
|
||||
// Add end time element
|
||||
|
@ -69,6 +72,7 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
|
|||
'ViewHelper',
|
||||
'Errors',
|
||||
array(array('close'=>'HtmlTag'), array('tag' => 'dd', 'closeOnly'=>true))));
|
||||
$endTime->setAttrib('alt', 'time');
|
||||
$this->addElement($endTime);
|
||||
|
||||
// Add duration element
|
||||
|
|
|
@ -419,10 +419,16 @@ function showErrorSections() {
|
|||
$("#schedule-record-rebroadcast").show();
|
||||
$("#add_show_rebroadcast_relative").show();
|
||||
}
|
||||
$('input:text').setMask()
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$.mask.masks = $.extend($.mask.masks,{
|
||||
date:{ mask: '9999-19-39'},
|
||||
time:{ mask: '29:69'}
|
||||
})
|
||||
|
||||
$('input:text').setMask()
|
||||
//setAddShowEvents();
|
||||
});
|
||||
|
||||
|
@ -438,6 +444,13 @@ $(window).resize(function(){
|
|||
});
|
||||
|
||||
$(window).load(function() {
|
||||
|
||||
$.mask.masks = $.extend($.mask.masks,{
|
||||
date:{ mask: '9999-19-39'},
|
||||
time:{ mask: '29:69'}
|
||||
})
|
||||
|
||||
$('input:text').setMask()
|
||||
|
||||
setAddShowEvents();
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,683 @@
|
|||
/**
|
||||
* 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);
|
||||
|
Loading…
Reference in New Issue