website/modules/contrib/webform/js/webform.ajaxdfb4.js
2023-09-30 09:40:37 +02:00

338 lines
11 KiB
JavaScript

/**
* @file
* JavaScript behaviors for Ajax.
*/
(function ($, Drupal, drupalSettings) {
'use strict';
Drupal.webform = Drupal.webform || {};
Drupal.webform.ajax = Drupal.webform.ajax || {};
// Allow scrollTopOffset to be custom defined or based on whether there is a
// floating toolbar.
Drupal.webform.ajax.scrollTopOffset = Drupal.webform.ajax.scrollTopOffset || ($('#toolbar-administration').length ? 140 : 10);
// Set global scroll top offset.
// @todo Remove in Webform 6.x.
Drupal.webform.scrollTopOffset = Drupal.webform.ajax.scrollTopOffset;
/**
* Provide Webform Ajax link behavior.
*
* Display fullscreen progress indicator instead of throbber.
* Copied from: Drupal.behaviors.AJAX
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior to a.webform-ajax-link.
*/
Drupal.behaviors.webformAjaxLink = {
attach: function (context) {
$('.webform-ajax-link', context).once('webform-ajax-link').each(function () {
var element_settings = {};
element_settings.progress = {type: 'fullscreen'};
// For anchor tags, these will go to the target of the anchor rather
// than the usual location.
var href = $(this).attr('href');
if (href) {
element_settings.url = href;
element_settings.event = 'click';
}
element_settings.dialogType = $(this).data('dialog-type');
element_settings.dialogRenderer = $(this).data('dialog-renderer');
element_settings.dialog = $(this).data('dialog-options');
element_settings.base = $(this).attr('id');
element_settings.element = this;
Drupal.ajax(element_settings);
// Close all open modal dialogs when opening off-canvas dialog.
if (element_settings.dialogRenderer === 'off_canvas') {
$(this).on('click', function () {
$('.ui-dialog.webform-ui-dialog:visible').find('.ui-dialog-content').dialog('close');
});
}
});
}
};
/**
* Adds a hash (#) to current pages location for links and buttons
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior to a[data-hash] or :button[data-hash].
*
* @see \Drupal\webform_ui\WebformUiEntityElementsForm::getElementRow
* @see Drupal.behaviors.webformFormTabs
*/
Drupal.behaviors.webformAjaxHash = {
attach: function (context) {
$('[data-hash]', context).once('webform-ajax-hash').each(function () {
var hash = $(this).data('hash');
if (hash) {
$(this).on('click', function () {
location.hash = $(this).data('hash');
});
}
});
}
};
/**
* Provide Ajax callback for confirmation back to link.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior to confirmation back to link.
*/
Drupal.behaviors.webformConfirmationBackAjax = {
attach: function (context) {
$('.js-webform-confirmation-back-link-ajax', context)
.once('webform-confirmation-back-ajax')
.on('click', function (event) {
var $form = $(this).parents('form');
// Trigger the Ajax call back for the hidden submit button.
// @see \Drupal\webform\WebformSubmissionForm::getCustomForm
$form.find('.js-webform-confirmation-back-submit-ajax').trigger('click');
// Move the progress indicator from the submit button to after this link.
// @todo Figure out a better way to set a progress indicator.
var $progress_indicator = $form.find('.ajax-progress');
if ($progress_indicator) {
$(this).after($progress_indicator);
}
// Cancel the click event.
event.preventDefault();
event.stopPropagation();
});
}
};
/** ********************************************************************** **/
// Ajax commands.
/** ********************************************************************** **/
/**
* Track the updated table row key.
*/
var updateKey;
/**
* Track the add element key.
*/
var addElement;
/**
* Command to insert new content into the DOM.
*
* @param {Drupal.Ajax} ajax
* {@link Drupal.Ajax} object created by {@link Drupal.ajax}.
* @param {object} response
* The response from the Ajax request.
* @param {string} response.data
* The data to use with the jQuery method.
* @param {string} [response.method]
* The jQuery DOM manipulation method to be used.
* @param {string} [response.selector]
* A optional jQuery selector string.
* @param {object} [response.settings]
* An optional array of settings that will be used.
* @param {number} [status]
* The XMLHttpRequest status.
*/
Drupal.AjaxCommands.prototype.webformInsert = function (ajax, response, status) {
// Insert the HTML.
this.insert(ajax, response, status);
// Add element.
if (addElement) {
var addSelector = (addElement === '_root_')
? '#webform-ui-add-element'
: '[data-drupal-selector="edit-webform-ui-elements-' + addElement + '-add"]';
$(addSelector).trigger('click');
}
// If not add element, then scroll to and highlight the updated table row.
if (!addElement && updateKey) {
var $element = $('tr[data-webform-key="' + updateKey + '"]');
// Highlight the updated element's row.
$element.addClass('color-success');
setTimeout(function () {$element.removeClass('color-success');}, 3000);
// Focus first tabbable item for the updated elements and handlers.
$element.find(':tabbable:not(.tabledrag-handle)').eq(0).trigger('focus');
// Scroll element into view.
Drupal.webformScrolledIntoView($element);
}
else {
// Focus main content.
$('#main-content').trigger('focus');
}
// Display main page's status message in a floating container.
var $wrapper = $(response.selector);
if ($wrapper.parents('.ui-dialog').length === 0) {
var $messages = $wrapper.find('.messages');
// If 'add element' don't show any messages.
if (addElement) {
$messages.remove();
}
else if ($messages.length) {
var $floatingMessage = $('#webform-ajax-messages');
if ($floatingMessage.length === 0) {
$floatingMessage = $('<div id="webform-ajax-messages" class="webform-ajax-messages"></div>');
$('body').append($floatingMessage);
}
if ($floatingMessage.is(':animated')) {
$floatingMessage.stop(true, true);
}
$floatingMessage.html($messages).show().delay(3000).fadeOut(1000);
}
}
updateKey = null; // Reset element update.
addElement = null; // Reset add element.
};
/**
* Scroll to top ajax command.
*
* @param {Drupal.Ajax} [ajax]
* A {@link Drupal.ajax} object.
* @param {object} response
* Ajax response.
* @param {string} response.selector
* Selector to use.
*
* @see Drupal.AjaxCommands.prototype.viewScrollTop
*/
Drupal.AjaxCommands.prototype.webformScrollTop = function (ajax, response) {
// Scroll top.
Drupal.webformScrollTop(response.selector, response.target);
// Focus on the form wrapper content bookmark if
// .js-webform-autofocus is not enabled.
// @see \Drupal\webform\Form\WebformAjaxFormTrait::buildAjaxForm
var $form = $(response.selector + '-content').find('form');
if (!$form.hasClass('js-webform-autofocus')) {
$(response.selector + '-content').trigger('focus');
}
};
/**
* Command to refresh the current webform page.
*
* @param {Drupal.Ajax} [ajax]
* {@link Drupal.Ajax} object created by {@link Drupal.ajax}.
* @param {object} response
* The response from the Ajax request.
* @param {string} response.url
* The URL to redirect to.
* @param {number} [status]
* The XMLHttpRequest status.
*/
Drupal.AjaxCommands.prototype.webformRefresh = function (ajax, response, status) {
// Get URL path name.
// @see https://stackoverflow.com/questions/6944744/javascript-get-portion-of-url-path
var a = document.createElement('a');
a.href = response.url;
var forceReload = (response.url.match(/\?reload=([^&]+)($|&)/)) ? RegExp.$1 : null;
if (forceReload) {
response.url = response.url.replace(/\?reload=([^&]+)($|&)/, '');
this.redirect(ajax, response, status);
return;
}
if (a.pathname === window.location.pathname && $('.webform-ajax-refresh').length) {
updateKey = (response.url.match(/[?|&]update=([^&]+)($|&)/)) ? RegExp.$1 : null;
addElement = (response.url.match(/[?|&]add_element=([^&]+)($|&)/)) ? RegExp.$1 : null;
$('.webform-ajax-refresh').trigger('click');
}
else {
// Clear unsaved information flag so that the current webform page
// can be redirected.
// @see Drupal.behaviors.webformUnsaved.clear
if (Drupal.behaviors.webformUnsaved) {
Drupal.behaviors.webformUnsaved.clear();
}
// For webform embedded in an iframe, open all redirects in the top
// of the browser window.
// @see \Drupal\webform_share\Controller\WebformShareController::page
if (drupalSettings.webform_share &&
drupalSettings.webform_share.page) {
window.top.location = response.url;
}
else {
this.redirect(ajax, response, status);
}
}
};
/**
* Command to close a off-canvas and modal dialog.
*
* If no selector is given, it defaults to trying to close the modal.
*
* @param {Drupal.Ajax} [ajax]
* {@link Drupal.Ajax} object created by {@link Drupal.ajax}.
* @param {object} response
* The response from the Ajax request.
* @param {string} response.selector
* Selector to use.
* @param {bool} response.persist
* Whether to persist the dialog element or not.
* @param {number} [status]
* The HTTP status code.
*/
Drupal.AjaxCommands.prototype.webformCloseDialog = function (ajax, response, status) {
if ($('#drupal-off-canvas').length) {
// Close off-canvas system tray which is not triggered by close dialog
// command.
// @see Drupal.behaviors.offCanvasEvents
$('#drupal-off-canvas').remove();
$('body').removeClass('js-tray-open');
// Remove all *.off-canvas events
$(document).off('.off-canvas');
$(window).off('.off-canvas');
var edge = document.documentElement.dir === 'rtl' ? 'left' : 'right';
var $mainCanvasWrapper = $('[data-off-canvas-main-canvas]');
$mainCanvasWrapper.css('padding-' + edge, 0);
// Resize tabs when closing off-canvas system tray.
$(window).trigger('resize.tabs');
}
// https://stackoverflow.com/questions/15763909/jquery-ui-dialog-check-if-exists-by-instance-method
if ($(response.selector).hasClass('ui-dialog-content')) {
this.closeDialog(ajax, response, status);
}
};
/**
* Triggers confirm page reload.
*
* @param {Drupal.Ajax} [ajax]
* A {@link Drupal.ajax} object.
* @param {object} response
* Ajax response.
* @param {string} response.message
* A message to be displayed in the confirm dialog.
*/
Drupal.AjaxCommands.prototype.webformConfirmReload = function (ajax, response) {
if (window.confirm(response.message)) {
window.location.reload(true);
}
};
})(jQuery, Drupal, drupalSettings);