fix bug comma

This commit is contained in:
2020-07-12 15:04:12 +07:00
parent e132f3b5c9
commit c27b800795
66 changed files with 15559 additions and 16 deletions

View File

@@ -173,6 +173,9 @@
<script src="~/BackendScript/js/bootstrap-datepicker-th/bootstrap-datepicker.th.js"></script>
<script src="~/BackendScript/assets/bootstrap-daterangepicker/moment.min.js"></script>
<script src="https://hrm.stin.ac.th/plugins/jQuery-Mask-Plugin-master/dist/jquery.mask.min.js"></script>
<script src="https://hrm.stin.ac.th/plugins/jquery-maskmoney-master/dist/jquery.maskMoney.min.js"></script>
<!--Select2-->
<script src='~/select2/js/select2.min.js' type='text/javascript'></script>
@@ -209,6 +212,53 @@
$( document ).on( 'focus', ':input', function(){
$( this ).attr( 'autocomplete', 'off' );
});
$(document).on('change', 'input.money', function() {
var value = parseFloat(parseFloat($(this).val()).toFixed(2));
$(this).maskMoney();
$(this).unbind("focus.maskMoney");
$(this).unbind("blur.maskMoney");
$(this).maskMoney('mask', value);
});
$(document).on('focus', 'input.money:not([readonly], :disabled)', function() {
$(this).maskMoney('destroy');
var val = $(this).maskMoney('unmasked')[0];
val = val === 0 ? '' : val;
$(this).val(val);
});
$(document).on('blur', 'input.money', function() {
preventDefault(event);
var value = $(this).val();
if (typeof value === 'string' && !value.includes(',')) {
$(this).val($(this).val());
$(this).change();
}
});
$('input.money').keypress(function(e){
e = e || window.event;
var key = e.which || e.charCode || e.keyCode,
keyPressedChar = "",
selection,
startPos,
endPos,
value;
if ((key >= 48 && key <= 57) || e.key == '.') {
} else {
preventDefault(e);
}
});
function preventDefault(e) {
if (e.preventDefault) { //standard browsers
e.preventDefault();
} else { // old internet explorer
e.returnValue = false;
}
}
});
</script>
</body>

View File

@@ -151,6 +151,10 @@
<script src="~/BackendScript/js/jquery.nicescroll.js" type="text/javascript"></script>
<script src="~/BackendScript/js/jquery.sparkline.js" type="text/javascript"></script>
<script src="~/BackendScript/js/respond.min.js"></script>
<script src="~/BackendScript/js/jQuery-Mask-Plugin-master/dist/jquery.mask.min.js"></script>
<script src="~/BackendScript/js/jquery-maskmoney-master/dist/jquery.maskMoney.min.js"></script>
<script src="~/BackendScript/js/jsrsasign-all-min.js"></script>
<script src="~/DataTables-1.10.16/js/jquery.dataTables.js" type="text/javascript"></script>
<script src="~/DataTables-1.10.16/js/dataTables.bootstrap4.min.js" type="text/javascript"></script>
@@ -168,6 +172,7 @@
<script src="~/BackendScript/js/bootstrap-datepicker-th/bootstrap-datepicker.th.js"></script>
<script src="~/BackendScript/assets/bootstrap-daterangepicker/moment.min.js"></script>
<!--Select2-->
<script src='~/select2/js/select2.min.js' type='text/javascript'></script>
@@ -184,20 +189,64 @@
<iframe id="myframe" class="iframe-con" src=""></iframe>
<script>
$('.allfontsize').click(function () {
var fontsize = $(this).data('fontsize');
$('body').attr('data-fontsize', fontsize);
});
</script>
<script>
$("#username").text(getCookie("emp_name"));
</script>
<script>
$(document).ready(function () {
$('.allfontsize').click(function () {
var fontsize = $(this).data('fontsize');
$('body').attr('data-fontsize', fontsize);
});
$("#username").text(getCookie("emp_name"));
$(document).ready(function(){
$( document ).on( 'focus', ':input', function(){
$( this ).attr( 'autocomplete', 'off' );
});
});
$('.money').maskMoney();
$(document).on('change', 'input.money', function() {
var value = parseFloat(parseFloat($(this).val()).toFixed(2));
$(this).maskMoney();
$(this).unbind("focus.maskMoney");
$(this).unbind("blur.maskMoney");
$(this).maskMoney('mask', value);
});
$(document).on('focus', 'input.money:not([readonly], :disabled)', function() {
$(this).maskMoney('destroy');
var val = $(this).maskMoney('unmasked')[0];
val = val === 0 ? '' : val;
$(this).val(val);
});
$(document).on('blur', 'input.money', function() {
preventDefault(event);
var value = $(this).val();
if (typeof value === 'string' && !value.includes(',')) {
$(this).val($(this).val());
$(this).change();
}
});
$('input.money').keypress(function(e){
e = e || window.event;
var key = e.which || e.charCode || e.keyCode,
keyPressedChar = "",
selection,
startPos,
endPos,
value;
if ((key >= 48 && key <= 57) || e.key == '.') {
} else {
preventDefault(e);
}
});
function preventDefault(e) {
if (e.preventDefault) { //standard browsers
e.preventDefault();
} else { // old internet explorer
e.returnValue = false;
}
}
})
</script>
</body>
</html>

View File

@@ -57,18 +57,18 @@
<div class='row'>
<div class="form-group col-md-6">
<label id="lab_eva_adjust_postponement_quota_limit_frame_quota" for="eva_adjust_postponement_quota_limit_frame_quota">กรอบโควต้าพิเศษร้อยละ</label>
<input onchange="Oneva_adjust_postponement_quota_limit_frame_quotaChange();" class="form-control" type="number" id="eva_adjust_postponement_quota_limit_frame_quota" iLabel="กรอบโควต้าพิเศษร้อยละ" iRequire="true" iGroup="eva_adjust_postponement_quota" />
<input onchange="Oneva_adjust_postponement_quota_limit_frame_quotaChange();" placeholder="0.00" class="form-control money mask_plugin" type="text" id="eva_adjust_postponement_quota_limit_frame_quota" iLabel="กรอบโควต้าพิเศษร้อยละ" iRequire="true" iGroup="eva_adjust_postponement_quota" />
</div>
<div class="form-group col-md-6">
<label id="lab_eva_adjust_postponement_quota_limit_quota" for="eva_adjust_postponement_quota_limit_quota">จำนวนเงินที่สามารถบริหารวงเงินโควต้าพิเศษ</label>
<input disabled class="form-control" type="number" id="eva_adjust_postponement_quota_limit_quota" iLabel="จำนวนเงินที่สามารถบริหารวงเงินโควต้าพิเศษ" iRequire="true" iGroup="eva_adjust_postponement_quota" />
<input disabled placeholder="0.00" class="form-control money mask_plugin" type="text" id="eva_adjust_postponement_quota_limit_quota" iLabel="จำนวนเงินที่สามารถบริหารวงเงินโควต้าพิเศษ" iRequire="true" iGroup="eva_adjust_postponement_quota" />
</div>
</div>
<div class='row'>
<div class="form-group col-md-6">
<label for="remain_quota">จำนวนเงินโควต้าพิเศษคงเหลือ</label>
<input disabled class="form-control" type="text" id="remain_quota" iLabel="จำนวนเงินโควต้าพิเศษคงเหลือ" iRequire="false" iGroup="eva_adjust_postponement_quota" />
<input disabled placeholder="0.00" class="form-control money mask_plugin" type="text" id="remain_quota" iLabel="จำนวนเงินโควต้าพิเศษคงเหลือ" iRequire="false" iGroup="eva_adjust_postponement_quota" />
</div>
<div class="form-group col-md-6">
@@ -76,8 +76,6 @@
<input class="form-control" type="text" id="eva_adjust_postponement_quota_command_no" iLabel="เลขที่คำสั่ง" iRequire="true" iGroup="eva_adjust_postponement_quota" />
</div>
</div>
</div>
</div>
</div>
@@ -139,6 +137,7 @@
if (id) {
eva_adjust_postponement_quota_SetEditForm(id);
eva_adjust_postponement_detail_quota_02_InitialForm(id);
} else {
eva_adjust_postponement_quota_SetCreateForm();
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,34 @@
{
"bitwise": true,
"browser": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"esnext": true,
"expr": true,
"globals": {
"console": false,
"define": false,
"document": false,
"expect": false,
"module": false,
"require": false,
"window": false
},
"immed": true,
"indent": 4,
"latedef": true,
"maxcomplexity": 15,
"newcap": true,
"noarg": true,
"node": true,
"noempty": true,
"nonstandard": true,
"quotmark": "single",
"regexp": true,
"smarttabs": true,
"strict": false,
"trailing": true,
"undef": true,
"unused": true
}

View File

@@ -0,0 +1 @@
1.9.3-p551

View File

@@ -0,0 +1,7 @@
language: node_js
node_js:
- "8.9.3"
before_script:
- npm install -g grunt-cli
- npm install
script: grunt test

View File

@@ -0,0 +1,914 @@
== v1.14.15 (Mar/08 2018 22:59 +0000 by Igor Escobar) ==
Bugfixes:
* rolling back change to fix caret positioning. it didnt worked on some devices
== v1.14.14 (Mar/02 2018 16:55 +0000 by Igor Escobar) ==
Bugfixes:
* fixing mask positioning delays
* unmask: also removing place holder if added on the first place.
* unmask: unsetting maxlength if we set it in the first place
== v1.14.13 (Dec/11 2017 18:59 +0000 by Igor Escobar) ==
Bugfixes:
* fixes caret issue explained on #636
* fixing use strict issue
== v1.14.12 (Oct/04 2017 09:57 +0100 by Igor Escobar) ==
Bugfixes:
* bug fixing on caret positioning on some devices
== v1.14.11 (May/30 2017 21:53 +0100 by Igor Escobar) ==
Bugfixes:
* fixing a lot of caret positioning issues. Thanks to @onuradsay
== v1.14.10 (Feb/13 2017 14:18 +0000 by Igor Escobar) ==
Bugfixes:
* fixing exception when oValue in undefined
== v1.14.9 (Jan/25 2017 11:17 +0000 by Igor Escobar) ==
Bugfixes:
* dont use input event when using samsung browser or old chrome versions
== v1.14.8 (Dec/26 2016 13:18 +0000 by Igor Escobar) ==
Bugfixes:
* fixing caret on android with chrome 28
== v1.14.7 (Dec/25 2016 03:51 +0000 by Igor Escobar) ==
Bugfixes:
* improving caret positioning when cursor is on the middle
== v1.14.6 (Dec/24 2016 17:14 +0000 by Igor Escobar) ==
Bugfixes:
* fix caret positioning with multiple mask chars
== v1.14.5 (Dec/24 2016 14:42 +0000 by Igor Escobar) ==
Changes:
* fixing reserved word
== v1.14.4 (Dec/24 2016 14:38 +0000 by Igor Escobar) ==
Bugfixes:
* fixing android cursor positioning (special thanks to @felipejunges and @fernandobandeira)
== v1.14.3 (Nov/28 2016 11:53 +0000 by Igor Escobar) ==
Bugfixes:
* fixing caret positioning on safari
== v1.14.2 (Nov/27 2016 20:04 +0000 by Igor Escobar) ==
Bugfixes:
* apply auto maxlength in case the mask doesn't have recursive pattern
== v1.14.1 (Nov/27 2016 19:20 +0000 by Igor Escobar) ==
Bugfixes:
* Fix input value mangling when inserting before a static mask character
* fixing caret position issue
== v1.14.0 (Apr/03 2016 17:52 +0100 by Igor Escobar) ==
Bugfixes:
* Fix cursor jumping while editing in non-IE browsers. Thanks to @archwyrm
Features:
* adding masked function for better angular use
== v1.13.9 (Mar/20 2016 16:17 +0000 by Igor Escobar) ==
Changes:
* giving the opportunity to pass watchInputs locally
== v1.13.8 (Mar/06 2016 23:25 +0000 by Igor Escobar) ==
Changes:
* adding support for meteor
== v1.13.7 (Mar/06 2016 22:46 +0000 by Igor Escobar) ==
Bugfixes:
* fixing onChange behaviour
== v1.13.6 (Mar/06 2016 22:14 +0000 by Igor Escobar) ==
Bugfixes:
* fixing deploy procedure
== v1.13.5 (Mar/06 2016 22:01 +0000 by Igor Escobar) ==
Changes:
* adding clearIfNotMatch to globalOptions
Bugfixes:
* fixing some bugs when using non-input elements
* fixing mobile issues at #348.
* using input event when supported
== v1.13.4 (Aug/07 2015 14:21 +0100 by Igor Escobar) ==
Bugfixes:
* Add check to ensure that there are input elements before using them
== v1.13.3 (Jul/16 2015 16:11 +0100 by Igor Escobar) ==
Changes:
* adding main property to package.json
== v1.13.2 (Jul/16 2015 16:06 +0100 by Igor Escobar) ==
Bugfixes:
* change event wasnt being triggered in some cases
== v1.13.1 (Jul/07 2015 15:38 +0100 by Igor Escobar) ==
Bugfixes:
* destroying input event too
== v1.13.0 (Jul/07 2015 15:26 +0100 by Igor Escobar) ==
Changes:
* removing the autocomplete default.
Bugfixes:
* fixing bower file thanks to @lazyants
Features:
* prevent glitch when invalid chars.
* turning off autocomplete when browsers doesn't support oninput event.
== v1.12.0 (Jul/07 2015 11:37 +0100 by Igor Escobar) ==
Features:
* giving an alternative to the autocomplete/autofill problem.
== v1.11.4 (Feb/26 2015 22:11 +0000 by Igor Escobar) ==
Changes:
* grunt, jshint and better applyDataMask. Thanks to @lagden
* automated deploy to npm
== v1.11.3 (Jan/28 2015 15:41 +0000 by Igor Escobar) ==
Changes:
* Added commonjs module definition
== v1.11.2 (Dec/26 2014 15:36 +0000 by Igor Escobar) ==
Bugfixes:
* unreachable code
== v1.11.1 (Dec/26 2014 15:34 +0000 by Igor Escobar) ==
Bugfixes:
* unreachable code
== v1.11.0 (Dec/26 2014 15:33 +0000 by Igor Escobar) ==
Features:
* implementing selectOnFocus and data-mask-selectonfocus option
* adding public method called: .applyDataMask in case you want to decide whether to apply masks in data-mask fields
== v1.10.13 (Nov/19 2014 16:06 +0000 by Igor Escobar) ==
Bugfixes:
* fixing bug with watchInputs feature when mask is used as a function and not a string.
== v1.10.12 (Nov/06 2014 13:08 +0000 by Igor Escobar) ==
Changes:
* making a few improvements to make selection, copy events easier
== v1.10.11 (Nov/06 2014 11:26 +0000 by Igor Escobar) ==
Bugfixes:
* we need to revaluate dataMask flags everytime
== v1.10.10 (Nov/06 2014 10:41 +0000 by Igor Escobar) ==
Bugfixes:
* fixing dynamically data-mask added elements
== v1.10.9 (Nov/05 2014 10:52 +0000 by Igor Escobar) ==
Bugfixes:
* data-mask wasnt working
== v1.10.8 (Nov/01 2014 13:49 +0000 by Igor Escobar) ==
Changes:
* we dont need to seek for data-mask every time
== v1.10.7 (Nov/01 2014 13:18 +0000 by Igor Escobar) ==
Changes:
* little optimization
== v1.10.6 (Oct/28 2014 13:59 +0000 by Igor Escobar) ==
Bugfixes:
* fixing weird cursor problems in weird cases.
* dynamically added inputs wasnt working
== v1.10.5 (Oct/23 2014 11:41 +0100 by Igor Escobar) ==
Bugfixes:
* fixing weird cursor problems in weird cases.
== v1.10.4 (Oct/23 2014 11:02 +0100 by Igor Escobar) ==
Bugfixes:
* fixing on the fly mask change feature.
== v1.10.3 (Oct/22 2014 09:50 +0100 by Igor Escobar) ==
Bugfixes:
* fixing unmask method.
== v1.10.2 (Oct/20 2014 16:38 +0100 by Igor Escobar) ==
Bugfixes:
* onChange event fired at the wrong time when the field already has a value.
== v1.10.1 (Oct/20 2014 16:08 +0100 by Igor Escobar) ==
Bugfixes:
* fixing onChange event behaviour
== v1.10.0 (Oct/20 2014 10:56 +0100 by Igor Escobar) ==
Features:
* adding a way to change global settings like translation object and the byPassKeys object.
== v1.9.2 (Oct/20 2014 10:08 +0100 by Igor Escobar) ==
Bugfixes:
* fixing fallback digits implementation. Thanks @A1rPun
== v1.9.1 (Oct/18 2014 12:27 +0100 by Igor Escobar) ==
Bugfixes:
* cant convert circular json exception
== v1.9.0 (Oct/18 2014 12:07 +0100 by Igor Escobar) ==
Features:
* adding onInvalid callback
== v1.8.0 (Oct/17 2014 11:35 +0100 by Igor Escobar) ==
Changes:
* removing automatic maxlength support
* making a few optimizations to make it faster and retro compatible with other libraries
* creating globalOptions to make it more fast and flexible
Bugfixes:
* fixing issue #196
Features:
* adding the fallback translation option
== v1.7.8 (Oct/15 2014 10:55 +0100 by Igor Escobar) ==
Bugfixes:
* change event may experience issues
* avoid maximum call stack trace error
== v1.7.7 (Sep/10 2014 22:31 +0100 by Igor Escobar) ==
Bugfixes:
* fixing clojure compile issue
== v1.7.6 (Sep/10 2014 22:14 +0100 by Igor Escobar) ==
Bugfixes:
* fixing clearifnotmatch in masks with literal digits
== v1.7.5 (Sep/09 2014 15:43 +0100 by Igor Escobar) ==
Bugfixes:
* fixing paste inside of empty fields.
== v1.7.4 (Aug/11 2014 14:53 +0100 by Igor Escobar) ==
Changes:
* smaller and reliable code
== v1.7.3 (Aug/11 2014 11:28 +0100 by Igor Escobar) ==
Bugfixes:
* fixing issue #185
== v1.7.2 (Aug/08 2014 11:11 +0100 by Igor Escobar) ==
Changes:
* smaller code
Bugfixes:
* fixing remove bug
== v1.7.1 (Aug/08 2014 00:55 +0100 by Igor Escobar) ==
Changes:
* upgrading zepto, smaller syntax and fixing build
== v1.7.0 (Aug/07 2014 23:56 +0100 by Igor Escobar) ==
Features:
* applying masks to dynamically added elements. (html/javascript notation)
== v1.6.5 (Jun/30 2014 10:24 +0100 by Igor Escobar) ==
Bugfixes:
* fixing clearIfNotMatch feature in cases of optional and recursive digits
== v1.6.4 (May/08 2014 23:54 +0100 by Igor Escobar) ==
Changes:
* testing some deployment stunts
== v1.6.3 (May/08 2014 23:51 +0100 by Igor Escobar) ==
Changes:
* testing some deployment stunts
== v1.6.2 (May/08 2014 23:45 +0100 by Igor Escobar) ==
Bugfixes:
* fuckin typo
== v1.6.1 (May/08 2014 23:39 +0100 by Igor Escobar) ==
Bugfixes:
* fixing autofocus bug
== v1.6.0 (May/07 2014 21:13 +0100 by Igor Escobar) ==
Bugfixes:
* fixing autofocus bug
Features:
* adding support to the clearIfNotMatch option
* HTML5 placeholder support
== v1.5.7 (May/01 2014 18:37 +0100 by Igor Escobar) ==
Changes:
* some cleanup and stuff
== v1.5.6 (May/01 2014 18:30 +0100 by Igor Escobar) ==
Bugfixes:
* Bug in calculating difference between mask characters between old and new field values
* Fix stack limit exceeded
== v1.5.5 (Apr/27 2014 13:47 +0100 by Igor Escobar) ==
Changes:
* UMD (Universal Module Definition) patterns for JavaScript modules
Bugfixes:
* caret position correction
* 114 - Fix onChange Event error
== v1.5.4 (Feb/09 2014 12:02 +0000 by Igor Escobar) ==
Changes:
* optmizing code
== v1.5.3 (Feb/08 2014 14:59 +0000 by Igor Escobar) ==
Bugfixes:
* fixing ctrl a bug
== v1.5.2 (Dec/20 2013 16:35 +0000 by Igor Escobar) ==
Changes:
* smaller source code
== v1.5.1 (Dec/18 2013 22:34 +0000 by Igor Escobar) ==
Changes:
* fixing some code climate problems
== v1.5.0 (Dec/18 2013 22:10 +0000 by Igor Escobar) ==
Bugfixes:
* fixing getCleanVal()
Features:
* new public method called cleanVal
== v1.4.2 (Dec/16 2013 15:48 +0000 by Igor Escobar) ==
Bugfixes:
* Dirty fix for masks not completing with a literal
== v1.4.1 (Dec/09 2013 21:23 +0000 by Igor Escobar) ==
Changes:
* revising ignored keys
== v1.4.0 (Nov/28 2013 18:06 +0000 by Igor Escobar) ==
Features:
* caret positioning implementation
== v1.3.1 (Oct/08 2013 20:38 +0100 by Igor Escobar) ==
Changes:
* adding more keys to ignore list to make the char navigation smoothly
Bugfixes:
* Sounds like 'options' has disappeared for some reason
== v1.3.0 (Sep/13 2013 10:37 +0100 by Igor Escobar) ==
Features:
* creating the maxlength option
== v1.2.0 (Sep/07 2013 12:07 +0100 by Igor Escobar) ==
Features:
* adding the possibility to put recursive digits inside masks
== v1.1.3 (Sep/04 2013 21:21 +0100 by Igor Escobar) ==
Bugfixes:
* fixing late masking
== v1.1.2 (Aug/26 2013 15:08 +0100 by Igor Escobar) ==
Bugfixes:
* fixing mask on div,span etc
== v1.1.1 (Aug/26 2013 14:42 +0100 by Igor Escobar) ==
Bugfixes:
* better callback handling
== v1.1.0 (Aug/24 2013 15:59 +0100 by Igor Escobar) ==
Features:
* adding onchange support
== v1.0.3 (Aug/23 2013 23:10 +0100 by Igor Escobar) ==
Changes:
* optimizations to mask on non html fields
== v1.0.2 (Aug/23 2013 22:46 +0100 by Igor Escobar) ==
Bugfixes:
* adding remask method do improve callback performance
== v1.0.1 (Aug/23 2013 22:01 +0100 by Igor Escobar) ==
Changes:
* normal releases again
== v1.0.0 (Aug/23 2013 21:59 +0100 by Igor Escobar) ==
Features:
* huge refactoring focusing no reduce source code weight and bugfixing
== v0.11.5 (Aug/20 2013 17:11 +0100 by Igor Escobar) ==
Bugfixes:
* bug fixing when mask range is bigger than 2 digits.
== v0.11.4 (Aug/19 2013 10:24 +0100 by Igor Escobar) ==
Changes:
* adding de delete key to byPassKeys
== v0.11.3 (Aug/18 2013 00:48 +0100 by Igor Escobar) ==
Bugfixes:
* fixing zepto compatibily
== v0.11.2 (Aug/17 2013 18:39 +0100 by Igor Escobar) ==
Bugfixes:
* jmask iterate all items
== v0.11.1 (Aug/17 2013 18:32 +0100 by Igor Escobar) ==
Changes:
* a little bit smaller source code
== v0.11.0 (Aug/16 2013 21:27 +0100 by Igor Escobar) ==
Bugfixes:
* Altered "ignored keys" hook to run events (i.e. onKeyPress) afterwards. Otherwise, we miss key triggered events when the user deletes the entire text box, etc.
Features:
* adding support to method getCleanVal
== v0.10.1 (Jul/26 2013 09:35 +0100 by ) ==
== v0.10.0 (Jul/19 2013 23:07 +0100 by Igor Escobar) ==
Features:
* adding data-mask support
== v0.9.1 (Jul/19 2013 22:35 +0100 by Igor Escobar) ==
Changes:
* jQuery-Mask-Plugin is now available at bower.io
Bugfixes:
* fixing addEventListener on IE7
== v0.9.0 (Apr/24 2013 07:44 +0100 by Igor Escobar) ==
Features:
* Adding compatibility with Zepto.js
== v0.8.0 (Apr/07 2013 18:39 +0100 by Igor Escobar) ==
Features:
* applying masks anything != than input :)
* implementing the possibility of range chars ex: A{1,3}
== v0.7.11 (Apr/05 2013 22:12 +0100 by Igor Escobar) ==
Changes:
* now when you type a wrong char, the plugin will make your text fit inside of the mask instead of lose your data.
== v0.7.10 (Apr/04 2013 22:14 +0100 by Igor Escobar) ==
Changes:
* changing yui-compressor to clojure-compiler
== v0.7.9 (Apr/04 2013 22:04 +0100 by Igor Escobar) ==
Changes:
* refactoring and implementation of optional mask digits
Bugfixes:
* fixing maxlength and adding a smarter mask removal. issue #18
== v0.7.8 (Mar/30 2013 00:48 +0000 by Igor Escobar) ==
Changes:
* a few changes to get the code smallest possible.
* removing unnecessary methods and making code smaller.
== v0.7.7 (Mar/29 2013 12:38 +0000 by Igor Escobar) ==
Bugfixes:
* fixing copy and paste problem related on issue #15
== v0.7.6 (Mar/29 2013 00:28 +0000 by Igor Escobar) ==
Bugfixes:
* correcting mask formatationg problem related on issue #16
== v0.7.5 (Mar/03 2013 20:56 +0000 by Igor Escobar) ==
Changes:
* generating .gz file on deploy
== v0.7.4 (Mar/03 2013 20:38 +0000 by Igor Escobar) ==
Changes:
* changing minifier jsmin to yui compressor.
== v0.7.3 (Mar/02 2013 01:12 +0000 by Igor Escobar) ==
Bugfixes:
* bug fixing when typed wrong data type on mixing masks.
== v0.7.2 (Feb/24 2013 22:02 +0000 by Igor Escobar) ==
Bugfixes:
* fuckin stupid comma.
== v0.7.1 (Feb/24 2013 21:57 +0000 by Igor Escobar) ==
Changes:
* testing the private method maskToRegex
* a little bit of changes to make the code more testable
== v0.7.0 (Feb/12 2013 00:30 +0000 by Igor Escobar) ==
Features:
* Now you can decide for jquery mask plugin how to interpret 0 to 9, A and S and even teach him how to reconize patterns.
== v0.6.3 (Feb/11 2013 12:20 +0000 by Igor Escobar) ==
Bugfixes:
* When the user paste a text and the last char is valid sanitize may fail
== v0.6.2 (Feb/11 2013 00:02 +0000 by Igor Escobar) ==
Bugfixes:
* allowing the user type the same character as the mask without erasing it.
== v0.6.1 (Jan/20 2013 23:57 +0000 by Igor Escobar) ==
Changes:
* changing the way ta deployment occurs to correct jquery plugins deployments.
== v0.6.0 (Jan/18 2013 17:19 +0000 by Igor Escobar) ==
Changes:
* Now pushing jQuery Mask Plugin to jQuery Plugins Repository
== v0.5.4 (Jan/17 2013 23:06 +0000 by Igor Escobar) ==
Changes:
* upgrading jquery plugins manifest file
== v0.5.3 (Jan/17 2013 22:48 +0000 by Igor Escobar) ==
Bugfixes:
* correctly generating jmask version inside of jquery mask source
== v0.5.2 (Jan/17 2013 22:43 +0000 by Igor Escobar) ==
Changes:
* Now pushing to jQuery Plugin Repository
== v0.5.1 (Jan/07 2013 23:33 +0000 by Igor Escobar) ==
Changes:
* improving the deploy process with the new stepup's upgrade.
== v0.5.0 (Oct/27 2012 13:40 +0100 by Igor Escobar) ==
Bugfixes:
* Bug fixes on OnSupport method with Firefox.
Features:
* the first parameter of the .mask() function, now accepts a string or a anonymous function
== v0.4.7 (Aug/06 2012 22:56 +0100 by Igor Escobar) ==
Changes:
* Nothing big, just class refactoring
== v0.4.6 (Aug/06 2012 01:25 +0100 by Igor Escobar) ==
Changes:
- better OOP design
- implementing the jquery data object on each mask field
- implementing the public method .remove to disable and remove the mask
== v0.4.5 (Aug/04 2012 01:31 +0100 by Igor Escobar) ==
Changes:
- improving support to complex jquery selectors
- performance improvement.
- callback handling improvement
== v0.4.4 (Jun/03 2012 21:01 +0100 by Igor Escobar) ==
Bugfixes:
* Bug fixes on Internet Explorer 8.
== v0.4.3 (Mar/19 2012 21:52 +0000 by Igor Escobar) ==
Bugfixes:
* Corrigindo bug para mascaras com +
== v0.4.2 (Mar/18 2012 15:28 +0000 by Igor Escobar) ==
Bugfixes:
* Mascara não pararecia no firefox
== v0.4.1 (Mar/18 2012 15:01 +0000 by Igor Escobar) ==
Bugfixes:
* Corrigindo tim das macaras.
== v0.4.0 (Mar/18 2012 14:51 +0000 by Igor Escobar) ==
Features:
* Implementado mascara reversa para moeda/cpf/rg/etc.
* Nova engine.
== v0.3.0 (Mar/14 2012 10:14 +0000 by Igor Escobar) ==
Changes:
* License and comments up to date.
Features:
* On-the-fly mask change.
* onComplete and onKeyPress new callbacks.
== v0.2.5 (Mar/13 2012 22:55 +0000 by Igor Escobar) ==
Bugfixes:
- Corrigindo ctrl+v com mascara errada. - Cortando dados que exceder a mascara no ctrl+v ou se segurar alguma tecla. - Refatorando algumas partes do código.
== v0.2.4 (Mar/13 2012 11:06 +0000 by Igor Escobar) ==
Changes:
* Codigo refatorado, otimizado, validação mais precisa e efetiva.
== v0.2.3 (Mar/13 2012 01:01 +0000 by Igor Escobar) ==
Changes:
* Melhorando expressoes regulares.
== v0.2.2 (Mar/13 2012 00:50 +0000 by Igor Escobar) ==
Bugfixes:
* Corrindo regex de validação
== v0.2.1 (Mar/13 2012 00:41 +0000 by Igor Escobar) ==
Bugfixes:
* Corrigida validação alphanumerica.
== v0.2.0 (Mar/13 2012 00:24 +0000 by Igor Escobar) ==
Features:
- Input Data Type Validation.
- Automatic MaxLength (When are not defined).
- Live Event Implemented for Ajax-based Apps.
- Mixed mask with validation.
* S for string digit
* A for alphanumeric digit
* 0 to 9 for numeric digit.
== v0.1.1 (Mar/10 2012 14:05 +0000 by Igor Escobar) ==
Bugfixes:
* Implementando Crossbrowser event handling.
== v0.1.0 (Mar/10 2012 13:10 +0000 by Igor Escobar) ==
Features:
* Implementando mascaras com espaço para data e hora
== v0.0.1 (Mar/10 2012 04:42 +0000 by Igor Escobar) ==
Changes:
* Refatorando o codigo para suportar multiplas instancias

