Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(uiPercentageMask): allow negative numbers with ui-negative-number attribute #300

Merged
merged 7 commits into from
Sep 22, 2017
10 changes: 10 additions & 0 deletions src/global/percentage/percentage.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,29 @@ <h2>ui-percentage-mask</h2>
$viewValue - <input type="text" name="field5" ng-model="percentageWithDefaultDecimals" ng-model-options="{allowInvalid:true}" ui-percentage-mask> <br>
$modelValue - <span ng-bind="percentageWithDefaultDecimals"></span>
<br>

<input type="text" name="field6" ng-model="percentageWith4Decimals" ng-model-options="{allowInvalid:true}" ui-percentage-mask="4" min="percentageWithDefaultDecimals" max="115"> <br>
<span ng-bind="percentageWith4Decimals"></span> - {{form.field6.$error}}
<br>

<input type="text" name="field60" ng-model="percentageWith0Decimals" ng-model-options="{allowInvalid:true}" ui-percentage-mask="0" ui-percentage-value min="0" max="100"> <br>
<span ng-bind="percentageWith0Decimals"></span> - {{form.field60.$error}}
<br>

Percentage: <input type="text" name="field25" ng-model="percentWithDynamicDecimals" ng-model-options="{allowInvalid:true}" ui-percentage-mask="pdecimals">
Decimals: <input type="text" name="field26" ng-model="pdecimals" ui-number-mask=0><br>
<span ng-bind="percentWithDynamicDecimals"></span> - {{form.field25.$error}}
<br>

<h4>ui-percentage-mask with ui-negative-number</h2>
$viewValue - <input type="text" name="field5" ng-model="percentageWithNegativeNumber" ng-model-options="{allowInvalid:true}" ui-percentage-mask ui-negative-number> <br>
$modelValue - <span ng-bind="percentageWithNegativeNumber"></span>
<br>

<h4>ui-percentage-value</h4>
$viewValue - <input type="text" name="field6" ng-model="percentageValue" ng-model-options="{allowInvalid:true}" ui-percentage-mask="4" ui-percentage-value min="percentageWithDefaultDecimals" max="115"> <br>
$modelValue - <span ng-bind="percentageValue"></span>

<h4>ui-percentage-mask without space before %</h4>
$viewValue - <input type="text" name="field29" ng-model="percentageValue" ng-model-options="{allowInvalid:true}" ui-percentage-mask="4" ui-percentage-value ui-hide-space min="percentageWithDefaultDecimals" max="115"> <br>
</form>
Expand Down
22 changes: 20 additions & 2 deletions src/global/percentage/percentage.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ function PercentageMaskDirective($locale, $parse, PreFormatters, NumberMasks) {
return value;
}

var prefix = (angular.isDefined(attrs.uiNegativeNumber) && value < 0) ? '-' : '';
var valueToFormat = preparePercentageToFormatter(value, decimals, modelValue.multiplier);
return viewMask.apply(valueToFormat) + (hideSpace ? '%' : ' %');

var percentSign = hideSpace ? '%' : ' %';
return prefix + viewMask.apply(valueToFormat) + percentSign;
}

