panopoly_magic-8.x-2.x-dev/js/panopoly_magic.preview.live.automatic.js
js/panopoly_magic.preview.live.automatic.js
(function ($, Drupal) {
// Used to only update preview after changes stop.
let timer = null;
// Holds the un-monkey-patched version of Drupal.behaviors.dialog.
let drupalBehaviorsDialogAttach = null;
// Used to as a "kill switch" to prevent the dialog from stealing focus on preview reload.
let preventDialogStealingFocus = false;
Drupal.behaviors.panopolyMagicLivePreview = {
attach: function (context) {
// e.keyCode: key
const discardKeyCode = [
16, // shift
17, // ctrl
18, // alt
20, // caps lock
33, // page up
34, // page down
35, // end
36, // home
37, // left arrow
38, // up arrow
39, // right arrow
40, // down arrow
9, // tab
13, // enter
27 // esc
];
const form_selector = 'form#layout-builder-add-block,form#layout-builder-update-block';
// Finds matching children or the current context itself.
// @see https://stackoverflow.com/questions/2828019/looking-for-jquery-find-method-that-includes-the-current-node
const $form = $(context).find(form_selector).addBack(form_selector);
const $preview = $form.find('.panopoly-magic-live-preview');
// When the preview is rendered, misc/dialog/dialog.ajax.js will steal focus from whatever it was on. Here we
// monkey-patch Drupal.behaviors.dialog.attach to give ourselves a "kill switch" for when the preview is
// rendering, that is the preventDialogStealFocus variable.
if (!drupalBehaviorsDialogAttach && Drupal.behaviors.dialog) {
drupalBehaviorsDialogAttach = Drupal.behaviors.dialog.attach;
Drupal.behaviors.dialog.attach = function (context, settings) {
const $context = $(context);
const $dialog = $context.closest('.ui-dialog-content');
if (preventDialogStealingFocus && $dialog.length > 0) {
preventDialogStealingFocus = false;
}
else if ($context.is(form_selector)) {
// Only update the buttons when running on the form as a whole.
if ($dialog.length) {
$dialog.trigger('dialogButtonsChange');
}
}
else {
drupalBehaviorsDialogAttach(context, settings);
}
};
}
if ($form.length === 0 || $preview.length === 0) {
return;
}
function triggerSubmit() {
if (timer) {
clearTimeout(timer);
}
// Prevent preview if 'Reusable' is checked because previews don't work with reusable widgets.
if (!$form.find('[data-drupal-selector="edit-reusable"]').is(':checked')) {
timer = setTimeout(submitForm, 500);
}
else {
timer = null;
}
}
// Submits the form.
function submitForm() {
// Clear timer.
timer = null;
// Disable the preview button.
$preview.prop('disabled', true);
// Prevent dialog.ajax.js from stealing focus.
preventDialogStealingFocus = true;
// Note: .click does not work here.
// See https://drupal.stackexchange.com/questions/11638/how-to-programmatically-trigger-a-click-on-an-ajax-enabled-form-submit-button
$preview.mousedown();
}
// Hide the preview button if 'Reusable' is checked because previews don't work with reusable widgets.
$(once('panopoly-magic-live-preview', $form.find('[data-drupal-selector="edit-reusable"]'))).change(function () {
$preview.prop('disabled', this.checked);
$preview.toggle(!this.checked)
});
// Text input.
$form.find('[type="text"], textarea, [type="number"]').on('keyup', function (e) {
// Filter out discarded keys.
if ($.inArray(e.keyCode, discardKeyCode) !== -1) {
return;
}
triggerSubmit();
});
// WYSIWYG.
if (typeof CKEDITOR !== 'undefined') {
CKEDITOR.on('instanceCreated', function(e) {
e.editor.on('change', triggerSubmit);
});
for (let instanceName in CKEDITOR.instances) {
CKEDITOR.instances[instanceName].on('change', triggerSubmit);
}
}
// Checkboxes, radios, colors, ranges, selects.
$form.find('[type="checkbox"], [type="radio"], [type="number"], [type="color"], [type="range"], select').on('change', function () {
triggerSubmit();
});
// Media Library widget.
var trackChange = function(index, element) {
var observer = new MutationObserver(function(mutations, observer) {
triggerSubmit();
});
observer.observe(element, { childList: true });
}
$form.find('.media-library-widget, .js-media-library-widget').parent().each(trackChange);
// Autocomplete fields.
$form.find('.form-autocomplete').on('autocompleteclose', function (e, ui) {
triggerSubmit();
});
}
}
})(jQuery, Drupal);