View File

@@ -0,0 +1,9 @@
### Have you take a look into our docs?
https://igorescobar.github.io/jQuery-Mask-Plugin/
### Want to contribute? Make sure you read this first
https://github.com/igorescobar/jQuery-Mask-Plugin#contributing
Is this plugin helping you out? Buy me a beer and cheers! :beer:
:bowtie: https://www.paypal.me/igorcescobar

View File

@@ -0,0 +1,36 @@
FROM phusion/baseimage:0.9.17
# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]
# Java 8 for Google's clojure compiler
RUN \
echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && \
echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list && \
add-apt-repository -y ppa:webupd8team/java && \
apt-get update && \
apt-get install -y oracle-java8-installer git unzip ruby-full && \
rm -rf /var/lib/apt/lists/* && \
rm -rf /var/cache/oracle-jdk8-installer
# Define commonly used JAVA_HOME variable
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
RUN mkdir /app
RUN mkdir /app/clojure-compiler
# Clojure compiler
RUN \
curl -O http://dl.google.com/closure-compiler/compiler-latest.zip && \
unzip compiler-latest.zip -d /app/clojure-compiler && \
chmod a+x /app/clojure-compiler && \
rm compiler-latest.zip
RUN gem install bundler pry step-up --no-rdoc --no-ri
# Install Node.js
RUN curl --silent --location https://deb.nodesource.com/setup_0.12 | sudo bash -
RUN apt-get install --yes nodejs
RUN npm install -g grunt-cli
WORKDIR /app/jquery-mask-plugin

View File

@@ -0,0 +1,43 @@
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);
grunt.initConfig({
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: ['src/{,*/}*.js']
},
connect: {
server: {
options: {
port: 9001,
base: './'
}
}
},
qunit: {
all: {
options: {
urls: [
'http://localhost:9001/test/test-for-jquery-1.11.1.html',
'http://localhost:9001/test/test-for-jquery-1.7.2.html',
'http://localhost:9001/test/test-for-jquery-1.8.3.html',
'http://localhost:9001/test/test-for-jquery-1.9.1.html',
'http://localhost:9001/test/test-for-jquery-2.1.1.html',
'http://localhost:9001/test/test-for-jquery-3.0.0.html',
'http://localhost:9001/test/test-for-zepto.html'
]
}
}
}
});
// A convenient task alias.
grunt.registerTask('test', ['jshint', 'connect', 'qunit']);
grunt.registerTask('default', ['test']);
};

View File

@@ -0,0 +1,22 @@
### Have you take a look into our docs?
https://igorescobar.github.io/jQuery-Mask-Plugin/
### Make sure your read this before opening a new issue:
https://github.com/igorescobar/jQuery-Mask-Plugin#problems-or-questions
#### Device
[...]
#### Browser (and version)?
[...]
#### Functional `jsfiddle` exemplifying your problem:
You can use this one as exemple: http://jsfiddle.net/igorescobar/6pco4om7/
#### Describe de problem depth:
[...]
Is this plugin helping you out? Buy me a beer and cheers! :beer:
:bowtie: https://www.paypal.me/igorcescobar

View File

@@ -0,0 +1,26 @@
Created by Igor Escobar on 2012-03-10. Please report any bug at http://blog.igorescobar.com
Copyright (c) 2012 Igor Escobar http://blog.igorescobar.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.

View File

