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

Support for negative values #49

Merged
merged 6 commits into from
Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion cypress/integration/clipboard-events.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ describe('Copy & Paste', () => {
cy.get('#digit-only-decimal').clear();
});

it.only('s', ()=> {
it('s', ()=> {
const dt = new DataTransfer();
dt.setData('text/plain', 'abc1.0s.1');
const pasteEvent = new ClipboardEvent('paste', {
Expand Down Expand Up @@ -264,4 +264,28 @@ describe('Copy & Paste', () => {

cy.get('#decimal-number').clear();
});

it('should accept negative sign (only once)', () => {
const dt = new DataTransfer();
dt.setData('text/plain', '-123');
const pasteEvent = new ClipboardEvent('paste', {
clipboardData: dt,
bubbles: true,
cancelable: true,
});

cy.get('#negative-digit-only').clear();

cy.get('#negative-digit-only').then(($el) => {
$el[0].dispatchEvent(pasteEvent);
cy.get('#negative-digit-only').should('have.value', '-123');
});

cy.get('#negative-digit-only').then(($el) => {
$el[0].dispatchEvent(pasteEvent);
cy.get('#negative-digit-only').should('have.value', '-123123');
});

cy.get('#negative-digit-only').clear();
});
});
45 changes: 34 additions & 11 deletions projects/uiowa/digit-only/src/lib/digit-only.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
})
export class DigitOnlyDirective implements OnChanges {
private hasDecimalPoint = false;
private hasNegativeSign = false;
private navigationKeys = [
'Backspace',
'Delete',
Expand All @@ -29,6 +30,8 @@ export class DigitOnlyDirective implements OnChanges {

@Input() decimal = false;
@Input() decimalSeparator = '.';
@Input() allowNegatives= false;
@Input() negativeSign = '-';
@Input() min = -Infinity;
@Input() max = Infinity;
@Input() pattern?: string | RegExp;
Expand Down Expand Up @@ -58,7 +61,8 @@ export class DigitOnlyDirective implements OnChanges {
@HostListener('beforeinput', ['$event'])
onBeforeInput(e: InputEvent): any {
if (isNaN(Number(e.data))) {
if (e.data === this.decimalSeparator) {
if (e.data === this.decimalSeparator
|| (e.data === this.negativeSign && this.allowNegatives)) {
return; // go on
}
e.preventDefault();
Expand Down Expand Up @@ -97,6 +101,17 @@ export class DigitOnlyDirective implements OnChanges {
}
}

if (e.key === this.negativeSign && this.allowNegatives) {
newValue = this.forecastValue(e.key);
if (newValue.charAt(0) !== this.negativeSign || newValue.split(this.negativeSign).length > 2) {
e.preventDefault();
return;
} else {
this.hasNegativeSign = newValue.split(this.negativeSign).length > -1;
return;
}
}

// Ensure that it is a number and stop the keypress
if (e.key === ' ' || isNaN(Number(e.key))) {
e.preventDefault();
Expand Down Expand Up @@ -145,6 +160,11 @@ export class DigitOnlyDirective implements OnChanges {

private pasteData(pastedContent: string): void {
const sanitizedContent = this.sanitizeInput(pastedContent);
if (sanitizedContent.includes(this.negativeSign)
&& this.hasNegativeSign
&& !this.getSelection().includes(this.negativeSign)) {
return;
}
const pasted = document.execCommand('insertText', false, sanitizedContent);
if (!pasted) {
if (this.inputElement.setRangeText) {
Expand Down Expand Up @@ -174,6 +194,7 @@ export class DigitOnlyDirective implements OnChanges {
this.hasDecimalPoint =
this.inputElement.value.indexOf(this.decimalSeparator) > -1;
}
this.hasNegativeSign = this.inputElement.value.indexOf(this.negativeSign) > -1;
}

// The following 2 methods were added from the below article for browsers that do not support setRangeText
Expand Down Expand Up @@ -206,22 +227,27 @@ export class DigitOnlyDirective implements OnChanges {

private sanitizeInput(input: string): string {
let result = '';
let regex;
if (this.decimal && this.isValidDecimal(input)) {
const regex = new RegExp(`[^0-9${this.decimalSeparator}]`, 'g');
result = input.replace(regex, '');
regex = new RegExp(`${this.getNegativeSignRegExp()}[^0-9${this.decimalSeparator}]`, 'g');
} else {
result = input.replace(/[^0-9]/g, '');
regex = new RegExp(`${this.getNegativeSignRegExp()}[^0-9]`, 'g');
}
result = input.replace(regex, '');

const maxLength = this.inputElement.maxLength;
if (maxLength > 0) {
// the input element has maxLength limit
const allowedLength = maxLength - this.inputElement.value.length;
const allowedLength = maxLength - this.inputElement.value.length + (result.includes(`${this.negativeSign}`) ? 1 : 0);
result = allowedLength > 0 ? result.substring(0, allowedLength) : '';
}
return result;
}

private getNegativeSignRegExp() : string {
return this.allowNegatives && (!this.hasNegativeSign || this.getSelection().includes(this.negativeSign)) ? `(?!^${this.negativeSign})` : '';
}

private isValidDecimal(string: string): boolean {
if (!this.hasDecimalPoint) {
return string.split(this.decimalSeparator).length <= 2;
Expand All @@ -247,11 +273,8 @@ export class DigitOnlyDirective implements OnChanges {
const selectionStart = this.inputElement.selectionStart ?? 0;
const selectionEnd = this.inputElement.selectionEnd ?? 0;
const oldValue = this.inputElement.value;
const selection = oldValue.substring(selectionStart, selectionEnd);
return selection
? oldValue.replace(selection, key)
: oldValue.substring(0, selectionStart) +
key +
oldValue.substring(selectionStart);
return oldValue.substring(0, selectionStart) +
key +
oldValue.substring(selectionEnd);
}
}
3 changes: 3 additions & 0 deletions src/app/digit-only-demos/digit-only-demos.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ <h3><code>digitOnly</code> directive</h3>
placeholder="000"
maxlength="3"
/>

<label for="negative-digit-only">Digit Only input box that can be negative</label>
<input id="negative-digit-only" type="text" digitOnly [allowNegatives]="true" placeholder="-123"/>
</section>

<section>
Expand Down