Browse Source

Added simple optional masks, or you can see it as clearing out optional masks on the tail when the input looses focus.
thx to Ross Hadden & Gilles van den Hoven for the code & idea

Robin Herbots 14 years ago
parent
commit
d32b6d3176
2 changed files with 173 additions and 64 deletions
  1. 132 56
      README
  2. 41 8
      jquery.inputmask.js

+ 132 - 56
README

@@ -6,125 +6,152 @@ A definition can have a cardinality and have multiple prevalidators.
 
 
 Example of some new definitions:
 Example of some new definitions:
 
 
-                'd': { //day
-
-                    "validator": "0[1-9]|[12][0-9]|3[01]",
-
-                    "cardinality": 2,
-
-                    "prevalidator": [{ "validator": "[0-3]", "cardinality": 1}]
-
-                },
-
-                'm': { //month
-
-                    "validator": "0[1-9]|1[012]",
-
-                    "cardinality": 2,
-
-                    "prevalidator": [{ "validator": "[01]", "cardinality": 1}]
-
-                },
-
-                'y': { //year
-
-                    "validator": "(19|20)\\d\\d",
-
-                    "cardinality": 4,
-
-                    "prevalidator": [
-
-                        { "validator": "[12]", "cardinality": 1 },
-
-                        { "validator": "(19|20)", "cardinality": 2 },
-
-                        { "validator": "(19|20)\\d", "cardinality": 3 }
-
-                        ]
-
+```javascript
+     'm': { //month
+        validator: function(chrs, buffer) {
+            var dayValue = buffer.join('').substr(0, 3);
+            return $.inputmask.defaults.aliases['dd/mm/yyyy'].regex.month.test(dayValue + chrs);
+        },
+        cardinality: 2,
+        prevalidator: [{ validator: "[01]", cardinality: 1}]
+    },
+    'y': { //year
+        validator: function(chrs, buffer) {
+            if ($.inputmask.defaults.aliases['dd/mm/yyyy'].regex.year.test(chrs)) {
+                var dayMonthValue = buffer.join('').substr(0, 6);
+                if (dayMonthValue != "29/02/")
+                    return true;
+                else {
+                    var year = parseInt(chrs);  //detect leap year
+                    if (year % 4 == 0)
+                        if (year % 100 == 0)
+                        if (year % 400 == 0)
+                        return true;
+                    else return false;
+                    else return true;
+                    else return false;
                 }
                 }
+            } else return false;
+        },
+        cardinality: 4,
+        prevalidator: [
+            { validator: "[12]", cardinality: 1 },
+            { validator: "(19|20)", cardinality: 2 },
+            { validator: "(19|20)\\d", cardinality: 3 }
+            ]
+    }
+},
+insertMode: false
+```
 
 
 These allow for a finer date validation then 99/99/9999 which also allows 33/33/3333 for example.  
 These allow for a finer date validation then 99/99/9999 which also allows 33/33/3333 for example.  
 In the jquery.inputmask.extentions.js you find a full date input validation which takes days, months & leap years into account.
 In the jquery.inputmask.extentions.js you find a full date input validation which takes days, months & leap years into account.
 
 
-Also extra features like mask-repetitions (greedy and non-gready) are included.  In the examples you will find more about them.
+Also extra features like mask-repetitions (greedy and non-gready) and many other additions are included.  In the examples you will find more about them.
 
 
 
 
 Usage:
 Usage:
 
 
-Include the js-files
+Include the js-files:
 
 
+```html
 <script src="jquery.js" type="text/javascript"></script>
 <script src="jquery.js" type="text/javascript"></script>
 <script src="jquery.inputmask.js" type="text/javascript"></script>
 <script src="jquery.inputmask.js" type="text/javascript"></script>
+<script src="jquery.inputmask.extentions.js" type="text/javascript"></script>
+```
 
 
 Define your masks:
 Define your masks:
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#date").inputmask("d/m/y");  //direct mask
    $("#date").inputmask("d/m/y");  //direct mask
    $("#phone").inputmask("mask", {"mask": "(999) 999-9999"}); //specifying fn & options
    $("#phone").inputmask("mask", {"mask": "(999) 999-9999"}); //specifying fn & options
    $("#tin").inputmask({"mask": "99-9999999"}); //specifying options only
    $("#tin").inputmask({"mask": "99-9999999"}); //specifying options only
 });
 });
