wekan/client/lib/inlinedform.js
copilot-swe-agent[bot] 97dd5d2064 Resolve merge conflicts by accepting PR #6131 changes
Co-authored-by: xet7 <15545+xet7@users.noreply.github.com>
2026-02-07 16:30:08 +00:00

144 lines
3.9 KiB
JavaScript

// A inlined form is used to provide a quick edition of single field for a given
// document. Clicking on a edit button should display the form to edit the field
// value. The form can then be submited, or just closed.
//
// When the form is closed we save non-submitted values in memory to avoid any
// data loss.
//
// Usage:
//
// +inlineForm
// // the content when the form is open
// else
// // the content when the form is close (optional)
// We can only have one inlined form element opened at a time
const currentlyOpenedForm = new ReactiveVar(null);
InlinedForm = BlazeComponent.extendComponent({
template() {
return 'inlinedForm';
},
onCreated() {
this.isOpen = new ReactiveVar(false);
},
onRendered() {
// Autofocus when form becomes open
this.autorun(() => {
if (this.isOpen.get()) {
Tracker.afterFlush(() => {
const input = this.find('textarea,input[type=text]');
if (input && typeof input.focus === 'function') {
setTimeout(() => {
input.focus();
// Select content if it exists (useful for editing)
if (input.value && input.select) {
input.select();
}
}, 50);
}
});
}
});
},
onDestroyed() {
currentlyOpenedForm.set(null);
},
open(evt) {
if (evt) {
evt.preventDefault();
// Close currently opened form, if any
EscapeActions.clickExecute(evt.target, 'inlinedForm');
} else {
// Close currently opened form, if any
EscapeActions.executeUpTo('inlinedForm');
}
this.isOpen.set(true);
currentlyOpenedForm.set(this);
},
close() {
this.isOpen.set(false);
currentlyOpenedForm.set(null);
},
getValue() {
const input = this.find('textarea,input[type=text]');
// \s without \n + unicode (https://developer.mozilla.org/de/docs/Web/JavaScript/Guide/Regular_Expressions#special-white-space)
return this.isOpen.get() && input && input.value.replaceAll(/[ \f\r\t\v]+$/gm, '');
},
events() {
return [
{
'click .js-close-inlined-form': this.close,
'pointerdown .js-open-inlined-form'(e) {
if (Utils.shouldIgnorePointer(e)) {
return;
}
// to measure the click duration
$(e.target).data("clickStart", new Date());
},
'pointerup .js-open-inlined-form'(e) {
if(Utils.shouldIgnorePointer(e)) {
return;
}
const start = $(e.target).data("clickStart",);
if (!start) {
return;
}
const end = new Date();
// 500ms feels reasonable for a simple click
if (end - start < 500) {
this.open(e);
}
$(e.target).data("clickStart", null);
},
// Pressing Ctrl+Enter should submit the form
'keydown form textarea'(evt) {
if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) {
this.find('button[type=submit]').click();
}
},
// Close the inlined form when after its submission
submit() {
if (this.currentData().autoclose !== false) {
Tracker.afterFlush(() => {
this.close();
});
}
},
},
];
},
}).register('inlinedForm');
// Press escape to close the currently opened inlinedForm
EscapeActions.register(
'inlinedForm',
() => {
currentlyOpenedForm.get().close();
},
() => {
return currentlyOpenedForm.get() !== null;
},
{
enabledOnClick: false,
},
);
// submit on click outside
//document.addEventListener('click', function(evt) {
// const openedForm = currentlyOpenedForm.get();
// const isClickOutside = $(evt.target).closest('.js-inlined-form').length === 0;
// if (openedForm && isClickOutside) {
// $('.js-inlined-form button[type=submit]').click();
// openedForm.close();
// }
//}, true);