Skip to content

Commit

Permalink
add Date value support for value
Browse files Browse the repository at this point in the history
  • Loading branch information
javadbat committed Oct 20, 2023
1 parent e7cbfdb commit 5a44877
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 74 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#changelog
## [3.9.0] - 2023-10-20
### new features
- add `Date` value support as a value input and output
## [3.8.1] - 2023-9-8
### fixed
- fix useless margin and size reduction
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ document.querySelector('jb-date-input').addEventListener('init',this.onCalendarE

//when calendar init all property and function and dom created and bind successully
document.querySelector('jb-date-input').addEventListener('load',this.onCalendarElementLoaded);
document.querySelector('jb-date-input').addEventListener('change',(e)=>{
//value in string
console.log(e.target.value)
//value in js Date object
console.log(e.target.valueInDate)
});
```

## date input type
Expand Down Expand Up @@ -180,6 +186,19 @@ document.querySelector('jb-date-input').setCalendarDefaultDateView(year,month,'G
//set default year and month for jalali input-type
document.querySelector('jb-date-input').setCalendarDefaultDateView(year,month,'JALALI');
```
## get value
you can get the selected date by using following method:
```javascript
// return string value base on your provided format and value type
document.querySelector('jb-date-input').value

// return javascript Date value (or null)
document.querySelector('jb-date-input').valueInDate

```
note that providing & getting value with `Date` is faster and more perfomant than using value string


## show persian number
if you want to show persian number instead of English number char you just have to set `use-persian-number` attribute like this:
```javascript
Expand Down Expand Up @@ -262,6 +281,7 @@ body{
| --jb-date-input-input-margin | input margin default is `4px 0` |
| --jb-date-input-box-shadow | input box-shadow default is none |
| --jb-date-input-box-shadow-focus | input box-shadow when input is focused default is none |
| --jb-date-input-calendar-trigger-display | set it no none to hide calendar icon |


if you want to change opened date picker style please read [jb-calendar](https://github.com/javadbat/jb-calendar) readme file
Expand Down
116 changes: 67 additions & 49 deletions lib/DateFactory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

import { DateInObject, DateRestrictions, DateRestrictionsValidResult, DateValidResult, InputTypes, JBDateInputValueObject, ValueTypes } from './Types';
import { getEmptyValueObject } from './Helpers';
import {getYear, getMonth, getTime as getTimeStamp, getUnixTime as getTimeStampInSecond, isEqual, isLeapYear, getDate} from 'date-fns';
import {newDate,isLeapYear as isJalaliLeapYear,isAfter,isBefore,getYear as getJalaliYear, getMonth as getJalaliMonth, getDate as getJalaliDate} from 'date-fns-jalali';
import { getYear, getMonth, getTime as getTimeStamp, getUnixTime as getTimeStampInSecond, isEqual, isLeapYear, getDate } from 'date-fns';
import { newDate, isLeapYear as isJalaliLeapYear, isAfter, isBefore, getYear as getJalaliYear, getMonth as getJalaliMonth, getDate as getJalaliDate } from 'date-fns-jalali';


export type DateFactoryConstructorArg = {
Expand Down Expand Up @@ -34,8 +34,8 @@ export class DateFactory {
get nicheNumbers() {
return this.#nicheNumbers;
}
get yearOnEmptyBaseOnValueType(){
if(this.#valueType == ValueTypes.jalali){
get yearOnEmptyBaseOnValueType() {
if (this.#valueType == ValueTypes.jalali) {
return this.#nicheNumbers.calendarYearOnEmpty.jalali;
}
return this.#nicheNumbers.calendarYearOnEmpty.gregorian;
Expand Down Expand Up @@ -104,7 +104,17 @@ export class DateFactory {
}
return resultDate;
}
getDateValueFromValueObject(valueObject: JBDateInputValueObject, type = this.valueType): string {
getDateValueFromValueObject(valueObject: JBDateInputValueObject):Date | null{
if(valueObject.gregorian.year && valueObject.gregorian.month && valueObject.gregorian.day){
const date = new Date(valueObject.gregorian.year,valueObject.gregorian.month,valueObject.gregorian.day);
return date;
}
return null;
}
/**
* @description use when user want component value and convert valueObject to user formatted value string base on format and value type
*/
getDateValueStringFromValueObject(valueObject: JBDateInputValueObject, type = this.valueType): string {
//this function convert inputed date to expected format base on valueType
const emptyYearString = '0000';
const emptyMonthString = '00';
Expand Down Expand Up @@ -136,7 +146,7 @@ export class DateFactory {
case 'JALALI':
return getJalaliValue();
case 'TIME_STAMP':
if(valueObject.timeStamp){
if (valueObject.timeStamp) {
return valueObject.timeStamp.toString();
}
}
Expand Down Expand Up @@ -223,9 +233,9 @@ export class DateFactory {
}
if (result.isValid && jalaliMonth == 12) {
//if everything was ok then we check for leap year
if (jalaliMonth == 12 && jalaliDay == 30){
if (jalaliMonth == 12 && jalaliDay == 30) {
const date = DateFactory.getDateFromJalali(jalaliYear, jalaliMonth, jalaliDay);
if(!isJalaliLeapYear(date)){
if (!isJalaliLeapYear(date)) {
result.isValid = false;
result.error = "INVALID_DAY_FOR_LEAP";
}
Expand Down Expand Up @@ -304,47 +314,53 @@ export class DateFactory {
return result;

}
getDateValueObjectBaseOnInputType(year:number,month:number,day:number,oldYear:number|null, oldMonth:number|null): JBDateInputValueObject{
if(this.#inputType == InputTypes.gregorian){
return this.#getDateValueFromGregorian(year,month,day,oldYear,oldMonth);
getDateValueObjectBaseOnInputType(year: number, month: number, day: number, oldYear: number | null, oldMonth: number | null): JBDateInputValueObject {
if (this.#inputType == InputTypes.gregorian) {
return this.#getDateValueFromGregorian(year, month, day, oldYear, oldMonth);
}
if(this.#inputType == InputTypes.jalali){
return this.#getDateValueFromJalali(year,month,day,oldYear,oldMonth);
if (this.#inputType == InputTypes.jalali) {
return this.#getDateValueFromJalali(year, month, day, oldYear, oldMonth);
}
console.error("INVALID_INPUT_TYPE");
return getEmptyValueObject();
}
getDateValueObjectBaseOnValueType(year:number,month:number,day:number,oldYear:number|null, oldMonth:number|null): JBDateInputValueObject{
if(this.#valueType == ValueTypes.gregorian){
return this.#getDateValueFromGregorian(year,month,day,oldYear,oldMonth);
getDateValueObjectBaseOnValueType(year: number, month: number, day: number, oldYear: number | null, oldMonth: number | null): JBDateInputValueObject {
if (this.#valueType == ValueTypes.gregorian) {
return this.#getDateValueFromGregorian(year, month, day, oldYear, oldMonth);
}
if(this.#valueType == ValueTypes.jalali){
return this.#getDateValueFromJalali(year,month,day,oldYear,oldMonth);
if (this.#valueType == ValueTypes.jalali) {
return this.#getDateValueFromJalali(year, month, day, oldYear, oldMonth);
}
if(this.#valueType == ValueTypes.timestamp){
return this.#getDateValueFromGregorian(year,month,day,oldYear,oldMonth);
if (this.#valueType == ValueTypes.timestamp) {
return this.#getDateValueFromGregorian(year, month, day, oldYear, oldMonth);
}
console.error("INVALID_INPUT_TYPE");
return getEmptyValueObject();
}
getDateValueObjectFromTimeStamp(timestamp:number): JBDateInputValueObject{
getDateValueObjectFromTimeStamp(timestamp: number): JBDateInputValueObject {
const date = new Date(timestamp);
const result:JBDateInputValueObject = {
return this.getDateObjectValueFromDateValue(date);
}
/**
* @description this function return date object base on javascript Date type
*/
getDateObjectValueFromDateValue(inputValue: Date): JBDateInputValueObject {
const result: JBDateInputValueObject = {
gregorian: {
year: getYear(date),
month: getMonth(date) + 1,
day: getDate(date)
year: getYear(inputValue),
month: getMonth(inputValue) + 1,
day: getDate(inputValue)
},
jalali: {
year: getJalaliYear(date),
month: getJalaliMonth(date) + 1,
day: getJalaliDate(date)
year: getJalaliYear(inputValue),
month: getJalaliMonth(inputValue) + 1,
day: getJalaliDate(inputValue)
},
timeStamp : getTimeStamp(date),
timeStamp: getTimeStamp(inputValue),
};
return result;
}
#getDateValueFromGregorian(gregorianYear: number, gregorianMonth: number, gregorianDay: number,oldGregorianYear:number|null, oldGregorianMonth:number|null): JBDateInputValueObject {
#getDateValueFromGregorian(gregorianYear: number, gregorianMonth: number, gregorianDay: number, oldGregorianYear: number | null, oldGregorianMonth: number | null): JBDateInputValueObject {

const valueObject: JBDateInputValueObject = getEmptyValueObject();
const dateValidationResult = DateFactory.checkGregorianDateValidation(gregorianYear, gregorianMonth, gregorianDay);
Expand Down Expand Up @@ -396,7 +412,7 @@ export class DateFactory {
valueObject.timeStamp = getTimeStamp(date);
return valueObject;
}
#getDateValueFromJalali(jalaliYear: number, jalaliMonth: number, jalaliDay: number, oldJalaliYear:number|null, oldJalaliMonth:number|null): JBDateInputValueObject {
#getDateValueFromJalali(jalaliYear: number, jalaliMonth: number, jalaliDay: number, oldJalaliYear: number | null, oldJalaliMonth: number | null): JBDateInputValueObject {
const valueObject = getEmptyValueObject();
const dateValidationResult = DateFactory.checkJalaliDateValidation(jalaliYear, jalaliMonth, jalaliDay);
if (!dateValidationResult.isValid) {
Expand Down Expand Up @@ -436,31 +452,33 @@ export class DateFactory {
const date = DateFactory.getDateFromJalali(jalaliYear, jalaliMonth, jalaliDay);
valueObject.gregorian = {
year: getYear(date),
month: getMonth(date)+1,
month: getMonth(date) + 1,
day: getDate(date)
};
valueObject.jalali = {
year: getJalaliYear(date),
month: getJalaliMonth(date)+1,
month: getJalaliMonth(date) + 1,
day: getJalaliDate(date)
};
valueObject.timeStamp = getTimeStamp(date);
return valueObject;
}
getDateObjectValueBaseOnFormat(valueString:string,format:string = this.#valueFormat):DateInObject{
getDateObjectValueBaseOnFormat(valueString: string, format: string = this.#valueFormat): DateInObject {
const res = DateFactory.#executeFormatAndExtractValue(valueString, format);
const dateInObject:DateInObject = {
year:null,
month:null,
day:null,
const dateInObject: DateInObject = {
year: null,
month: null,
day: null,
};
if(res && res.groups){
dateInObject.year = parseInt(res.groups.year) ;
dateInObject.month = parseInt(res.groups.month) ;
dateInObject.day = parseInt(res.groups.day) ;
if (res && res.groups) {
dateInObject.year = parseInt(res.groups.year);
dateInObject.month = parseInt(res.groups.month);
dateInObject.day = parseInt(res.groups.day);
}
return dateInObject;
}


static #executeFormatAndExtractValue(value: string, format: string) {
const regexString = format.replace('YYYY', '(?<year>[\\d]{4})').replace('MM', '(?<month>[\\d]{2})').replace('DD', '(?<day>[\\d]{2})')
.replace('HH', '(?<hour>[\\d]{2})').replace('mm', '(?<minute>[\\d]{2})').replace('ss', '(?<second>[\\d]{2})').replace('SSS', '(?<miliSecond>[\\d]{3})')
Expand All @@ -469,11 +487,11 @@ export class DateFactory {
const res = regex.exec(value);
return res;
}
static getDate(year: number, month: number, day: number, inputType:InputTypes):Date{
if(inputType == InputTypes.jalali){
return DateFactory.getDateFromJalali(year,month,day);
static getDate(year: number, month: number, day: number, inputType: InputTypes): Date {
if (inputType == InputTypes.jalali) {
return DateFactory.getDateFromJalali(year, month, day);
}
return DateFactory.getDateFromGregorian(year,month,day);
return DateFactory.getDateFromGregorian(year, month, day);
}
static getDateFromGregorian(year: number, month: number, day: number): Date {
return new Date(year, month - 1, day);
Expand All @@ -500,8 +518,8 @@ export class DateFactory {
};
const date = DateFactory.getDate(year, month, day, dateInputType);
if (dateRestrictions.min) {
const minValid = isAfter(date,dateRestrictions.min) || isEqual(date, dateRestrictions.min);

const minValid = isAfter(date, dateRestrictions.min) || isEqual(date, dateRestrictions.min);
if (!minValid) {
result.min = {
isValid: false,
Expand All @@ -510,7 +528,7 @@ export class DateFactory {
}
}
if (dateRestrictions.max) {
const maxValid = isBefore(date,dateRestrictions.max) || isEqual(date, dateRestrictions.max);
const maxValid = isBefore(date, dateRestrictions.max) || isEqual(date, dateRestrictions.max);
if (!maxValid) {
result.max = {
isValid: false,
Expand Down
2 changes: 1 addition & 1 deletion lib/JBDateInput.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
}

.calendar-trigger {
display: block;
display: var(--jb-date-input-calendar-trigger-display, block);
width: var(--jb-date-input-calendar-trigger-width, 28px);
height: var(--jb-date-input-calendar-trigger-height, 28px);
margin: 4px 0;
Expand Down
63 changes: 40 additions & 23 deletions lib/JBDateInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,22 @@ export class JBDateInputWebComponent extends HTMLElement {
const value = this.getDateValue();
return value;
}
set value(value: string) {

this.setDateValue(value);
set value(value: string | Date) {
this.#setDateValue(value);
this.updateinputTextFromValue();
this.#updateFormAssossicatedValue();
}
#updateFormAssossicatedValue():void{
//in html form we need to get date input value in native way this function update and set value of the input so form can get it when needed
if (this.internals_ && typeof this.internals_.setFormValue == "function") {
this.internals_.setFormValue(this.value);
}
}
/**
* @description return date value if value valid and return null if inputed value is not valid
*/
get valueInDate():Date|null{
return this.#dateFactory.getDateValueFromValueObject(this.#valueObject);
}
get inputValue() {
return this.#inputValue;
}
Expand Down Expand Up @@ -602,22 +606,26 @@ export class JBDateInputWebComponent extends HTMLElement {
* @return {String} value base on format and date type
*/
getDateValue(type: ValueTypes = this.valueType): string {
return this.#dateFactory.getDateValueFromValueObject(this.#valueObject, type);
return this.#dateFactory.getDateValueStringFromValueObject(this.#valueObject, type);
}

setDateValue(value: string) {
//when user change value this function called and update inner value object base on user value
switch (this.#dateFactory.valueType) {
case ValueTypes.gregorian:
case ValueTypes.jalali:
this.setDateValueFromString(value);
break;
case ValueTypes.timestamp:
this.setDateValueFromTimeStamp(value);
break;
/**
* when user change value this function called and update inner value object base on user value
*/
#setDateValue(value: string | Date) {
if(typeof value == "string"){
switch (this.#dateFactory.valueType) {
case ValueTypes.gregorian:
case ValueTypes.jalali:
this.#setDateValueFromString(value);
break;
case ValueTypes.timestamp:
this.#setDateValueFromTimeStamp(value);
break;
}
}else if(value instanceof Date){
this.#setDateValueFromDate(value);
}
this.#updateFormAssossicatedValue();

}
setValueObjNull() {
// mean we reset calendar value and set it to null
Expand All @@ -639,17 +647,26 @@ export class JBDateInputWebComponent extends HTMLElement {
this.elements.calendar.data.selectedMonth = value.month;
}
}

setDateValueFromTimeStamp(value: string) {
/**
* @description set date value from javascript Date
*/
#setDateValueFromDate(value:Date){
const valueObject = this.#dateFactory.getDateObjectValueFromDateValue(value);
this.#valueObject = valueObject;
this.updateCalendarView();
}
/**
* @description set date value from timestamp base on valueType
*/
#setDateValueFromTimeStamp(value: string) {
const timeStamp = parseInt(value);
this.#valueObject = this.#dateFactory.getDateValueObjectFromTimeStamp(timeStamp);
this.updateCalendarView();
}
/**
* set date value from string base on valueType
* @param {string} value
* @description set date value from string base on valueType
*/
setDateValueFromString(value: string) {
#setDateValueFromString(value: string) {
const dateInObject = this.#dateFactory.getDateObjectValueBaseOnFormat(value);

if (dateInObject.year && dateInObject.month && dateInObject.day) {
Expand Down Expand Up @@ -918,7 +935,7 @@ export class JBDateInputWebComponent extends HTMLElement {

if (typeof validation.validator == "function") {
const valueObject = this.getValueObjectFromInputText(text);
const valueText = this.#dateFactory.getDateValueFromValueObject(valueObject);
const valueText = this.#dateFactory.getDateValueStringFromValueObject(valueObject);
// we cant use this.#valueObj becuase in some scenario its not updated
testRes = validation.validator(text, valueObject, valueText);
}
Expand Down
Loading

0 comments on commit 5a44877

Please sign in to comment.