From 0e29dfa6174f1b76d2965faf8966e0fb6efdbebd Mon Sep 17 00:00:00 2001 From: James Date: Mon, 3 Oct 2011 16:43:32 -0400 Subject: [PATCH] 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 --- .../controllers/ScheduleController.php | 1 + airtime_mvc/application/forms/AddShowWhen.php | 4 + .../public/js/airtime/schedule/add-show.js | 17 +- .../public/js/meioMask/jquery.meio.mask.js | 683 ++++++++++++++++++ 4 files changed, 703 insertions(+), 2 deletions(-) create mode 100644 airtime_mvc/public/js/meioMask/jquery.meio.mask.js diff --git a/airtime_mvc/application/controllers/ScheduleController.php b/airtime_mvc/application/controllers/ScheduleController.php index 0757856ea..6555f02ed 100644 --- a/airtime_mvc/application/controllers/ScheduleController.php +++ b/airtime_mvc/application/controllers/ScheduleController.php @@ -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'); diff --git a/airtime_mvc/application/forms/AddShowWhen.php b/airtime_mvc/application/forms/AddShowWhen.php index 3ed5d35b0..65079a21d 100644 --- a/airtime_mvc/application/forms/AddShowWhen.php +++ b/airtime_mvc/application/forms/AddShowWhen.php @@ -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 diff --git a/airtime_mvc/public/js/airtime/schedule/add-show.js b/airtime_mvc/public/js/airtime/schedule/add-show.js index eaa7d44fa..41193dd4e 100644 --- a/airtime_mvc/public/js/airtime/schedule/add-show.js +++ b/airtime_mvc/public/js/airtime/schedule/add-show.js @@ -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(); + }); diff --git a/airtime_mvc/public/js/meioMask/jquery.meio.mask.js b/airtime_mvc/public/js/meioMask/jquery.meio.mask.js new file mode 100644 index 000000000..f4406cc1d --- /dev/null +++ b/airtime_mvc/public/js/meioMask/jquery.meio.mask.js @@ -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: + // + 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 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); + \ No newline at end of file