+```
 
 
-Extra options:
+## Extra options:
 
 
-change the placeholder
+### change the placeholder
 
 
+
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#date").inputmask("d/m/y",{ "placeholder": "*" });
    $("#date").inputmask("d/m/y",{ "placeholder": "*" });
 });
 });
+```
 
 
 or a multi-char placeholder
 or a multi-char placeholder
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#date").inputmask("d/m/y",{ "placeholder": "dd/mm/yyyy" });
    $("#date").inputmask("d/m/y",{ "placeholder": "dd/mm/yyyy" });
 });
 });
+```
 
 
-execute a function when the mask is completed
+### execute a function when the mask is completed, incomplete or cleared
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#date").inputmask("d/m/y",{ "oncomplete": function(){ alert('inputmask complete'); } });
    $("#date").inputmask("d/m/y",{ "oncomplete": function(){ alert('inputmask complete'); } });
+   $("#date").inputmask("d/m/y",{ "onincomplete": function(){ alert('inputmask incomplete'); } });
+   $("#date").inputmask("d/m/y",{ "oncleared": function(){ alert('inputmask cleared'); } });
 });
 });
+```
 
 
-mask repeat function
+### mask repeat function
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#number").inputmask({ "mask": "9", "repeat": 10 });  // ~ mask "9999999999"
    $("#number").inputmask({ "mask": "9", "repeat": 10 });  // ~ mask "9999999999"
 });
 });
+```
 
 
-mask non-greedy repeat function
+### mask non-greedy repeat function
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#number").inputmask({ "mask": "9", "repeat": 10, "greedy": false });  // ~ mask "9" or mask "99" or ... mask "9999999999"
    $("#number").inputmask({ "mask": "9", "repeat": 10, "greedy": false });  // ~ mask "9" or mask "99" or ... mask "9999999999"
 });
 });
+```
 
 
-get the unmaskedvalue
+### get the unmaskedvalue
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#number").inputmask('unmaskedvalue');
    $("#number").inputmask('unmaskedvalue');
 });
 });
+```
 
 
-set a value and apply mask
+### set a value and apply mask
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#number").inputmask('setvalue', 12345); 
    $("#number").inputmask('setvalue', 12345); 
 });
 });
+```
 
 
 when the option patch_eval is set to true the same can be done with the traditionnal jquery.val function
 when the option patch_eval is set to true the same can be done with the traditionnal jquery.val function
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#number").val(12345); 
    $("#number").val(12345); 
 });
 });
+```
 
 
 with the autoUnmaskoption you can change the return of $.fn.val  to unmaskedvalue or the maskedvalue
 with the autoUnmaskoption you can change the return of $.fn.val  to unmaskedvalue or the maskedvalue
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    	$('#<%= tbDate.ClientID%>').inputmask({ "mask": "d/m/y", 'autoUnmask' : true});	//  value: 23/03/1973
    	$('#<%= tbDate.ClientID%>').inputmask({ "mask": "d/m/y", 'autoUnmask' : true});	//  value: 23/03/1973
 
 
 	alert($('#<%= tbDate.ClientID%>').val());	// shows 23031973     (autoUnmask: true)
 	alert($('#<%= tbDate.ClientID%>').val());	// shows 23031973     (autoUnmask: true)
 });
 });
+```
 
 
-add custom definitions
+### add custom definitions
 
 
+```javascript
 $.extend($.inputmask.defaults.definitions, {
 $.extend($.inputmask.defaults.definitions, {
     'f': {
     'f': {
         "validator": "[0-9\(\)\.\+/ ]",
         "validator": "[0-9\(\)\.\+/ ]",
@@ -132,47 +159,74 @@ $.extend($.inputmask.defaults.definitions, {
         'prevalidator': null
         'prevalidator': null
     }
     }
 });
 });
+```
 
 
-set defaults
+### set defaults
 
 
+```javascript
 $.extend($.inputmask.defaults, {
 $.extend($.inputmask.defaults, {
     'autounmask': true
     'autounmask': true
 });
 });
+```
 
 
-numeric input direction
+### numeric input direction
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
     $('#test').inputmask('€ 999.999.999,99', { numericInput: true });    //   123456  =>  € ___.__1.234,56
     $('#test').inputmask('€ 999.999.999,99', { numericInput: true });    //   123456  =>  € ___.__1.234,56
 });
 });
