imask
Version:
vanilla javascript input mask
149 lines (136 loc) • 3.76 kB
JavaScript
import MaskedPattern from './pattern.js';
import MaskedRange from './range.js';
import IMask from '../core/holder.js';
import { isString } from '../core/utils.js';
import '../core/change-details.js';
import './base.js';
import '../core/continuous-tail-details.js';
import './factory.js';
import './pattern/chunk-tail-details.js';
import './pattern/cursor.js';
import './pattern/fixed-definition.js';
import './pattern/input-definition.js';
import './regexp.js';
const DefaultPattern = 'd{.}`m{.}`Y';
// Make format and parse required when pattern is provided
/** Date mask */
class MaskedDate extends MaskedPattern {
static extractPatternOptions(opts) {
const {
mask,
pattern,
...patternOpts
} = opts;
return {
...patternOpts,
mask: isString(mask) ? mask : pattern
};
}
/** Pattern mask for date according to {@link MaskedDate#format} */
/** Start date */
/** End date */
/** Format typed value to string */
/** Parse string to get typed value */
constructor(opts) {
super(MaskedDate.extractPatternOptions({
...MaskedDate.DEFAULTS,
...opts
}));
}
updateOptions(opts) {
super.updateOptions(opts);
}
_update(opts) {
const {
mask,
pattern,
blocks,
...patternOpts
} = {
...MaskedDate.DEFAULTS,
...opts
};
const patternBlocks = Object.assign({}, MaskedDate.GET_DEFAULT_BLOCKS());
// adjust year block
if (opts.min) patternBlocks.Y.from = opts.min.getFullYear();
if (opts.max) patternBlocks.Y.to = opts.max.getFullYear();
if (opts.min && opts.max && patternBlocks.Y.from === patternBlocks.Y.to) {
patternBlocks.m.from = opts.min.getMonth() + 1;
patternBlocks.m.to = opts.max.getMonth() + 1;
if (patternBlocks.m.from === patternBlocks.m.to) {
patternBlocks.d.from = opts.min.getDate();
patternBlocks.d.to = opts.max.getDate();
}
}
Object.assign(patternBlocks, this.blocks, blocks);
super._update({
...patternOpts,
mask: isString(mask) ? mask : pattern,
blocks: patternBlocks
});
}
doValidate(flags) {
const date = this.date;
return super.doValidate(flags) && (!this.isComplete || this.isDateExist(this.value) && date != null && (this.min == null || this.min <= date) && (this.max == null || date <= this.max));
}
/** Checks if date is exists */
isDateExist(str) {
return this.format(this.parse(str, this), this).indexOf(str) >= 0;
}
/** Parsed Date */
get date() {
return this.typedValue;
}
set date(date) {
this.typedValue = date;
}
get typedValue() {
return this.isComplete ? super.typedValue : null;
}
set typedValue(value) {
super.typedValue = value;
}
maskEquals(mask) {
return mask === Date || super.maskEquals(mask);
}
optionsIsChanged(opts) {
return super.optionsIsChanged(MaskedDate.extractPatternOptions(opts));
}
}
MaskedDate.GET_DEFAULT_BLOCKS = () => ({
d: {
mask: MaskedRange,
from: 1,
to: 31,
maxLength: 2
},
m: {
mask: MaskedRange,
from: 1,
to: 12,
maxLength: 2
},
Y: {
mask: MaskedRange,
from: 1900,
to: 9999
}
});
MaskedDate.DEFAULTS = {
...MaskedPattern.DEFAULTS,
mask: Date,
pattern: DefaultPattern,
format: (date, masked) => {
if (!date) return '';
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0');
const year = date.getFullYear();
return [day, month, year].join('.');
},
parse: (str, masked) => {
const [day, month, year] = str.split('.').map(Number);
return new Date(year, month - 1, day);
}
};
IMask.MaskedDate = MaskedDate;
export { MaskedDate as default };