@@ -0,0 +1,137 @@
# jQuery Mask Plugin
A jQuery Plugin to make masks on form fields and HTML elements.
[![Build Status](https://travis-ci.org/igorescobar/jQuery-Mask-Plugin.png)](https://travis-ci.org/igorescobar/jQuery-Mask-Plugin)
[![Code Climate](https://codeclimate.com/github/igorescobar/jQuery-Mask-Plugin.png)](https://codeclimate.com/github/igorescobar/jQuery-Mask-Plugin)
[![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/jquery-mask-plugin/badge?style=rounded)](https://www.jsdelivr.com/package/npm/jquery-mask-plugin)
[![CDNJS](https://img.shields.io/cdnjs/v/jquery.mask.svg)](https://cdnjs.com/libraries/jquery.mask)
# Documentation, Demos & Usage Examples
https://igorescobar.github.io/jQuery-Mask-Plugin/
## Features
* Lightweight (~2kb minified, ~1kb gziped).
* Built-in support for dynamically added elements.
* Masks on any HTML element (no need to server-side mask anymore!)!
* HTML notation support (data-mask, data-mask-recursive, data-mask-clearifnotmatch).
* String/Numeric/Alpha/Mixed masks.
* Reverse mask support for masks on numeric fields.
* Sanitization.
* Optional digits.
* Recursive Digits.
* Fallback Digits.
* Advanced mask initialization.
* Advanced Callbacks.
* On-the-fly mask change.
* Mask removal.
* Full customization.
* Compatibility with React/UMD/Zepto.js/Angular.JS.
* HTML5 placeholder support.
* Clear the field if it not matches support.
## Want to buy me a beer? :heart_eyes:
http://paypal.me/igorcescobar
## Install it via Package Managers
### Bower
`bower install jquery-mask-plugin`
### NPM
`npm i jquery-mask-plugin`
### Meteor
`meteor add igorescobar:jquery-mask-plugin`
### Packagist/Composer
`composer require igorescobar/jquery-mask-plugin`
## CDNs
### CDNjs
https://cdnjs.com/libraries/jquery.mask
### JSDelivr
http://www.jsdelivr.com/projects/jquery.mask
## RubyGems
```ruby
gem 'jquery_mask_rails' # more details at http://bit.ly/jquery-mask-gem
```
## Tutorials
### English
* [Masks with jQuery Mask Plugin](http://bit.ly/masks-with-jquery-mask-plugin)
* [Using jQuery Mask Plugin With Zepto.js](http://bit.ly/using-jquery-mask-plugin-with-zeptojs)
### Portuguese
* [Mascaras com JQuery Mask Plugin](http://bit.ly/mascaras-com-jquery-mask-plugin)
* [Mascara Javascript para os novos telefones de São Paulo](http://bit.ly/mascara-javascript-para-os-novos-telefones-de-sao-paulo)
### Fun (or not) facts
* [Ive had the chance to troll Donald Trump. But I didnt.](http://www.igorescobar.com/blog/2016/08/21/ive-the-chance-to-troll-donald-trump-but-i-didnt/)
## Compatibility
jQuery Mask Plugin has been tested with jQuery 1.7+ on all major browsers:
* Firefox 2+ (Win, Mac, Linux);
* IE7+ (Win);
* Chrome 6+ (Win, Mac, Linux, Android, iPhone);
* Safari 3.2+ (Win, Mac, iPhone);
* Opera 8+ (Win, Mac, Linux, Android, iPhone).
* Android Default Browser v4+
## Typescript support
Definition can be found [here](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/jquery-mask-plugin).
To install, open terminal and navigate to your working directory.
### Typescript 1.x users
* Install [typings](https://github.com/typings/typings) by running `npm install typings --global`.
* Then install the definition by running `typings install dt~jquery-mask-plugin --global --save`.
### Typescript 2.x users
* Use npm `npm install --save-dev @types/jquery-mask-plugin`.
For configuration options and troubleshooting refer to these repositories:
* [Typings](https://github.com/typings/typings)
* [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped)
* [Typescript](https://github.com/Microsoft/TypeScript)
## Problems or Questions?
Before opening a new [issue](https://github.com/igorescobar/jQuery-Mask-Plugin/issues) take a look on those frequently asked questions:
#### [How to integrate with React.js?](https://github.com/igorescobar/jQuery-Mask-Plugin/issues/498)
#### [How to integrate with Angular.js?](https://github.com/igorescobar/jQuery-Mask-Plugin/issues/499)
#### [How to integrate with Vue.js?](https://github.com/ankurk91/vue-jquery-mask)
#### [Problems with old versions of Android keyboard](https://github.com/igorescobar/jQuery-Mask-Plugin/issues/135)
#### [Negative numbers, or currency related problems](https://github.com/igorescobar/jQuery-Mask-Plugin/issues/436#issuecomment-253176511)
#### [Prefix or sufix on the Mask](https://github.com/igorescobar/jQuery-Mask-Plugin/issues/166)
#### [Add validation?](https://github.com/igorescobar/jQuery-Mask-Plugin/issues/387#issuecomment-192998092)
#### [Field type number, email not working?](https://github.com/igorescobar/jQuery-Mask-Plugin/issues/450#issuecomment-253225719)
#### [Want to keep the placeholder as the user types?](https://github.com/igorescobar/jQuery-Mask-Plugin/issues/633#issuecomment-350819224)
#### [E-mail mask?](https://github.com/igorescobar/jQuery-Mask-Plugin/issues/582)
## Bugs?
Did you read our [docs](https://igorescobar.github.io/jQuery-Mask-Plugin/docs.html)? Yes? Cool! So now... make sure that you have a *functional* [jsfiddle](http://jsfiddle.net/) exemplifying your problem and open an [issue](https://github.com/igorescobar/jQuery-Mask-Plugin/issues) for us. Don't know how to do it? Use this [fiddle example](http://jsfiddle.net/igorescobar/6pco4om7/).
## Contributing
* **Bug Reporting**: Yes! You can contribute opening [issues](https://github.com/igorescobar/jQuery-Mask-Plugin/issues)!
* **Documenting**: Do you think that something in our [docs](https://github.com/igorescobar/jQuery-Mask-Plugin/tree/gh-pages) should be better? Do you have a cool idea to increase the awesomeness? Summit your pull request with your idea!
* **Bug Fixing**: No time to lose? Fix it and help others! Write some [tests](https://github.com/igorescobar/jQuery-Mask-Plugin/tree/master/test) to make sure that everything are working propertly.
* **Improving**: Open an [issue](https://github.com/igorescobar/jQuery-Mask-Plugin/issues) and lets discuss it. Just to make sure that you're on the right track.
* **Sharing**: Yes! Have we saved some of your time? Are you enjoying our mask plugin? Sharing is caring! Tweet it! Facebook it! Linkedin It(?!) :D
* **Donating**: Hey, now that you don't need to worry about masks again... buy me a coffee, beer or a PlayStation 4 (Xbox One also accepted!) :o)
### Unit Tests
We use [QUnit](http://qunitjs.com/) and [GruntJS](http://gruntjs.com/). To run our test suit is just run: ```grunt test``` in your console or you can open those ```test-for*.html``` files inside of our ```test/``` folder.
In case you're familiar with [Docker](https://www.docker.com/) here is how you can use it:
```bash
docker build -t jquery-mask .
CONTAINER_ID=$(docker run -d -v $PWD:/app/jquery-mask-plugin jquery-mask)
docker exec $CONTAINER_ID sh -c "npm install"
docker exec -it $CONTAINER_ID /bin/bash
grunt test
```
## Contributors
* [Igor Lima](https://github.com/igorlima)
* [Mark Simmons](https://github.com/Markipelago)
* [Gabriel Schammah](https://github.com/gschammah)
* [Marcelo Manzan](https://github.com/kawamanza)
* [See the full list](https://github.com/igorescobar/jQuery-Mask-Plugin/graphs/contributors)

View File

@@ -0,0 +1,12 @@
{
"name": "jquery-mask-plugin",
"version": "1.14.15",
"main": "dist/jquery.mask.js",
"ignore": [
"deploy.rb",
"jquery.mask.json",
"Gruntfile.js",
"test/*",
".*"
]
}

View File

@@ -0,0 +1,10 @@
{
"name": "jQuery-Mask-Plugin",
"description": "A jQuery Plugin to make masks on form fields and HTML elements.",
"version": "1.14.15",
"keywords": ["javascript", "mask", "form"],
"scripts": [
"dist/jquery.mask.js"
],
"main": "dist/jquery.mask.js"
}

View File

@@ -0,0 +1,19 @@
{
"name": "igorescobar/jquery-mask-plugin",
"type": "library",
"description": "A jQuery Plugin to make masks on form fields and html elements.",
"keywords": ["jquery", "mask", "plugin"],
"homepage": "https://github.com/igorescobar/jQuery-Mask-Plugin",
"license": "MIT",
"authors": [
{
"name": "Igor Escobar",
"email": "blog@igorescobar.com",
"homepage": "https://about.me/igorescobar",
"role": "Developer"
}
],
"support": {
"issues": "https://github.com/igorescobar/jQuery-Mask-Plugin/issues"
}
}

View File

@@ -0,0 +1,77 @@
require 'rubygems'
require 'zlib'
JMASK_FILE = 'src/jquery.mask.js'
JMASK_MIN_FILE = 'dist/jquery.mask.min.js'
GHPAGES_JMASK_MIN_FILE = 'js/jquery.mask.min.js'
JMASK_VERSION = `stepup version --next-release`.delete("\n")
BOWER_MANIFEST_FILE = 'bower.json'
NPM_MANIFEST_FILE = 'package.json'
METEOR_MANIFEST_FILE = 'package.js'
COMPONENT_MANIFEST_FILE = 'component.json'
abort("No notes, do deal.") if JMASK_VERSION.empty?
puts '# PUTTING NEW VERSION INSIDE OF JQUERY MASK FILE'
unversioned_jmask_file = File.open(JMASK_FILE, 'rb') { |file| file.read }
File.open(JMASK_FILE, 'w') do |file|
file.write(unversioned_jmask_file.gsub(/\* @version: (v[0-9.+]+)/, "\* @version: #{JMASK_VERSION}"))
end
puts '# COPYING NEW JMASK FILE TO DIST/'
`yes | cp #{JMASK_FILE} dist/`
[BOWER_MANIFEST_FILE, NPM_MANIFEST_FILE, COMPONENT_MANIFEST_FILE, METEOR_MANIFEST_FILE].each { |manifest_name|
puts "# UPGRADING #{manifest_name} "
manifest_file = File.open(manifest_name, 'rb') { |file| file.read }
File.open(manifest_name, 'w') do |file|
file.write(manifest_file.gsub(/"version": "([0-9.+]+)"/, "\"version\": \"#{JMASK_VERSION.gsub("v", "")}\""))
end
}
puts '# GENERATING MIN FILE'
jquery_mask_min_file = nil
File.open(JMASK_FILE, 'r') do |file|
minFile = File.open(JMASK_MIN_FILE, 'w')
minFile.puts("// jQuery Mask Plugin #{JMASK_VERSION}")
minFile.puts("// github.com/igorescobar/jQuery-Mask-Plugin")
jquery_mask_min_file = `java -jar ../clojure-compiler/compiler.jar --js src/jquery.mask.js --charset UTF-8`
minFile.puts(jquery_mask_min_file)
minFile.close
end
puts '# GENERATING A NEW COMMIT WITH VERSIONED FILEs'
`git commit -am 'generating jquery mask files #{JMASK_VERSION}'`
puts '# PUSHING CHANGES TO REMOTE'
`git pull --rebase && git push`
puts '# CREATING NEW VERSION'
`stepup version create --no-editor`
puts '# UPGRATING CHANGELOG'
`stepup changelog --format=wiki > CHANGELOG.md`
`git commit -am "upgrading changelog"`
`git push`
puts '# UPGRADING gh-pages'
`git checkout gh-pages`
`git pull origin gh-pages`
minFile = File.open(GHPAGES_JMASK_MIN_FILE, 'w')
minFile.puts("// jQuery Mask Plugin #{JMASK_VERSION}")
minFile.puts("// github.com/igorescobar/jQuery-Mask-Plugin")
minFile.puts(jquery_mask_min_file)
minFile.close
`git commit -am "upgrading plugin file"`
`git push`
`git checkout master`
puts '# PUBLISHING NPM PACKAGE'
`npm publish`
puts '# PUBLISHING METEOR PACKAGE'
`meteor publish`
puts '# DONE!'

View File

@@ -0,0 +1,604 @@
/**
* jquery.mask.js
* @version: v1.14.15
* @author: Igor Escobar
*
* Created by Igor Escobar on 2012-03-10. Please report any bug at github.com/igorescobar/jQuery-Mask-Plugin
*
* Copyright (c) 2012 Igor Escobar http://igorescobar.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.
*/
/* jshint laxbreak: true */
/* jshint maxcomplexity:17 */
/* global define */
// UMD (Universal Module Definition) patterns for JavaScript modules that work everywhere.
// https://github.com/umdjs/umd/blob/master/templates/jqueryPlugin.js
(function (factory, jQuery, Zepto) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports === 'object') {
module.exports = factory(require('jquery'));
} else {
factory(jQuery || Zepto);
}
}(function ($) {
'use strict';
var Mask = function (el, mask, options) {
var p = {
invalid: [],
getCaret: function () {
try {
var sel,
pos = 0,
ctrl = el.get(0),
dSel = document.selection,
cSelStart = ctrl.selectionStart;
// IE Support
if (dSel && navigator.appVersion.indexOf('MSIE 10') === -1) {
sel = dSel.createRange();
sel.moveStart('character', -p.val().length);
pos = sel.text.length;
}
// Firefox support
else if (cSelStart || cSelStart === '0') {
pos = cSelStart;
}
return pos;
} catch (e) {}
},
setCaret: function(pos) {
try {
if (el.is(':focus')) {
var range, ctrl = el.get(0);
// Firefox, WebKit, etc..
if (ctrl.setSelectionRange) {
ctrl.setSelectionRange(pos, pos);
} else { // IE
range = ctrl.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
} catch (e) {}
},
events: function() {
el
.on('keydown.mask', function(e) {
el.data('mask-keycode', e.keyCode || e.which);
el.data('mask-previus-value', el.val());
el.data('mask-previus-caret-pos', p.getCaret());
p.maskDigitPosMapOld = p.maskDigitPosMap;
})
.on($.jMaskGlobals.useInput ? 'input.mask' : 'keyup.mask', p.behaviour)
.on('paste.mask drop.mask', function() {
setTimeout(function() {
el.keydown().keyup();
}, 100);
})
.on('change.mask', function(){
el.data('changed', true);
})
.on('blur.mask', function(){
if (oldValue !== p.val() && !el.data('changed')) {
el.trigger('change');
}
el.data('changed', false);
})
// it's very important that this callback remains in this position
// otherwhise oldValue it's going to work buggy
.on('blur.mask', function() {
oldValue = p.val();
})
// select all text on focus
.on('focus.mask', function (e) {
if (options.selectOnFocus === true) {
$(e.target).select();
}
})
// clear the value if it not complete the mask
.on('focusout.mask', function() {
if (options.clearIfNotMatch && !regexMask.test(p.val())) {
p.val('');
}
});
},
getRegexMask: function() {
var maskChunks = [], translation, pattern, optional, recursive, oRecursive, r;
for (var i = 0; i < mask.length; i++) {
translation = jMask.translation[mask.charAt(i)];
if (translation) {
pattern = translation.pattern.toString().replace(/.{1}$|^.{1}/g, '');
optional = translation.optional;
recursive = translation.recursive;
if (recursive) {
maskChunks.push(mask.charAt(i));
oRecursive = {digit: mask.charAt(i), pattern: pattern};
} else {
maskChunks.push(!optional && !recursive ? pattern : (pattern + '?'));
}
} else {
maskChunks.push(mask.charAt(i).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
}
}
r = maskChunks.join('');
if (oRecursive) {
r = r.replace(new RegExp('(' + oRecursive.digit + '(.*' + oRecursive.digit + ')?)'), '($1)?')
.replace(new RegExp(oRecursive.digit, 'g'), oRecursive.pattern);
}
return new RegExp(r);
},
destroyEvents: function() {
el.off(['input', 'keydown', 'keyup', 'paste', 'drop', 'blur', 'focusout', ''].join('.mask '));
},
val: function(v) {
var isInput = el.is('input'),
method = isInput ? 'val' : 'text',
r;
if (arguments.length > 0) {
if (el[method]() !== v) {
el[method](v);
}
r = el;
} else {
r = el[method]();
}
return r;
},
calculateCaretPosition: function() {
var oldVal = el.data('mask-previus-value') || '',
newVal = p.getMasked(),
caretPosNew = p.getCaret();
if (oldVal !== newVal) {
var caretPosOld = el.data('mask-previus-caret-pos') || 0,
newValL = newVal.length,
oldValL = oldVal.length,
maskDigitsBeforeCaret = 0,
maskDigitsAfterCaret = 0,
maskDigitsBeforeCaretAll = 0,
maskDigitsBeforeCaretAllOld = 0,
i = 0;
for (i = caretPosNew; i < newValL; i++) {
if (!p.maskDigitPosMap[i]) {
break;
}
maskDigitsAfterCaret++;
}
for (i = caretPosNew - 1; i >= 0; i--) {
if (!p.maskDigitPosMap[i]) {
break;
}
maskDigitsBeforeCaret++;
}
for (i = caretPosNew - 1; i >= 0; i--) {
if (p.maskDigitPosMap[i]) {
maskDigitsBeforeCaretAll++;
}
}
for (i = caretPosOld - 1; i >= 0; i--) {
if (p.maskDigitPosMapOld[i]) {
maskDigitsBeforeCaretAllOld++;
}
}
// if the cursor is at the end keep it there
if (caretPosNew > oldValL) {
caretPosNew = newValL * 10;
} else if (caretPosOld >= caretPosNew && caretPosOld !== oldValL) {
if (!p.maskDigitPosMapOld[caretPosNew]) {
var caretPos = caretPosNew;
caretPosNew -= maskDigitsBeforeCaretAllOld - maskDigitsBeforeCaretAll;
caretPosNew -= maskDigitsBeforeCaret;
if (p.maskDigitPosMap[caretPosNew]) {
caretPosNew = caretPos;
}
}
}
else if (caretPosNew > caretPosOld) {
caretPosNew += maskDigitsBeforeCaretAll - maskDigitsBeforeCaretAllOld;
caretPosNew += maskDigitsAfterCaret;
}
}
return caretPosNew;
},
behaviour: function(e) {
e = e || window.event;
p.invalid = [];
var keyCode = el.data('mask-keycode');
if ($.inArray(keyCode, jMask.byPassKeys) === -1) {
var newVal = p.getMasked(),
caretPos = p.getCaret();
// this is a compensation to devices/browsers that don't compensate
// caret positioning the right way
setTimeout(function() {
p.setCaret(p.calculateCaretPosition());
}, $.jMaskGlobals.keyStrokeCompensation);
p.val(newVal);
p.setCaret(caretPos);
return p.callbacks(e);
}
},
getMasked: function(skipMaskChars, val) {
var buf = [],
value = val === undefined ? p.val() : val + '',
m = 0, maskLen = mask.length,
v = 0, valLen = value.length,
offset = 1, addMethod = 'push',
resetPos = -1,
maskDigitCount = 0,
maskDigitPosArr = [],
lastMaskChar,
check;
if (options.reverse) {
addMethod = 'unshift';
offset = -1;
lastMaskChar = 0;
m = maskLen - 1;
v = valLen - 1;
check = function () {
return m > -1 && v > -1;
};
} else {
lastMaskChar = maskLen - 1;
check = function () {
return m < maskLen && v < valLen;
};
}
var lastUntranslatedMaskChar;
while (check()) {
var maskDigit = mask.charAt(m),
valDigit = value.charAt(v),
translation = jMask.translation[maskDigit];
if (translation) {
if (valDigit.match(translation.pattern)) {
buf[addMethod](valDigit);
if (translation.recursive) {
if (resetPos === -1) {
resetPos = m;
} else if (m === lastMaskChar && m !== resetPos) {
m = resetPos - offset;
}
if (lastMaskChar === resetPos) {
m -= offset;
}
}
m += offset;
} else if (valDigit === lastUntranslatedMaskChar) {
// matched the last untranslated (raw) mask character that we encountered
// likely an insert offset the mask character from the last entry; fall
// through and only increment v
maskDigitCount--;
lastUntranslatedMaskChar = undefined;
} else if (translation.optional) {
m += offset;
v -= offset;
} else if (translation.fallback) {
buf[addMethod](translation.fallback);
m += offset;
v -= offset;
} else {
p.invalid.push({p: v, v: valDigit, e: translation.pattern});
}
v += offset;
} else {
if (!skipMaskChars) {
buf[addMethod](maskDigit);
}
if (valDigit === maskDigit) {
maskDigitPosArr.push(v);
v += offset;
} else {
lastUntranslatedMaskChar = maskDigit;
maskDigitPosArr.push(v + maskDigitCount);
maskDigitCount++;
}
m += offset;
}
}
var lastMaskCharDigit = mask.charAt(lastMaskChar);
if (maskLen === valLen + 1 && !jMask.translation[lastMaskCharDigit]) {
buf.push(lastMaskCharDigit);
}
var newVal = buf.join('');
p.mapMaskdigitPositions(newVal, maskDigitPosArr, valLen);
return newVal;
},
mapMaskdigitPositions: function(newVal, maskDigitPosArr, valLen) {
var maskDiff = options.reverse ? newVal.length - valLen : 0;
p.maskDigitPosMap = {};
for (var i = 0; i < maskDigitPosArr.length; i++) {
p.maskDigitPosMap[maskDigitPosArr[i] + maskDiff] = 1;
}
},
callbacks: function (e) {
var val = p.val(),
changed = val !== oldValue,
defaultArgs = [val, e, el, options],
callback = function(name, criteria, args) {
if (typeof options[name] === 'function' && criteria) {
options[name].apply(this, args);
}
};
callback('onChange', changed === true, defaultArgs);
callback('onKeyPress', changed === true, defaultArgs);
callback('onComplete', val.length === mask.length, defaultArgs);
callback('onInvalid', p.invalid.length > 0, [val, e, el, p.invalid, options]);
}
};
el = $(el);
var jMask = this, oldValue = p.val(), regexMask;
mask = typeof mask === 'function' ? mask(p.val(), undefined, el, options) : mask;
// public methods
jMask.mask = mask;
jMask.options = options;
jMask.remove = function() {
var caret = p.getCaret();
if (jMask.options.placeholder) {
el.removeAttr('placeholder');
}
if (el.data('mask-maxlength')) {
el.removeAttr('maxlength');
}
p.destroyEvents();
p.val(jMask.getCleanVal());
p.setCaret(caret);
return el;
};
// get value without mask
jMask.getCleanVal = function() {
return p.getMasked(true);
};
// get masked value without the value being in the input or element
jMask.getMaskedVal = function(val) {
return p.getMasked(false, val);
};
jMask.init = function(onlyMask) {
onlyMask = onlyMask || false;
options = options || {};
jMask.clearIfNotMatch = $.jMaskGlobals.clearIfNotMatch;
jMask.byPassKeys = $.jMaskGlobals.byPassKeys;
jMask.translation = $.extend({}, $.jMaskGlobals.translation, options.translation);
jMask = $.extend(true, {}, jMask, options);
regexMask = p.getRegexMask();
if (onlyMask) {
p.events();
p.val(p.getMasked());
} else {
if (options.placeholder) {
el.attr('placeholder' , options.placeholder);
}
// this is necessary, otherwise if the user submit the form
// and then press the "back" button, the autocomplete will erase
// the data. Works fine on IE9+, FF, Opera, Safari.
if (el.data('mask')) {
el.attr('autocomplete', 'off');
}
// detect if is necessary let the user type freely.
// for is a lot faster than forEach.
for (var i = 0, maxlength = true; i < mask.length; i++) {
var translation = jMask.translation[mask.charAt(i)];
if (translation && translation.recursive) {
maxlength = false;
break;
}
}
if (maxlength) {
el.attr('maxlength', mask.length).data('mask-maxlength', true);
}
p.destroyEvents();
p.events();
var caret = p.getCaret();
p.val(p.getMasked());
p.setCaret(caret);
}
};
jMask.init(!el.is('input'));
};
$.maskWatchers = {};
var HTMLAttributes = function () {
var input = $(this),
options = {},
prefix = 'data-mask-',
mask = input.attr('data-mask');
if (input.attr(prefix + 'reverse')) {
options.reverse = true;
}
if (input.attr(prefix + 'clearifnotmatch')) {
options.clearIfNotMatch = true;
}
if (input.attr(prefix + 'selectonfocus') === 'true') {
options.selectOnFocus = true;
}
if (notSameMaskObject(input, mask, options)) {
return input.data('mask', new Mask(this, mask, options));
}
},
notSameMaskObject = function(field, mask, options) {
options = options || {};
var maskObject = $(field).data('mask'),
stringify = JSON.stringify,
value = $(field).val() || $(field).text();
try {
if (typeof mask === 'function') {
mask = mask(value);
}
return typeof maskObject !== 'object' || stringify(maskObject.options) !== stringify(options) || maskObject.mask !== mask;
} catch (e) {}
},
eventSupported = function(eventName) {
var el = document.createElement('div'), isSupported;
eventName = 'on' + eventName;
isSupported = (eventName in el);
if ( !isSupported ) {
el.setAttribute(eventName, 'return;');
isSupported = typeof el[eventName] === 'function';
}
el = null;
return isSupported;
};
$.fn.mask = function(mask, options) {
options = options || {};
var selector = this.selector,
globals = $.jMaskGlobals,
interval = globals.watchInterval,
watchInputs = options.watchInputs || globals.watchInputs,
maskFunction = function() {
if (notSameMaskObject(this, mask, options)) {
return $(this).data('mask', new Mask(this, mask, options));
}
};
$(this).each(maskFunction);
if (selector && selector !== '' && watchInputs) {
clearInterval($.maskWatchers[selector]);
$.maskWatchers[selector] = setInterval(function(){
$(document).find(selector).each(maskFunction);
}, interval);
}
return this;
};
$.fn.masked = function(val) {
return this.data('mask').getMaskedVal(val);
};
$.fn.unmask = function() {
clearInterval($.maskWatchers[this.selector]);
delete $.maskWatchers[this.selector];
return this.each(function() {
var dataMask = $(this).data('mask');
if (dataMask) {
dataMask.remove().removeData('mask');
}
});
};
$.fn.cleanVal = function() {
return this.data('mask').getCleanVal();
};
$.applyDataMask = function(selector) {
selector = selector || $.jMaskGlobals.maskElements;
var $selector = (selector instanceof $) ? selector : $(selector);
$selector.filter($.jMaskGlobals.dataMaskAttr).each(HTMLAttributes);
};
var globals = {
maskElements: 'input,td,span,div',
dataMaskAttr: '*[data-mask]',
dataMask: true,
watchInterval: 300,
watchInputs: true,
keyStrokeCompensation: 10,
// old versions of chrome dont work great with input event
useInput: !/Chrome\/[2-4][0-9]|SamsungBrowser/.test(window.navigator.userAgent) && eventSupported('input'),
watchDataMask: false,
byPassKeys: [9, 16, 17, 18, 36, 37, 38, 39, 40, 91],
translation: {
'0': {pattern: /\d/},
'9': {pattern: /\d/, optional: true},
'#': {pattern: /\d/, recursive: true},
'A': {pattern: /[a-zA-Z0-9]/},
'S': {pattern: /[a-zA-Z]/}
}
};
$.jMaskGlobals = $.jMaskGlobals || {};
globals = $.jMaskGlobals = $.extend(true, {}, globals, $.jMaskGlobals);
// looking for inputs with data-mask attribute
if (globals.dataMask) {
$.applyDataMask();
}
setInterval(function() {
if ($.jMaskGlobals.watchDataMask) {
$.applyDataMask();
}
}, globals.watchInterval);
}, window.jQuery, window.Zepto));

View File

@@ -0,0 +1,19 @@
// jQuery Mask Plugin v1.14.15
// github.com/igorescobar/jQuery-Mask-Plugin
var $jscomp={scope:{},findInternal:function(a,l,d){a instanceof String&&(a=String(a));for(var p=a.length,h=0;h<p;h++){var b=a[h];if(l.call(d,b,h,a))return{i:h,v:b}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(a,l,d){if(d.get||d.set)throw new TypeError("ES3 does not support getters and setters.");a!=Array.prototype&&a!=Object.prototype&&(a[l]=d.value)};
$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(a,l,d,p){if(l){d=$jscomp.global;a=a.split(".");for(p=0;p<a.length-1;p++){var h=a[p];h in d||(d[h]={});d=d[h]}a=a[a.length-1];p=d[a];l=l(p);l!=p&&null!=l&&$jscomp.defineProperty(d,a,{configurable:!0,writable:!0,value:l})}};
$jscomp.polyfill("Array.prototype.find",function(a){return a?a:function(a,d){return $jscomp.findInternal(this,a,d).v}},"es6-impl","es3");
(function(a,l,d){"function"===typeof define&&define.amd?define(["jquery"],a):"object"===typeof exports?module.exports=a(require("jquery")):a(l||d)})(function(a){var l=function(b,e,f){var c={invalid:[],getCaret:function(){try{var a,r=0,g=b.get(0),e=document.selection,f=g.selectionStart;if(e&&-1===navigator.appVersion.indexOf("MSIE 10"))a=e.createRange(),a.moveStart("character",-c.val().length),r=a.text.length;else if(f||"0"===f)r=f;return r}catch(C){}},setCaret:function(a){try{if(b.is(":focus")){var c,
g=b.get(0);g.setSelectionRange?g.setSelectionRange(a,a):(c=g.createTextRange(),c.collapse(!0),c.moveEnd("character",a),c.moveStart("character",a),c.select())}}catch(B){}},events:function(){b.on("keydown.mask",function(a){b.data("mask-keycode",a.keyCode||a.which);b.data("mask-previus-value",b.val());b.data("mask-previus-caret-pos",c.getCaret());c.maskDigitPosMapOld=c.maskDigitPosMap}).on(a.jMaskGlobals.useInput?"input.mask":"keyup.mask",c.behaviour).on("paste.mask drop.mask",function(){setTimeout(function(){b.keydown().keyup()},
100)}).on("change.mask",function(){b.data("changed",!0)}).on("blur.mask",function(){d===c.val()||b.data("changed")||b.trigger("change");b.data("changed",!1)}).on("blur.mask",function(){d=c.val()}).on("focus.mask",function(b){!0===f.selectOnFocus&&a(b.target).select()}).on("focusout.mask",function(){f.clearIfNotMatch&&!h.test(c.val())&&c.val("")})},getRegexMask:function(){for(var a=[],b,c,f,n,d=0;d<e.length;d++)(b=m.translation[e.charAt(d)])?(c=b.pattern.toString().replace(/.{1}$|^.{1}/g,""),f=b.optional,
(b=b.recursive)?(a.push(e.charAt(d)),n={digit:e.charAt(d),pattern:c}):a.push(f||b?c+"?":c)):a.push(e.charAt(d).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"));a=a.join("");n&&(a=a.replace(new RegExp("("+n.digit+"(.*"+n.digit+")?)"),"($1)?").replace(new RegExp(n.digit,"g"),n.pattern));return new RegExp(a)},destroyEvents:function(){b.off("input keydown keyup paste drop blur focusout ".split(" ").join(".mask "))},val:function(a){var c=b.is("input")?"val":"text";if(0<arguments.length){if(b[c]()!==a)b[c](a);
c=b}else c=b[c]();return c},calculateCaretPosition:function(){var a=b.data("mask-previus-value")||"",e=c.getMasked(),g=c.getCaret();if(a!==e){var f=b.data("mask-previus-caret-pos")||0,e=e.length,d=a.length,m=a=0,h=0,l=0,k;for(k=g;k<e&&c.maskDigitPosMap[k];k++)m++;for(k=g-1;0<=k&&c.maskDigitPosMap[k];k--)a++;for(k=g-1;0<=k;k--)c.maskDigitPosMap[k]&&h++;for(k=f-1;0<=k;k--)c.maskDigitPosMapOld[k]&&l++;g>d?g=10*e:f>=g&&f!==d?c.maskDigitPosMapOld[g]||(f=g,g=g-(l-h)-a,c.maskDigitPosMap[g]&&(g=f)):g>f&&
(g=g+(h-l)+m)}return g},behaviour:function(f){f=f||window.event;c.invalid=[];var e=b.data("mask-keycode");if(-1===a.inArray(e,m.byPassKeys)){var e=c.getMasked(),g=c.getCaret();setTimeout(function(){c.setCaret(c.calculateCaretPosition())},a.jMaskGlobals.keyStrokeCompensation);c.val(e);c.setCaret(g);return c.callbacks(f)}},getMasked:function(a,b){var g=[],d=void 0===b?c.val():b+"",n=0,h=e.length,q=0,l=d.length,k=1,r="push",p=-1,t=0,y=[],v,z;f.reverse?(r="unshift",k=-1,v=0,n=h-1,q=l-1,z=function(){return-1<
n&&-1<q}):(v=h-1,z=function(){return n<h&&q<l});for(var A;z();){var x=e.charAt(n),w=d.charAt(q),u=m.translation[x];if(u)w.match(u.pattern)?(g[r](w),u.recursive&&(-1===p?p=n:n===v&&n!==p&&(n=p-k),v===p&&(n-=k)),n+=k):w===A?(t--,A=void 0):u.optional?(n+=k,q-=k):u.fallback?(g[r](u.fallback),n+=k,q-=k):c.invalid.push({p:q,v:w,e:u.pattern}),q+=k;else{if(!a)g[r](x);w===x?(y.push(q),q+=k):(A=x,y.push(q+t),t++);n+=k}}d=e.charAt(v);h!==l+1||m.translation[d]||g.push(d);g=g.join("");c.mapMaskdigitPositions(g,
y,l);return g},mapMaskdigitPositions:function(a,b,e){a=f.reverse?a.length-e:0;c.maskDigitPosMap={};for(e=0;e<b.length;e++)c.maskDigitPosMap[b[e]+a]=1},callbacks:function(a){var h=c.val(),g=h!==d,m=[h,a,b,f],q=function(a,b,c){"function"===typeof f[a]&&b&&f[a].apply(this,c)};q("onChange",!0===g,m);q("onKeyPress",!0===g,m);q("onComplete",h.length===e.length,m);q("onInvalid",0<c.invalid.length,[h,a,b,c.invalid,f])}};b=a(b);var m=this,d=c.val(),h;e="function"===typeof e?e(c.val(),void 0,b,f):e;m.mask=
e;m.options=f;m.remove=function(){var a=c.getCaret();m.options.placeholder&&b.removeAttr("placeholder");b.data("mask-maxlength")&&b.removeAttr("maxlength");c.destroyEvents();c.val(m.getCleanVal());c.setCaret(a);return b};m.getCleanVal=function(){return c.getMasked(!0)};m.getMaskedVal=function(a){return c.getMasked(!1,a)};m.init=function(d){d=d||!1;f=f||{};m.clearIfNotMatch=a.jMaskGlobals.clearIfNotMatch;m.byPassKeys=a.jMaskGlobals.byPassKeys;m.translation=a.extend({},a.jMaskGlobals.translation,f.translation);
m=a.extend(!0,{},m,f);h=c.getRegexMask();if(d)c.events(),c.val(c.getMasked());else{f.placeholder&&b.attr("placeholder",f.placeholder);b.data("mask")&&b.attr("autocomplete","off");d=0;for(var l=!0;d<e.length;d++){var g=m.translation[e.charAt(d)];if(g&&g.recursive){l=!1;break}}l&&b.attr("maxlength",e.length).data("mask-maxlength",!0);c.destroyEvents();c.events();d=c.getCaret();c.val(c.getMasked());c.setCaret(d)}};m.init(!b.is("input"))};a.maskWatchers={};var d=function(){var b=a(this),e={},f=b.attr("data-mask");
b.attr("data-mask-reverse")&&(e.reverse=!0);b.attr("data-mask-clearifnotmatch")&&(e.clearIfNotMatch=!0);"true"===b.attr("data-mask-selectonfocus")&&(e.selectOnFocus=!0);if(p(b,f,e))return b.data("mask",new l(this,f,e))},p=function(b,e,f){f=f||{};var c=a(b).data("mask"),d=JSON.stringify;b=a(b).val()||a(b).text();try{return"function"===typeof e&&(e=e(b)),"object"!==typeof c||d(c.options)!==d(f)||c.mask!==e}catch(t){}},h=function(a){var b=document.createElement("div"),d;a="on"+a;d=a in b;d||(b.setAttribute(a,
"return;"),d="function"===typeof b[a]);return d};a.fn.mask=function(b,d){d=d||{};var e=this.selector,c=a.jMaskGlobals,h=c.watchInterval,c=d.watchInputs||c.watchInputs,t=function(){if(p(this,b,d))return a(this).data("mask",new l(this,b,d))};a(this).each(t);e&&""!==e&&c&&(clearInterval(a.maskWatchers[e]),a.maskWatchers[e]=setInterval(function(){a(document).find(e).each(t)},h));return this};a.fn.masked=function(a){return this.data("mask").getMaskedVal(a)};a.fn.unmask=function(){clearInterval(a.maskWatchers[this.selector]);
delete a.maskWatchers[this.selector];return this.each(function(){var b=a(this).data("mask");b&&b.remove().removeData("mask")})};a.fn.cleanVal=function(){return this.data("mask").getCleanVal()};a.applyDataMask=function(b){b=b||a.jMaskGlobals.maskElements;(b instanceof a?b:a(b)).filter(a.jMaskGlobals.dataMaskAttr).each(d)};h={maskElements:"input,td,span,div",dataMaskAttr:"*[data-mask]",dataMask:!0,watchInterval:300,watchInputs:!0,keyStrokeCompensation:10,useInput:!/Chrome\/[2-4][0-9]|SamsungBrowser/.test(window.navigator.userAgent)&&
h("input"),watchDataMask:!1,byPassKeys:[9,16,17,18,36,37,38,39,40,91],translation:{0:{pattern:/\d/},9:{pattern:/\d/,optional:!0},"#":{pattern:/\d/,recursive:!0},A:{pattern:/[a-zA-Z0-9]/},S:{pattern:/[a-zA-Z]/}}};a.jMaskGlobals=a.jMaskGlobals||{};h=a.jMaskGlobals=a.extend(!0,{},h,a.jMaskGlobals);h.dataMask&&a.applyDataMask();setInterval(function(){a.jMaskGlobals.watchDataMask&&a.applyDataMask()},h.watchInterval)},window.jQuery,window.Zepto);

View File

@@ -0,0 +1,4 @@
web:
build: .
volumes:
- ./:/app/jquery-mask-plugin

View File

@@ -0,0 +1,14 @@
Package.describe({
"name": "igorescobar:jquery-mask-plugin",
"version": "1.14.15",
"summary": "A jQuery Plugin to make masks on form fields and HTML elements.",
"git": "git@github.com:igorescobar/jQuery-Mask-Plugin.git",
"documentation": "README.md"
});
Package.onUse(function(api) {
api.versionsFrom('1.2.1');
api.use('ecmascript');
api.addFiles('dist/jquery.mask.js', 'client');
api.addFiles('dist/jquery.mask.min.js', 'client');
});

View File

@@ -0,0 +1,34 @@
{
"name": "jquery-mask-plugin",
"version": "1.14.15",
"description": "A jQuery Plugin to make masks on form fields and html elements.",
"author": "Igor Escobar <blog@igorescobar.com>",
"homepage": "http://igorescobar.github.io/jQuery-Mask-Plugin/",
"main": "./dist/jquery.mask.js",
"repository": {
"type": "git",
"url": "https://github.com/igorescobar/jQuery-Mask-Plugin"
},
"bugs": {
"url": "https://github.com/igorescobar/jQuery-Mask-Plugin/issues"
},
"keywords": [
"mask",
"masks",
"form",
"input",
"jquery-plugin"
],
"license": "MIT",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-connect": "*",
"grunt-contrib-jshint": "^0.11.0",
"grunt-contrib-qunit": "*",
"grunt-contrib-uglify": "*",
"jshint-stylish": "^1.0.0",
"load-grunt-tasks": "^3.1.0",
"time-grunt": "^1.0.0",
"request": "2.81.0"
}
}

View File

@@ -0,0 +1,604 @@
/**
* jquery.mask.js
* @version: v1.14.15
* @author: Igor Escobar
*
* Created by Igor Escobar on 2012-03-10. Please report any bug at github.com/igorescobar/jQuery-Mask-Plugin
*
* Copyright (c) 2012 Igor Escobar http://igorescobar.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.
*/
/* jshint laxbreak: true */
/* jshint maxcomplexity:17 */
/* global define */
// UMD (Universal Module Definition) patterns for JavaScript modules that work everywhere.
// https://github.com/umdjs/umd/blob/master/templates/jqueryPlugin.js
(function (factory, jQuery, Zepto) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports === 'object' && typeof Meteor === 'undefined') {
module.exports = factory(require('jquery'));
} else {
factory(jQuery || Zepto);
}
}(function ($) {
'use strict';
var Mask = function (el, mask, options) {
var p = {
invalid: [],
getCaret: function () {
try {
var sel,
pos = 0,
ctrl = el.get(0),
dSel = document.selection,
cSelStart = ctrl.selectionStart;
// IE Support
if (dSel && navigator.appVersion.indexOf('MSIE 10') === -1) {
sel = dSel.createRange();
sel.moveStart('character', -p.val().length);
pos = sel.text.length;
}
// Firefox support
else if (cSelStart || cSelStart === '0') {
pos = cSelStart;
}
return pos;
} catch (e) {}
},
setCaret: function(pos) {
try {
if (el.is(':focus')) {
var range, ctrl = el.get(0);
// Firefox, WebKit, etc..
if (ctrl.setSelectionRange) {
ctrl.setSelectionRange(pos, pos);
} else { // IE
range = ctrl.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
} catch (e) {}
},
events: function() {
el
.on('keydown.mask', function(e) {
el.data('mask-keycode', e.keyCode || e.which);
el.data('mask-previus-value', el.val());
el.data('mask-previus-caret-pos', p.getCaret());
p.maskDigitPosMapOld = p.maskDigitPosMap;
})
.on($.jMaskGlobals.useInput ? 'input.mask' : 'keyup.mask', p.behaviour)
.on('paste.mask drop.mask', function() {
setTimeout(function() {
el.keydown().keyup();
}, 100);
})
.on('change.mask', function(){
el.data('changed', true);
})
.on('blur.mask', function(){
if (oldValue !== p.val() && !el.data('changed')) {
el.trigger('change');
}
el.data('changed', false);
})
// it's very important that this callback remains in this position
// otherwhise oldValue it's going to work buggy
.on('blur.mask', function() {
oldValue = p.val();
})
// select all text on focus
.on('focus.mask', function (e) {
if (options.selectOnFocus === true) {
$(e.target).select();
}
})
// clear the value if it not complete the mask
.on('focusout.mask', function() {
if (options.clearIfNotMatch && !regexMask.test(p.val())) {
p.val('');
}
});
},
getRegexMask: function() {
var maskChunks = [], translation, pattern, optional, recursive, oRecursive, r;
for (var i = 0; i < mask.length; i++) {
translation = jMask.translation[mask.charAt(i)];
if (translation) {
pattern = translation.pattern.toString().replace(/.{1}$|^.{1}/g, '');
optional = translation.optional;
recursive = translation.recursive;
if (recursive) {
maskChunks.push(mask.charAt(i));
oRecursive = {digit: mask.charAt(i), pattern: pattern};
} else {
maskChunks.push(!optional && !recursive ? pattern : (pattern + '?'));
}
} else {
maskChunks.push(mask.charAt(i).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
}
}
r = maskChunks.join('');
if (oRecursive) {
r = r.replace(new RegExp('(' + oRecursive.digit + '(.*' + oRecursive.digit + ')?)'), '($1)?')
.replace(new RegExp(oRecursive.digit, 'g'), oRecursive.pattern);
}
return new RegExp(r);
},
destroyEvents: function() {
el.off(['input', 'keydown', 'keyup', 'paste', 'drop', 'blur', 'focusout', ''].join('.mask '));
},
val: function(v) {
var isInput = el.is('input'),
method = isInput ? 'val' : 'text',
r;
if (arguments.length > 0) {
if (el[method]() !== v) {
el[method](v);
}
r = el;
} else {
r = el[method]();
}
return r;
},
calculateCaretPosition: function() {
var oldVal = el.data('mask-previus-value') || '',
newVal = p.getMasked(),
caretPosNew = p.getCaret();
if (oldVal !== newVal) {
var caretPosOld = el.data('mask-previus-caret-pos') || 0,
newValL = newVal.length,
oldValL = oldVal.length,
maskDigitsBeforeCaret = 0,
maskDigitsAfterCaret = 0,
maskDigitsBeforeCaretAll = 0,
maskDigitsBeforeCaretAllOld = 0,
i = 0;
for (i = caretPosNew; i < newValL; i++) {
if (!p.maskDigitPosMap[i]) {
break;
}
maskDigitsAfterCaret++;
}
for (i = caretPosNew - 1; i >= 0; i--) {
if (!p.maskDigitPosMap[i]) {
break;
}
maskDigitsBeforeCaret++;
}
for (i = caretPosNew - 1; i >= 0; i--) {
if (p.maskDigitPosMap[i]) {
maskDigitsBeforeCaretAll++;
}
}
for (i = caretPosOld - 1; i >= 0; i--) {
if (p.maskDigitPosMapOld[i]) {
maskDigitsBeforeCaretAllOld++;
}
}
// if the cursor is at the end keep it there
if (caretPosNew > oldValL) {
caretPosNew = newValL * 10;
} else if (caretPosOld >= caretPosNew && caretPosOld !== oldValL) {
if (!p.maskDigitPosMapOld[caretPosNew]) {
var caretPos = caretPosNew;
caretPosNew -= maskDigitsBeforeCaretAllOld - maskDigitsBeforeCaretAll;
caretPosNew -= maskDigitsBeforeCaret;
if (p.maskDigitPosMap[caretPosNew]) {
caretPosNew = caretPos;
}
}
}
else if (caretPosNew > caretPosOld) {
caretPosNew += maskDigitsBeforeCaretAll - maskDigitsBeforeCaretAllOld;
caretPosNew += maskDigitsAfterCaret;
}
}
return caretPosNew;
},
behaviour: function(e) {
e = e || window.event;
p.invalid = [];
var keyCode = el.data('mask-keycode');
if ($.inArray(keyCode, jMask.byPassKeys) === -1) {
var newVal = p.getMasked(),
caretPos = p.getCaret();
// this is a compensation to devices/browsers that don't compensate
// caret positioning the right way
setTimeout(function() {
p.setCaret(p.calculateCaretPosition());
}, $.jMaskGlobals.keyStrokeCompensation);
p.val(newVal);
p.setCaret(caretPos);
return p.callbacks(e);
}
},
getMasked: function(skipMaskChars, val) {
var buf = [],
value = val === undefined ? p.val() : val + '',
m = 0, maskLen = mask.length,
v = 0, valLen = value.length,
offset = 1, addMethod = 'push',
resetPos = -1,
maskDigitCount = 0,
maskDigitPosArr = [],
lastMaskChar,
check;
if (options.reverse) {
addMethod = 'unshift';
offset = -1;
lastMaskChar = 0;
m = maskLen - 1;
v = valLen - 1;
check = function () {
return m > -1 && v > -1;
};
} else {
lastMaskChar = maskLen - 1;
check = function () {
return m < maskLen && v < valLen;
};
}
var lastUntranslatedMaskChar;
while (check()) {
var maskDigit = mask.charAt(m),
valDigit = value.charAt(v),
translation = jMask.translation[maskDigit];
if (translation) {
if (valDigit.match(translation.pattern)) {
buf[addMethod](valDigit);
if (translation.recursive) {
if (resetPos === -1) {
resetPos = m;
} else if (m === lastMaskChar && m !== resetPos) {
m = resetPos - offset;
}
if (lastMaskChar === resetPos) {
m -= offset;
}
}
m += offset;
} else if (valDigit === lastUntranslatedMaskChar) {
// matched the last untranslated (raw) mask character that we encountered
// likely an insert offset the mask character from the last entry; fall
// through and only increment v
maskDigitCount--;
lastUntranslatedMaskChar = undefined;
} else if (translation.optional) {
m += offset;
v -= offset;
} else if (translation.fallback) {
buf[addMethod](translation.fallback);
m += offset;
v -= offset;
} else {
p.invalid.push({p: v, v: valDigit, e: translation.pattern});
}
v += offset;
} else {
if (!skipMaskChars) {
buf[addMethod](maskDigit);
}
if (valDigit === maskDigit) {
maskDigitPosArr.push(v);
v += offset;
} else {
lastUntranslatedMaskChar = maskDigit;
maskDigitPosArr.push(v + maskDigitCount);
maskDigitCount++;
}
m += offset;
}
}
var lastMaskCharDigit = mask.charAt(lastMaskChar);
if (maskLen === valLen + 1 && !jMask.translation[lastMaskCharDigit]) {
buf.push(lastMaskCharDigit);
}
var newVal = buf.join('');
p.mapMaskdigitPositions(newVal, maskDigitPosArr, valLen);
return newVal;
},
mapMaskdigitPositions: function(newVal, maskDigitPosArr, valLen) {
var maskDiff = options.reverse ? newVal.length - valLen : 0;
p.maskDigitPosMap = {};
for (var i = 0; i < maskDigitPosArr.length; i++) {
p.maskDigitPosMap[maskDigitPosArr[i] + maskDiff] = 1;
}
},
callbacks: function (e) {
var val = p.val(),
changed = val !== oldValue,
defaultArgs = [val, e, el, options],
callback = function(name, criteria, args) {
if (typeof options[name] === 'function' && criteria) {
options[name].apply(this, args);
}
};
callback('onChange', changed === true, defaultArgs);
callback('onKeyPress', changed === true, defaultArgs);
callback('onComplete', val.length === mask.length, defaultArgs);
callback('onInvalid', p.invalid.length > 0, [val, e, el, p.invalid, options]);
}
};
el = $(el);
var jMask = this, oldValue = p.val(), regexMask;
mask = typeof mask === 'function' ? mask(p.val(), undefined, el, options) : mask;
// public methods
jMask.mask = mask;
jMask.options = options;
jMask.remove = function() {
var caret = p.getCaret();
if (jMask.options.placeholder) {
el.removeAttr('placeholder');
}
if (el.data('mask-maxlength')) {
el.removeAttr('maxlength');
}
p.destroyEvents();
p.val(jMask.getCleanVal());
p.setCaret(caret);
return el;
};
// get value without mask
jMask.getCleanVal = function() {
return p.getMasked(true);
};
// get masked value without the value being in the input or element
jMask.getMaskedVal = function(val) {
return p.getMasked(false, val);
};
jMask.init = function(onlyMask) {
onlyMask = onlyMask || false;
options = options || {};
jMask.clearIfNotMatch = $.jMaskGlobals.clearIfNotMatch;
jMask.byPassKeys = $.jMaskGlobals.byPassKeys;
jMask.translation = $.extend({}, $.jMaskGlobals.translation, options.translation);
jMask = $.extend(true, {}, jMask, options);
regexMask = p.getRegexMask();
if (onlyMask) {
p.events();
p.val(p.getMasked());
} else {
if (options.placeholder) {
el.attr('placeholder' , options.placeholder);
}
// this is necessary, otherwise if the user submit the form
// and then press the "back" button, the autocomplete will erase
// the data. Works fine on IE9+, FF, Opera, Safari.
if (el.data('mask')) {
el.attr('autocomplete', 'off');
}
// detect if is necessary let the user type freely.
// for is a lot faster than forEach.
for (var i = 0, maxlength = true; i < mask.length; i++) {
var translation = jMask.translation[mask.charAt(i)];
if (translation && translation.recursive) {
maxlength = false;
break;
}
}
if (maxlength) {
el.attr('maxlength', mask.length).data('mask-maxlength', true);
}
p.destroyEvents();
p.events();
var caret = p.getCaret();
p.val(p.getMasked());
p.setCaret(caret);
}
};
jMask.init(!el.is('input'));
};
$.maskWatchers = {};
var HTMLAttributes = function () {
var input = $(this),
options = {},
prefix = 'data-mask-',
mask = input.attr('data-mask');
if (input.attr(prefix + 'reverse')) {
options.reverse = true;
}
if (input.attr(prefix + 'clearifnotmatch')) {
options.clearIfNotMatch = true;
}
if (input.attr(prefix + 'selectonfocus') === 'true') {
options.selectOnFocus = true;
}
if (notSameMaskObject(input, mask, options)) {
return input.data('mask', new Mask(this, mask, options));
}
},
notSameMaskObject = function(field, mask, options) {
options = options || {};
var maskObject = $(field).data('mask'),
stringify = JSON.stringify,
value = $(field).val() || $(field).text();
try {
if (typeof mask === 'function') {
mask = mask(value);
}
return typeof maskObject !== 'object' || stringify(maskObject.options) !== stringify(options) || maskObject.mask !== mask;
} catch (e) {}
},
eventSupported = function(eventName) {
var el = document.createElement('div'), isSupported;
eventName = 'on' + eventName;
isSupported = (eventName in el);
if ( !isSupported ) {
el.setAttribute(eventName, 'return;');
isSupported = typeof el[eventName] === 'function';
}
el = null;
return isSupported;
};
$.fn.mask = function(mask, options) {
options = options || {};
var selector = this.selector,
globals = $.jMaskGlobals,
interval = globals.watchInterval,
watchInputs = options.watchInputs || globals.watchInputs,
maskFunction = function() {
if (notSameMaskObject(this, mask, options)) {
return $(this).data('mask', new Mask(this, mask, options));
}
};
$(this).each(maskFunction);
if (selector && selector !== '' && watchInputs) {
clearInterval($.maskWatchers[selector]);
$.maskWatchers[selector] = setInterval(function(){
$(document).find(selector).each(maskFunction);
}, interval);
}
return this;
};
$.fn.masked = function(val) {
return this.data('mask').getMaskedVal(val);
};
$.fn.unmask = function() {
clearInterval($.maskWatchers[this.selector]);
delete $.maskWatchers[this.selector];
return this.each(function() {
var dataMask = $(this).data('mask');
if (dataMask) {
dataMask.remove().removeData('mask');
}
});
};
$.fn.cleanVal = function() {
return this.data('mask').getCleanVal();
};
$.applyDataMask = function(selector) {
selector = selector || $.jMaskGlobals.maskElements;
var $selector = (selector instanceof $) ? selector : $(selector);
$selector.filter($.jMaskGlobals.dataMaskAttr).each(HTMLAttributes);
};
var globals = {
maskElements: 'input,td,span,div',
dataMaskAttr: '*[data-mask]',
dataMask: true,
watchInterval: 300,
watchInputs: true,
keyStrokeCompensation: 10,
// old versions of chrome dont work great with input event
useInput: !/Chrome\/[2-4][0-9]|SamsungBrowser/.test(window.navigator.userAgent) && eventSupported('input'),
watchDataMask: false,
byPassKeys: [9, 16, 17, 18, 36, 37, 38, 39, 40, 91],
translation: {
'0': {pattern: /\d/},
'9': {pattern: /\d/, optional: true},
'#': {pattern: /\d/, recursive: true},
'A': {pattern: /[a-zA-Z0-9]/},
'S': {pattern: /[a-zA-Z]/}
}
};
$.jMaskGlobals = $.jMaskGlobals || {};
globals = $.jMaskGlobals = $.extend(true, {}, globals, $.jMaskGlobals);
// looking for inputs with data-mask attribute
if (globals.dataMask) {
$.applyDataMask();
}
setInterval(function() {
if ($.jMaskGlobals.watchDataMask) {
$.applyDataMask();
}
}, globals.watchInterval);
}, window.jQuery, window.Zepto));

View File

@@ -0,0 +1,718 @@
var QUNIT = true;
$(document).ready(function(){
var testfield = $('.simple-field'),
testfieldDataMask = $('.simple-field-data-mask'),
testfieldDataMaskWithReverse = $('.simple-field-data-mask-reverse'),
testfieldDataMaskWithClearIfNotMatch = $('.simple-field-data-mask-clearifnotmatch'),
testfieldDataMaskWithClearIfNotMatchAndOptionalMask = $('.simple-field-data-mask-clearifnotmatch-and-optional-mask'),
testdiv = $('.simple-div'),
typeTest = function (typedValue, obj) {
obj = typeof obj === "undefined" ? testfield : obj;
return obj.keydown().val(typedValue).trigger('input').val();
},
typeDivTest = function(typedValue){
return testdiv.keydown().text(typedValue).trigger('input').text();
};
module('Setting Up');
test("test if the mask method exists after plugin insertion", function() {
equal( typeof testfield.mask , "function" , "mask function should exists" );
});
module('Simple Masks');
test("Masks with only numbers.", function(){
testfield.mask('000000');
equal( typeTest("1."), "1");
equal( typeTest('1éáa2aaaaqwo'), "12");
equal( typeTest('1234567'), "123456");
});
test("When I change the mask on-the-fly things should work normally", function(){
testfield.mask('0000.0000');
equal( typeTest("1."), "1");
equal( typeTest('1éáa2aaaaqwo'), "12");
equal( typeTest('1234567'), "1234.567");
// changing on-the-fly
testfield.mask('0.000.000');
equal( typeTest("1."), "1.");
equal( typeTest('1éáa2aaaaqwo'), "1.2");
equal( typeTest('1234567'), "1.234.567");
});
test("When I change the mask on-the-fly with onChange callback things should work normally", function(){
var masks = ['0000.00009', '0.0000.0000'];
var SPphoneMask = function(phone){
return phone.length <= 9 ? masks[0] : masks[1];
};
testfield.mask(SPphoneMask, {onChange: function(phone, e, currentField, options){
$(currentField).mask(SPphoneMask(phone), options);
}});
equal( typeTest("1"), "1");
equal( typeTest("12"), "12");
equal( typeTest("123"), "123");
equal( typeTest("1234"), "1234");
equal( typeTest("12345"), "1234.5");
equal( typeTest("123456"), "1234.56");
equal( typeTest("1234567"), "1234.567");
equal( typeTest("12345678"), "1234.5678");
equal( typeTest("123456789"), "1.2345.6789");
});
test("When I change the mask on-the-fly with onKeyPress callback things should work normally", function(){
var masks = ['0000.00009', '0.0000.0000'];
var SPphoneMask = function(phone){
return phone.length <= 9 ? masks[0] : masks[1];
};
testfield.mask(SPphoneMask, {onKeyPress: function(phone, e, currentField, options){
$(currentField).mask(SPphoneMask(phone), options);
}});
equal( typeTest("1"), "1");
equal( typeTest("12"), "12");
equal( typeTest("123"), "123");
equal( typeTest("1234"), "1234");
equal( typeTest("12345"), "1234.5");
equal( typeTest("123456"), "1234.56");
equal( typeTest("1234567"), "1234.567");
equal( typeTest("12345678"), "1234.5678");
equal( typeTest("123456789"), "1.2345.6789");
});
test("#onInvalid callback. should call when invalid", function(){
testfield.mask('00/00/0000', {onInvalid: function(val, e, el, invalid, options){
equal(val, "1")
equal(typeof e, "object")
equal(typeof el, "object")
equal(invalid.length, 1);
equal(invalid[0]["e"], "/\\d/");
equal(invalid[0]["p"], 1);
equal(invalid[0]["v"], "a");
equal(typeof options.onInvalid, "function");
}});
equal( typeTest("1a") , "1");
});
test("#onInvalid callback. should not call when valid", function(){
var callback = sinon.spy();
testfield.mask('00/00/0000', {onInvalid: callback});
equal( typeTest("11") , "11");
equal(callback.called, false)
});
test('When I typed a char thats the same as the mask char', function(){
testfield.unmask();
testfield.mask('00/00/0000');
equal( typeTest("00/"), "00/");
equal( typeTest("00a"), "00/");
equal( typeTest("00a00/00"), "00/00/00");
equal( typeTest("0a/00/00"), "00/00/0");
equal( typeTest("0a/0a/00"), "00/00");
});
test('When I typed exactly the same as the mask', function(){
testfield.mask('00/00/0000');
equal( typeTest("00"), "00");
equal( typeTest("00/"), "00/");
equal( typeTest("aa/"), "");
equal( typeTest("00/0"), "00/0");
equal( typeTest("00/00"), "00/00");
equal( typeTest("00/00/0"), "00/00/0");
equal( typeTest("00/00/00"), "00/00/00");
});
test("Testing masks with a literal on the last char", function () {
testfield.mask("(99)");
equal( typeTest("(99"), "(99)");
});
module('Masks with numbers and especial characters');
test("Masks with numbers and special characters.", function(){
testfield.mask('(000) 000-0000');
equal( typeTest("1"), "(1");
equal( typeTest('12'), "(12");
equal( typeTest('123'), "(123");
equal( typeTest('1234'), "(123) 4");
equal( typeTest('12345'), "(123) 45");
equal( typeTest('(123) 456'), "(123) 456");
equal( typeTest('(123) 4567'), "(123) 456-7");
});
test("Testing masks with a annonymous function", function(){
testfield.mask(function(){
return "(123) 456-7899"
});
equal( typeTest("1"), "(1");
equal( typeTest('12'), "(12");
equal( typeTest('123'), "(123");
equal( typeTest('1234'), "(123) 4");
equal( typeTest('12345'), "(123) 45");
equal( typeTest('123456'), "(123) 456");
equal( typeTest('1234567'), "(123) 456-7");
});
test("Masks with numbers, strings e special characters", function(){
testfield.mask('(999) A99-SSSS');
equal( typeTest("(1"), "(1");
equal( typeTest('(12'), "(12");
equal( typeTest('(123'), "(123");
equal( typeTest('(123) 4'), "(123) 4");
equal( typeTest('(123) A'), "(123) A");
equal( typeTest('123.'), "(123) ");
equal( typeTest('(123) 45'), "(123) 45");
equal( typeTest('(123) 456'), "(123) 456");
equal( typeTest('(123) 456-A'), "(123) 456-A");
equal( typeTest('(123) 456-AB'), "(123) 456-AB");
equal( typeTest('(123) 456-ABC'), "(123) 456-ABC");
equal( typeTest('(123) 456-ABCD'), "(123) 456-ABCD");
equal( typeTest('(123) 456-ABCDE'), "(123) 456-ABCD");
equal( typeTest('(123) 456-ABCD1'), "(123) 456-ABCD");
});
test("Masks with numbers, strings e special characters #2 ", function(){
testfield.mask('AAA 000-S0S');
equal( typeTest("1"), "1");
equal( typeTest('12'), "12");
equal( typeTest('123'), "123");
equal( typeTest('123 4'), "123 4");
equal( typeTest('123 45'), "123 45");
equal( typeTest('123 456'), "123 456");
equal( typeTest('123 456-7'), "123 456-");
});
module("Testing Reversible Masks");
test("Testing a CPF Mask", function(){
testfield.mask('000.000.000-00', {reverse: true});
equal( typeTest("1"), "1");
equal( typeTest("12"), "12");
equal( typeTest("123"), "1-23");
equal( typeTest("12-34"), "12-34");
equal( typeTest("123-45"), "123-45");
equal( typeTest("1.234-56"), "1.234-56");
equal( typeTest("12.345-67"), "12.345-67");
equal( typeTest("123.456-78"), "123.456-78");
equal( typeTest("1.234.567-89"), "1.234.567-89");
equal( typeTest("12.345.678-90"), "12.345.678-90");
equal( typeTest("123.456.789-00"), "123.456.789-00");
equal( typeTest("123.456.789-00"), "123.456.789-00");
equal( typeTest("123.456.789a00"), "123.456.789-00");
equal( typeTest("123-a5"), "12-35");
equal( typeTest("1"), "1");
equal( typeTest("12"), "12");
equal( typeTest("1-23"), "1-23");
equal( typeTest("12-34"), "12-34");
equal( typeTest("12-345"), "123-45");
equal( typeTest("1.234-56"), "1.234-56");
equal( typeTest("12.345-67"), "12.345-67");
equal( typeTest("123.456-78"), "123.456-78");
equal( typeTest("1.234.567-89"), "1.234.567-89");
equal( typeTest("12.345.678-90"), "12.345.678-90");
equal( typeTest("123.456.789-00"), "123.456.789-00");
equal( typeTest("123.456.789-00"), "123.456.789-00");
equal( typeTest("123.456.789a00"), "123.456.789-00");
});
test("Testing Reverse numbers with recursive mask", function(){
testfield.mask("#.##0,00", {reverse: true});
equal(typeTest(""), "");
equal(typeTest("1"), "1");
equal(typeTest("12"), "12");
equal(typeTest("123"), "1,23");
equal(typeTest("1,234"), "12,34");
equal(typeTest("12,345"), "123,45");
equal(typeTest("123,456"), "1.234,56");
equal(typeTest("1.234,567"), "12.345,67");
equal(typeTest("12.345,678"), "123.456,78");
equal(typeTest("123.456,789"), "1.234.567,89");
equal(typeTest("1.234.567,890"), "12.345.678,90");
equal(typeTest("12.345.678,901"), "123.456.789,01");
equal(typeTest("123.456.789,012"), "1.234.567.890,12");
equal(typeTest("1.234.567.890,1"), "123.456.789,01");
equal(typeTest("123.456.789,0"), "12.345.678,90");
equal(typeTest("12.345.678,9"), "1.234.567,89");
equal(typeTest("1.234.567,8"), "123.456,78");
});
test("Testing numbers with recursive mask", function(){
testfield.mask("0#.#");
equal(typeTest(""), "");
equal(typeTest("1"), "1");
equal(typeTest("12"), "12");
equal(typeTest("12."), "12.");
equal(typeTest("12.3"), "12.3");
equal(typeTest("12.34"), "12.34");
equal(typeTest("12.345"), "12.34.5");
equal(typeTest("12.34.5."), "12.34.5");
equal(typeTest("12.34.56"), "12.34.56");
equal(typeTest("12.34.567"), "12.34.56.7");
equal(typeTest("12.34.56."), "12.34.56.");
equal(typeTest("12.34.56"), "12.34.56");
equal(typeTest("12.34.5"), "12.34.5");
});
test("Testing numbers with recursive mask with one #", function(){
testfield.mask("0#", {});
equal(typeTest(""), "");
equal(typeTest("1"), "1");
equal(typeTest("12"), "12");
equal(typeTest("123"), "123");
equal(typeTest("1234"), "1234");
equal(typeTest("12345"), "12345");
equal(typeTest("12345"), "12345");
equal(typeTest("123456"), "123456");
equal(typeTest("1234567"), "1234567");
equal(typeTest("123456."), "123456");
equal(typeTest("123456"), "123456");
equal(typeTest("12345"), "12345");
});
test("Testing numbers with recursive mask with one # and reverse", function(){
testfield.mask("#0", {reverse: true});
equal(typeTest(""), "");
equal(typeTest("1"), "1");
equal(typeTest("12"), "12");
equal(typeTest("123"), "123");
equal(typeTest("1234"), "1234");
equal(typeTest("12345"), "12345");
equal(typeTest("12345"), "12345");
equal(typeTest("123456"), "123456");
equal(typeTest("1234567"), "1234567");
equal(typeTest("123456."), "123456");
equal(typeTest("123456"), "123456");
equal(typeTest("12345"), "12345");
});
test("Testing reversible masks with a literal on the last char", function () {
testfield.mask("(99)");
equal( typeTest("(99"), "(99)");
});
module('Removing mask');
test("when I get the unmasked value", function(){
testfield.mask('(00) 0000-0000', { placeholder: '(__) ____-____' });
equal(typeTest("1299999999"), "(12) 9999-9999");
testfield.unmask()
equal(testfield.val(), "1299999999");
if (window.Zepto) {
equal(testfield.attr('placeholder'), '');
equal(testfield.attr('maxlength'), null);
} else {
equal(testfield.attr('placeholder'), undefined);
equal(testfield.attr('maxlength'), undefined);
}
});
module('Getting Unmasked Value');
test("when I get the unmasked value", function(){
testfield.mask('(00) 0000-0000');
equal( typeTest("1299999999"), "(12) 9999-9999");
equal( testfield.cleanVal(), "1299999999");
});
test("when I get the unmasked value with recursive mask", function(){
testfield.mask('#.##0,00', {reverse:true});
equal( typeTest("123123123123123123", testfield), "1.231.231.231.231.231,23");
equal( testfield.cleanVal(), "123123123123123123");
});
module('Masking a value programmatically');
test("when I get the masked value programmatically", function(){
testfield.mask('(00) 0000-0000');
typeTest("1299999999", testfield);
equal( testfield.masked("3488888888"), "(34) 8888-8888");
});
module('personalized settings')
test("when adding more itens to the table translation",function(){
testfield.mask('00/00/0000', {'translation': {0: {pattern: /[0-9*]/}}});
equal( typeTest('12/34/5678'), '12/34/5678');
equal( typeTest('**/34/5678'), '**/34/5678');
});
test("when adding more itens to the table translation #2",function(){
testfield.mask('00/YY/0000', {'translation': {'Y': {pattern: /[0-9*]/}}});
equal( typeTest('12/34/5678'), '12/34/5678');
equal( typeTest('12/**/5678'), '12/**/5678');
});
test("when adding more itens to the table translation #3",function(){
var old_translation = $.jMaskGlobals.translation
$.jMaskGlobals.translation = {
'1': {pattern: /\d/},
'9': {pattern: /\d/, optional: true},
'#': {pattern: /\d/, recursive: true},
'A': {pattern: /[a-zA-Z0-9]/},
'S': {pattern: /[a-zA-Z]/}
};
testfield.mask('00/11/1111');
equal( typeTest('12/12/5678'), '00/12/1256');
testfield.mask('11/00/1111');
equal( typeTest('12/12/5678'), '12/00/1256');
$.jMaskGlobals.translation = old_translation;
});
test("when adding more itens to the table translation #fallback",function(){
testfield.mask('zz/z0/0000', {'translation': {'z': {pattern: /[0-9*]/, fallback: '*'}}});
equal( typeTest('12/:4/5678'), '12/*4/5678');
equal( typeTest('::/:4/5678'), '**/*4/5678');
});
test("test the translation #fallback #1" , function(){
testfield.mask('00t00', {'translation': {'t': {pattern: /[:,.]/, fallback: ':'}}});
equal( typeTest('1'), '1');
equal( typeTest('13'), '13');
equal( typeTest('137'), '13:7');
equal( typeTest('1337'), '13:37');
equal( typeTest('13z00'), '13:00');
});
test("test the translation #fallback #2" , function(){
testfield.mask('00/t0/t0', {'translation': {'t': {pattern: /[:,.*]/, fallback: '*'}}});
equal( typeTest('1'), '1');
equal( typeTest('13'), '13');
equal( typeTest('13/'), '13/');
equal( typeTest('13/a'), '13/*');
equal( typeTest('13/a1z1'), '13/*1/*1');
});
test("test the translation #fallback #3" , function(){
testfield.mask('tt/00/00', {'translation': {'t': {pattern: /[:,.*]/, fallback: '*'}}});
equal( typeTest('*'), '*');
equal( typeTest('13'), '**/13');
equal( typeTest('13/'), '**/13/');
equal( typeTest('13/a'), '**/13/');
equal( typeTest('13/a1z1'), '**/13/11');
});
test("when adding opcional chars",function(){
testfield.mask('099.099.099.099');
equal( typeTest('0.0.0.0'), '0.0.0.0');
equal( typeTest('00.00.00.00'), '00.00.00.00');
equal( typeTest('00.000.00.000'), '00.000.00.000');
equal( typeTest('000.00.000.00'), '000.00.000.00');
equal( typeTest('000.000.000.000'), '000.000.000.000');
equal( typeTest('000000000000'), '000.000.000.000');
equal( typeTest('0'), '0');
equal( typeTest('00'), '00');
equal( typeTest('00.'), '00.');
equal( typeTest('00.0'), '00.0');
equal( typeTest('00.00'), '00.00');
equal( typeTest('00.00.'), '00.00.');
equal( typeTest('00.00.000'), '00.00.000');
equal( typeTest('00.00.000.'), '00.00.000.');
equal( typeTest('00.00.000.0'), '00.00.000.0');
equal( typeTest('00..'), '00.');
});
test("when aplying mask on a element different than a form field",function(){
testdiv.mask('000.000.000-00', {reverse: true});
equal( typeDivTest('12312312312'), '123.123.123-12');
equal( typeDivTest('123.123.123-12'), '123.123.123-12');
equal( typeDivTest('123.123a123-12'), '123.123.123-12');
equal( typeDivTest('191'), '1-91');
testdiv.mask('00/00/0000');
equal( typeDivTest('000000'), '00/00/00');
equal( typeDivTest('00000000'), '00/00/0000');
equal( typeDivTest('00/00/0000'), '00/00/0000');
equal( typeDivTest('0a/00/0000'), '00/00/000');
});
module('Testing data-mask attribute support');
test("Testing data-mask attribute", function(){
equal( typeTest("00/", testfieldDataMask), "00/");
equal( typeTest("00a", testfieldDataMask), "00/");
equal( typeTest("00a00/00", testfieldDataMask), "00/00/00");
equal( typeTest("0a/00/00", testfieldDataMask), "00/00/0");
equal( typeTest("0a/0a/00", testfieldDataMask), "00/00");
equal( typeTest("00000000", testfieldDataMask), "00/00/0000");
});
test("Testing data-mask-reverse attribute", function(){
equal( typeTest("0000", testfieldDataMaskWithReverse), "00,00");
equal( typeTest("000000", testfieldDataMaskWithReverse), "0.000,00");
equal( typeTest("0000000000", testfieldDataMaskWithReverse), "00.000.000,00");
});
module('Event fire test');
// TODO: need to understand why zepto.js isnt calling change event!
if(!window.Zepto) {
test('onChange Test', 2, function(){
testfield.unmask();
var callback = sinon.spy();
var mock = sinon.mock()
var typeAndBlur = function(typedValue){
testfield.trigger('keydown');
testfield.val(typedValue);
testfield.trigger('input');
testfield.trigger("blur");
};
testfield.mask('000.(000).000/0-0');
testfield.on("change", callback);
typeAndBlur("");
typeAndBlur("1");
typeAndBlur("12");
typeAndBlur("123");
typeAndBlur("1234");
typeAndBlur("12345");
typeAndBlur("123456");
typeAndBlur("1234567");
typeAndBlur("12345678");
typeAndBlur("123456789");
typeAndBlur("123456789");
typeAndBlur("1234567891");
typeAndBlur("12345678912");
equal(testfield.val(), "123.(456).789/1-2" );
equal(true, sinon.match(11).or(12).test(callback.callCount))
testfield.off("change");
testfield.unmask();
});
}
test('onDrop Test', function(){
ok(true, "todo");
});
module('testing Remove If Not Match Feature');
test('test when clearifnotmatch javascript notation', 4, function(){
var typeAndFocusOut = function(typedValue){
testfield.keydown().val(typedValue).trigger('input');
testfield.trigger("focusout");
};
testfield.mask('000');
typeAndFocusOut("1");
equal( testfield.val(), "1" );
testfield.mask('000', {clearIfNotMatch: true});
typeAndFocusOut("1");
equal( testfield.val(), "" );
typeAndFocusOut("12");
equal( testfield.val(), "" );
typeAndFocusOut("123");
equal( testfield.val(), "123" );
});
test('test when clearifnotmatch javascript notation #2', 4, function(){
var typeAndFocusOut = function(typedValue){
testfield.keydown().val(typedValue).trigger('input');
testfield.trigger("focusout");
};
testfield.mask('7 (000) 000-0000');
typeAndFocusOut("1");
equal( testfield.val(), "7 (1" );
testfield.mask('7 (000) 000-0000', {clearIfNotMatch: true});
typeAndFocusOut("1");
equal( testfield.val(), "" );
typeAndFocusOut("12");
equal( testfield.val(), "" );
typeAndFocusOut("7 (123) 123-1234");
equal( testfield.val(), "7 (123) 123-1234" );
});
test('test when clearifnotmatch is HTML notation', 3, function(){
var typeAndFocusOut = function(typedValue){
testfieldDataMaskWithClearIfNotMatch.keydown().val(typedValue).trigger('input');
testfieldDataMaskWithClearIfNotMatch.trigger("focusout");
};
typeAndFocusOut("1");
equal( testfieldDataMaskWithClearIfNotMatch.val(), "" );
typeAndFocusOut("12");
equal( testfieldDataMaskWithClearIfNotMatch.val(), "" );
typeAndFocusOut("123");
equal( testfieldDataMaskWithClearIfNotMatch.val(), "123" );
});
module('testing Remove If Not Match Feature');
test('test when clearifnotmatch javascript notation', 1, function(){
testfield.mask('000', {placeholder: '___'});
equal( testfield.attr('placeholder'), "___" );
});
test('test when clearifnotmatch with optional mask', 9, function(){
// html notation
var typeAndBlur = function(field, typedValue){
field.keydown().val(typedValue).trigger('input');
field.trigger("focusout");
};
typeAndBlur(testfieldDataMaskWithClearIfNotMatchAndOptionalMask, "1");
equal( testfieldDataMaskWithClearIfNotMatchAndOptionalMask.val(), "" );
typeAndBlur(testfieldDataMaskWithClearIfNotMatchAndOptionalMask, "12");
equal( testfieldDataMaskWithClearIfNotMatchAndOptionalMask.val(), "12" );
typeAndBlur(testfieldDataMaskWithClearIfNotMatchAndOptionalMask, "123");
equal( testfieldDataMaskWithClearIfNotMatchAndOptionalMask.val(), "123" );
// javascript notation
testfield.mask('099.099.099.099', {clearIfNotMatch: true});
typeAndBlur(testfield, "1");
equal( testfield.val(), "" );
typeAndBlur(testfield, "123.");
equal( testfield.val(), "" );
typeAndBlur(testfield, "123.0");
equal( testfield.val(), "" );
typeAndBlur(testfield, "123.01.000.");
equal( testfield.val(), "" );
typeAndBlur(testfield, "123.01.000.123");
equal( testfield.val(), "123.01.000.123" );
typeAndBlur(testfield, "0.0.0.0");
equal( testfield.val(), "0.0.0.0" );
});
test('test when clearifnotmatch with recursive mask', 4, function(){
// html notation
var typeAndBlur = function(field, typedValue){
field.keydown().val(typedValue).trigger('input');
field.trigger("focusout");
};
// javascript notation
testfield.mask('#.##0,00', {clearIfNotMatch: true, reverse: true});
typeAndBlur(testfield, "0");
equal( testfield.val(), "" );
typeAndBlur(testfield, "00");
equal( testfield.val(), "" );
typeAndBlur(testfield, "0,00");
equal( testfield.val(), "0,00" );
typeAndBlur(testfield, "1.000,00");
equal( testfield.val(), "1.000,00" );
});
module('dynamically loaded elements')
test('#non-inputs', function(){
expect(5);
var $container = $('#container-dy-non-inputs');
var clock = this.clock;
var ticker;
var tester;
var c = 0;
function write() {
if (c >= 5) {
clearInterval(ticker);
clearInterval(tester);
return;
}
c++;
$container.append('<div class="c">' + c + c + c + c + '</div>');
clock.tick(1000);
};
function testIt() {
var cs = $container.find('.c');
$.each(cs, function(k, field){
var t = k + 1;
equal($(field).text(), '' + t + t + ':' + t + t);
t++;
});
};
ticker = setInterval(write, 1000);
write();
$('.c', $container).mask('00:00');
testIt()
});
});

View File

@@ -0,0 +1,244 @@
/**
* QUnit v1.11.0 - A JavaScript Unit Testing Framework
*
* http://qunitjs.com
*
* Copyright 2012 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
/** Font Family and Sizes */
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
}
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
#qunit-tests { font-size: smaller; }
/** Resets */
#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
margin: 0;
padding: 0;
}
/** Header */
#qunit-header {
padding: 0.5em 0 0.5em 1em;
color: #8699a4;
background-color: #0d3349;
font-size: 1.5em;
line-height: 1em;
font-weight: normal;
border-radius: 5px 5px 0 0;
-moz-border-radius: 5px 5px 0 0;
-webkit-border-top-right-radius: 5px;
-webkit-border-top-left-radius: 5px;
}
#qunit-header a {
text-decoration: none;
color: #c2ccd1;
}
#qunit-header a:hover,
#qunit-header a:focus {
color: #fff;
}
#qunit-testrunner-toolbar label {
display: inline-block;
padding: 0 .5em 0 .1em;
}
#qunit-banner {
height: 5px;
}
#qunit-testrunner-toolbar {
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
overflow: hidden;
}
#qunit-userAgent {
padding: 0.5em 0 0.5em 2.5em;
background-color: #2b81af;
color: #fff;
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
#qunit-modulefilter-container {
float: right;
}
/** Tests: Pass/Fail */
#qunit-tests {
list-style-position: inside;
}
#qunit-tests li {
padding: 0.4em 0.5em 0.4em 2.5em;
border-bottom: 1px solid #fff;
list-style-position: inside;
}
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
display: none;
}
#qunit-tests li strong {
cursor: pointer;
}
#qunit-tests li a {
padding: 0.5em;
color: #c2ccd1;
text-decoration: none;
}
#qunit-tests li a:hover,
#qunit-tests li a:focus {
color: #000;
}
#qunit-tests li .runtime {
float: right;
font-size: smaller;
}
.qunit-assert-list {
margin-top: 0.5em;
padding: 0.5em;
background-color: #fff;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
.qunit-collapsed {
display: none;
}
#qunit-tests table {
border-collapse: collapse;
margin-top: .2em;
}
#qunit-tests th {
text-align: right;
vertical-align: top;
padding: 0 .5em 0 0;
}
#qunit-tests td {
vertical-align: top;
}
#qunit-tests pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
}
#qunit-tests del {
background-color: #e0f2be;
color: #374e0c;
text-decoration: none;
}
#qunit-tests ins {
background-color: #ffcaca;
color: #500;
text-decoration: none;
}
/*** Test Counts */
#qunit-tests b.counts { color: black; }
#qunit-tests b.passed { color: #5E740B; }
#qunit-tests b.failed { color: #710909; }
#qunit-tests li li {
padding: 5px;
background-color: #fff;
border-bottom: none;
list-style-position: inside;
}
/*** Passing Styles */
#qunit-tests li li.pass {
color: #3c510c;
background-color: #fff;
border-left: 10px solid #C6E746;
}
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
#qunit-tests .pass .test-name { color: #366097; }
#qunit-tests .pass .test-actual,
#qunit-tests .pass .test-expected { color: #999999; }
#qunit-banner.qunit-pass { background-color: #C6E746; }
/*** Failing Styles */
#qunit-tests li li.fail {
color: #710909;
background-color: #fff;
border-left: 10px solid #EE5757;
white-space: pre;
}
#qunit-tests > li:last-child {
border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
}
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
#qunit-tests .fail .test-name,
#qunit-tests .fail .module-name { color: #000000; }
#qunit-tests .fail .test-actual { color: #EE5757; }
#qunit-tests .fail .test-expected { color: green; }
#qunit-banner.qunit-fail { background-color: #EE5757; }
/** Result */
#qunit-testresult {
padding: 0.5em 0.5em 0.5em 2.5em;
color: #2b81af;
background-color: #D2E0E6;
border-bottom: 1px solid white;
}
#qunit-testresult .module-name {
font-weight: bold;
}
/** Fixture */
#qunit-fixture {
position: absolute;
top: -10000px;
left: -10000px;
width: 1000px;
height: 1000px;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/**
* sinon-qunit 1.0.0, 2010/12/09
*
* @author Christian Johansen (christian@cjohansen.no)
*
* (The BSD License)
*
* Copyright (c) 2010-2011, Christian Johansen, christian@cjohansen.no
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Christian Johansen nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*global sinon, QUnit, test*/
sinon.assert.fail = function (msg) {
QUnit.ok(false, msg);
};
sinon.assert.pass = function (assertion) {
QUnit.ok(true, assertion);
};
sinon.config = {
injectIntoThis: true,
injectInto: null,
properties: ["spy", "stub", "mock", "clock", "sandbox"],
useFakeTimers: true,
useFakeServer: false
};
(function (global) {
var qTest = QUnit.test;
QUnit.test = global.test = function (testName, expected, callback, async) {
if (arguments.length === 2) {
callback = expected;
expected = null;
}
return qTest(testName, expected, sinon.test(callback), async);
};
}(this));

View File

@@ -0,0 +1,62 @@
/**
* sinon-qunit 1.0.0, 2010/12/09
*
* @author Christian Johansen (christian@cjohansen.no)
*
* (The BSD License)
*
* Copyright (c) 2010-2011, Christian Johansen, christian@cjohansen.no
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Christian Johansen nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*global sinon, QUnit, test*/
sinon.assert.fail = function (msg) {
QUnit.ok(false, msg);
};
sinon.assert.pass = function (assertion) {
QUnit.ok(true, assertion);
};
sinon.config = {
injectIntoThis: true,
injectInto: null,
properties: ["spy", "stub", "mock", "clock", "sandbox"],
useFakeTimers: true,
useFakeServer: false
};
(function (global) {
var qTest = QUnit.test;
QUnit.test = global.test = function (testName, expected, callback, async) {
if (arguments.length === 2) {
callback = expected;
expected = null;
}
return qTest(testName, expected, sinon.test(callback), async);
};
}(this));

View File

@@ -0,0 +1,35 @@
<html>
<head>
<title>jQuery-Mask-Plugin UnitTesting</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css" type="text/css" media="all">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1 id="qunit-header">jQuery-Mask-Plugin QUnit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup, will be hidden</div>
<!-- testing area -->
<input class="simple-field" type="text" />
<input class="simple-field-data-mask" type="text" data-mask="00/00/0000"/>
<input class="simple-field-data-mask-selectonfocus" type="text" data-mask="00/00/0000" data-mask-selectonfocus="true" />
<input class="simple-field-data-mask-reverse" type="text" data-mask="#.##0,00" data-mask-reverse="true" data-mask-maxlength="false"/>
<input class="simple-field-data-mask-clearifnotmatch" data-mask="000" type="text" data-mask-clearifnotmatch="true" />
<input class="simple-field-data-mask-clearifnotmatch-and-optional-mask" data-mask="009" type="text" data-mask-clearifnotmatch="true" />
<div class="simple-div"></div>
<div id="container-dy-non-inputs"> </div>
<!--/ testing area-->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>
<script type="text/javascript" src="./sinon-1.10.3.js"></script>
<script type="text/javascript" src="./sinon-qunit-1.0.0.js"></script>
<script type="text/javascript" src="../src/jquery.mask.js"></script>
<script type="text/javascript" src="jquery.mask.test.js"></script>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<html>
<head>
<title>jQuery-Mask-Plugin UnitTesting</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css" type="text/css" media="all">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1 id="qunit-header">jQuery-Mask-Plugin QUnit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup, will be hidden</div>
<!-- testing area -->
<input class="simple-field" type="text" />
<input class="simple-field-data-mask" type="text" data-mask="00/00/0000"/>
<input class="simple-field-data-mask-selectonfocus" type="text" data-mask="00/00/0000" data-mask-selectonfocus="true" />
<input class="simple-field-data-mask-reverse" type="text" data-mask="#.##0,00" data-mask-reverse="true" data-mask-maxlength="false"/>
<input class="simple-field-data-mask-clearifnotmatch" data-mask="000" type="text" data-mask-clearifnotmatch="true" />
<input class="simple-field-data-mask-clearifnotmatch-and-optional-mask" data-mask="009" type="text" data-mask-clearifnotmatch="true" />
<div class="simple-div"></div>
<div id="container-dy-non-inputs"> </div>
<!--/ testing area-->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>
<script type="text/javascript" src="./sinon-1.10.3.js"></script>
<script type="text/javascript" src="./sinon-qunit-1.0.0.js"></script>
<script type="text/javascript" src="../src/jquery.mask.js"></script>
<script type="text/javascript" src="jquery.mask.test.js"></script>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<html>
<head>
<title>jQuery-Mask-Plugin UnitTesting</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css" type="text/css" media="all">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1 id="qunit-header">jQuery-Mask-Plugin QUnit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup, will be hidden</div>
<!-- testing area -->
<input class="simple-field" type="text" />
<input class="simple-field-data-mask" type="text" data-mask="00/00/0000"/>
<input class="simple-field-data-mask-selectonfocus" type="text" data-mask="00/00/0000" data-mask-selectonfocus="true" />
<input class="simple-field-data-mask-reverse" type="text" data-mask="#.##0,00" data-mask-reverse="true" data-mask-maxlength="false"/>
<input class="simple-field-data-mask-clearifnotmatch" data-mask="000" type="text" data-mask-clearifnotmatch="true" />
<input class="simple-field-data-mask-clearifnotmatch-and-optional-mask" data-mask="009" type="text" data-mask-clearifnotmatch="true" />
<div class="simple-div"></div>
<div id="container-dy-non-inputs"> </div>
<!--/ testing area-->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>
<script type="text/javascript" src="./sinon-1.10.3.js"></script>
<script type="text/javascript" src="./sinon-qunit-1.0.0.js"></script>
<script type="text/javascript" src="../src/jquery.mask.js"></script>
<script type="text/javascript" src="jquery.mask.test.js"></script>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<html>
<head>
<title>jQuery-Mask-Plugin UnitTesting</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css" type="text/css" media="all">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1 id="qunit-header">jQuery-Mask-Plugin QUnit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup, will be hidden</div>
<!-- testing area -->
<input class="simple-field" type="text" />
<input class="simple-field-data-mask" type="text" data-mask="00/00/0000"/>
<input class="simple-field-data-mask-selectonfocus" type="text" data-mask="00/00/0000" data-mask-selectonfocus="true" />
<input class="simple-field-data-mask-reverse" type="text" data-mask="#.##0,00" data-mask-reverse="true" data-mask-maxlength="false"/>
<input class="simple-field-data-mask-clearifnotmatch" data-mask="000" type="text" data-mask-clearifnotmatch="true" />
<input class="simple-field-data-mask-clearifnotmatch-and-optional-mask" data-mask="009" type="text" data-mask-clearifnotmatch="true" />
<div class="simple-div"></div>
<div id="container-dy-non-inputs"> </div>
<!--/ testing area-->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>
<script type="text/javascript" src="./sinon-1.10.3.js"></script>
<script type="text/javascript" src="./sinon-qunit-1.0.0.js"></script>
<script type="text/javascript" src="../src/jquery.mask.js"></script>
<script type="text/javascript" src="jquery.mask.test.js"></script>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<html>
<head>
<title>jQuery-Mask-Plugin UnitTesting</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css" type="text/css" media="all">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1 id="qunit-header">jQuery-Mask-Plugin QUnit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup, will be hidden</div>
<!-- testing area -->
<input class="simple-field" type="text" />
<input class="simple-field-data-mask" type="text" data-mask="00/00/0000"/>
<input class="simple-field-data-mask-selectonfocus" type="text" data-mask="00/00/0000" data-mask-selectonfocus="true" />
<input class="simple-field-data-mask-reverse" type="text" data-mask="#.##0,00" data-mask-reverse="true" data-mask-maxlength="false"/>
<input class="simple-field-data-mask-clearifnotmatch" data-mask="000" type="text" data-mask-clearifnotmatch="true" />
<input class="simple-field-data-mask-clearifnotmatch-and-optional-mask" data-mask="009" type="text" data-mask-clearifnotmatch="true" />
<div class="simple-div"></div>
<div id="container-dy-non-inputs"> </div>
<!--/ testing area-->
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>
<script type="text/javascript" src="./sinon-1.10.3.js"></script>
<script type="text/javascript" src="./sinon-qunit-1.0.0.js"></script>
<script type="text/javascript" src="../src/jquery.mask.js"></script>
<script type="text/javascript" src="jquery.mask.test.js"></script>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<html>
<head>
<title>jQuery-Mask-Plugin UnitTesting</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css" type="text/css" media="all">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1 id="qunit-header">jQuery-Mask-Plugin QUnit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup, will be hidden</div>
<!-- testing area -->
<input class="simple-field" type="text" />
<input class="simple-field-data-mask" type="text" data-mask="00/00/0000"/>
<input class="simple-field-data-mask-selectonfocus" type="text" data-mask="00/00/0000" data-mask-selectonfocus="true" />
<input class="simple-field-data-mask-reverse" type="text" data-mask="#.##0,00" data-mask-reverse="true" data-mask-maxlength="false"/>
<input class="simple-field-data-mask-clearifnotmatch" data-mask="000" type="text" data-mask-clearifnotmatch="true" />
<input class="simple-field-data-mask-clearifnotmatch-and-optional-mask" data-mask="009" type="text" data-mask-clearifnotmatch="true" />
<div class="simple-div"></div>
<div id="container-dy-non-inputs"> </div>
<!--/ testing area-->
<script type="text/javascript" src="http://code.jquery.com/jquery-3.0.0.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>
<script type="text/javascript" src="./sinon-1.10.3.js"></script>
<script type="text/javascript" src="./sinon-qunit-1.0.0.js"></script>
<script type="text/javascript" src="../src/jquery.mask.js"></script>
<script type="text/javascript" src="jquery.mask.test.js"></script>
</body>
</html>

View File

@@ -0,0 +1,36 @@
<html>
<head>
<title>Zepto-Mask-Plugin UnitTesting</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css" type="text/css" media="all">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1 id="qunit-header">Zepto-Mask-Plugin QUnit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup, will be hidden</div>
<!-- testing area -->
<input class="simple-field" type="text" />
<input class="simple-field-data-mask" type="text" data-mask="00/00/0000"/>
<input class="simple-field-data-mask-selectonfocus" type="text" data-mask="00/00/0000" data-mask-selectonfocus="true" />
<input class="simple-field-data-mask-reverse" type="text" data-mask="#.##0,00" data-mask-reverse="true" data-mask-maxlength="false"/>
<input class="simple-field-data-mask-clearifnotmatch" data-mask="000" type="text" data-mask-clearifnotmatch="true" />
<input class="simple-field-data-mask-clearifnotmatch-and-optional-mask" data-mask="009" type="text" data-mask-clearifnotmatch="true" />
<div class="simple-div"></div>
<div id="container-dy-non-inputs"> </div>
<!--/ testing area-->
<script type="text/javascript" src="zepto/zepto.min.js"></script>
<script type="text/javascript" src="zepto/data.js"></script>
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>
<script type="text/javascript" src="./sinon-1.10.3.js"></script>
<script type="text/javascript" src="./sinon-qunit-1.0.0.js"></script>
<script type="text/javascript" src="../src/jquery.mask.js"></script>
<script type="text/javascript" src="jquery.mask.test.js"></script>
</body>
</html>

View File

@@ -0,0 +1,80 @@
// Zepto.js
// (c) 2010-2014 Thomas Fuchs
// Zepto.js may be freely distributed under the MIT license.
// The following code is heavily inspired by jQuery's $.fn.data()
;(function($){
var data = {}, dataAttr = $.fn.data, camelize = $.camelCase,
exp = $.expando = 'Zepto' + (+new Date()), emptyArray = []
// Get value from node:
// 1. first try key as given,
// 2. then try camelized key,
// 3. fall back to reading "data-*" attribute.
function getData(node, name) {
var id = node[exp], store = id && data[id]
if (name === undefined) return store || setData(node)
else {
if (store) {
if (name in store) return store[name]
var camelName = camelize(name)
if (camelName in store) return store[camelName]
}
return dataAttr.call($(node), name)
}
}
// Store value under camelized key on node
function setData(node, name, value) {
var id = node[exp] || (node[exp] = ++$.uuid),
store = data[id] || (data[id] = attributeData(node))
if (name !== undefined) store[camelize(name)] = value
return store
}
// Read all "data-*" attributes from a node
function attributeData(node) {
var store = {}
$.each(node.attributes || emptyArray, function(i, attr){
if (attr.name.indexOf('data-') == 0)
store[camelize(attr.name.replace('data-', ''))] =
$.zepto.deserializeValue(attr.value)
})
return store
}
$.fn.data = function(name, value) {
return value === undefined ?
// set multiple values via object
$.isPlainObject(name) ?
this.each(function(i, node){
$.each(name, function(key, value){ setData(node, key, value) })
}) :
// get value from first element
(0 in this ? getData(this[0], name) : undefined) :
// set value on all elements
this.each(function(){ setData(this, name, value) })
}
$.fn.removeData = function(names) {
if (typeof names == 'string') names = names.split(/\s+/)
return this.each(function(){
var id = this[exp], store = id && data[id]
if (store) $.each(names || store, function(key){
delete store[names ? camelize(this) : key]
})
})
}
// Generate extended `remove` and `empty` functions
;['remove', 'empty'].forEach(function(methodName){
var origFn = $.fn[methodName]
$.fn[methodName] = function() {
var elements = this.find('*')
if (methodName === 'remove') elements = elements.add(this)
elements.removeData()
return origFn.call(this)
}
})
})(Zepto)

View File

@@ -0,0 +1,282 @@
// Zepto.js
// (c) 2010-2014 Thomas Fuchs
// Zepto.js may be freely distributed under the MIT license.
;(function($){
var _zid = 1, undefined,
slice = Array.prototype.slice,
isFunction = $.isFunction,
isString = function(obj){ return typeof obj == 'string' },
handlers = {},
specialEvents={},
focusinSupported = 'onfocusin' in window,
focus = { focus: 'focusin', blur: 'focusout' },
hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }
specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'
function zid(element) {
return element._zid || (element._zid = _zid++)
}
function findHandlers(element, event, fn, selector) {
event = parse(event)
if (event.ns) var matcher = matcherFor(event.ns)
return (handlers[zid(element)] || []).filter(function(handler) {
return handler
&& (!event.e || handler.e == event.e)
&& (!event.ns || matcher.test(handler.ns))
&& (!fn || zid(handler.fn) === zid(fn))
&& (!selector || handler.sel == selector)
})
}
function parse(event) {
var parts = ('' + event).split('.')
return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
}
function matcherFor(ns) {
return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')
}
function eventCapture(handler, captureSetting) {
return handler.del &&
(!focusinSupported && (handler.e in focus)) ||
!!captureSetting
}
function realEvent(type) {
return hover[type] || (focusinSupported && focus[type]) || type
}
function add(element, events, fn, data, selector, delegator, capture){
var id = zid(element), set = (handlers[id] || (handlers[id] = []))
events.split(/\s/).forEach(function(event){
if (event == 'ready') return $(document).ready(fn)
var handler = parse(event)
handler.fn = fn
handler.sel = selector
// emulate mouseenter, mouseleave
if (handler.e in hover) fn = function(e){
var related = e.relatedTarget
if (!related || (related !== this && !$.contains(this, related)))
return handler.fn.apply(this, arguments)
}
handler.del = delegator
var callback = delegator || fn
handler.proxy = function(e){
e = compatible(e)
if (e.isImmediatePropagationStopped()) return
e.data = data
var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))
if (result === false) e.preventDefault(), e.stopPropagation()
return result
}
handler.i = set.length
set.push(handler)
if ('addEventListener' in element)
element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
})
}
function remove(element, events, fn, selector, capture){
var id = zid(element)
;(events || '').split(/\s/).forEach(function(event){
findHandlers(element, event, fn, selector).forEach(function(handler){
delete handlers[id][handler.i]
if ('removeEventListener' in element)
element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
})
})
}
$.event = { add: add, remove: remove }
$.proxy = function(fn, context) {
var args = (2 in arguments) && slice.call(arguments, 2)
if (isFunction(fn)) {
var proxyFn = function(){ return fn.apply(context, args ? args.concat(slice.call(arguments)) : arguments) }
proxyFn._zid = zid(fn)
return proxyFn
} else if (isString(context)) {
if (args) {
args.unshift(fn[context], fn)
return $.proxy.apply(null, args)
} else {
return $.proxy(fn[context], fn)
}
} else {
throw new TypeError("expected function")
}
}
$.fn.bind = function(event, data, callback){
return this.on(event, data, callback)
}
$.fn.unbind = function(event, callback){
return this.off(event, callback)
}
$.fn.one = function(event, selector, data, callback){
return this.on(event, selector, data, callback, 1)
}
var returnTrue = function(){return true},
returnFalse = function(){return false},
ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$)/,
eventMethods = {
preventDefault: 'isDefaultPrevented',
stopImmediatePropagation: 'isImmediatePropagationStopped',
stopPropagation: 'isPropagationStopped'
}
function compatible(event, source) {
if (source || !event.isDefaultPrevented) {
source || (source = event)
$.each(eventMethods, function(name, predicate) {
var sourceMethod = source[name]
event[name] = function(){
this[predicate] = returnTrue
return sourceMethod && sourceMethod.apply(source, arguments)
}
event[predicate] = returnFalse
})
if (source.defaultPrevented !== undefined ? source.defaultPrevented :
'returnValue' in source ? source.returnValue === false :
source.getPreventDefault && source.getPreventDefault())
event.isDefaultPrevented = returnTrue
}
return event
}
function createProxy(event) {
var key, proxy = { originalEvent: event }
for (key in event)
if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]
return compatible(proxy, event)
}
$.fn.delegate = function(selector, event, callback){
return this.on(event, selector, callback)
}
$.fn.undelegate = function(selector, event, callback){
return this.off(event, selector, callback)
}
$.fn.live = function(event, callback){
$(document.body).delegate(this.selector, event, callback)
return this
}
$.fn.die = function(event, callback){
$(document.body).undelegate(this.selector, event, callback)
return this
}
$.fn.on = function(event, selector, data, callback, one){
var autoRemove, delegator, $this = this
if (event && !isString(event)) {
$.each(event, function(type, fn){
$this.on(type, selector, data, fn, one)
})
return $this
}
if (!isString(selector) && !isFunction(callback) && callback !== false)
callback = data, data = selector, selector = undefined
if (isFunction(data) || data === false)
callback = data, data = undefined
if (callback === false) callback = returnFalse
return $this.each(function(_, element){
if (one) autoRemove = function(e){
remove(element, e.type, callback)
return callback.apply(this, arguments)
}
if (selector) delegator = function(e){
var evt, match = $(e.target).closest(selector, element).get(0)
if (match && match !== element) {
evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))
}
}
add(element, event, callback, data, selector, delegator || autoRemove)
})
}
$.fn.off = function(event, selector, callback){
var $this = this
if (event && !isString(event)) {
$.each(event, function(type, fn){
$this.off(type, selector, fn)
})
return $this
}
if (!isString(selector) && !isFunction(callback) && callback !== false)
callback = selector, selector = undefined
if (callback === false) callback = returnFalse
return $this.each(function(){
remove(this, event, callback, selector)
})
}
$.fn.trigger = function(event, args){
event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
event._args = args
return this.each(function(){
// items in the collection might not be DOM elements
if('dispatchEvent' in this) this.dispatchEvent(event)
else $(this).triggerHandler(event, args)
})
}
// triggers event handlers on current element just as if an event occurred,
// doesn't trigger an actual event, doesn't bubble
$.fn.triggerHandler = function(event, args){
var e, result
this.each(function(i, element){
e = createProxy(isString(event) ? $.Event(event) : event)
e._args = args
e.target = element
$.each(findHandlers(element, event.type || event), function(i, handler){
result = handler.proxy(e)
if (e.isImmediatePropagationStopped()) return false
})
})
return result
}
// shortcut methods for `.bind(event, fn)` for each event type
;('focusin focusout load resize scroll unload click dblclick '+
'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+
'change select keydown keypress keyup error').split(' ').forEach(function(event) {
$.fn[event] = function(callback) {
return callback ?
this.bind(event, callback) :
this.trigger(event)
}
})
;['focus', 'blur'].forEach(function(name) {
$.fn[name] = function(callback) {
if (callback) this.bind(name, callback)
else this.each(function(){
try { this[name]() }
catch(e) {}
})
return this
}
})
$.Event = function(type, props) {
if (!isString(type)) props = type, type = props.type
var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
event.initEvent(type, bubbles, true)
return compatible(event)
}
})(Zepto)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

