From 35cdebea711e541dd03877dc171bc2229fbe89a3 Mon Sep 17 00:00:00 2001 From: Max Huang Date: Tue, 16 Aug 2016 22:39:41 +1000 Subject: [PATCH] [Issue-79] Angular directive: use $formatters --- .eslintrc.js | 3 +-- README.md | 8 ++++---- bower.json | 2 +- dist/cleave-angular.js | 31 +++++++++++++++++++------------ dist/cleave-angular.min.js | 4 ++-- dist/cleave-react.min.js | 2 +- dist/cleave.min.js | 2 +- doc/angularjs-directive-usage.md | 24 ++++++++++++------------ package.json | 2 +- src/Cleave.angular.js | 31 +++++++++++++++++++------------ test/NumeralFormatter_spec.js | 2 +- 11 files changed, 62 insertions(+), 49 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index d6a0a406..a2855b2b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,8 +1,7 @@ module.exports = { "parser": "babel-eslint", "globals": { - "angular": 1, - "Cleave": 1 + "angular": 1 }, "rules": { "quotes": [ diff --git a/README.md b/README.md index 2f513e7d..f8d3734a 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ First include the directive module: ``` -And in the model: +And in your model: ```js angular.module('app', ['cleave.js']) @@ -165,7 +165,7 @@ angular.module('app', ['cleave.js']) }; $scope.model = { - value: '' + rawValue: '' }; $scope.options = { @@ -177,11 +177,11 @@ angular.module('app', ['cleave.js']) }); ``` -Then easily you can apply `cleave` directive with `input` field: +Then easily you can apply `cleave` directive to `input` field: ```html
-
``` diff --git a/bower.json b/bower.json index 0d8925e4..8e720a9a 100644 --- a/bower.json +++ b/bower.json @@ -8,7 +8,7 @@ "form", "input" ], - "version": "0.6.9", + "version": "0.6.10", "author": { "name": "Max Huang", "email": "risonhuang@gmail.com", diff --git a/dist/cleave-angular.js b/dist/cleave-angular.js index 62bdfabe..b4879735 100644 --- a/dist/cleave-angular.js +++ b/dist/cleave-angular.js @@ -823,19 +823,26 @@ angular.module('cleave.js', []) onValueChange: '&?' }, - controller: function ($scope, $element) { - $scope.cleave = new Cleave($element[0], $scope.options); - $scope.onValueChange = $scope.onValueChange || null; - }, + compile: function () { + return { + pre: function ($scope, $element, attrs, ngModelCtrl) { + $scope.cleave = new window.Cleave($element[0], $scope.options); - link: function ($scope, $element, attrs, ngModel) { - if ($scope.onValueChange) { - $scope.$watch(function () { - return ngModel.$modelValue; - }, function () { - $scope.onValueChange()($scope.cleave.getFormattedValue(), $scope.cleave.getRawValue()); - }); - } + ngModelCtrl.$formatters.push(function (val) { + $scope.cleave.setRawValue(val); + + return $scope.cleave.getFormattedValue(); + }); + + ngModelCtrl.$parsers.push(function (newFormattedValue) { + if ($scope.onValueChange) { + $scope.onValueChange()(newFormattedValue); + } + + return $scope.cleave.getRawValue(); + }); + } + }; } }; }); diff --git a/dist/cleave-angular.min.js b/dist/cleave-angular.min.js index 0eceefd6..559ea89d 100644 --- a/dist/cleave-angular.min.js +++ b/dist/cleave-angular.min.js @@ -1,8 +1,8 @@ /*! - * cleave.js - 0.6.9 + * cleave.js - 0.6.10 * https://github.com/nosir/cleave.js * Apache License Version 2.0 * * Copyright (C) 2012-2016 Max Huang https://github.com/nosir/ */ -!function(window,document,undefined){"use strict";var Cleave=function(element,opts){var owner=this;"string"==typeof element?owner.element=document.querySelector(element):owner.element="undefined"!=typeof element.length&&element.length>0?element[0]:element,opts.initValue=owner.element.value,owner.properties=Cleave.DefaultProperties.assign({},opts),owner.init()};Cleave.prototype={init:function(){var owner=this,pps=owner.properties;(pps.numeral||pps.phone||pps.creditCard||pps.date||0!==pps.blocksLength||pps.prefix)&&(pps.maxLength=Cleave.Util.getMaxLength(pps.blocks),owner.onChangeListener=owner.onChange.bind(owner),owner.onKeyDownListener=owner.onKeyDown.bind(owner),owner.element.addEventListener("input",owner.onChangeListener),owner.element.addEventListener("keydown",owner.onKeyDownListener),owner.initPhoneFormatter(),owner.initDateFormatter(),owner.initNumeralFormatter(),owner.onInput(pps.initValue))},initNumeralFormatter:function(){var owner=this,pps=owner.properties;pps.numeral&&(pps.numeralFormatter=new Cleave.NumeralFormatter(pps.numeralDecimalMark,pps.numeralDecimalScale,pps.numeralThousandsGroupStyle,pps.delimiter))},initDateFormatter:function(){var owner=this,pps=owner.properties;pps.date&&(pps.dateFormatter=new Cleave.DateFormatter(pps.datePattern),pps.blocks=pps.dateFormatter.getBlocks(),pps.blocksLength=pps.blocks.length,pps.maxLength=Cleave.Util.getMaxLength(pps.blocks))},initPhoneFormatter:function(){var owner=this,pps=owner.properties;if(pps.phone)try{pps.phoneFormatter=new Cleave.PhoneFormatter(new window.Cleave.AsYouTypeFormatter(pps.phoneRegionCode),pps.delimiter)}catch(ex){throw new Error("Please include phone-type-formatter.{country}.js lib")}},onKeyDown:function(event){var owner=this,pps=owner.properties,charCode=event.which||event.keyCode;return 8===charCode&&Cleave.Util.isDelimiter(owner.element.value.slice(-1),pps.delimiter,pps.delimiters)?void(pps.backspace=!0):void(pps.backspace=!1)},onChange:function(){this.onInput(this.element.value)},onInput:function(value){var owner=this,pps=owner.properties,prev=value,Util=Cleave.Util;return pps.numeral||!pps.backspace||Util.isDelimiter(value.slice(-1),pps.delimiter,pps.delimiters)||(value=Util.headStr(value,value.length-1)),pps.phone?(pps.result=pps.phoneFormatter.format(value),void owner.updateValueState()):pps.numeral?(pps.result=pps.prefix+pps.numeralFormatter.format(value),void owner.updateValueState()):(pps.date&&(value=pps.dateFormatter.getValidatedDate(value)),value=Util.stripDelimiters(value,pps.delimiter,pps.delimiters),value=Util.getPrefixStrippedValue(value,pps.prefixLength),value=pps.numericOnly?Util.strip(value,/[^\d]/g):value,value=pps.uppercase?value.toUpperCase():value,value=pps.lowercase?value.toLowerCase():value,pps.prefix&&(value=pps.prefix+value,0===pps.blocksLength)?(pps.result=value,void owner.updateValueState()):(pps.creditCard&&owner.updateCreditCardPropsByValue(value),value=Util.headStr(value,pps.maxLength),pps.result=Util.getFormattedValue(value,pps.blocks,pps.blocksLength,pps.delimiter,pps.delimiters),void(prev===pps.result&&prev!==pps.prefix||owner.updateValueState())))},updateCreditCardPropsByValue:function(value){var creditCardInfo,owner=this,pps=owner.properties,Util=Cleave.Util;Util.headStr(pps.result,4)!==Util.headStr(value,4)&&(creditCardInfo=Cleave.CreditCardDetector.getInfo(value,pps.creditCardStrictMode),pps.blocks=creditCardInfo.blocks,pps.blocksLength=pps.blocks.length,pps.maxLength=Util.getMaxLength(pps.blocks),pps.creditCardType!==creditCardInfo.type&&(pps.creditCardType=creditCardInfo.type,pps.onCreditCardTypeChanged.call(owner,pps.creditCardType)))},updateValueState:function(){var owner=this;owner.element.value=owner.properties.result},setPhoneRegionCode:function(phoneRegionCode){var owner=this,pps=owner.properties;pps.phoneRegionCode=phoneRegionCode,owner.initPhoneFormatter(),owner.onChange()},setRawValue:function(value){var owner=this,pps=owner.properties;value=value.toString(),pps.numeral&&(value=value.replace(".",pps.numeralDecimalMark)),owner.element.value=value,owner.onInput(value)},getRawValue:function(){var owner=this,pps=owner.properties,inputValue=owner.element.value;return pps.numeral?pps.numeralFormatter.getRawValue(inputValue):Cleave.Util.stripDelimiters(inputValue,pps.delimiter,pps.delimiters)},getFormattedValue:function(){return this.element.value},destroy:function(){var owner=this;owner.element.removeEventListener("input",owner.onChangeListener),owner.element.removeEventListener("keydown",owner.onKeyDownListener)},toString:function(){return"[Cleave Object]"}},"object"==typeof module&&"object"==typeof module.exports&&(Cleave.NumeralFormatter=require("./shortcuts/NumeralFormatter"),Cleave.DateFormatter=require("./shortcuts/DateFormatter"),Cleave.PhoneFormatter=require("./shortcuts/PhoneFormatter"),Cleave.CreditCardDetector=require("./shortcuts/CreditCardDetector"),Cleave.Util=require("./utils/Util"),Cleave.DefaultProperties=require("./common/DefaultProperties"),module.exports=exports=Cleave);var Util={noop:function(){},strip:function(value,re){return value.replace(re,"")},isDelimiter:function(letter,delimiter,delimiters){return 0===delimiters.length?letter===delimiter:delimiters.some(function(current){return letter===current?!0:void 0})},stripDelimiters:function(value,delimiter,delimiters){if(0===delimiters.length){var delimiterRE=delimiter?new RegExp("\\"+delimiter,"g"):"";return value.replace(delimiterRE,"")}return delimiters.forEach(function(current){value=value.replace(new RegExp("\\"+current,"g"),"")}),value},headStr:function(str,length){return str.slice(0,length)},getMaxLength:function(blocks){return blocks.reduce(function(previous,current){return previous+current},0)},getPrefixStrippedValue:function(value,prefixLength){return value.slice(prefixLength)},getFormattedValue:function(value,blocks,blocksLength,delimiter,delimiters){var currentDelimiter,result="",multipleDelimiters=delimiters.length>0;return blocks.forEach(function(length,index){if(value.length>0){var sub=value.slice(0,length),rest=value.slice(length);result+=sub,currentDelimiter=multipleDelimiters?delimiters[index]||currentDelimiter:delimiter,sub.length===length&&blocksLength-1>index&&(result+=currentDelimiter),value=rest}}),result}};"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=Util);var DefaultProperties={assign:function(target,opts){return target=target||{},opts=opts||{},target.creditCard=!!opts.creditCard,target.creditCardStrictMode=!!opts.creditCardStrictMode,target.creditCardType="",target.onCreditCardTypeChanged=opts.onCreditCardTypeChanged||function(){},target.phone=!!opts.phone,target.phoneRegionCode=opts.phoneRegionCode||"AU",target.phoneFormatter={},target.date=!!opts.date,target.datePattern=opts.datePattern||["d","m","Y"],target.dateFormatter={},target.numeral=!!opts.numeral,target.numeralDecimalScale=opts.numeralDecimalScale>=0?opts.numeralDecimalScale:2,target.numeralDecimalMark=opts.numeralDecimalMark||".",target.numeralThousandsGroupStyle=opts.numeralThousandsGroupStyle||"thousand",target.numericOnly=target.creditCard||target.date||!!opts.numericOnly,target.uppercase=!!opts.uppercase,target.lowercase=!!opts.lowercase,target.prefix=target.creditCard||target.phone||target.date?"":opts.prefix||"",target.prefixLength=target.prefix.length,target.initValue=opts.initValue||"",target.delimiter=opts.delimiter||""===opts.delimiter?opts.delimiter:opts.date?"/":opts.numeral?",":(opts.phone," "),target.delimiters=opts.delimiters||[],target.blocks=opts.blocks||[],target.blocksLength=target.blocks.length,target.maxLength=0,target.backspace=!1,target.result="",target}};"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=DefaultProperties);var CreditCardDetector={blocks:{uatp:[4,5,6],amex:[4,6,5],diners:[4,6,4],discover:[4,4,4,4],mastercard:[4,4,4,4],dankort:[4,4,4,4],instapayment:[4,4,4,4],jcb:[4,4,4,4],maestro:[4,4,4,4],visa:[4,4,4,4],generalLoose:[4,4,4,4],generalStrict:[4,4,4,7]},re:{uatp:/^(?!1800)1\d{0,14}/,amex:/^3[47]\d{0,13}/,discover:/^(?:6011|65\d{0,2}|64[4-9]\d?)\d{0,12}/,diners:/^3(?:0([0-5]|9)|[689]\d?)\d{0,11}/,mastercard:/^(5[1-5]|2[2-7])\d{0,14}/,dankort:/^(5019|4175|4571)\d{0,12}/,instapayment:/^63[7-9]\d{0,13}/,jcb:/^(?:2131|1800|35\d{0,2})\d{0,12}/,maestro:/^(?:5[0678]\d{0,2}|6304|67\d{0,2})\d{0,12}/,visa:/^4\d{0,15}/},getInfo:function(value,strictMode){var blocks=CreditCardDetector.blocks,re=CreditCardDetector.re;return strictMode=!!strictMode,re.amex.test(value)?{type:"amex",blocks:blocks.amex}:re.uatp.test(value)?{type:"uatp",blocks:blocks.uatp}:re.diners.test(value)?{type:"diners",blocks:blocks.diners}:re.discover.test(value)?{type:"discover",blocks:blocks.discover}:re.mastercard.test(value)?{type:"mastercard",blocks:blocks.mastercard}:re.dankort.test(value)?{type:"dankort",blocks:blocks.dankort}:re.instapayment.test(value)?{type:"instapayment",blocks:blocks.instapayment}:re.jcb.test(value)?{type:"jcb",blocks:blocks.jcb}:re.maestro.test(value)?{type:"maestro",blocks:blocks.maestro}:re.visa.test(value)?{type:"visa",blocks:blocks.visa}:strictMode?{type:"unknown",blocks:blocks.generalStrict}:{type:"unknown",blocks:blocks.generalLoose}}};"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=CreditCardDetector);var DateFormatter=function(datePattern){var owner=this;owner.blocks=[],owner.datePattern=datePattern,owner.initBlocks()};DateFormatter.prototype={initBlocks:function(){var owner=this;owner.datePattern.forEach(function(value){"Y"===value?owner.blocks.push(4):owner.blocks.push(2)})},getBlocks:function(){return this.blocks},getValidatedDate:function(value){var owner=this,result="";return value=value.replace(/[^\d]/g,""),owner.blocks.forEach(function(length,index){if(value.length>0){var sub=value.slice(0,length),sub0=sub.slice(0,1),rest=value.slice(length);switch(owner.datePattern[index]){case"d":"00"===sub?sub="01":parseInt(sub0,10)>3?sub="0"+sub0:parseInt(sub,10)>31&&(sub="31");break;case"m":"00"===sub?sub="01":parseInt(sub0,10)>1?sub="0"+sub0:parseInt(sub,10)>12&&(sub="12")}result+=sub,value=rest}}),result}},"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=DateFormatter);var NumeralFormatter=function(numeralDecimalMark,numeralDecimalScale,numeralThousandsGroupStyle,delimiter){var owner=this;owner.numeralDecimalMark=numeralDecimalMark||".",owner.numeralDecimalScale=numeralDecimalScale>=0?numeralDecimalScale:2,owner.numeralThousandsGroupStyle=numeralThousandsGroupStyle||NumeralFormatter.groupStyle.thousand,owner.delimiter=delimiter||""===delimiter?delimiter:",",owner.delimiterRE=delimiter?new RegExp("\\"+delimiter,"g"):""};NumeralFormatter.groupStyle={thousand:"thousand",lakh:"lakh",wan:"wan"},NumeralFormatter.prototype={getRawValue:function(value){return value.replace(this.delimiterRE,"").replace(this.numeralDecimalMark,".")},format:function(value){var parts,partInteger,owner=this,partDecimal="";switch(value=value.replace(/[A-Za-z]/g,"").replace(owner.numeralDecimalMark,"M").replace(/^\-/,"N").replace(/[^\dMN]/g,"").replace("N","-").replace("M",owner.numeralDecimalMark).replace(/^(-)?0+(?=\d)/,"$1"),partInteger=value,value.indexOf(owner.numeralDecimalMark)>=0&&(parts=value.split(owner.numeralDecimalMark),partInteger=parts[0],partDecimal=owner.numeralDecimalMark+parts[1].slice(0,owner.numeralDecimalScale)),owner.numeralThousandsGroupStyle){case NumeralFormatter.groupStyle.lakh:partInteger=partInteger.replace(/(\d)(?=(\d\d)+\d$)/g,"$1"+owner.delimiter);break;case NumeralFormatter.groupStyle.wan:partInteger=partInteger.replace(/(\d)(?=(\d{4})+$)/g,"$1"+owner.delimiter);break;default:partInteger=partInteger.replace(/(\d)(?=(\d{3})+$)/g,"$1"+owner.delimiter)}return partInteger.toString()+(owner.numeralDecimalScale>0?partDecimal.toString():"")}},"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=NumeralFormatter);var PhoneFormatter=function(formatter,delimiter){var owner=this;owner.delimiter=delimiter||""===delimiter?delimiter:" ",owner.delimiterRE=delimiter?new RegExp("\\"+delimiter,"g"):"",owner.formatter=formatter};PhoneFormatter.prototype={setFormatter:function(formatter){this.formatter=formatter},format:function(phoneNumber){var owner=this;owner.formatter.clear(),phoneNumber=phoneNumber.replace(/[^\d+]/g,""),phoneNumber=phoneNumber.replace(owner.delimiterRE,"");for(var current,result="",validated=!1,i=0,iMax=phoneNumber.length;iMax>i;i++)current=owner.formatter.inputDigit(phoneNumber.charAt(i)),/[\s()-]/g.test(current)?(result=current,validated=!0):validated||(result=current);return result=result.replace(/[()]/g,""),result=result.replace(/[\s-]/g,owner.delimiter)}},"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=PhoneFormatter),Cleave.NumeralFormatter=NumeralFormatter,Cleave.DateFormatter=DateFormatter,Cleave.PhoneFormatter=PhoneFormatter,Cleave.CreditCardDetector=CreditCardDetector,Cleave.Util=Util,Cleave.DefaultProperties=DefaultProperties,"object"==typeof module&&"object"==typeof module.exports?module.exports=exports=Cleave:"function"==typeof define&&define.amd?define(function(){return Cleave}):"object"==typeof window&&(window.Cleave=Cleave)}(window,document),angular.module("cleave.js",[]).directive("cleave",function(){return{restrict:"A",require:"ngModel",scope:{options:"=",onValueChange:"&?"},controller:function($scope,$element){$scope.cleave=new Cleave($element[0],$scope.options),$scope.onValueChange=$scope.onValueChange||null},link:function($scope,$element,attrs,ngModel){$scope.onValueChange&&$scope.$watch(function(){return ngModel.$modelValue},function(){$scope.onValueChange()($scope.cleave.getFormattedValue(),$scope.cleave.getRawValue())})}}}); \ No newline at end of file +!function(window,document,undefined){"use strict";var Cleave=function(element,opts){var owner=this;"string"==typeof element?owner.element=document.querySelector(element):owner.element="undefined"!=typeof element.length&&element.length>0?element[0]:element,opts.initValue=owner.element.value,owner.properties=Cleave.DefaultProperties.assign({},opts),owner.init()};Cleave.prototype={init:function(){var owner=this,pps=owner.properties;(pps.numeral||pps.phone||pps.creditCard||pps.date||0!==pps.blocksLength||pps.prefix)&&(pps.maxLength=Cleave.Util.getMaxLength(pps.blocks),owner.onChangeListener=owner.onChange.bind(owner),owner.onKeyDownListener=owner.onKeyDown.bind(owner),owner.element.addEventListener("input",owner.onChangeListener),owner.element.addEventListener("keydown",owner.onKeyDownListener),owner.initPhoneFormatter(),owner.initDateFormatter(),owner.initNumeralFormatter(),owner.onInput(pps.initValue))},initNumeralFormatter:function(){var owner=this,pps=owner.properties;pps.numeral&&(pps.numeralFormatter=new Cleave.NumeralFormatter(pps.numeralDecimalMark,pps.numeralDecimalScale,pps.numeralThousandsGroupStyle,pps.delimiter))},initDateFormatter:function(){var owner=this,pps=owner.properties;pps.date&&(pps.dateFormatter=new Cleave.DateFormatter(pps.datePattern),pps.blocks=pps.dateFormatter.getBlocks(),pps.blocksLength=pps.blocks.length,pps.maxLength=Cleave.Util.getMaxLength(pps.blocks))},initPhoneFormatter:function(){var owner=this,pps=owner.properties;if(pps.phone)try{pps.phoneFormatter=new Cleave.PhoneFormatter(new window.Cleave.AsYouTypeFormatter(pps.phoneRegionCode),pps.delimiter)}catch(ex){throw new Error("Please include phone-type-formatter.{country}.js lib")}},onKeyDown:function(event){var owner=this,pps=owner.properties,charCode=event.which||event.keyCode;return 8===charCode&&Cleave.Util.isDelimiter(owner.element.value.slice(-1),pps.delimiter,pps.delimiters)?void(pps.backspace=!0):void(pps.backspace=!1)},onChange:function(){this.onInput(this.element.value)},onInput:function(value){var owner=this,pps=owner.properties,prev=value,Util=Cleave.Util;return pps.numeral||!pps.backspace||Util.isDelimiter(value.slice(-1),pps.delimiter,pps.delimiters)||(value=Util.headStr(value,value.length-1)),pps.phone?(pps.result=pps.phoneFormatter.format(value),void owner.updateValueState()):pps.numeral?(pps.result=pps.prefix+pps.numeralFormatter.format(value),void owner.updateValueState()):(pps.date&&(value=pps.dateFormatter.getValidatedDate(value)),value=Util.stripDelimiters(value,pps.delimiter,pps.delimiters),value=Util.getPrefixStrippedValue(value,pps.prefixLength),value=pps.numericOnly?Util.strip(value,/[^\d]/g):value,value=pps.uppercase?value.toUpperCase():value,value=pps.lowercase?value.toLowerCase():value,pps.prefix&&(value=pps.prefix+value,0===pps.blocksLength)?(pps.result=value,void owner.updateValueState()):(pps.creditCard&&owner.updateCreditCardPropsByValue(value),value=Util.headStr(value,pps.maxLength),pps.result=Util.getFormattedValue(value,pps.blocks,pps.blocksLength,pps.delimiter,pps.delimiters),void(prev===pps.result&&prev!==pps.prefix||owner.updateValueState())))},updateCreditCardPropsByValue:function(value){var creditCardInfo,owner=this,pps=owner.properties,Util=Cleave.Util;Util.headStr(pps.result,4)!==Util.headStr(value,4)&&(creditCardInfo=Cleave.CreditCardDetector.getInfo(value,pps.creditCardStrictMode),pps.blocks=creditCardInfo.blocks,pps.blocksLength=pps.blocks.length,pps.maxLength=Util.getMaxLength(pps.blocks),pps.creditCardType!==creditCardInfo.type&&(pps.creditCardType=creditCardInfo.type,pps.onCreditCardTypeChanged.call(owner,pps.creditCardType)))},updateValueState:function(){var owner=this;owner.element.value=owner.properties.result},setPhoneRegionCode:function(phoneRegionCode){var owner=this,pps=owner.properties;pps.phoneRegionCode=phoneRegionCode,owner.initPhoneFormatter(),owner.onChange()},setRawValue:function(value){var owner=this,pps=owner.properties;value=value.toString(),pps.numeral&&(value=value.replace(".",pps.numeralDecimalMark)),owner.element.value=value,owner.onInput(value)},getRawValue:function(){var owner=this,pps=owner.properties,inputValue=owner.element.value;return pps.numeral?pps.numeralFormatter.getRawValue(inputValue):Cleave.Util.stripDelimiters(inputValue,pps.delimiter,pps.delimiters)},getFormattedValue:function(){return this.element.value},destroy:function(){var owner=this;owner.element.removeEventListener("input",owner.onChangeListener),owner.element.removeEventListener("keydown",owner.onKeyDownListener)},toString:function(){return"[Cleave Object]"}},"object"==typeof module&&"object"==typeof module.exports&&(Cleave.NumeralFormatter=require("./shortcuts/NumeralFormatter"),Cleave.DateFormatter=require("./shortcuts/DateFormatter"),Cleave.PhoneFormatter=require("./shortcuts/PhoneFormatter"),Cleave.CreditCardDetector=require("./shortcuts/CreditCardDetector"),Cleave.Util=require("./utils/Util"),Cleave.DefaultProperties=require("./common/DefaultProperties"),module.exports=exports=Cleave);var Util={noop:function(){},strip:function(value,re){return value.replace(re,"")},isDelimiter:function(letter,delimiter,delimiters){return 0===delimiters.length?letter===delimiter:delimiters.some(function(current){return letter===current?!0:void 0})},stripDelimiters:function(value,delimiter,delimiters){if(0===delimiters.length){var delimiterRE=delimiter?new RegExp("\\"+delimiter,"g"):"";return value.replace(delimiterRE,"")}return delimiters.forEach(function(current){value=value.replace(new RegExp("\\"+current,"g"),"")}),value},headStr:function(str,length){return str.slice(0,length)},getMaxLength:function(blocks){return blocks.reduce(function(previous,current){return previous+current},0)},getPrefixStrippedValue:function(value,prefixLength){return value.slice(prefixLength)},getFormattedValue:function(value,blocks,blocksLength,delimiter,delimiters){var currentDelimiter,result="",multipleDelimiters=delimiters.length>0;return blocks.forEach(function(length,index){if(value.length>0){var sub=value.slice(0,length),rest=value.slice(length);result+=sub,currentDelimiter=multipleDelimiters?delimiters[index]||currentDelimiter:delimiter,sub.length===length&&blocksLength-1>index&&(result+=currentDelimiter),value=rest}}),result}};"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=Util);var DefaultProperties={assign:function(target,opts){return target=target||{},opts=opts||{},target.creditCard=!!opts.creditCard,target.creditCardStrictMode=!!opts.creditCardStrictMode,target.creditCardType="",target.onCreditCardTypeChanged=opts.onCreditCardTypeChanged||function(){},target.phone=!!opts.phone,target.phoneRegionCode=opts.phoneRegionCode||"AU",target.phoneFormatter={},target.date=!!opts.date,target.datePattern=opts.datePattern||["d","m","Y"],target.dateFormatter={},target.numeral=!!opts.numeral,target.numeralDecimalScale=opts.numeralDecimalScale>=0?opts.numeralDecimalScale:2,target.numeralDecimalMark=opts.numeralDecimalMark||".",target.numeralThousandsGroupStyle=opts.numeralThousandsGroupStyle||"thousand",target.numericOnly=target.creditCard||target.date||!!opts.numericOnly,target.uppercase=!!opts.uppercase,target.lowercase=!!opts.lowercase,target.prefix=target.creditCard||target.phone||target.date?"":opts.prefix||"",target.prefixLength=target.prefix.length,target.initValue=opts.initValue||"",target.delimiter=opts.delimiter||""===opts.delimiter?opts.delimiter:opts.date?"/":opts.numeral?",":(opts.phone," "),target.delimiters=opts.delimiters||[],target.blocks=opts.blocks||[],target.blocksLength=target.blocks.length,target.maxLength=0,target.backspace=!1,target.result="",target}};"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=DefaultProperties);var CreditCardDetector={blocks:{uatp:[4,5,6],amex:[4,6,5],diners:[4,6,4],discover:[4,4,4,4],mastercard:[4,4,4,4],dankort:[4,4,4,4],instapayment:[4,4,4,4],jcb:[4,4,4,4],maestro:[4,4,4,4],visa:[4,4,4,4],generalLoose:[4,4,4,4],generalStrict:[4,4,4,7]},re:{uatp:/^(?!1800)1\d{0,14}/,amex:/^3[47]\d{0,13}/,discover:/^(?:6011|65\d{0,2}|64[4-9]\d?)\d{0,12}/,diners:/^3(?:0([0-5]|9)|[689]\d?)\d{0,11}/,mastercard:/^(5[1-5]|2[2-7])\d{0,14}/,dankort:/^(5019|4175|4571)\d{0,12}/,instapayment:/^63[7-9]\d{0,13}/,jcb:/^(?:2131|1800|35\d{0,2})\d{0,12}/,maestro:/^(?:5[0678]\d{0,2}|6304|67\d{0,2})\d{0,12}/,visa:/^4\d{0,15}/},getInfo:function(value,strictMode){var blocks=CreditCardDetector.blocks,re=CreditCardDetector.re;return strictMode=!!strictMode,re.amex.test(value)?{type:"amex",blocks:blocks.amex}:re.uatp.test(value)?{type:"uatp",blocks:blocks.uatp}:re.diners.test(value)?{type:"diners",blocks:blocks.diners}:re.discover.test(value)?{type:"discover",blocks:blocks.discover}:re.mastercard.test(value)?{type:"mastercard",blocks:blocks.mastercard}:re.dankort.test(value)?{type:"dankort",blocks:blocks.dankort}:re.instapayment.test(value)?{type:"instapayment",blocks:blocks.instapayment}:re.jcb.test(value)?{type:"jcb",blocks:blocks.jcb}:re.maestro.test(value)?{type:"maestro",blocks:blocks.maestro}:re.visa.test(value)?{type:"visa",blocks:blocks.visa}:strictMode?{type:"unknown",blocks:blocks.generalStrict}:{type:"unknown",blocks:blocks.generalLoose}}};"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=CreditCardDetector);var DateFormatter=function(datePattern){var owner=this;owner.blocks=[],owner.datePattern=datePattern,owner.initBlocks()};DateFormatter.prototype={initBlocks:function(){var owner=this;owner.datePattern.forEach(function(value){"Y"===value?owner.blocks.push(4):owner.blocks.push(2)})},getBlocks:function(){return this.blocks},getValidatedDate:function(value){var owner=this,result="";return value=value.replace(/[^\d]/g,""),owner.blocks.forEach(function(length,index){if(value.length>0){var sub=value.slice(0,length),sub0=sub.slice(0,1),rest=value.slice(length);switch(owner.datePattern[index]){case"d":"00"===sub?sub="01":parseInt(sub0,10)>3?sub="0"+sub0:parseInt(sub,10)>31&&(sub="31");break;case"m":"00"===sub?sub="01":parseInt(sub0,10)>1?sub="0"+sub0:parseInt(sub,10)>12&&(sub="12")}result+=sub,value=rest}}),result}},"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=DateFormatter);var NumeralFormatter=function(numeralDecimalMark,numeralDecimalScale,numeralThousandsGroupStyle,delimiter){var owner=this;owner.numeralDecimalMark=numeralDecimalMark||".",owner.numeralDecimalScale=numeralDecimalScale>=0?numeralDecimalScale:2,owner.numeralThousandsGroupStyle=numeralThousandsGroupStyle||NumeralFormatter.groupStyle.thousand,owner.delimiter=delimiter||""===delimiter?delimiter:",",owner.delimiterRE=delimiter?new RegExp("\\"+delimiter,"g"):""};NumeralFormatter.groupStyle={thousand:"thousand",lakh:"lakh",wan:"wan"},NumeralFormatter.prototype={getRawValue:function(value){return value.replace(this.delimiterRE,"").replace(this.numeralDecimalMark,".")},format:function(value){var parts,partInteger,owner=this,partDecimal="";switch(value=value.replace(/[A-Za-z]/g,"").replace(owner.numeralDecimalMark,"M").replace(/^\-/,"N").replace(/[^\dMN]/g,"").replace("N","-").replace("M",owner.numeralDecimalMark).replace(/^(-)?0+(?=\d)/,"$1"),partInteger=value,value.indexOf(owner.numeralDecimalMark)>=0&&(parts=value.split(owner.numeralDecimalMark),partInteger=parts[0],partDecimal=owner.numeralDecimalMark+parts[1].slice(0,owner.numeralDecimalScale)),owner.numeralThousandsGroupStyle){case NumeralFormatter.groupStyle.lakh:partInteger=partInteger.replace(/(\d)(?=(\d\d)+\d$)/g,"$1"+owner.delimiter);break;case NumeralFormatter.groupStyle.wan:partInteger=partInteger.replace(/(\d)(?=(\d{4})+$)/g,"$1"+owner.delimiter);break;default:partInteger=partInteger.replace(/(\d)(?=(\d{3})+$)/g,"$1"+owner.delimiter)}return partInteger.toString()+(owner.numeralDecimalScale>0?partDecimal.toString():"")}},"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=NumeralFormatter);var PhoneFormatter=function(formatter,delimiter){var owner=this;owner.delimiter=delimiter||""===delimiter?delimiter:" ",owner.delimiterRE=delimiter?new RegExp("\\"+delimiter,"g"):"",owner.formatter=formatter};PhoneFormatter.prototype={setFormatter:function(formatter){this.formatter=formatter},format:function(phoneNumber){var owner=this;owner.formatter.clear(),phoneNumber=phoneNumber.replace(/[^\d+]/g,""),phoneNumber=phoneNumber.replace(owner.delimiterRE,"");for(var current,result="",validated=!1,i=0,iMax=phoneNumber.length;iMax>i;i++)current=owner.formatter.inputDigit(phoneNumber.charAt(i)),/[\s()-]/g.test(current)?(result=current,validated=!0):validated||(result=current);return result=result.replace(/[()]/g,""),result=result.replace(/[\s-]/g,owner.delimiter)}},"object"==typeof module&&"object"==typeof module.exports&&(module.exports=exports=PhoneFormatter),Cleave.NumeralFormatter=NumeralFormatter,Cleave.DateFormatter=DateFormatter,Cleave.PhoneFormatter=PhoneFormatter,Cleave.CreditCardDetector=CreditCardDetector,Cleave.Util=Util,Cleave.DefaultProperties=DefaultProperties,"object"==typeof module&&"object"==typeof module.exports?module.exports=exports=Cleave:"function"==typeof define&&define.amd?define(function(){return Cleave}):"object"==typeof window&&(window.Cleave=Cleave)}(window,document),angular.module("cleave.js",[]).directive("cleave",function(){return{restrict:"A",require:"ngModel",scope:{options:"=",onValueChange:"&?"},compile:function(){return{pre:function($scope,$element,attrs,ngModelCtrl){$scope.cleave=new window.Cleave($element[0],$scope.options),ngModelCtrl.$formatters.push(function(val){return $scope.cleave.setRawValue(val),$scope.cleave.getFormattedValue()}),ngModelCtrl.$parsers.push(function(newFormattedValue){return $scope.onValueChange&&$scope.onValueChange()(newFormattedValue),$scope.cleave.getRawValue()})}}}}}); \ No newline at end of file diff --git a/dist/cleave-react.min.js b/dist/cleave-react.min.js index f041e173..960fdad0 100644 --- a/dist/cleave-react.min.js +++ b/dist/cleave-react.min.js @@ -1,5 +1,5 @@ /*! - * cleave.js - 0.6.9 + * cleave.js - 0.6.10 * https://github.com/nosir/cleave.js * Apache License Version 2.0 * diff --git a/dist/cleave.min.js b/dist/cleave.min.js index 63a475d2..9d065bb4 100644 --- a/dist/cleave.min.js +++ b/dist/cleave.min.js @@ -1,5 +1,5 @@ /*! - * cleave.js - 0.6.9 + * cleave.js - 0.6.10 * https://github.com/nosir/cleave.js * Apache License Version 2.0 * diff --git a/doc/angularjs-directive-usage.md b/doc/angularjs-directive-usage.md index c452cb80..d90133f5 100644 --- a/doc/angularjs-directive-usage.md +++ b/doc/angularjs-directive-usage.md @@ -26,7 +26,7 @@ angular.module('app', ['cleave.js']) }; $scope.model = { - value: '' + rawValue: '' }; $scope.options = { @@ -38,18 +38,20 @@ angular.module('app', ['cleave.js']) }); ``` -Then you can just use `cleave` directive with `input` field: +Then easily you can apply `cleave` directive to `input` field: ```html
-
``` ## Advanced usage -Sometimes you might want to get the raw value. Here is the way to deal with it: +By using `Cleave.js`, angular renders the input field with the formatted value, but keeps `ng-model` value as the raw value. + +If you are looking to obtain the formatted value, here is the way: First in you model: @@ -57,9 +59,8 @@ First in you model: angular.module('app', ['cleave.js']) .controller('AppController', function($scope) { - $scope.onCleaveValueChange = function(formattedValue, rawValue) { + $scope.onCleaveValueChange = function(formattedValue) { $scope.model.formattedValue = formattedValue; - $scope.model.rawValue = rawValue; }; $scope.onCreditCardTypeChanged = function(type) { @@ -67,7 +68,8 @@ angular.module('app', ['cleave.js']) }; $scope.model = { - value: '' + rawValue: '', + formattedValue: '' }; $scope.options = { @@ -83,18 +85,16 @@ Then in your html: ```html
- -

raw value: {{model.rawValue}}

+

raw (ng-model) value: {{model.rawValue}}

formatted value: {{model.formattedValue}}

-

ng-model value: {{model.value}}

-

type: {{model.creditCardType}}

``` As you can see, by passing the function (without `()`) to `on-value-change`, you register a callback from `cleave.js` directive. -Then in the callback, it returns `formattedValue` and `rawValue`. `formattedValue` here is same as your `ng-model` value. +Then in the callback, it returns `formattedValue` as the only parameter. diff --git a/package.json b/package.json index f83b5223..a331604f 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "form", "input" ], - "version": "0.6.9", + "version": "0.6.10", "author": { "name": "Max Huang", "url": "http://github.com/nosir", diff --git a/src/Cleave.angular.js b/src/Cleave.angular.js index c2ba735d..97ac7727 100644 --- a/src/Cleave.angular.js +++ b/src/Cleave.angular.js @@ -9,19 +9,26 @@ angular.module('cleave.js', []) onValueChange: '&?' }, - controller: function ($scope, $element) { - $scope.cleave = new Cleave($element[0], $scope.options); - $scope.onValueChange = $scope.onValueChange || null; - }, + compile: function () { + return { + pre: function ($scope, $element, attrs, ngModelCtrl) { + $scope.cleave = new window.Cleave($element[0], $scope.options); + + ngModelCtrl.$formatters.push(function (val) { + $scope.cleave.setRawValue(val); + + return $scope.cleave.getFormattedValue(); + }); + + ngModelCtrl.$parsers.push(function (newFormattedValue) { + if ($scope.onValueChange) { + $scope.onValueChange()(newFormattedValue); + } - link: function ($scope, $element, attrs, ngModel) { - if ($scope.onValueChange) { - $scope.$watch(function () { - return ngModel.$modelValue; - }, function () { - $scope.onValueChange()($scope.cleave.getFormattedValue(), $scope.cleave.getRawValue()); - }); - } + return $scope.cleave.getRawValue(); + }); + } + }; } }; }); diff --git a/test/NumeralFormatter_spec.js b/test/NumeralFormatter_spec.js index c89c36f3..11c17b92 100644 --- a/test/NumeralFormatter_spec.js +++ b/test/NumeralFormatter_spec.js @@ -10,7 +10,7 @@ describe('NumeralFormatter', function () { title.push('Thousands Group Style: ' + numeral.thousandsGroupStyle); } - if (numeral.numeralDecimalScale !== undefined) { + if (numeral.numeralDecimalScale || numeral.numeralDecimalScale === 0) { title.push('Decimal Scale: ' + numeral.numeralDecimalScale); }