Skip to content

Commit

Permalink
feat(admin): Add validation message to TinyMCE on save
Browse files Browse the repository at this point in the history
Add support for TinyMCE's Notifications Manager to provide validity feedback: we add an error notification when the form dispatches an `invalid` event.

Since TinyMCE does not properly support editors inside dialogs, notifications are positionned absolutely, outside of the modal, from the bottom of the DOM. This risks positioning them outside of the viewport. To work around this issue, a debounced `scroll` event is used to reposition any notifications.
  • Loading branch information
mcaskill committed Mar 12, 2024
1 parent 725acd0 commit 46af62b
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 4 deletions.
94 changes: 91 additions & 3 deletions packages/admin/assets/dist/scripts/charcoal.admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,48 @@ Charcoal.Admin = (function () {
return jqxhr;
};

/**
* Creates a debounced function.
*
* A debounced function delays invoking `callback` until after
* `delay` milliseconds have elapsed since the last time the
* debounced function was invoked.
*
* Useful for behaviour that should only happen _before_ or
* _after_ an event has stopped occurring.
*
* @template {function} T
*
* @param {T} callback - The function to debounce.
* @param {number} delay - The number of milliseconds to wait.
* @param {boolean} [immediate] -
* If `true`, `callback` is invoked before `delay`.
* If `false`, `callback` is invoked after `delay`.
* @return {function<T>} The new debounced function.
*/
Admin.debounce = function (callback, delay, immediate = false) {
var timeout = null

return function () {
var args = arguments;

clearTimeout(timeout);

const later = function () {
timeout = null;
if (!immediate) {
callback.apply(null, args);
}
}

if (immediate && !timeout) {
callback.apply(null, args);
}

timeout = setTimeout(later, delay);
}
};

return Admin;

}());
Expand Down Expand Up @@ -12696,9 +12738,7 @@ Charcoal.Admin.Property_Input_Selectize_Tags.prototype.init_clipboard = function
return [];
}

const data = JSON.parse(json);
console.log(data);
return data;
return JSON.parse(json);
} catch (err) {
console.warn('[Charcoal.Property.Tabulator]', 'Could not retrieve input value:', err);

Expand Down Expand Up @@ -13455,6 +13495,7 @@ Charcoal.Admin.Property_Input_Text.prototype.set_split_on = function (splitOn) {
Charcoal.Admin.Property_Input_Text.prototype.destroy = function () {
}

/* global formWidgetL10n */
/* eslint-disable consistent-this */
/**
* TinyMCE implementation for WYSIWYG inputs
Expand Down Expand Up @@ -13504,6 +13545,53 @@ Charcoal.Admin.Property_Input_Tinymce.prototype.parent = Charcoal.Admin.Property
*/
Charcoal.Admin.Property_Input_Tinymce.prototype.init = function () {
this.create_tinymce();
this.bind_events();
};

Charcoal.Admin.Property_Input_Tinymce.prototype.bind_events = function () {
var that = this;

var element = this.element();

element.on('invalid', function (event) {
var editor = that.editor();
var control = event.target;

if (editor && control) {
var validity = control.validity;
for (var key in validity) {
if (key === 'valid') {
continue;
}

if (!validity[key]) {
continue;
}

if (formWidgetL10n.validation[key]) {
editor.notificationManager.open({
text: formWidgetL10n.validation[key],
type: 'error'
});
return;
}
}
}
});

var container = element.closest('.modal-open .modal');
if (!container.length) {
container = $(document);
}

container.on('scroll', Charcoal.Admin.debounce(function () {
var editor = that.editor();
if (editor) {
editor.notificationManager.getNotifications().forEach(function (notification) {
notification.moveRel()
});
}
}, 50));
};

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/admin/assets/dist/scripts/charcoal.admin.min.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* global formWidgetL10n */
/* eslint-disable consistent-this */
/**
* TinyMCE implementation for WYSIWYG inputs
Expand Down Expand Up @@ -47,6 +48,53 @@ Charcoal.Admin.Property_Input_Tinymce.prototype.parent = Charcoal.Admin.Property
*/
Charcoal.Admin.Property_Input_Tinymce.prototype.init = function () {
this.create_tinymce();
this.bind_events();
};

Charcoal.Admin.Property_Input_Tinymce.prototype.bind_events = function () {
var that = this;

var element = this.element();

element.on('invalid', function (event) {
var editor = that.editor();
var control = event.target;

if (editor && control) {
var validity = control.validity;
for (var key in validity) {
if (key === 'valid') {
continue;
}

if (!validity[key]) {
continue;
}

if (formWidgetL10n.validation[key]) {
editor.notificationManager.open({
text: formWidgetL10n.validation[key],
type: 'error'
});
return;
}
}
}
});

var container = element.closest('.modal-open .modal');
if (!container.length) {
container = $(document);
}

container.on('scroll', Charcoal.Admin.debounce(function () {
var editor = that.editor();
if (editor) {
editor.notificationManager.getNotifications().forEach(function (notification) {
notification.moveRel()
});
}
}, 50));
};

/**
Expand Down

0 comments on commit 46af62b

Please sign in to comment.