View File

@@ -0,0 +1,41 @@
{
"bitwise": true,
"boss": true,
"browser": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"eqnull": true,
"expr": true,
"immed": true,
"noarg": true,
"node": true,
"onevar": true,
"quotmark": "double",
"smarttabs": true,
"trailing": true,
"unused": true,
"globals": {
"jQuery": true,
"$": true,
"devel": true,
// QUnit
"QUnit": true,
"test": true,
"module": true,
"expect": true,
"stop": true,
"start": true,
"ok": true,
"equal": true,
"notEqual": true,
"deepEqual": true,
"notDeepEqual": true,
"strictEqual": true,
"notStrictEqual": true,
"raises": true,
// util functions
"keypress": true,
"keydown": true
}
}

View File

@@ -0,0 +1,8 @@
language: node_js
node_js:
- 4
install:
- npm install grunt-cli -g
- npm install -g bower
- npm install
- bower install

View File

@@ -0,0 +1,75 @@
module.exports = function(grunt) {
"use strict";
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
meta: {
banner: "/*\n" +
" * <%= pkg.title || pkg.name %> - v<%= pkg.version %>\n" +
" * <%= pkg.description %>\n" +
" * <%= pkg.homepage %>\n" +
" *\n" +
" * Made by <%= pkg.author.name %>\n" +
" * Under <%= pkg.license %> License\n" +
" */\n"
},
jshint: {
all: ["Gruntfile.js", "src/**/*.js", "test/**/*.js", "!test/util.js"],
options: {
jshintrc: true
}
},
concat: {
dist: {
src: ["src/jquery.maskMoney.js"],
dest: "dist/jquery.maskMoney.js"
},
options: {
banner: "<%= meta.banner %>"
}
},
uglify: {
options: {
banner: "<%= meta.banner %>",
mangle: {
reserved: ["jQuery", "$"]
}
},
build: {
files: [
{ src: "src/jquery.maskMoney.js", dest: "dist/jquery.maskMoney.min.js" },
]
}
},
qunit: {
all: ["test/*.html"]
},
jquerymanifest: {
options: {
source: grunt.file.readJSON("package.json"),
overrides: {
"name": "maskMoney",
"title": "jQuery maskMoney",
"download": "https://raw.github.com/plentz/jquery-maskmoney/master/dist/jquery.maskMoney.min.js",
"docs": "http://github.com/plentz/jquery-maskmoney",
"demo": "http://plentz.github.com/jquery-maskmoney",
"keywords": ["form", "input", "mask", "money"]
}
}
},
watch: {
files: ["test/*.html", "test/*.js", "src/*.js"],
tasks: ["jshint", "qunit"]
}
});
grunt.loadNpmTasks("grunt-contrib-concat");
grunt.loadNpmTasks("grunt-contrib-jshint");
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.loadNpmTasks("grunt-jquerymanifest");
grunt.loadNpmTasks("grunt-contrib-qunit");
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.registerTask("test", ["jshint", "qunit"]);
grunt.registerTask("default", ["jshint", "qunit", "concat", "uglify", "jquerymanifest"]);
};

