Home Reference Source

src/types/data/text.js

  1. import {PhoneNumberFormat, PhoneNumberUtil} from 'google-libphonenumber';
  2.  
  3. import DataType, {validationErrors} from './';
  4. import ValidationError from './validationError';
  5.  
  6. const phoneUtil = PhoneNumberUtil.getInstance();
  7.  
  8. /**
  9. * The DataType for text values.
  10. *
  11. * |Name|Type|Attribute|Description|
  12. * |----|----|---------|-----------|
  13. * |type|{@link string}| <ul><li>optional</li><li>default: 'raw'</li></ul> | The type of text to handle. This affects both validation and display. 'raw' &vert; 'email' &vert; 'url' &vert; 'ssn' &vert; 'zipCode' &vert; 'tel' &vert; 'password' |
  14. * |multi|{@link boolean}| <ul><li>optional</li><li>default: false</ul></ul> | Whether or not to allow newline characters in the text. |
  15. * |mask|{@link string}| <ul><li>optional</li><li>default: '###-##-####' (for `type='ssn'` only)</ul> | A mask to use while editing the value. |
  16. *
  17. * @extends {DataType}
  18. */
  19. export default class TextType extends DataType {
  20. static typeName = 'text';
  21.  
  22. static regexps = {
  23. email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
  24. url: /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/,
  25. ssn: /^(\d{3}-?\d{2}-?\d{4}|XXX-XX-XXXX)$/,
  26. ssnDisplay: /^(\d{3}-\d{2}-\d{4}|XXX-XX-XXXX)$/,
  27. ssnReplace: /(\d{3})(\d{2})(\d{4})/,
  28. zipCode: /^\d{5}([ \-]\d{4})?$/,
  29. };
  30.  
  31. getType() {
  32. return this.options.get('textType', 'raw');
  33. }
  34.  
  35. isMultiLined() {
  36. return this.options.get('multi', false);
  37. }
  38.  
  39. getMask() {
  40. const defaultMask = this.getType() == 'ssn' ? '###-##-####' : '';
  41. return this.options.get('mask', defaultMask);
  42. }
  43.  
  44. hasValue(value, checkDefault) {
  45. if (!super.hasValue(value, checkDefault)) {
  46. return false;
  47. }
  48. return typeof value == 'string' && value.length > 0;
  49. }
  50.  
  51. getDefaultValue() {
  52. return super.getDefaultValue('');
  53. }
  54.  
  55. format(value) {
  56. switch (this.getType()) {
  57. case 'tel':
  58. return this.getDisplay(value);
  59.  
  60. default:
  61. return value || '';
  62. }
  63. }
  64.  
  65. getDisplay(value) {
  66. switch (this.getType()) {
  67. case 'password':
  68. return '********';
  69.  
  70. case 'tel':
  71. try {
  72. const telno = phoneUtil.parse(value, 'US');
  73. return phoneUtil.format(telno, PhoneNumberFormat.NATIONAL);
  74. } catch (e) {}
  75. return value || '';
  76.  
  77. case 'ssn':
  78. if (!TextType.regexps.ssnDisplay.test(value)) {
  79. return value.replace(TextType.regexps.ssnReplace, "$1-$2-$3");
  80. }
  81. return value || '';
  82.  
  83. default:
  84. if (this.isMultiLined()) {
  85. if (value && value.includes('\n')) {
  86. return `${value.split('\n')[0]}...`;
  87. }
  88. }
  89. return value || '';
  90. }
  91. }
  92.  
  93. validate(value) {
  94. return super.validate(value, () => {
  95. const type = this.getType();
  96. switch (type) {
  97. case 'email':
  98. case 'url':
  99. case 'ssn':
  100. case 'zipCode':
  101. if (!TextType.regexps[type].test(value)) {
  102. return new ValidationError(validationErrors[type], this);
  103. }
  104. return;
  105.  
  106. case 'tel':
  107. try {
  108. const telno = phoneUtil.parse(value, 'US');
  109. if (!phoneUtil.isValidNumber(telno)) {
  110. return new ValidationError(validationErrors.tel, this);
  111. }
  112. } catch (e) {
  113. return new ValidationError(e.message, this);
  114. }
  115. return;
  116.  
  117. case 'password':
  118. default:
  119. if (!this.isMultiLined() && value.includes('\n')) {
  120. return new ValidationError(validationErrors.singleline, this);
  121. }
  122. return;
  123. }
  124. });
  125. }
  126.  
  127. filter(filterValue, rowValue) {
  128. const filterString = `${filterValue}`.toLowerCase();
  129. const rowString = `${rowValue}`.toLowerCase();
  130. return rowString.indexOf(filterString) >= 0;
  131. }
  132. }