Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form: refix close popup on label click (T1258881) #28617

Merged
merged 1 commit into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import $ from '@js/core/renderer';
import { extend } from '@js/core/utils/extend';
import { captionize } from '@js/core/utils/inflector';
import { each } from '@js/core/utils/iterator';
import { isBoolean, isDefined, isFunction } from '@js/core/utils/type';
import { isDefined, isFunction } from '@js/core/utils/type';
import type { dxDropDownEditorOptions } from '@js/ui/drop_down_editor/ui.drop_down_editor';
import type { FormItemComponent } from '@js/ui/form';
import type { dxOverlayOptions } from '@js/ui/overlay';
import type { Properties as PopupProperties } from '@js/ui/popup';
import type dxTextBox from '@js/ui/text_box';

import { SIMPLE_ITEM_TYPE } from './constants';
Expand Down Expand Up @@ -167,12 +167,10 @@ export function convertToLabelMarkOptions(
};
}

// eslint-disable-next-line @typescript-eslint/naming-convention
function _getDropDownEditorOptions(
function getDropDownEditorOptions(
$parent,
editorType: FormItemComponent,
editorInputId: string,
onContentReadyExternal?: DropDownOptions['onContentReady'],
): DropDownOptions {
const isDropDownEditor = DROP_DOWN_EDITORS.includes(editorType);

Expand All @@ -181,33 +179,28 @@ function _getDropDownEditorOptions(
}

return {
onContentReady: (e) => {
const { component } = e;
// @ts-expect-error // unpublished option
onPopupInitialized: ({ component, popup }): void => {
const openOnFieldClick = component.option('openOnFieldClick') as DropDownOptions['openOnFieldClick'];
const initialHideOnOutsideClick = component.option('dropDownOptions.hideOnOutsideClick') as dxOverlayOptions<dxTextBox>['hideOnOutsideClick'];

if (openOnFieldClick) {
component.option('dropDownOptions', {
hideOnOutsideClick: (e) => {
if (isBoolean(initialHideOnOutsideClick)) {
return initialHideOnOutsideClick;
}
const initialHideOnOutsideClick = popup.option('hideOnOutsideClick') as PopupProperties['hideOnOutsideClick'];

const $target = $(e.target);
const $label = $parent.find(`label[for="${editorInputId}"]`);
const isLabelClicked = !!$target.closest($label).length;
// Do not overwrite boolean hideOnOutsideClick
if (openOnFieldClick && isFunction(initialHideOnOutsideClick)) {
const hideOnOutsideClick: PopupProperties['hideOnOutsideClick'] = (e) => {
const $target = $(e.target);
const $label = $parent.find(`label[for="${editorInputId}"]`);
const isLabelClicked = !!$target.closest($label).length;

if (!isFunction(initialHideOnOutsideClick)) {
return !isLabelClicked;
}
return !isLabelClicked && initialHideOnOutsideClick(e);
};

return !isLabelClicked && initialHideOnOutsideClick(e);
},
component.option('dropDownOptions', {
hideOnOutsideClick,
});
}

if (isFunction(onContentReadyExternal)) {
onContentReadyExternal(e);
popup.option({
hideOnOutsideClick,
});
}
},
};
Expand Down Expand Up @@ -245,7 +238,7 @@ function _convertToEditorOptions({
const stylingMode = externalEditorOptions?.stylingMode || editorStylingMode;
const useSpecificLabelOptions = EDITORS_WITH_SPECIFIC_LABELS.includes(editorType);

const dropDownEditorOptions = _getDropDownEditorOptions($parent, editorType, editorInputId, externalEditorOptions?.onContentReady);
const dropDownEditorOptions = getDropDownEditorOptions($parent, editorType, editorInputId);

const result = extend(
true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4580,15 +4580,100 @@ QUnit.test('form should be dirty when some editors are dirty', function(assert)
// NOTE: In the real environment, clicking the label triggers a click on the editor,
// toggling the popup visibility if openOnFieldClick=true.
// This assertion only takes hideOnOutsideClick into account
if(hideOnOutsideClick === false) {
assert.true(editorInstance.option('opened'), `drop down list ${openOnFieldClick ? 'is hidden by triggered input click' : 'is visible'}`);
} else {
assert.strictEqual(editorInstance.option('opened'), openOnFieldClick, `drop down list is hidden by ${openOnFieldClick ? 'triggered input click' : 'outside click'}`);
switch(hideOnOutsideClick) {
case true:
assert.false(editorInstance.option('opened'), 'drop down list is hidden by outside click');
break;
case false:
assert.true(editorInstance.option('opened'), `drop down list ${openOnFieldClick ? 'is hidden by triggered input click' : 'is visible'}`);
break;
default:
assert.strictEqual(editorInstance.option('opened'), openOnFieldClick, `drop down list is hidden by ${openOnFieldClick ? 'triggered input click' : 'outside click'}`);
}
});
});
});

QUnit.test('DropDownEditor popup must toggle on input or dropDownButton click if openOnFieldClick = true', function(assert) {
const $form = $('#form').dxForm({
formData: { CustomerID: 'VINET' },
items: [{
itemType: 'group',
colCount: 2,
items: [{
dataField: 'CustomerID',
editorType: 'dxSelectBox',
editorOptions: {
items: ['VINET', 'VALUE', 'VINS'],
value: '',
openOnFieldClick: true,
},
}],
}],
});

const $dropDownEditorInput = $form.find(`.${EDITOR_INPUT_CLASS}`);
const $dropDownButton = $form.find(`.${DROP_DOWN_EDITOR_BUTTON_CLASS}`);

pointerMock($dropDownEditorInput).click();

const editorInstance = $form.dxForm('instance').getEditor('CustomerID');

assert.true(editorInstance.option('opened'), 'drop down list is visible');

pointerMock($dropDownEditorInput).click();

assert.false(editorInstance.option('opened'), 'drop down list is hidden');

pointerMock($dropDownButton).click();

assert.true(editorInstance.option('opened'), 'drop down list is visible');

pointerMock($dropDownButton).click();

assert.false(editorInstance.option('opened'), 'drop down list is hidden');
});

QUnit.test('DropDownEditor popup must toggle on dropDownButton click if openOnFieldClick = false', function(assert) {
const $form = $('#form').dxForm({
formData: { CustomerID: 'VINET' },
items: [{
itemType: 'group',
colCount: 2,
items: [{
dataField: 'CustomerID',
editorType: 'dxSelectBox',
editorOptions: {
items: ['VINET', 'VALUE', 'VINS'],
value: '',
openOnFieldClick: false,
},
}],
}],
});

const $dropDownEditorInput = $form.find(`.${EDITOR_INPUT_CLASS}`);
const $dropDownButton = $form.find(`.${DROP_DOWN_EDITOR_BUTTON_CLASS}`);

pointerMock($dropDownEditorInput).click();

const editorInstance = $form.dxForm('instance').getEditor('CustomerID');

assert.false(editorInstance.option('opened'), 'drop down list is hidden');

pointerMock($dropDownButton).click();

assert.true(editorInstance.option('opened'), 'drop down list is visible');

pointerMock($dropDownEditorInput).click();

assert.true(editorInstance.option('opened'), 'drop down list is visible');

pointerMock($dropDownButton).click();

assert.false(editorInstance.option('opened'), 'drop down list is hidden');
});

QUnit.module('reset', () => {
[
['dxCalendar', new Date(2019, 1, 2), { dxCalendar: new Date(2019, 1, 3) } ],
Expand Down
Loading