wagtail/client/src/entrypoints/admin/page-editor.js

148 wiersze
4.2 KiB
JavaScript

import $ from 'jquery';
import { cleanForSlug } from '../../utils/text';
import { inlinePanel } from '../../includes/inlinePanel';
import { ngettext } from '../../utils/gettext';
window.InlinePanel = inlinePanel;
window.cleanForSlug = cleanForSlug;
function initSlugAutoPopulate() {
let slugFollowsTitle = false;
// eslint-disable-next-line func-names
$('#id_title').on('focus', function () {
/* slug should only follow the title field if its value matched the title's value at the time of focus */
const currentSlug = $('#id_slug').val();
const slugifiedTitle = cleanForSlug(this.value, true);
slugFollowsTitle = currentSlug === slugifiedTitle;
});
// eslint-disable-next-line func-names
$('#id_title').on('keyup keydown keypress blur', function () {
if (slugFollowsTitle) {
const slugifiedTitle = cleanForSlug(this.value, true);
$('#id_slug').val(slugifiedTitle);
}
});
}
window.initSlugAutoPopulate = initSlugAutoPopulate;
function initSlugCleaning() {
// eslint-disable-next-line func-names
$('#id_slug').on('blur', function () {
// if a user has just set the slug themselves, don't remove stop words etc, just illegal characters
$(this).val(cleanForSlug($(this).val(), false));
});
}
window.initSlugCleaning = initSlugCleaning;
function initErrorDetection() {
const errorSections = {};
// first count up all the errors
$('.error-message,.help-critical').each(function collectError() {
const parentSection = $(this).closest('section[role="tabpanel"]');
if (!errorSections[parentSection.attr('id')]) {
errorSections[parentSection.attr('id')] = 0;
}
errorSections[parentSection.attr('id')] =
errorSections[parentSection.attr('id')] + 1;
});
// now identify them on each tab
Object.entries(errorSections).forEach(([sectionId, errorCount]) => {
const tabErrorsElement = $(`[data-tabs] a[href="#${sectionId}"]`).find(
'[data-tabs-errors]',
);
// show and add error count
tabErrorsElement
.addClass('!w-flex')
.find('[data-tabs-errors-count]')
.text(errorCount);
// update label for screen readers
tabErrorsElement
.find('[data-tabs-errors-statement]')
.text(
ngettext(
'(%(errorCount)s error)',
'(%(errorCount)s errors)',
errorCount,
).replace('%(errorCount)s', errorCount),
);
});
}
window.initErrorDetection = initErrorDetection;
function initKeyboardShortcuts() {
// eslint-disable-next-line no-undef
Mousetrap.bind(['mod+p'], () => {
const previewToggle = document.querySelector(
'[data-side-panel-toggle="preview"]',
);
if (previewToggle) previewToggle.click();
return false;
});
// eslint-disable-next-line no-undef
Mousetrap.bind(['mod+s'], () => {
$('.action-save').trigger('click');
return false;
});
}
window.initKeyboardShortcuts = initKeyboardShortcuts;
$(() => {
/* Only non-live pages should auto-populate the slug from the title */
if (!$('body').hasClass('page-is-live')) {
initSlugAutoPopulate();
}
initSlugCleaning();
initErrorDetection();
initKeyboardShortcuts();
});
let updateFooterTextTimeout = -1;
window.updateFooterSaveWarning = (formDirty, commentsDirty) => {
const warningContainer = $('[data-unsaved-warning]');
const warnings = warningContainer.find('[data-unsaved-type]');
const anyDirty = formDirty || commentsDirty;
const typeVisibility = {
all: formDirty && commentsDirty,
any: anyDirty,
comments: commentsDirty && !formDirty,
edits: formDirty && !commentsDirty,
};
let hiding = false;
if (anyDirty) {
warningContainer.removeClass('footer__container--hidden');
} else {
if (!warningContainer.hasClass('footer__container--hidden')) {
hiding = true;
}
warningContainer.addClass('footer__container--hidden');
}
clearTimeout(updateFooterTextTimeout);
const updateWarnings = () => {
for (const warning of warnings) {
const visible = typeVisibility[warning.dataset.unsavedType];
warning.hidden = !visible;
}
};
if (hiding) {
// If hiding, we want to keep the text as-is before it disappears
updateFooterTextTimeout = setTimeout(updateWarnings, 1050);
} else {
updateWarnings();
}
};