View File

@@ -0,0 +1,22 @@
Copyright (c) 2007-2013 Diego Plentz (plentz.org)
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.

View File

@@ -0,0 +1,103 @@
# jQuery maskMoney [![Build Status](https://travis-ci.org/plentz/jquery-maskmoney.png)](https://travis-ci.org/plentz/jquery-maskmoney)
Just a simple way to create masks to your currency form fields with [jQuery](http://jquery.com/).
***
### Download
To get the latest(minified) version, [click here](https://cdn.rawgit.com/plentz/jquery-maskmoney/master/dist/jquery.maskMoney.min.js).
You can also use [CloudFlare's cdnjs](http://cdnjs.com/). Just choose the version you want to use [here](http://cdnjs.com/libraries/jquery-maskmoney/).
***
### Show Time!
To view a complete demonstration of it's features and usage, access our [examples page](http://plentz.github.com/jquery-maskmoney)!
***
### Usage:
```html
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
<script src="dist/jquery.maskMoney.min.js" type="text/javascript"></script>
</head>
<body>
<input type="text" id="currency" />
</body>
<script>
$(function() {
$('#currency').maskMoney();
})
</script>
```
***
### Options:
The options that you can set are:
* `prefix`: the prefix to be displayed before(aha!) the value entered by the user(example: "US$ 1234.23"). default: ''
* `suffix`: the suffix to be displayed after the value entered by the user(example: "1234.23 €"). default: ''
* `affixesStay`: set if the prefix and suffix will stay in the field's value after the user exits the field. default: true
* `thousands`: the thousands separator. default: ','
* `decimal`: the decimal separator. default: '.'
* `precision`: how many decimal places are allowed. default: 2
* `allowZero`: use this setting to prevent users from inputing zero. default: false
* `allowNegative`: use this setting to prevent users from inputing negative values. default: false
* `formatOnBlur`: delay formatting of text field until focus leaves the field. default: false
* `reverse`: by default, `maskMoney` applies keystrokes from right to left. use this setting to apply keystrokes from left to right.
* `selectAllOnFocus`: select all text in the input when the element fires the focus event. default :false
* `allowEmpty`: allow empty input values, so that when you delete the number it doesn't reset to 0.00. default: false
__IMPORTANT__: if you try to bind maskMoney to a read only field, nothing will happen, since we ignore completely read only fields. So, if you have a read only field, try to bind maskMoney to it, it will not work. Even if you change the field removing the readonly property, you will need to re-bind maskMoney to make it work.
***
### Bonus!
We have 3 bonus methods that can be useful to you:
* `.maskMoney('destroy')` removes maskMoney from an element.
* `.maskMoney('mask')` apply the mask to your input. This method can work as a setter as well, if you pass a value to it, like this `.maskMoney('mask', 1999.99)`
* `.maskMoney('unmasked')` return a float value (ex.: 'R$ 1.234,56' => 1234.56). PS: If you have only one input field, you should use this way `.maskMoney('unmasked')[0]`, since it will always return an array.
You can also configure maskMoney options using the data-* API instead of passing it as a hash in the `.maskMoney` method call. To use it, simply set the options using `data-<option>`, like this:
```html
<input type="text" data-affixes-stay="true" data-prefix="R$ " data-thousands="." data-decimal="," />
```
And when you bind maskMoney to that field, we will read those options. **ATTENTION**: for settings that isn't entirely lowercase, you will need to use dashes instead of capital letters. For example, to set `allowZero`, you will need to add a attribute called `data-allow-zero`.
***
### Tests:
To run our test suite, just clone the repo and open `test/index.html`. If you want to run it using nodejs, clone the repo and run:
```
npm install
bower install
grunt test
```
***
### Contributors:
* [Aurélio Saraiva](http://github.com/aureliosaraiva)
* [Raul Pereira da Silva](http://raulpereira.com)
* [Diego Plentz](http://plentz.org)
* [Otávio Ribeiro Medeiros](http://github.com/otaviomedeiros)
* [Víctor Cruz](http://github.com/xtream)
* [Synapse Studios](http://github.com/synapsestudios)
* [Guilherme Garnier](http://blog.guilhermegarnier.com/)
* [Plínio Balduino](http://github.com/pbalduino)
* [Luis Fernando Gomes](https://github.com/luiscoms)
* [Gary Moore](http://www.gmoore.net/)
* [Daniel Loureiro](https://github.com/loureirorg)
* [Thiago Silva](http://twitter.com/tafs7/)
* [Guilherme Nagatomo](https://github.com/guilhermehn)
* [Andrew Duncan](https://github.com/abduncan)
***
### License:
__jQuery-maskMoney__ is released under the MIT license.

View File

@@ -0,0 +1,25 @@
{
"name": "jquery-maskmoney",
"version": "3.1.1",
"homepage": "https://github.com/plentz/jquery-maskmoney",
"authors": [
"Diego Plentz <diego@plentz.org>"
],
"description": "jQuery plugin to mask data entry in the input text in the form of money (currency).",
"main": "dist/jquery.maskMoney.js",
"keywords": [
"form",
"money",
"jquery"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test"
],
"dependencies": {
"jquery": "^3.2.1"
}
}

View File

@@ -0,0 +1,110 @@
<html>
<head>
<meta charset="utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
<script src="../src/jquery.maskMoney.js" type="text/javascript"></script>
<!-- just necessary for syntax highlight -->
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css' />
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css' />
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'></script>
<style type="text/css">
body { font-family: helvetica, sans-serif; }
h1 { font-size: 2em;}
h4 {font-weight: 100; }
h4 code { background-color: whitesmoke; }
</style>
</head>
<body>
<h1>jQuery-maskMoney examples</h1>
<p>jQuery plugin to mask data entry in the input text in the form of money (currency). <a href="https://github.com/plentz/jquery-maskmoney">Project home @ github</a></p>
<input type="text" id="demo1" value="0.01" />
<script type="text/javascript">$("#demo1").maskMoney();</script>
<pre class="brush: js">$("#demo1").maskMoney();</pre>
<input type="text" id="demo2" />
<script type="text/javascript">$("#demo2").maskMoney({thousands:',', decimal:'.', allowZero: true, suffix: ' €'});</script>
<pre class="brush: js">$("#demo2").maskMoney({thousands:'', decimal:'.', allowZero:true, suffix: ' €'});</pre>
<input type="text" id="demo3" />
<script type="text/javascript">$("#demo3").maskMoney({prefix:'R$ ', allowNegative: true, thousands:'.', decimal:',', affixesStay: false});</script>
<pre class="brush: js">$("#demo3").maskMoney({prefix:'R$ ', allowNegative: true, thousands:'.', decimal:',', affixesStay: false});</pre>
<input type="text" id="demo4" data-thousands="." data-decimal="," data-prefix="R$ " />
<script type="text/javascript">$("#demo4").maskMoney();</script>
<pre class="brush: js">$("#demo4").maskMoney();</pre>
<pre class="brush: html"><input type="text" id="demo4" data-thousands="." data-decimal="," data-prefix="R$ " /></pre>
<input type="text" id="demo5" value="1234567.89"/>
<script type="text/javascript">$("#demo5").maskMoney({prefix:'R$ ', thousands:'.', decimal:',', affixesStay: true});</script>
<input type="button" onclick="$('#demo5').maskMoney('mask')" value="trigger mask event at demo5"/>
<pre class="brush: js">$("#demo5").maskMoney('mask');</pre>
<input type="text" id="demo6"/>
<script type="text/javascript">$("#demo6").maskMoney({prefix:'R$ ', thousands:'.', decimal:',', affixesStay: true});</script>
<input type="button" onclick="$('#demo6').maskMoney('mask', 1999.99)" value="trigger mask event at demo6, passing a float value as parameter"/>
<pre class="brush: js">$("#demo6").maskMoney('mask', 1999.99);</pre>
<input type="text" id="demo7"/>
<script type="text/javascript">$("#demo7").maskMoney();</script>
<input type="button" onclick="$('#demo7').maskMoney('destroy')" value="remove maskmoney from demo7"/>
<pre class="brush: js">$("#demo6").maskMoney('destroy');</pre>
<input type="text" id="demo8" value="R$ 1.231.231,23"/>
<script type="text/javascript">$("#demo8").maskMoney();</script>
<input type="button" onclick="var num = $('#demo8').maskMoney('unmasked')[0];alert('type: '+typeof(num) + ', value: ' + num)" value="alert unmasked value and type from demo7"/>
<pre class="brush: js">
var num = $('#demo8').maskMoney('unmasked')[0];
alert('type: '+ typeof(num) + ', value: ' + num)
</pre>
<input type="text" id="demo9" value="$15.45" />
<script type="text/javascript">
$("#demo9").maskMoney({ formatOnBlur: true, prefix: '$' });
</script>
<pre class="brush: js">$("#demo9").maskMoney({ formatOnBlur: true, prefix: '$' });</pre>
<input type="text" id="demo10" value="$15.45" />
<script type="text/javascript">
$("#demo10").maskMoney({ formatOnBlur: true, reverse: true, prefix: '$' });
</script>
<h4>Note: The <code>reverse</code> option is meant to be used with the <code>formatOnBlur</code> option.</h4>
<pre class="brush: js">
$("#demo10").maskMoney({ formatOnBlur: true, reverse: true, prefix: '$' });
</pre>
<input type="text" id="demo11" value="45.55" />
<script type="text/javascript">
$("#demo11").maskMoney({ selectAllOnFocus: true });
</script>
<pre class="brush: js">$("#demo11").maskMoney({ selectAllOnFocus: true });</pre>
<input type="text" id="demo12" value=""/>
<script type="text/javascript">$("#demo12").maskMoney({ formatOnBlur: true, reverse: true, prefix: '$', selectAllOnFocus: true });</script>
<input type="button" onclick="var num = $('#demo12').maskMoney('applyMask', $('#demo12').val());alert('Mask applied '+ num)" value="alert masked value from demo12"/>
<pre class="brush: js">
$("#demo12").maskMoney({ formatOnBlur: true, reverse: true, prefix: '$', selectAllOnFocus: true });
var num = $('#demo12').maskMoney('applyMask', $('#demo12').val());
alert('Mask applied '+ num);
</pre>
<input type="text" id="demo13" value="45" />
<script type="text/javascript">
$("#demo13").maskMoney({ formatOnBlur: true, reverse: true, prefix: '$', selectAllOnFocus: true, precision: 0 });
</script>
<pre class="brush: js">$("#demo13").maskMoney({ formatOnBlur: true, reverse: true, prefix: '$', selectAllOnFocus: true, precision: 0 });</pre>
<input type="text" id="demo14" value="" />
<script type="text/javascript">
$("#demo14").maskMoney({ formatOnBlur: true, reverse: true, prefix: '$', selectAllOnFocus: true, precision: 4, allowEmpty: true });
</script>
<pre class="brush: js">$("#demo14").maskMoney({ formatOnBlur: true, reverse: true, prefix: '$', selectAllOnFocus: true, precision: 4, allowEmpty: true });</pre>
</body>
<script type="text/javascript">
SyntaxHighlighter.all()
</script>
</html>

View File

@@ -0,0 +1,591 @@
/*
* jquery-maskmoney - v3.1.1
* jQuery plugin to mask data entry in the input text in the form of money (currency)
* https://github.com/plentz/jquery-maskmoney
*
* Made by Diego Plentz
* Under MIT License
*/
(function ($) {
"use strict";
if (!$.browser) {
$.browser = {};
$.browser.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase());
$.browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
$.browser.opera = /opera/.test(navigator.userAgent.toLowerCase());
$.browser.msie = /msie/.test(navigator.userAgent.toLowerCase());
$.browser.device = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase());
}
var defaultOptions = {
prefix: "",
suffix: "",
affixesStay: true,
thousands: ",",
decimal: ".",
precision: 2,
allowZero: false,
allowNegative: false,
doubleClickSelection: true,
allowEmpty: false,
bringCaretAtEndOnFocus: true
},
methods = {
destroy: function () {
$(this).unbind(".maskMoney");
if ($.browser.msie) {
this.onpaste = null;
}
return this;
},
applyMask: function (value) {
var $input = $(this);
// data-* api
var settings = $input.data("settings");
return maskValue(value, settings);
},
mask: function (value) {
return this.each(function () {
var $this = $(this);
if (typeof value === "number") {
$this.val(value);
}
return $this.trigger("mask");
});
},
unmasked: function () {
return this.map(function () {
var value = ($(this).val() || "0"),
isNegative = value.indexOf("-") !== -1,
decimalPart;
// get the last position of the array that is a number(coercion makes "" to be evaluated as false)
$(value.split(/\D/).reverse()).each(function (index, element) {
if (element) {
decimalPart = element;
return false;
}
});
value = value.replace(/\D/g, "");
value = value.replace(new RegExp(decimalPart + "$"), "." + decimalPart);
if (isNegative) {
value = "-" + value;
}
return parseFloat(value);
});
},
unmaskedWithOptions: function () {
return this.map(function () {
var value = ($(this).val() || "0"),
settings = $(this).data("settings") || defaultOptions,
regExp = new RegExp((settings.thousandsForUnmasked || settings.thousands), "g");
value = value.replace(regExp, "");
return parseFloat(value);
});
},
init: function (parameters) {
// the default options should not be shared with others
parameters = $.extend($.extend({}, defaultOptions), parameters);
return this.each(function () {
var $input = $(this), settings,
onFocusValue;
// data-* api
settings = $.extend({}, parameters);
settings = $.extend(settings, $input.data());
// Store settings for use with the applyMask method.
$input.data("settings", settings);
function getInputSelection() {
var el = $input.get(0),
start = 0,
end = 0,
normalizedValue,
range,
textInputRange,
len,
endRange;
if (typeof el.selectionStart === "number" && typeof el.selectionEnd === "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else {
range = document.selection.createRange();
if (range && range.parentElement() === el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
} // getInputSelection
function canInputMoreNumbers() {
var haventReachedMaxLength = !($input.val().length >= $input.attr("maxlength") && $input.attr("maxlength") >= 0),
selection = getInputSelection(),
start = selection.start,
end = selection.end,
haveNumberSelected = (selection.start !== selection.end && $input.val().substring(start, end).match(/\d/)) ? true : false,
startWithZero = ($input.val().substring(0, 1) === "0");
return haventReachedMaxLength || haveNumberSelected || startWithZero;
}
function setCursorPosition(pos) {
// Do not set the position if
// the we're formatting on blur.
// This is because we do not want
// to refocus on the control after
// the blur.
if (!!settings.formatOnBlur) {
return;
}
$input.each(function (index, elem) {
if (elem.setSelectionRange) {
elem.focus();
elem.setSelectionRange(pos, pos);
} else if (elem.createTextRange) {
var range = elem.createTextRange();
range.collapse(true);
range.moveEnd("character", pos);
range.moveStart("character", pos);
range.select();
}
});
}
function maskAndPosition(startPos) {
var originalLen = $input.val().length,
newLen;
$input.val(maskValue($input.val(), settings));
newLen = $input.val().length;
// If the we're using the reverse option,
// do not put the cursor at the end of
// the input. The reverse option allows
// the user to input text from left to right.
if (!settings.reverse) {
startPos = startPos - (originalLen - newLen);
}
setCursorPosition(startPos);
}
function mask() {
var value = $input.val();
if (settings.allowEmpty && value === "") {
return;
}
var decimalPointIndex = value.indexOf(settings.decimal);
if (settings.precision > 0) {
if(decimalPointIndex < 0){
value += settings.decimal + new Array(settings.precision + 1).join(0);
}
else {
// If the following decimal part dosen't have enough length against the precision, it needs to be filled with zeros.
var integerPart = value.slice(0, decimalPointIndex),
decimalPart = value.slice(decimalPointIndex + 1);
value = integerPart + settings.decimal + decimalPart +
new Array((settings.precision + 1) - decimalPart.length).join(0);
}
} else if (decimalPointIndex > 0) {
// if the precision is 0, discard the decimal part
value = value.slice(0, decimalPointIndex);
}
$input.val(maskValue(value, settings));
}
function changeSign() {
var inputValue = $input.val();
if (settings.allowNegative) {
if (inputValue !== "" && inputValue.charAt(0) === "-") {
return inputValue.replace("-", "");
} else {
return "-" + inputValue;
}
} else {
return inputValue;
}
}
function preventDefault(e) {
if (e.preventDefault) { //standard browsers
e.preventDefault();
} else { // old internet explorer
e.returnValue = false;
}
}
function fixMobile() {
if ($.browser.device) {
$input.attr("type", "tel");
}
}
function keypressEvent(e) {
e = e || window.event;
var key = e.which || e.charCode || e.keyCode,
decimalKeyCode = settings.decimal.charCodeAt(0);
//added to handle an IE "special" event
if (key === undefined) {
return false;
}
// any key except the numbers 0-9. if we're using settings.reverse,
// allow the user to input the decimal key
if ((key < 48 || key > 57) && (key !== decimalKeyCode || !settings.reverse)) {
return handleAllKeysExceptNumericalDigits(key, e);
} else if (!canInputMoreNumbers()) {
return false;
} else {
if (key === decimalKeyCode && shouldPreventDecimalKey()) {
return false;
}
if (settings.formatOnBlur) {
return true;
}
preventDefault(e);
applyMask(e);
return false;
}
}
function shouldPreventDecimalKey() {
// If all text is selected, we can accept the decimal
// key because it will replace everything.
if (isAllTextSelected()) {
return false;
}
return alreadyContainsDecimal();
}
function isAllTextSelected() {
var length = $input.val().length;
var selection = getInputSelection();
// This should if all text is selected or if the
// input is empty.
return selection.start === 0 && selection.end === length;
}
function alreadyContainsDecimal() {
return $input.val().indexOf(settings.decimal) > -1;
}
function applyMask(e) {
e = e || window.event;
var key = e.which || e.charCode || e.keyCode,
keyPressedChar = "",
selection,
startPos,
endPos,
value;
if (key >= 48 && key <= 57) {
keyPressedChar = String.fromCharCode(key);
}
selection = getInputSelection();
startPos = selection.start;
endPos = selection.end;
value = $input.val();
$input.val(value.substring(0, startPos) + keyPressedChar + value.substring(endPos, value.length));
maskAndPosition(startPos + 1);
}
function handleAllKeysExceptNumericalDigits(key, e) {
// -(minus) key
if (key === 45) {
$input.val(changeSign());
return false;
// +(plus) key
} else if (key === 43) {
$input.val($input.val().replace("-", ""));
return false;
// enter key or tab key
} else if (key === 13 || key === 9) {
return true;
} else if ($.browser.mozilla && (key === 37 || key === 39) && e.charCode === 0) {
// needed for left arrow key or right arrow key with firefox
// the charCode part is to avoid allowing "%"(e.charCode 0, e.keyCode 37)
return true;
} else { // any other key with keycode less than 48 and greater than 57
preventDefault(e);
return true;
}
}
function keydownEvent(e) {
e = e || window.event;
var key = e.which || e.charCode || e.keyCode,
selection,
startPos,
endPos,
value,
lastNumber;
//needed to handle an IE "special" event
if (key === undefined) {
return false;
}
selection = getInputSelection();
startPos = selection.start;
endPos = selection.end;
if (key === 8 || key === 46 || key === 63272) { // backspace or delete key (with special case for safari)
preventDefault(e);
value = $input.val();
// not a selection
if (startPos === endPos) {
// backspace
if (key === 8) {
if (settings.suffix === "") {
startPos -= 1;
} else {
// needed to find the position of the last number to be erased
lastNumber = value.split("").reverse().join("").search(/\d/);
startPos = value.length - lastNumber - 1;
endPos = startPos + 1;
}
//delete
} else {
endPos += 1;
}
}
$input.val(value.substring(0, startPos) + value.substring(endPos, value.length));
maskAndPosition(startPos);
return false;
} else if (key === 9) { // tab key
return true;
} else { // any other key
return true;
}
}
function focusEvent() {
onFocusValue = $input.val();
mask();
var input = $input.get(0),
textRange;
if (!!settings.selectAllOnFocus) {
input.select();
} else if (input.createTextRange && settings.bringCaretAtEndOnFocus) {
textRange = input.createTextRange();
textRange.collapse(false); // set the cursor at the end of the input
textRange.select();
}
}
function cutPasteEvent() {
setTimeout(function () {
mask();
}, 0);
}
function getDefaultMask() {
var n = parseFloat("0") / Math.pow(10, settings.precision);
return (n.toFixed(settings.precision)).replace(new RegExp("\\.", "g"), settings.decimal);
}
function blurEvent(e) {
if ($.browser.msie) {
keypressEvent(e);
}
if (!!settings.formatOnBlur && $input.val() !== onFocusValue) {
applyMask(e);
}
if ($input.val() === "" && settings.allowEmpty) {
$input.val("");
} else if ($input.val() === "" || $input.val() === setSymbol(getDefaultMask(), settings)) {
if (!settings.allowZero) {
$input.val("");
} else if (!settings.affixesStay) {
$input.val(getDefaultMask());
} else {
$input.val(setSymbol(getDefaultMask(), settings));
}
} else {
if (!settings.affixesStay) {
var newValue = $input.val().replace(settings.prefix, "").replace(settings.suffix, "");
$input.val(newValue);
}
}
if ($input.val() !== onFocusValue) {
$input.change();
}
}
function clickEvent() {
var input = $input.get(0),
length;
if (!!settings.selectAllOnFocus) {
// selectAllOnFocus will be handled by
// the focus event. The focus event is
// also fired when the input is clicked.
return;
} else if (input.setSelectionRange && settings.bringCaretAtEndOnFocus) {
length = $input.val().length;
input.setSelectionRange(length, length);
} else {
$input.val($input.val());
}
}
function doubleClickEvent() {
var input = $input.get(0),
start,
length;
if (input.setSelectionRange && settings.bringCaretAtEndOnFocus) {
length = $input.val().length;
start = settings.doubleClickSelection ? 0 : length;
input.setSelectionRange(start, length);
} else {
$input.val($input.val());
}
}
fixMobile();
$input.unbind(".maskMoney");
$input.bind("keypress.maskMoney", keypressEvent);
$input.bind("keydown.maskMoney", keydownEvent);
$input.bind("blur.maskMoney", blurEvent);
$input.bind("focus.maskMoney", focusEvent);
$input.bind("click.maskMoney", clickEvent);
$input.bind("dblclick.maskMoney", doubleClickEvent);
$input.bind("cut.maskMoney", cutPasteEvent);
$input.bind("paste.maskMoney", cutPasteEvent);
$input.bind("mask.maskMoney", mask);
});
}
};
function setSymbol(value, settings) {
var operator = "";
if (value.indexOf("-") > -1) {
value = value.replace("-", "");
operator = "-";
}
if (value.indexOf(settings.prefix) > -1) {
value = value.replace(settings.prefix, "");
}
if (value.indexOf(settings.suffix) > -1) {
value = value.replace(settings.suffix, "");
}
return operator + settings.prefix + value + settings.suffix;
}
function maskValue(value, settings) {
if (settings.allowEmpty && value === "") {
return "";
}
if (!!settings.reverse) {
return maskValueReverse(value, settings);
}
return maskValueStandard(value, settings);
}
function maskValueStandard(value, settings) {
var negative = (value.indexOf("-") > -1 && settings.allowNegative) ? "-" : "",
onlyNumbers = value.replace(/[^0-9]/g, ""),
integerPart = onlyNumbers.slice(0, onlyNumbers.length - settings.precision),
newValue,
decimalPart,
leadingZeros;
newValue = buildIntegerPart(integerPart, negative, settings);
if (settings.precision > 0) {
decimalPart = onlyNumbers.slice(onlyNumbers.length - settings.precision);
leadingZeros = new Array((settings.precision + 1) - decimalPart.length).join(0);
newValue += settings.decimal + leadingZeros + decimalPart;
}
return setSymbol(newValue, settings);
}
function maskValueReverse(value, settings) {
var negative = (value.indexOf("-") > -1 && settings.allowNegative) ? "-" : "",
valueWithoutSymbol = value.replace(settings.prefix, "").replace(settings.suffix, ""),
integerPart = valueWithoutSymbol.split(settings.decimal)[0],
newValue,
decimalPart = "";
if (integerPart === "") {
integerPart = "0";
}
newValue = buildIntegerPart(integerPart, negative, settings);
if (settings.precision > 0) {
var arr = valueWithoutSymbol.split(settings.decimal);
if (arr.length > 1) {
decimalPart = arr[1];
}
newValue += settings.decimal + decimalPart;
var rounded = Number.parseFloat((integerPart + "." + decimalPart)).toFixed(settings.precision);
var roundedDecimalPart = rounded.toString().split(settings.decimal)[1];
newValue = newValue.split(settings.decimal)[0] + "." + roundedDecimalPart;
}
return setSymbol(newValue, settings);
}
function buildIntegerPart(integerPart, negative, settings) {
// remove initial zeros
integerPart = integerPart.replace(/^0*/g, "");
// put settings.thousands every 3 chars
integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, settings.thousands);
if (integerPart === "") {
integerPart = "0";
}
return negative + integerPart;
}
$.fn.maskMoney = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === "object" || !method) {
return methods.init.apply(this, arguments);
} else {
$.error("Method " + method + " does not exist on jQuery.maskMoney");
}
};
})(window.jQuery || window.Zepto);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,31 @@
{
"name": "maskMoney",
"version": "3.1.1",
"title": "jQuery maskMoney",
"author": {
"name": "Diego Plentz",
"email": "diego@plentz.org",
"url": "http://plentz.org"
},
"licenses": [
{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"dependencies": {
"jquery": "latest"
},
"description": "jQuery plugin to mask data entry in the input text in the form of money (currency)",
"keywords": [
"form",
"input",
"mask",
"money"
],
"docs": "http://github.com/plentz/jquery-maskmoney",
"demo": "http://plentz.github.com/jquery-maskmoney",
"download": "https://raw.github.com/plentz/jquery-maskmoney/master/dist/jquery.maskMoney.min.js",
"bugs": "https://github.com/plentz/jquery-maskmoney/issues",
"homepage": "https://github.com/plentz/jquery-maskmoney"
}

View File

@@ -0,0 +1,49 @@
{
"name": "jquery-maskmoney",
"filename": "jquery.maskMoney.min.js",
"description": "jQuery plugin to mask data entry in the input text in the form of money (currency)",
"version": "3.1.1",
"homepage": "https://github.com/plentz/jquery-maskmoney",
"repository": {
"type": "git",
"url": "https://github.com/plentz/jquery-maskmoney.git"
},
"bugs": "https://github.com/plentz/jquery-maskmoney/issues",
"author": {
"name": "Diego Plentz",
"email": "diego@plentz.org",
"url": "http://plentz.org"
},
"dependencies": {
"jquery": "latest"
},
"engines": {
"node": ">=4"
},
"main": "dist/jquery.maskMoney.js",
"npmName": "jquery-maskmoney",
"npmFileMap": [
{
"basePath": "/dist/",
"files": [
"jquery.maskMoney.min.js"
]
}
],
"devDependencies": {
"amdefine": "latest",
"grunt": "latest",
"grunt-cli": "latest",
"grunt-contrib-concat": "latest",
"grunt-contrib-jshint": "latest",
"grunt-contrib-qunit": "latest",
"grunt-contrib-uglify": "latest",
"grunt-contrib-watch": "latest",
"grunt-jquerymanifest": "latest"
},
"license": "MIT",
"scripts": {
"test": "grunt test --verbose",
"build": "grunt"
}
}

View File

@@ -0,0 +1,591 @@
(function ($) {
"use strict";
if (!$.browser) {
$.browser = {};
$.browser.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase());
$.browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
$.browser.opera = /opera/.test(navigator.userAgent.toLowerCase());
$.browser.msie = /msie/.test(navigator.userAgent.toLowerCase());
$.browser.device = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase());
}
var defaultOptions = {
prefix: "",
suffix: "",
affixesStay: true,
thousands: ",",
decimal: ".",
precision: 2,
allowZero: false,
allowNegative: false,
doubleClickSelection: true,
allowEmpty: false,
bringCaretAtEndOnFocus: true
},
methods = {
destroy: function () {
$(this).unbind(".maskMoney");
if ($.browser.msie) {
this.onpaste = null;
}
return this;
},
applyMask: function (value) {
var $input = $(this);
// data-* api
var settings = $input.data("settings");
return maskValue(value, settings);
},
mask: function (value) {
return this.each(function () {
var $this = $(this);
if (typeof value === "number") {
$this.val(value);
}
return $this.trigger("mask");
});
},
unmasked: function () {
return this.map(function () {
var value = ($(this).val() || "0"),
isNegative = value.indexOf("-") !== -1,
decimalPart;
// get the last position of the array that is a number(coercion makes "" to be evaluated as false)
$(value.split(/\D/).reverse()).each(function (index, element) {
if (element) {
decimalPart = element;
return false;
}
});
value = value.replace(/\D/g, "");
value = value.replace(new RegExp(decimalPart + "$"), "." + decimalPart);
if (isNegative) {
value = "-" + value;
}
return parseFloat(value);
});
},
unmaskedWithOptions: function () {
return this.map(function () {
var value = ($(this).val() || "0"),
settings = $(this).data("settings") || defaultOptions,
regExp = new RegExp((settings.thousandsForUnmasked || settings.thousands), "g");
value = value.replace(regExp, "");
return parseFloat(value);
});
},
init: function (parameters) {
// the default options should not be shared with others
parameters = $.extend($.extend({}, defaultOptions), parameters);
return this.each(function () {
var $input = $(this), settings,
onFocusValue;
// data-* api
settings = $.extend({}, parameters);
settings = $.extend(settings, $input.data());
// Store settings for use with the applyMask method.
$input.data("settings", settings);
function getInputSelection() {
var el = $input.get(0),
start = 0,
end = 0,
normalizedValue,
range,
textInputRange,
len,
endRange;
if (typeof el.selectionStart === "number" && typeof el.selectionEnd === "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else {
range = document.selection.createRange();
if (range && range.parentElement() === el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
} // getInputSelection
function canInputMoreNumbers() {
var haventReachedMaxLength = !($input.val().length >= $input.attr("maxlength") && $input.attr("maxlength") >= 0),
selection = getInputSelection(),
start = selection.start,
end = selection.end,
haveNumberSelected = (selection.start !== selection.end && $input.val().substring(start, end).match(/\d/)) ? true : false,
startWithZero = ($input.val().substring(0, 1) === "0");
return haventReachedMaxLength || haveNumberSelected || startWithZero;
}
function setCursorPosition(pos) {
// Do not set the position if
// the we're formatting on blur.
// This is because we do not want
// to refocus on the control after
// the blur.
if (!!settings.formatOnBlur) {
return;
}
$input.each(function (index, elem) {
if (elem.setSelectionRange) {
elem.focus();
elem.setSelectionRange(pos, pos);
} else if (elem.createTextRange) {
var range = elem.createTextRange();
range.collapse(true);
range.moveEnd("character", pos);
range.moveStart("character", pos);
range.select();
}
});
}
function maskAndPosition(startPos) {
var originalLen = $input.val().length,
newLen;
$input.val(maskValue($input.val(), settings));
newLen = $input.val().length;
// If the we're using the reverse option,
// do not put the cursor at the end of
// the input. The reverse option allows
// the user to input text from left to right.
if (!settings.reverse) {
startPos = startPos - (originalLen - newLen);
}
setCursorPosition(startPos);
}
function mask() {
var value = $input.val();
if (settings.allowEmpty && value === "") {
return;
}
var isNumber = !isNaN(value);
var decimalPointIndex = isNumber? value.indexOf("."): value.indexOf(settings.decimal);
if (settings.precision > 0) {
if(decimalPointIndex < 0){
value += settings.decimal + new Array(settings.precision + 1).join(0);
}
else {
// If the following decimal part dosen't have enough length against the precision, it needs to be filled with zeros.
var integerPart = value.slice(0, decimalPointIndex),
decimalPart = value.slice(decimalPointIndex + 1);
value = integerPart + settings.decimal + decimalPart +
new Array((settings.precision + 1) - decimalPart.length).join(0);
}
} else if (decimalPointIndex > 0) {
// if the precision is 0, discard the decimal part
value = value.slice(0, decimalPointIndex);
}
$input.val(maskValue(value, settings));
}
function changeSign() {
var inputValue = $input.val();
if (settings.allowNegative) {
if (inputValue !== "" && inputValue.charAt(0) === "-") {
return inputValue.replace("-", "");
} else {
return "-" + inputValue;
}
} else {
return inputValue;
}
}
function preventDefault(e) {
if (e.preventDefault) { //standard browsers
e.preventDefault();
} else { // old internet explorer
e.returnValue = false;
}
}
function fixMobile() {
if ($.browser.device) {
$input.attr("type", "tel");
}
}
function keypressEvent(e) {
e = e || window.event;
var key = e.which || e.charCode || e.keyCode,
decimalKeyCode = settings.decimal.charCodeAt(0);
//added to handle an IE "special" event
if (key === undefined) {
return false;
}
// any key except the numbers 0-9. if we're using settings.reverse,
// allow the user to input the decimal key
if ((key < 48 || key > 57) && (key !== decimalKeyCode || !settings.reverse)) {
return handleAllKeysExceptNumericalDigits(key, e);
} else if (!canInputMoreNumbers()) {
return false;
} else {
if (key === decimalKeyCode && shouldPreventDecimalKey()) {
return false;
}
if (settings.formatOnBlur) {
return true;
}
preventDefault(e);
applyMask(e);
return false;
}
}
function shouldPreventDecimalKey() {
// If all text is selected, we can accept the decimal
// key because it will replace everything.
if (isAllTextSelected()) {
return false;
}
return alreadyContainsDecimal();
}
function isAllTextSelected() {
var length = $input.val().length;
var selection = getInputSelection();
// This should if all text is selected or if the
// input is empty.
return selection.start === 0 && selection.end === length;
}
function alreadyContainsDecimal() {
return $input.val().indexOf(settings.decimal) > -1;
}
function applyMask(e) {
e = e || window.event;
var key = e.which || e.charCode || e.keyCode,
keyPressedChar = "",
selection,
startPos,
endPos,
value;
if (key >= 48 && key <= 57) {
keyPressedChar = String.fromCharCode(key);
}
selection = getInputSelection();
startPos = selection.start;
endPos = selection.end;
value = $input.val();
$input.val(value.substring(0, startPos) + keyPressedChar + value.substring(endPos, value.length));
maskAndPosition(startPos + 1);
}
function handleAllKeysExceptNumericalDigits(key, e) {
// -(minus) key
if (key === 45) {
$input.val(changeSign());
return false;
// +(plus) key
} else if (key === 43) {
$input.val($input.val().replace("-", ""));
return false;
// enter key or tab key
} else if (key === 13 || key === 9) {
return true;
} else if ($.browser.mozilla && (key === 37 || key === 39) && e.charCode === 0) {
// needed for left arrow key or right arrow key with firefox
// the charCode part is to avoid allowing "%"(e.charCode 0, e.keyCode 37)
return true;
} else { // any other key with keycode less than 48 and greater than 57
preventDefault(e);
return true;
}
}
function keydownEvent(e) {
e = e || window.event;
var key = e.which || e.charCode || e.keyCode,
selection,
startPos,
endPos,
value,
lastNumber;
//needed to handle an IE "special" event
if (key === undefined) {
return false;
}
selection = getInputSelection();
startPos = selection.start;
endPos = selection.end;
if (key === 8 || key === 46 || key === 63272) { // backspace or delete key (with special case for safari)
preventDefault(e);
value = $input.val();
// not a selection
if (startPos === endPos) {
// backspace
if (key === 8) {
if (settings.suffix === "") {
startPos -= 1;
} else {
// needed to find the position of the last number to be erased
lastNumber = value.split("").reverse().join("").search(/\d/);
startPos = value.length - lastNumber - 1;
endPos = startPos + 1;
}
//delete
} else {
endPos += 1;
}
}
$input.val(value.substring(0, startPos) + value.substring(endPos, value.length));
maskAndPosition(startPos);
return false;
} else if (key === 9) { // tab key
return true;
} else { // any other key
return true;
}
}
function focusEvent() {
onFocusValue = $input.val();
mask();
var input = $input.get(0),
textRange;
if (!!settings.selectAllOnFocus) {
input.select();
} else if (input.createTextRange && settings.bringCaretAtEndOnFocus) {
textRange = input.createTextRange();
textRange.collapse(false); // set the cursor at the end of the input
textRange.select();
}
}
function cutPasteEvent() {
setTimeout(function () {
mask();
}, 0);
}
function getDefaultMask() {
var n = parseFloat("0") / Math.pow(10, settings.precision);
return (n.toFixed(settings.precision)).replace(new RegExp("\\.", "g"), settings.decimal);
}
function blurEvent(e) {
if ($.browser.msie) {
keypressEvent(e);
}
if (!!settings.formatOnBlur && $input.val() !== onFocusValue) {
applyMask(e);
}
if ($input.val() === "" && settings.allowEmpty) {
$input.val("");
} else if ($input.val() === "" || $input.val() === setSymbol(getDefaultMask(), settings)) {
if (!settings.allowZero) {
$input.val("");
} else if (!settings.affixesStay) {
$input.val(getDefaultMask());
} else {
$input.val(setSymbol(getDefaultMask(), settings));
}
} else {
if (!settings.affixesStay) {
var newValue = $input.val().replace(settings.prefix, "").replace(settings.suffix, "");
$input.val(newValue);
}
}
if ($input.val() !== onFocusValue) {
$input.change();
}
}
function clickEvent() {
var input = $input.get(0),
length;
if (!!settings.selectAllOnFocus) {
// selectAllOnFocus will be handled by
// the focus event. The focus event is
// also fired when the input is clicked.
return;
} else if (input.setSelectionRange && settings.bringCaretAtEndOnFocus) {
length = $input.val().length;
input.setSelectionRange(length, length);
} else {
$input.val($input.val());
}
}
function doubleClickEvent() {
var input = $input.get(0),
start,
length;
if (input.setSelectionRange && settings.bringCaretAtEndOnFocus) {
length = $input.val().length;
start = settings.doubleClickSelection ? 0 : length;
input.setSelectionRange(start, length);
} else {
$input.val($input.val());
}
}
fixMobile();
$input.unbind(".maskMoney");
$input.bind("keypress.maskMoney", keypressEvent);
$input.bind("keydown.maskMoney", keydownEvent);
$input.bind("blur.maskMoney", blurEvent);
$input.bind("focus.maskMoney", focusEvent);
$input.bind("click.maskMoney", clickEvent);
$input.bind("dblclick.maskMoney", doubleClickEvent);
$input.bind("cut.maskMoney", cutPasteEvent);
$input.bind("paste.maskMoney", cutPasteEvent);
$input.bind("mask.maskMoney", mask);
});
}
};
function setSymbol(value, settings) {
var operator = "";
if (value.indexOf("-") > -1) {
value = value.replace("-", "");
operator = "-";
}
if (value.indexOf(settings.prefix) > -1) {
value = value.replace(settings.prefix, "");
}
if (value.indexOf(settings.suffix) > -1) {
value = value.replace(settings.suffix, "");
}
return operator + settings.prefix + value + settings.suffix;
}
function maskValue(value, settings) {
if (settings.allowEmpty && value === "") {
return "";
}
if (!!settings.reverse) {
return maskValueReverse(value, settings);
}
return maskValueStandard(value, settings);
}
function maskValueStandard(value, settings) {
var negative = (value.indexOf("-") > -1 && settings.allowNegative) ? "-" : "",
onlyNumbers = value.replace(/[^0-9]/g, ""),
integerPart = onlyNumbers.slice(0, onlyNumbers.length - settings.precision),
newValue,
decimalPart,
leadingZeros;
newValue = buildIntegerPart(integerPart, negative, settings);
if (settings.precision > 0) {
if(!isNaN(value) && value.indexOf(".")){
var precision = value.substr(value.indexOf(".") + 1);
onlyNumbers += new Array((settings.precision + 1) - precision.length).join(0);
integerPart = onlyNumbers.slice(0, onlyNumbers.length - settings.precision);
newValue = buildIntegerPart(integerPart, negative, settings);
}
decimalPart = onlyNumbers.slice(onlyNumbers.length - settings.precision);
leadingZeros = new Array((settings.precision + 1) - decimalPart.length).join(0);
newValue += settings.decimal + leadingZeros + decimalPart;
}
return setSymbol(newValue, settings);
}
function maskValueReverse(value, settings) {
var negative = (value.indexOf("-") > -1 && settings.allowNegative) ? "-" : "",
valueWithoutSymbol = value.replace(settings.prefix, "").replace(settings.suffix, ""),
integerPart = valueWithoutSymbol.split(settings.decimal)[0],
newValue,
decimalPart = "";
if (integerPart === "") {
integerPart = "0";
}
newValue = buildIntegerPart(integerPart, negative, settings);
if (settings.precision > 0) {
var arr = valueWithoutSymbol.split(settings.decimal);
if (arr.length > 1) {
decimalPart = arr[1];
}
newValue += settings.decimal + decimalPart;
var rounded = Number.parseFloat((integerPart + "." + decimalPart)).toFixed(settings.precision);
var roundedDecimalPart = rounded.toString().split(settings.decimal)[1];
newValue = newValue.split(settings.decimal)[0] + "." + roundedDecimalPart;
}
return setSymbol(newValue, settings);
}
function buildIntegerPart(integerPart, negative, settings) {
// remove initial zeros
integerPart = integerPart.replace(/^0*/g, "");
// put settings.thousands every 3 chars
integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, settings.thousands);
if (integerPart === "") {
integerPart = "0";
}
return negative + integerPart;
}
$.fn.maskMoney = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === "object" || !method) {
return methods.init.apply(this, arguments);
} else {
$.error("Method " + method + " does not exist on jQuery.maskMoney");
}
};
})(window.jQuery || window.Zepto);

View File

@@ -0,0 +1,31 @@
"use strict";
module("change");
test("it calls the change event when the field's value is changed", function() {
var input = $("#input1").maskMoney(),
changeWasCalled = false;
input.change(function() {
changeWasCalled = true;
});
input.val("0.01");
input.trigger("focus");
keypress(input, 1);
input.trigger("blur");
ok(changeWasCalled, "change was called");
equal(input.val(), "0.11", "changed value");
});
test("it doesn't call the change event when the field's value is unchanged", function() {
var input = $("#input1").maskMoney(),
changeWasCalled = false;
input.change(function() {
changeWasCalled = true;
});
input.val("0.01");
input.trigger("focus");
input.trigger("blur");
ok(!changeWasCalled, "change was not called");
equal(input.val(), "0.01", "changed value");
});

View File

@@ -0,0 +1,27 @@
"use strict";
// stop()/start() is used when you have async tests. since we use setTimeout({}, 0)
// to call mask() inside cutPasteEvent function, we need to use them
module("cut & paste");
test("when cuting", function() {
stop();
var input = $("#input1").maskMoney();
input.val("12345678");
input.trigger("cut");
setTimeout( function() {
start();
equal(input.val(), "12,345,678.00", "format the value of the field");
}, 1);
});
test("when pasting", function() {
stop();
var input = $("#input1").maskMoney();
input.val("12345678");
input.trigger("paste");
setTimeout( function() {
start();
equal(input.val(), "12,345,678.00", "format the value of the field");
}, 1);
});

View File

@@ -0,0 +1,27 @@
"use strict";
module("data-dash api");
test("with field configured using data-* attributes", function() {
var input = $("#input3").maskMoney();
input.val("12345678");
input.trigger("focus");
equal(input.val(), "R$12.345.678,00", "configure maskMoney using data-* attributes");
});
test("configuring a setting that isn't a single word", function() {
var input = $("#input3");
input.attr("data-allow-zero", "true");
input.maskMoney();
input.val("0");
input.trigger("mask");
equal(input.val(), "R$0,00", "it works by using dashes-pattern instead of camelCase");
});
test("allow to configure multiple fields using data-* attributes", function() {
var input = $(".multiple-dash").maskMoney();
input.val("12345678");
input.trigger("focus");
equal($("#input3").val(), "R$12.345.678,00", "configure maskMoney using data-* attributes");
equal($("#input4").val(), "U$12,345,678.00", "configure maskMoney using data-* attributes");
});

View File

@@ -0,0 +1,17 @@
"use strict";
module("empty");
test("allow empty inputs", function() {
var input = $("#input1").maskMoney({ precision: 2, allowEmpty: true });
input.val("");
input.trigger("focus");
equal(input.val(), "", "allow empty inputs");
});
test("don't allow empty inputs", function() {
var input = $("#input1").maskMoney({ precision: 2, allowEmpty: false });
input.val("");
input.trigger("focus");
equal(input.val(), "0.00", "don't allow empty inputs");
});

View File

@@ -0,0 +1,9 @@
"use strict";
module("focus");
test("with default mask", function() {
var input = $("#input1").maskMoney();
input.val("12345678");
input.trigger("focus");
equal(input.val(), "12,345,678.00", "format the value of the field on focus");
});

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery maskMoney Test Suite</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.23.1.css">
<script src="../bower_components/jquery/dist/jquery.min.js"></script>
<script src="http://code.jquery.com/qunit/qunit-1.23.1.js"></script>
<script src="../src/jquery.maskMoney.js"></script>
<script src="util.js"></script>
<script src="init_and_destroy_test.js"></script>
<script src="mask_test.js"></script>
<script src="data_dash_test.js"></script>
<script src="unmasked_test.js"></script>
<script src="focus_test.js"></script>
<script src="change_test.js"></script>
<script src="typing_test.js"></script>
<script src="cut_paste_test.js"></script>
<script src="selection_test.js"></script>
<script src="empty_test.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture">
<input type="text" id="input1" class="all"/>
<input type="text" id="input2" class="all"/>
<input type="text" class="multiple-dash" id="input3" data-prefix="R$" data-thousands="." data-decimal=","/>
<input type="text" class="multiple-dash" id="input4" data-prefix="U$" data-thousands="," data-decimal="."/>
</div>
</body>
</html>

View File

@@ -0,0 +1,26 @@
"use strict";
test("chainable", function() {
ok($("#input1").maskMoney().val("123"), "can be chained");
equal($("#input1").val(), "123", "class was added correctly from chaining");
});
test("init", function() {
var input = $("#input1").maskMoney(),
events;
events = jQuery._data(input.get(0), "events");
ok(events.blur, "attached the blur event");
ok(events.keypress, "attached the keypress event");
ok(events.keydown, "attached the keydown event");
ok(events.focus, "attached the focus event");
ok(events.click, "attached the click event");
});
test("destroy", function() {
var input = $("#input1").maskMoney(),
events;
input.maskMoney("destroy");
events = jQuery._data(input.get(0), "events");
equal(events, undefined, "destroy method removed all attached events");
});

View File

@@ -0,0 +1,82 @@
"use strict";
module("mask");
test("when triggered in a empty field", function() {
var input = $("#input1").maskMoney();
input.val("");
input.maskMoney("mask");
equal(input.val(), "0.00", "set zero as the value");
});
test("with a lot of leading zeros", function() {
var input = $("#input1").maskMoney();
input.val("000000000123");
input.maskMoney("mask");
equal(input.val(), "123.00", "removes the unecessary zeroes");
});
QUnit.skip("with a pre-formatted number", function() {
var input = $("#input1").maskMoney();
input.val("123,45");
input.maskMoney("mask");
equal(input.val(), "123.45", "keeps the number precision");
});
QUnit.skip("with a pre-formatted number smaller than the set precision", function() {
var input = $("#input1").maskMoney();
input.val("123,4");
input.maskMoney("mask");
equal(input.val(), "123.40", "keeps the number precision");
});
test("with negative symbol and a field that doesn't allow negative ", function() {
var input = $("#input1").maskMoney({allowNegative: false});
input.val("-123");
input.maskMoney("mask");
equal(input.val(), "123.00", "removes negative symbol");
});
QUnit.skip("with a number as parameter", function() {
var input = $("#input1").maskMoney();
input.maskMoney("mask", 123456.70);
equal(input.val(), "123,456.70");
});
test("with a number as parameter", function() {
var input = $("#input1").maskMoney({ precision: 0 });
input.maskMoney("mask", 1000);
equal(input.val(), "1,000");
});
test("with a decimal number as parameter", function() {
var input = $("#input1").maskMoney();
input.maskMoney("mask", 1.1);
equal(input.val(), "1.10");
});
test("with a decimal number as parameter and different symbol", function() {
var input = $("#input1").maskMoney({thousands: ".", decimal: ","});
input.maskMoney("mask", 2001.1);
equal(input.val(), "2.001,10");
});
test("without a decimal number as parameter and different symbol", function() {
var input = $("#input1").maskMoney({thousands: ".", decimal: ","});
input.maskMoney("mask", 2001);
equal(input.val(), "2.001,00");
});
test("with a negative number as parameter", function() {
var input = $("#input1").maskMoney({allowNegative: true});
input.maskMoney("mask", -123456.78);
equal(input.val(), "-123,456.78");
});
test("with a suffix", function() {
var input = $("#input1").maskMoney({suffix: " €"});
input.maskMoney("mask", 20316.22);
equal(input.val(), "20,316.22 €");
});

View File

@@ -0,0 +1,19 @@
"use strict";
module("double click selection");
test("when double clicking", function() {
var input = $("#input1").maskMoney();
input.val("123.45");
input.maskMoney("mask");
input.trigger("dblclick");
equal(input.val(), "123.45", "the content does not change");
});
test("when double clicking and hitting delete", function() {
var input = $("#input1").maskMoney();
input.val("12345");
input.maskMoney("mask");
input.trigger("dblclick");
keydown(input, "backspace");
equal(input.val(), "0.00", "all the content is cleared");
});

View File

@@ -0,0 +1,36 @@
"use strict";
module("typing");
test("accepts keys in sequence", function() {
var input = $("#input1").maskMoney();
input.trigger("focus");
keypress(input, 1);
keypress(input, 2);
keypress(input, 3);
keypress(input, 4);
keypress(input, 5);
keypress(input, 6);
equal(input.val(), "1,234.56", "accept the input and format correctly");
});
test("with a suffix", function() {
var input = $("#input1").maskMoney({suffix: " €"});
input.trigger("focus");
keypress(input, 1);
keypress(input, 2);
keypress(input, 3);
keypress(input, 4);
keypress(input, 5);
equal(input.val(), "123.45 €", "accept the input and format correctly");
});
test("with a pre-set value", function() {
var input = $("#input1").maskMoney();
input.val("1");
input.trigger("focus");
keypress(input, 2);
equal(input.val(), "10.02", "accept the input and format correctly");
});

View File

@@ -0,0 +1,68 @@
"use strict";
module("unmasked");
test("with prefix", function() {
var input = $("#input1"),
unmasked;
input.val("+ 123.456,78");
unmasked = input.maskMoney("unmasked")[0];
equal(unmasked, 123456.78, "unmask method return the correct number when the field value has prefix");
});
test("with suffix", function() {
var input = $("#input1"),
unmasked;
input.val("123.456,78 €");
unmasked = input.maskMoney("unmasked")[0];
equal(unmasked, 123456.78, "unmask method return the correct number when the field value has suffix");
});
test("with prefix and suffix", function() {
var input = $("#input1"),
unmasked;
input.val("+ 123.456,78 €");
unmasked = input.maskMoney("unmasked")[0];
equal(unmasked, 123456.78, "unmask method return the correct number when the field value has prefix and suffix");
});
test("with negative number", function() {
var input = $("#input1"),
unmasked;
input.val("-R$ 123.456,78");
unmasked = input.maskMoney("unmasked")[0];
equal(unmasked, -123456.78, "unmask method return the correct number when the field value has prefix and suffix");
});
test("with collection of fields", function() {
var input = $(".all"),
unmaskedCollection;
$("#input1").val("+ 123.456,78 €");
$("#input2").val("R$ 876.543,21");
unmaskedCollection = input.maskMoney("unmasked").get();
deepEqual(unmaskedCollection, [123456.78, 876543.21], "unmask method return the correct number when the field value has prefix and suffix");
});
test("without options", function() {
var input = $("#input1"),
unmasked;
input.val("123,456");
unmasked = input.maskMoney("unmaskedWithOptions")[0];
equal(unmasked, 123456, "unmask method return the correct number even when options are not passed");
});
test("with decimal part", function() {
var input = $("#input1"),
unmasked;
input.val("123,456.01");
unmasked = input.maskMoney("unmaskedWithOptions")[0];
equal(unmasked, 123456.01, "unmask method return the correct number when the field value has a decimal part");
});
test("with options specified", function() {
var input = $("#input1"),
unmasked;
input.val("123.456");
input.maskMoney({ thousandsForUnmasked : "\\.", thousands:"." });
unmasked = input.maskMoney("unmaskedWithOptions")[0];
equal(unmasked, 123456, "unmask method return the correct number when options are set");
});

View File

@@ -0,0 +1,26 @@
"use strict";
var KEY_TO_KEYCODE_MAP = {
0: 48, 1: 49,
2: 50, 3: 51,
4: 52, 5: 53,
6: 54, 7: 55,
8: 56, 9: 57,
"shift": 16, "ctrl": 17, "alt": 18,
"backspace": 8, "tab": 9,
"enter": 13, "esc": 27, "space": 32,
"left": 37, "up": 38,
"right": 39, "down": 40,
"delete": 46,
"home": 36, "end": 35,
",": 188, ".": 190,
"-": 189, "=": 187,
};
function keypress(input, key) {
input.trigger($.Event("keypress", { keyCode: KEY_TO_KEYCODE_MAP[key] } ));
}
function keydown(input, key) {
input.trigger($.Event("keydown", { keyCode: KEY_TO_KEYCODE_MAP[key] } ));
}

File diff suppressed because one or more lines are too long