function parse(value) {
Expand All @@ -62,16 +65,31 @@ function PercentageMaskDirective($locale, $parse, PreFormatters, NumberMasks) {
}

var valueToFormat = PreFormatters.clearDelimitersAndLeadingZeros(value) || '0';

if (value.length > 1 && value.indexOf('%') === -1) {
valueToFormat = valueToFormat.slice(0,valueToFormat.length-1);
valueToFormat = valueToFormat.slice(0, valueToFormat.length - 1);
}

if (backspacePressed && value.length === 1 && value !== '%') {
valueToFormat = '0';
}

var percentSign = hideSpace ? '%' : ' %';
var formatedValue = viewMask.apply(valueToFormat) + percentSign;
var actualNumber = parseFloat(modelMask.apply(valueToFormat));

if (angular.isDefined(attrs.uiNegativeNumber)) {
var isNegative = (value[0] === '-'),
needsToInvertSign = (value.slice(-1) === '-');

//only apply the minus sign if it is negative or(exclusive) or the first character
//needs to be negative and the number is different from zero
if ((needsToInvertSign ^ isNegative) || value === '-') {
actualNumber *= -1;
formatedValue = '-' + ((actualNumber !== 0) ? formatedValue : '');
}
}

if (ctrl.$viewValue !== formatedValue) {
ctrl.$setViewValue(formatedValue);
ctrl.$render();
Expand Down
23 changes: 23 additions & 0 deletions src/global/percentage/percentage.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,28 @@ describe('ui.utils.masks.percentage', function() {
expect(input.getAttribute('value')).toEqual(formatedNumberAsString + percent);
}
});

it('should accept negative numbers when the ui-negative attribute is present', function() {
var input = element(by.model('percentageWithNegativeNumber'));
input.clear();

input.sendKeys('123418-');
expect(input.getAttribute('value')).toEqual('-1.234,18 %');
input.sendKeys('-');
expect(input.getAttribute('value')).toEqual('1.234,18 %');
input.sendKeys('-');
expect(input.getAttribute('value')).toEqual('-1.234,18 %');
input.sendKeys('-');
expect(input.getAttribute('value')).toEqual('1.234,18 %');
input.sendKeys('-');
expect(input.getAttribute('value')).toEqual('-1.234,18 %');
input.sendKeys(9);
expect(input.getAttribute('value')).toEqual('-12.341,89 %');
input.sendKeys(protractor.Key.BACK_SPACE);
expect(input.getAttribute('value')).toEqual('-1.234,18 %');
input.sendKeys('-');
input.sendKeys(9);
expect(input.getAttribute('value')).toEqual('12.341,89 %');
});
});
});
35 changes: 29 additions & 6 deletions src/global/percentage/percentage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ describe('ui-percentage-mask', function() {
var model = input.controller('ngModel');
expect(model.$viewValue).toBe('75.00 %');
expect(model.$valid).toBe(true);
input.val('69920').triggerHandler('input');
input.val('69.92 %').triggerHandler('input');
expect(model.$valid).toBe(false);
input.val('108120').triggerHandler('input');
input.val('108.12 %').triggerHandler('input');
expect(model.$valid).toBe(true);
});

Expand All @@ -134,12 +134,36 @@ describe('ui-percentage-mask', function() {
var model = input.controller('ngModel');
expect(model.$viewValue).toBe('75.00 %');
expect(model.$valid).toBe(true);
input.val('101000').triggerHandler('input');
input.val('101.00 %').triggerHandler('input');
expect(model.$valid).toBe(false);
input.val('99990').triggerHandler('input');
input.val('99.99 %').triggerHandler('input');
expect(model.$valid).toBe(true);
});

it('should erase a digit if % is not there', function() {
var input = TestUtil.compile('<input ng-model="model" ui-percentage-mask>');
var model = input.controller('ngModel');

input.val('12.34').triggerHandler('input');
expect(model.$viewValue).toBe('1.23 %');
expect(model.$modelValue).toBe(0.0123);
});

it('should accept negative numbers if "ui-negative-number" is defined', function() {
var input = TestUtil.compile('<input ng-model="model" ui-percentage-mask ui-negative-number>');
var model = input.controller('ngModel');

input.val('-12.34 %').triggerHandler('input');
expect(model.$viewValue).toBe('-12.34 %');
expect(model.$modelValue).toBe(-0.1234);
input.val('-12.34 %-').triggerHandler('input');
expect(model.$viewValue).toBe('12.34 %');
expect(model.$modelValue).toBe(0.1234);
input.val('12.34 %-').triggerHandler('input');
expect(model.$viewValue).toBe('-12.34 %');
expect(model.$modelValue).toBe(-0.1234);
});

it('should format initial model values with percentage value', function() {
var input = TestUtil.compile('<input ng-model="model" ui-percentage-mask ui-percentage-value>', {
model: '1234.5'
Expand All @@ -149,7 +173,7 @@ describe('ui-percentage-mask', function() {
expect(model.$viewValue).toBe('1,234.50 %');
});

it('should allow changing the number of decimals', angular.mock.inject(function($rootScope) {
it('should allow changing the number of decimals with percentage value', angular.mock.inject(function($rootScope) {
var input = TestUtil.compile('<input ng-model="model" ui-percentage-mask="decimals" ui-percentage-value>', {
model: '1234.501',
decimals: 2
Expand All @@ -164,5 +188,4 @@ describe('ui-percentage-mask', function() {
$rootScope.$digest();
expect(model.$viewValue).toBe('1,234.50 %');
}));

});