| 1 |
import MaskedPattern from './pattern.js'; |
| 2 |
import MaskedRange from './range.js'; |
| 3 |
import IMask from '../core/holder.js'; |
| 4 |
import { isString } from '../core/utils.js'; |
| 5 |
import '../core/change-details.js'; |
| 6 |
import './base.js'; |
| 7 |
import '../core/continuous-tail-details.js'; |
| 8 |
import './factory.js'; |
| 9 |
import './pattern/chunk-tail-details.js'; |
| 10 |
import './pattern/cursor.js'; |
| 11 |
import './pattern/fixed-definition.js'; |
| 12 |
import './pattern/input-definition.js'; |
| 13 |
import './regexp.js'; |
| 14 |
|
| 15 |
const DefaultPattern = 'd{.}`m{.}`Y'; |
| 16 |
|
| 17 |
// Make format and parse required when pattern is provided |
| 18 |
|
| 19 |
/** Date mask */ |
| 20 |
class MaskedDate extends MaskedPattern { |
| 21 |
static extractPatternOptions(opts) { |
| 22 |
const { |
| 23 |
mask, |
| 24 |
pattern, |
| 25 |
...patternOpts |
| 26 |
} = opts; |
| 27 |
return { |
| 28 |
...patternOpts, |
| 29 |
mask: isString(mask) ? mask : pattern |
| 30 |
}; |
| 31 |
} |
| 32 |
|
| 33 |
/** Pattern mask for date according to {@link MaskedDate#format} */ |
| 34 |
|
| 35 |
/** Start date */ |
| 36 |
|
| 37 |
/** End date */ |
| 38 |
|
| 39 |
/** Format typed value to string */ |
| 40 |
|
| 41 |
/** Parse string to get typed value */ |
| 42 |
|
| 43 |
constructor(opts) { |
| 44 |
super(MaskedDate.extractPatternOptions({ |
| 45 |
...MaskedDate.DEFAULTS, |
| 46 |
...opts |
| 47 |
})); |
| 48 |
} |
| 49 |
updateOptions(opts) { |
| 50 |
super.updateOptions(opts); |
| 51 |
} |
| 52 |
_update(opts) { |
| 53 |
const { |
| 54 |
mask, |
| 55 |
pattern, |
| 56 |
blocks, |
| 57 |
...patternOpts |
| 58 |
} = { |
| 59 |
...MaskedDate.DEFAULTS, |
| 60 |
...opts |
| 61 |
}; |
| 62 |
const patternBlocks = Object.assign({}, MaskedDate.GET_DEFAULT_BLOCKS()); |
| 63 |
// adjust year block |
| 64 |
if (opts.min) patternBlocks.Y.from = opts.min.getFullYear(); |
| 65 |
if (opts.max) patternBlocks.Y.to = opts.max.getFullYear(); |
| 66 |
if (opts.min && opts.max && patternBlocks.Y.from === patternBlocks.Y.to) { |
| 67 |
patternBlocks.m.from = opts.min.getMonth() + 1; |
| 68 |
patternBlocks.m.to = opts.max.getMonth() + 1; |
| 69 |
if (patternBlocks.m.from === patternBlocks.m.to) { |
| 70 |
patternBlocks.d.from = opts.min.getDate(); |
| 71 |
patternBlocks.d.to = opts.max.getDate(); |
| 72 |
} |
| 73 |
} |
| 74 |
Object.assign(patternBlocks, this.blocks, blocks); |
| 75 |
super._update({ |
| 76 |
...patternOpts, |
| 77 |
mask: isString(mask) ? mask : pattern, |
| 78 |
blocks: patternBlocks |
| 79 |
}); |
| 80 |
} |
| 81 |
doValidate(flags) { |
| 82 |
const date = this.date; |
| 83 |
return super.doValidate(flags) && (!this.isComplete || this.isDateExist(this.value) && date != null && (this.min == null || this.min <= date) && (this.max == null || date <= this.max)); |
| 84 |
} |
| 85 |
|
| 86 |
/** Checks if date is exists */ |
| 87 |
isDateExist(str) { |
| 88 |
return this.format(this.parse(str, this), this).indexOf(str) >= 0; |
| 89 |
} |
| 90 |
|
| 91 |
/** Parsed Date */ |
| 92 |
get date() { |
| 93 |
return this.typedValue; |
| 94 |
} |
| 95 |
set date(date) { |
| 96 |
this.typedValue = date; |
| 97 |
} |
| 98 |
get typedValue() { |
| 99 |
return this.isComplete ? super.typedValue : null; |
| 100 |
} |
| 101 |
set typedValue(value) { |
| 102 |
super.typedValue = value; |
| 103 |
} |
| 104 |
maskEquals(mask) { |
| 105 |
return mask === Date || super.maskEquals(mask); |
| 106 |
} |
| 107 |
optionsIsChanged(opts) { |
| 108 |
return super.optionsIsChanged(MaskedDate.extractPatternOptions(opts)); |
| 109 |
} |
| 110 |
} |
| 111 |
MaskedDate.GET_DEFAULT_BLOCKS = () => ({ |
| 112 |
d: { |
| 113 |
mask: MaskedRange, |
| 114 |
from: 1, |
| 115 |
to: 31, |
| 116 |
maxLength: 2 |
| 117 |
}, |
| 118 |
m: { |
| 119 |
mask: MaskedRange, |
| 120 |
from: 1, |
| 121 |
to: 12, |
| 122 |
maxLength: 2 |
| 123 |
}, |
| 124 |
Y: { |
| 125 |
mask: MaskedRange, |
| 126 |
from: 1900, |
| 127 |
to: 9999 |
| 128 |
} |
| 129 |
}); |
| 130 |
MaskedDate.DEFAULTS = { |
| 131 |
...MaskedPattern.DEFAULTS, |
| 132 |
mask: Date, |
| 133 |
pattern: DefaultPattern, |
| 134 |
format: (date, masked) => { |
| 135 |
if (!date) return ''; |
| 136 |
const day = String(date.getDate()).padStart(2, '0'); |
| 137 |
const month = String(date.getMonth() + 1).padStart(2, '0'); |
| 138 |
const year = date.getFullYear(); |
| 139 |
return [day, month, year].join('.'); |
| 140 |
}, |
| 141 |
parse: (str, masked) => { |
| 142 |
const [day, month, year] = str.split('.').map(Number); |
| 143 |
return new Date(year, month - 1, day); |
| 144 |
} |
| 145 |
}; |
| 146 |
IMask.MaskedDate = MaskedDate; |
| 147 |
|
| 148 |
export { MaskedDate as default }; |
| 149 |
|