UNPKG

@eclipse-scout/core

Version:
231 lines (195 loc) 7.84 kB
/* * Copyright (c) 2010, 2025 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ import {aria, LookupRow, objects, ProposalFieldEventMap, ProposalFieldModel, SmartField, SmartFieldLookupResult, strings} from '../../../index'; import $ from 'jquery'; export class ProposalField extends SmartField<string> implements ProposalFieldModel { declare model: ProposalFieldModel; declare eventMap: ProposalFieldEventMap; declare self: ProposalField; trimText: boolean; lookupOnAcceptByText: boolean; constructor() { super(); this.maxLength = 4000; this.trimText = true; this.lookupOnAcceptByText = false; this._addCloneProperties(['lookupOnAcceptByText']); } protected override _getValueFromLookupRow(lookupRow: LookupRow<string>): string { return lookupRow.text; } protected override _getLastSearchText(): string { return this.value; } override cssClassName(): string { return 'proposal-field'; } protected override _addAriaFieldDescription() { aria.addHiddenDescriptionAndLinkToElement(this.$field, this.id + '-func-desc', this.session.text('ui.AriaProposalFieldDescription')); } protected override _handleEnterKey(event: JQuery.KeyDownEvent) { // The state of 'this.popup' is different on various browsers. On some browsers (IE11) we don't // do CSS animations. This means IE11 sets the popup to null immediately whereas other browsers // use a timeout. Anyway: in case the popup is open at the time the user presses enter, we must // stop propagation (e.g. to avoid calls of other registered enter key-shortcuts, like the default // button on a form). See Widget.js for details about removing with or without CSS animations. let hasPopup = !!this.popup; let promise = this.acceptInput(); if (promise) { promise.always(this.closePopup.bind(this)); } else { this.closePopup(); } if (hasPopup) { event.stopPropagation(); } } protected override _lookupByTextOrAllDone(result: SmartFieldLookupResult<string>) { if (super._handleException(result)) { return; } if (result.lookupRows.length === 0) { this.setLoading(false); this._handleEmptyResult(); return; } super._lookupByTextOrAllDone(result); } protected override _formatValue(value: string): string { if (objects.isNullOrUndefined(value)) { return ''; } if (this.lookupRow) { return this._formatLookupRow(this.lookupRow); } return value; } protected override _validateValue(value: string): string { if (objects.isNullOrUndefined(value)) { return value; } let validValue = strings.asString(value); if (this.trimText) { validValue = validValue.trim(); } if (validValue === '') { validValue = null; } return validValue; } protected override _ensureValue(value: string): string { return strings.asString(value); } /** * When 'clear' has been clicked (searchText is empty), we want to call customTextAccepted, * so the new value is sent to the server #221199. */ protected override _acceptByText(sync: boolean, searchText: string) { $.log.isDebugEnabled() && $.log.debug('(ProposalField#_acceptByText) searchText=', searchText); let async = !sync; // In case sync=true we cannot wait for the results of the lookup-call, // that's why we simply accept the text that's already in the field if (async && this.lookupOnAcceptByText && strings.hasText(searchText)) { super._acceptByTextAsync(searchText); } else { this._customTextAccepted(searchText); } } /** * Only used in case lookupOnAcceptByText is true. It's basically the same code * as in the smart-field but without the error handling. */ protected override _acceptByTextDone(result: SmartFieldLookupResult<string>) { this._userWasTyping = false; this._extendResult(result); if (this.isPopupOpen()) { this.popup.setLookupResult(result); } // when there's exactly one result, we accept that lookup row if (result.uniqueMatch) { let lookupRow = result.uniqueMatch; if (this._isLookupRowActive(lookupRow)) { this.setLookupRow(lookupRow); this._inputAccepted(); return; } } this._customTextAccepted(result.text); } protected override _checkResetLookupRow(value: string): boolean { return this.lookupRow && this.lookupRow.text !== value; } protected override _checkSearchTextChanged(searchText: string): boolean { return this._checkDisplayTextChanged(searchText); } protected _customTextAccepted(searchText: string) { this._setLookupRow(null); // only reset property lookup this._setValue(searchText); this._inputAccepted(true, false); } override getValueForSelection(): string { return this._showSelection() ? this.lookupRow.key : null; } /** * In ProposalField value and display-text is the same. When a custom text has been entered, * the value is set and the lookup-row is null. */ protected override _copyValuesFromField(otherField: ProposalField) { this.lookupSeqNo = otherField.lookupSeqNo; if (this.lookupRow !== otherField.lookupRow) { this._setLookupRow(otherField.lookupRow); // only set property lookup } this.setErrorStatus(otherField.errorStatus); this.setDisplayText(otherField.displayText); this.setValue(otherField.value); } protected override _acceptInput(sync: boolean, searchText: string, searchTextEmpty: boolean, searchTextChanged: boolean, selectedLookupRow: LookupRow<string>): JQuery.Promise<void> | void { if (this.touchMode) { $.log.isDebugEnabled() && $.log.debug('(ProposalField#_acceptInput) Always send acceptInput for touch field'); // When the lookup is accepted by text (e.g. when lookupOnAcceptByText = true), the SmartField#acceptInput cannot // detect the selectedLookupRow, because it just takes the selected row of the Proposal chooser this._inputAccepted(true, !!this.lookupRow); return; } // 1. Do nothing when search text did not change and is equals to the text of the current lookup row if (!searchTextChanged && !selectedLookupRow && this.lookupRow && this.lookupRow.text === searchText) { $.log.isDebugEnabled() && $.log.debug('(ProposalField#_acceptInput) unchanged: text is equals. Close popup'); this._inputAccepted(false); return; } // 2. proposal chooser is open -> use the selected row as value if (selectedLookupRow) { $.log.isDebugEnabled() && $.log.debug('(ProposalField#_acceptInput) lookup-row selected. Set lookup-row, close popup lookupRow=', selectedLookupRow.toString()); this.clearErrorStatus(); this.setLookupRow(selectedLookupRow); this._inputAccepted(); return; } // 3. proposal chooser is not open -> try to accept the current display text // this causes a lookup which may fail and open a new proposal chooser (property // change for 'result'). if (searchTextChanged) { this.clearErrorStatus(); this._acceptByText(sync, searchText); } else if (!this._hasUiError()) { this._inputAccepted(false); } else { // even though there's nothing to do, someone could wait for our promise to be resolved this._acceptInputDeferred.resolve(); } return this._acceptInputDeferred.promise(); } setTrimText(trimText: boolean) { this.setProperty('trimText', trimText); } protected override _computeEmpty() { return strings.empty(this.value); } }