+```
 
 
-remove the inputmask
+### remove the inputmask
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
     $('#test').inputmask('remove');
     $('#test').inputmask('remove');
 });
 });
+```
 
 
-escape special mask chars
+### escape special mask chars
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
     $("#months").inputmask("m \\months");
     $("#months").inputmask("m \\months");
 });
 });
+```
 
 
-remove incomplete input on blur - clearIncomplete
+### clearIncomplete - remove incomplete input on blur
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
     $("#ssn").inputmask("999-99-9999",{placeholder:" ", clearIncomplete: true });
     $("#ssn").inputmask("999-99-9999",{placeholder:" ", clearIncomplete: true });
 });
 });
+```
+
+### Optional Masks
+
+When `clearMaskOnLostFocus: true` is set in the options (default), the mask will always clearout masks marked as optional when not filled in.
+
+For example, given:
 
 
-oncleared option
+```javascript
+$('#test').inputmask('999[-AAA]');
+```
+While the field has focus and is blank, users will see the full mask `___-___`.
+When the required part of the mask is filled and the field loses focus, the user will see `123`.
+When both the required and optional parts of the mask are filled out and the field loses focus, the user will see `123-abc`.
 
 
+### oncleared option
+
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
     $("#ssn").inputmask("999-99-9999",{placeholder:" ", oncleared: function(){ alert('Set focus somewhere else ;-)');} });
     $("#ssn").inputmask("999-99-9999",{placeholder:" ", oncleared: function(){ alert('Set focus somewhere else ;-)');} });
 });
 });
+```
 
 
-aliases option
+### aliases option
 
 
 First you have to create an alias definition (more examples can be found in jquery.inputmask.extentions.js)
 First you have to create an alias definition (more examples can be found in jquery.inputmask.extentions.js)
 
 
+```javascript
 $.extend($.inputmask.defaults.aliases, {
 $.extend($.inputmask.defaults.aliases, {
         'date': {
         'date': {
             mask: "d/m/y"
             mask: "d/m/y"
@@ -181,32 +235,54 @@ $.extend($.inputmask.defaults.aliases, {
 	    alias: "date"
 	    alias: "date"
 	}
 	}
 });
 });
+```
+
+use:
 
 
-use;
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#date").inputmask("date");       => equals to    $("#date").inputmask("d/m/y");
    $("#date").inputmask("date");       => equals to    $("#date").inputmask("d/m/y");
 });
 });
+```
 
 
 or use the dd/mm/yyyy alias of the date alias:
 or use the dd/mm/yyyy alias of the date alias:
+
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#date").inputmask("dd/mm/yyyy");       => equals to    $("#date").inputmask("d/m/y");
    $("#date").inputmask("dd/mm/yyyy");       => equals to    $("#date").inputmask("d/m/y");
 });
 });
+```
 
 
-auto upper/lower- casing inputmask
+### auto upper/lower- casing inputmask
 
 
 see jquery.inputmask.extentions.js for an example how to define "auto"-casing in a definition (definition A)
 see jquery.inputmask.extentions.js for an example how to define "auto"-casing in a definition (definition A)
 casing can be null, "upper" or "lower"
 casing can be null, "upper" or "lower"
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#test").inputmask("999-AAA");       => 123abc ===> 123-ABC 
    $("#test").inputmask("999-AAA");       => 123abc ===> 123-ABC 
 });
 });
+```
 
 
-getemptymask command
+### getemptymask command
 
 
 return the default (empty) mask value
 return the default (empty) mask value
 
 
+```javascript
 $(document).ready(function(){
 $(document).ready(function(){
    $("#test").inputmask("999-AAA");    
    $("#test").inputmask("999-AAA");    
    alert($("#test").inputmask("getemptymask"));    => "___-___" 
    alert($("#test").inputmask("getemptymask"));    => "___-___" 
 });
 });
+```
+
+### RTL input 
+
+Just add the dir="rtl" attribute to the input element
+
+```html
+<input id="test" dir="rtl" />
+```
+
+-----------------------------------------
+
 
 

+ 41 - 8
jquery.inputmask.js

@@ -3,7 +3,7 @@ Input Mask plugin for jquery
 http://github.com/RobinHerbots/jquery.inputmask
 http://github.com/RobinHerbots/jquery.inputmask
 Copyright (c) 2010 Robin Herbots
 Copyright (c) 2010 Robin Herbots
 Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
 Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-Version: 0.5.0 - dev
