Et2Select: Handle paste of CSV into selects with allowFreeEntries

Special handling for Et2SelectEmail to handle email addresses that may have a name or comma
This commit is contained in:
nathan 2023-01-31 09:47:46 -07:00
parent 5cb375fabf
commit ab56ad1171
2 changed files with 69 additions and 0 deletions

View File

@ -242,6 +242,39 @@ export class Et2SelectEmail extends Et2Select
} }
super.set_value(val); super.set_value(val);
} }
/**
* Sometimes users paste multiple comma separated values at once. Split them then handle normally.
* Overridden here to handle email addresses that may have commas using the regex from the validator.
*
* @param {ClipboardEvent} event
* @protected
*/
protected _handlePaste(event : ClipboardEvent)
{
event.preventDefault();
let paste = event.clipboardData.getData('text');
if(!paste)
{
return;
}
const selection = window.getSelection();
if(selection.rangeCount)
{
selection.deleteFromDocument();
}
// Trim line start / end anchors off validation regex, make global
let regex = new RegExp(IsEmail.EMAIL_PREG.toString().substring(2, IsEmail.EMAIL_PREG.toString().length - 3), 'g');
let values = paste.match(regex);
values.forEach(v =>
{
this.createFreeEntry(v.trim());
});
this.dropdown.hide();
}
} }
// @ts-ignore TypeScript is not recognizing that this widget is a LitElement // @ts-ignore TypeScript is not recognizing that this widget is a LitElement

View File

@ -302,6 +302,7 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
this._handleSearchChange = this._handleSearchChange.bind(this); this._handleSearchChange = this._handleSearchChange.bind(this);
this._handleSearchKeyDown = this._handleSearchKeyDown.bind(this); this._handleSearchKeyDown = this._handleSearchKeyDown.bind(this);
this._handleEditKeyDown = this._handleEditKeyDown.bind(this); this._handleEditKeyDown = this._handleEditKeyDown.bind(this);
this._handlePaste = this._handlePaste.bind(this);
} }
connectedCallback() connectedCallback()
@ -594,6 +595,11 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
// Need our own change to catch the change event from search input // Need our own change to catch the change event from search input
this.addEventListener("change", this._handleChange); this.addEventListener("change", this._handleChange);
if(this.allowFreeEntries)
{
this.addEventListener("paste", this._handlePaste);
}
this.updateComplete.then(() => this.updateComplete.then(() =>
{ {
// Search messes up event order. Since it throws its own bubbling change event, // Search messes up event order. Since it throws its own bubbling change event,
@ -614,6 +620,7 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
this.removeEventListener("sl-after-show", this._handleAfterShow); this.removeEventListener("sl-after-show", this._handleAfterShow);
this.removeEventListener("sl-clear", this._handleClear) this.removeEventListener("sl-clear", this._handleClear)
this.removeEventListener("change", this._handleChange); this.removeEventListener("change", this._handleChange);
this.removeEventListener("paste", this._handlePaste);
this._searchInputNode?.removeEventListener("change", this._handleSearchChange); this._searchInputNode?.removeEventListener("change", this._handleSearchChange);
} }
@ -925,6 +932,35 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
} }
} }
/**
* Sometimes users paste multiple comma separated values at once. Split them then handle normally.
*
* @param {ClipboardEvent} event
* @protected
*/
protected _handlePaste(event : ClipboardEvent)
{
event.preventDefault();
let paste = event.clipboardData.getData('text');
if(!paste)
{
return;
}
const selection = window.getSelection();
if(selection.rangeCount)
{
selection.deleteFromDocument();
}
let values = paste.split(/,\t/);
values.forEach(v =>
{
this.createFreeEntry(v.trim());
});
this.dropdown.hide();
}
/** /**
* Start searching * Start searching
* *