mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
refactor(picker): making multi-column select type ahead more flexible with how it picks numbers
This commit is contained in:
@@ -410,8 +410,13 @@ export class Picker implements ComponentInterface {
|
||||
colEl: HTMLIonPickerColumnElement,
|
||||
value: string,
|
||||
zeroBehavior: 'start' | 'end' = 'start'
|
||||
) => {
|
||||
): boolean => {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const behavior = zeroBehavior === 'start' ? /^0+/ : /0$/;
|
||||
value = value.replace(behavior, '');
|
||||
const option = Array.from(colEl.querySelectorAll('ion-picker-column-option')).find((el) => {
|
||||
return el.disabled !== true && el.textContent!.replace(behavior, '') === value;
|
||||
});
|
||||
@@ -419,8 +424,45 @@ export class Picker implements ComponentInterface {
|
||||
if (option) {
|
||||
colEl.setValue(option.value);
|
||||
}
|
||||
|
||||
return !!option;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to intelligently search the first and second
|
||||
* column as if they're number columns for the provided numbers
|
||||
* where the first two numbers inpu are the first column
|
||||
* and the last 2 are the last column. Tries to allow for the first
|
||||
* number to be ignored for situations where typos occurred.
|
||||
*/
|
||||
private multiColumnSearch = (firstColumn: HTMLIonPickerColumnElement, secondColumn: HTMLIonPickerColumnElement, input: string) => {
|
||||
if (input.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const inputArray = input.split('');
|
||||
const hourValue = inputArray.slice(0, 2).join('');
|
||||
const foundHour = this.searchColumn(firstColumn, hourValue);
|
||||
|
||||
if (inputArray.length > 2 && foundHour) {
|
||||
const minuteValue = inputArray.slice(2, 4).join('');
|
||||
this.searchColumn(secondColumn, minuteValue);
|
||||
} else if (!foundHour && inputArray.length >= 1) {
|
||||
let singleDigitHour = inputArray[0];
|
||||
let singleDigitFound = this.searchColumn(firstColumn, singleDigitHour);
|
||||
if (!singleDigitFound) {
|
||||
inputArray.shift();
|
||||
singleDigitHour = inputArray[0];
|
||||
singleDigitFound = this.searchColumn(firstColumn, singleDigitHour);
|
||||
}
|
||||
|
||||
if (singleDigitFound && inputArray.length > 1) {
|
||||
const remainingDigits = inputArray.slice(1, 3).join('');
|
||||
this.searchColumn(secondColumn, remainingDigits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private selectMultiColumn = () => {
|
||||
const { inputEl, el } = this;
|
||||
if (!inputEl) {
|
||||
@@ -432,108 +474,16 @@ export class Picker implements ComponentInterface {
|
||||
const firstColumn = numericPickers[0];
|
||||
const lastColumn = numericPickers[1];
|
||||
|
||||
// Get the maximum value from the first column's options
|
||||
const columnOptions = Array.from(firstColumn.querySelectorAll('ion-picker-column-option'));
|
||||
const maxFirstColumnValue = Math.max(
|
||||
...columnOptions
|
||||
.map((option) => parseInt(option.textContent?.trim() || '0', 10)) // Extract and parse text content
|
||||
.filter((num) => !isNaN(num)) // Ensure valid numbers only
|
||||
);
|
||||
|
||||
// check for 24-hour format
|
||||
const allowTwo = maxFirstColumnValue >= 20;
|
||||
|
||||
let value = inputEl.value;
|
||||
let minuteValue;
|
||||
switch (value.length) {
|
||||
case 1:
|
||||
this.searchColumn(firstColumn, value);
|
||||
break;
|
||||
/**
|
||||
* If the first character is `0` or `1` or allowed '2' it is
|
||||
* possible that users are trying to type `09`
|
||||
* or `11` into the hour field, so we should look
|
||||
* at that first.
|
||||
*/
|
||||
case 2:
|
||||
const firstCharacter = inputEl.value.substring(0, 1);
|
||||
value =
|
||||
firstCharacter === '0' || firstCharacter === '1' || (allowTwo && firstCharacter === '2')
|
||||
? inputEl.value
|
||||
: firstCharacter;
|
||||
if (value.length > 4) {
|
||||
const startIndex = inputEl.value.length - 4;
|
||||
const newString = inputEl.value.substring(startIndex);
|
||||
|
||||
this.searchColumn(firstColumn, value);
|
||||
|
||||
/**
|
||||
* If only checked the first value,
|
||||
* we can check the second value
|
||||
* for a match in the minutes column
|
||||
*/
|
||||
if (value.length === 1) {
|
||||
minuteValue = inputEl.value.substring(inputEl.value.length - 1);
|
||||
this.searchColumn(lastColumn, minuteValue, 'end');
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
/**
|
||||
* If the first character is `0` or `1` or allowed '2' it is
|
||||
* possible that users are trying to type `09`
|
||||
* or `11` into the hour field, so we should look
|
||||
* at that first.
|
||||
*/
|
||||
const firstCharacterAgain = inputEl.value.substring(0, 1);
|
||||
value =
|
||||
firstCharacterAgain === '0' || firstCharacterAgain === '1' || (allowTwo && firstCharacterAgain === '2')
|
||||
? inputEl.value.substring(0, 2)
|
||||
: firstCharacterAgain;
|
||||
|
||||
this.searchColumn(firstColumn, value);
|
||||
|
||||
/**
|
||||
* If only checked the first value,
|
||||
* we can check the second value
|
||||
* for a match in the minutes column
|
||||
*/
|
||||
minuteValue = value.length === 1 ? inputEl.value.substring(1) : inputEl.value.substring(2);
|
||||
|
||||
this.searchColumn(lastColumn, minuteValue, 'end');
|
||||
break;
|
||||
case 4:
|
||||
/**
|
||||
* If the first character is `0` or `1` or allowed '2' it is
|
||||
* possible that users are trying to type `09`
|
||||
* or `11` into the hour field, so we should look
|
||||
* at that first.
|
||||
*/
|
||||
const firstCharacterAgainAgain = inputEl.value.substring(0, 1);
|
||||
value =
|
||||
firstCharacterAgainAgain === '0' ||
|
||||
firstCharacterAgainAgain === '1' ||
|
||||
(allowTwo && firstCharacterAgainAgain === '2')
|
||||
? inputEl.value.substring(0, 2)
|
||||
: firstCharacterAgainAgain;
|
||||
this.searchColumn(firstColumn, value);
|
||||
|
||||
/**
|
||||
* If only checked the first value,
|
||||
* we can check the second value
|
||||
* for a match in the minutes column
|
||||
*/
|
||||
const minuteValueAgain =
|
||||
value.length === 1
|
||||
? inputEl.value.substring(1, inputEl.value.length)
|
||||
: inputEl.value.substring(2, inputEl.value.length);
|
||||
this.searchColumn(lastColumn, minuteValueAgain, 'end');
|
||||
|
||||
break;
|
||||
default:
|
||||
const startIndex = inputEl.value.length - 4;
|
||||
const newString = inputEl.value.substring(startIndex);
|
||||
|
||||
inputEl.value = newString;
|
||||
this.selectMultiColumn();
|
||||
break;
|
||||
inputEl.value = newString;
|
||||
value = newString;
|
||||
}
|
||||
|
||||
this.multiColumnSearch(firstColumn, lastColumn, value);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user