+Version: 0.5.1 - dev
  
  
 This plugin is based on the masked input plugin written by Josh Bush (digitalbush.com)
 This plugin is based on the masked input plugin written by Josh Bush (digitalbush.com)
 */
 */
@@ -492,9 +492,12 @@ This plugin is based on the masked input plugin written by Josh Bush (digitalbus
                 if (!input.attr("readonly")) {
                 if (!input.attr("readonly")) {
                     input.bind("mouseenter.inputmask", function() {
                     input.bind("mouseenter.inputmask", function() {
                         var input = $(this);
                         var input = $(this);
-                        if (!input.hasClass('focus.inputmask') && _val.call(input).length == 0) {
-                            buffer = _buffer.slice();
-                            writeBuffer(input, buffer);
+                        if (!input.hasClass('focus.inputmask')) {
+                        	if(_val.call(input).length == 0) {
+                            	buffer = _buffer.slice();
+                            	writeBuffer(input, buffer);
+                        	} else if (_val.call(input).length < buffer.length)
+                        				writeBuffer(input, buffer);
                         }
                         }
                     }).bind("blur.inputmask", function() {
                     }).bind("blur.inputmask", function() {
                         var input = $(this);
                         var input = $(this);
@@ -502,8 +505,22 @@ This plugin is based on the masked input plugin written by Josh Bush (digitalbus
                         if (_val.call(input) != undoBuffer) {
                         if (_val.call(input) != undoBuffer) {
                             input.change();
                             input.change();
                         }
                         }
-                        if (opts.clearMaskOnLostFocus && _val.call(input) == _buffer.join(''))
-                            _val.call(input, '');
+                        if (opts.clearMaskOnLostFocus) {
+                         	if(_val.call(input) == _buffer.join(''))
+                            	_val.call(input, '');
+                            else { //clearout optional tail of the mask 
+                            	var tmpBuffer = buffer.slice();
+                            	for(var pos = tmpBuffer.length - 1; pos >= 0 ; pos--) {
+                            		 var testPos = determineTestPosition(pos);
+                            		 if(tests[testPos].optionality){
+                            		 	if(getPlaceHolder(pos) == tmpBuffer[pos] || !isMask(pos))
+                            		 		tmpBuffer.pop();
+                            		 	else break;
+                            		 } else break;
+               					}
+               					writeBuffer(input, tmpBuffer);
+                            }
+                        }
                         if ((opts.clearIncomplete || opts.onincomplete) && checkVal(input, buffer, true) != getMaskLength()) {
                         if ((opts.clearIncomplete || opts.onincomplete) && checkVal(input, buffer, true) != getMaskLength()) {
                             if (opts.onincomplete) {
                             if (opts.onincomplete) {
                                 opts.onincomplete.call(input);
                                 opts.onincomplete.call(input);
@@ -523,8 +540,24 @@ This plugin is based on the masked input plugin written by Josh Bush (digitalbus
                         undoBuffer = _val.call(input);
                         undoBuffer = _val.call(input);
                     }).bind("mouseleave.inputmask", function() {
                     }).bind("mouseleave.inputmask", function() {
                         var input = $(this);
                         var input = $(this);
-                        if (opts.clearMaskOnLostFocus && !input.hasClass('focus.inputmask') && _val.call(input) == _buffer.join(''))
-                            _val.call(input, '');
+                        if (opts.clearMaskOnLostFocus) {
+                         	if(!input.hasClass('focus.inputmask')) {
+                         		if(_val.call(input) == _buffer.join(''))
+                            	_val.call(input, '');
+                            	else { //clearout optional tail of the mask 
+                            		var tmpBuffer = buffer.slice();
+                            		for(var pos = tmpBuffer.length - 1; pos >= 0 ; pos--) {
+                            			 var testPos = determineTestPosition(pos);
+                            		 	if(tests[testPos].optionality){
+                            		 		if(getPlaceHolder(pos) == tmpBuffer[pos] || !isMask(pos))
+                            		 			tmpBuffer.pop();
+                            		 		else break;
+                            		 	} else break;
+               						}
+               						writeBuffer(input, tmpBuffer);
+                            	}
+                            }
+                        }
                     }).bind("click.inputmask", function() {
                     }).bind("click.inputmask", function() {
                         var input = $(this);
                         var input = $(this);
                         setTimeout(function() {
                         setTimeout(function() {