Chris@0: /** Chris@0: * @file Chris@0: * Handles AJAX submission and response in Views UI. Chris@0: */ Chris@0: Chris@17: (function($, Drupal, drupalSettings) { Chris@0: /** Chris@0: * Ajax command for highlighting elements. Chris@0: * Chris@0: * @param {Drupal.Ajax} [ajax] Chris@0: * An Ajax object. Chris@0: * @param {object} response Chris@0: * The Ajax response. Chris@0: * @param {string} response.selector Chris@0: * The selector in question. Chris@0: * @param {number} [status] Chris@0: * The HTTP status code. Chris@0: */ Chris@17: Drupal.AjaxCommands.prototype.viewsHighlight = function( Chris@17: ajax, Chris@17: response, Chris@17: status, Chris@17: ) { Chris@0: $('.hilited').removeClass('hilited'); Chris@0: $(response.selector).addClass('hilited'); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Ajax command to set the form submit action in the views modal edit form. Chris@0: * Chris@0: * @param {Drupal.Ajax} [ajax] Chris@0: * An Ajax object. Chris@0: * @param {object} response Chris@0: * The Ajax response. Contains .url Chris@0: * @param {string} [status] Chris@0: * The XHR status code? Chris@0: */ Chris@17: Drupal.AjaxCommands.prototype.viewsSetForm = function( Chris@17: ajax, Chris@17: response, Chris@17: status, Chris@17: ) { Chris@0: const $form = $('.js-views-ui-dialog form'); Chris@0: // Identify the button that was clicked so that .ajaxSubmit() can use it. Chris@0: // We need to do this for both .click() and .mousedown() since JavaScript Chris@0: // code might trigger either behavior. Chris@17: const $submitButtons = $form Chris@17: .find('input[type=submit].js-form-submit, button.js-form-submit') Chris@17: .once('views-ajax-submit'); Chris@17: $submitButtons.on('click mousedown', function() { Chris@0: this.form.clk = this; Chris@0: }); Chris@17: $form.once('views-ajax-submit').each(function() { Chris@0: const $form = $(this); Chris@14: const elementSettings = { Chris@0: url: response.url, Chris@0: event: 'submit', Chris@0: base: $form.attr('id'), Chris@0: element: this, Chris@0: }; Chris@14: const ajaxForm = Drupal.ajax(elementSettings); Chris@0: ajaxForm.$form = $form; Chris@0: }); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Ajax command to show certain buttons in the views edit form. Chris@0: * Chris@0: * @param {Drupal.Ajax} [ajax] Chris@0: * An Ajax object. Chris@0: * @param {object} response Chris@0: * The Ajax response. Chris@0: * @param {bool} response.changed Chris@0: * Whether the state changed for the buttons or not. Chris@0: * @param {number} [status] Chris@0: * The HTTP status code. Chris@0: */ Chris@17: Drupal.AjaxCommands.prototype.viewsShowButtons = function( Chris@17: ajax, Chris@17: response, Chris@17: status, Chris@17: ) { Chris@0: $('div.views-edit-view div.form-actions').removeClass('js-hide'); Chris@0: if (response.changed) { Chris@0: $('div.views-edit-view div.view-changed.messages').removeClass('js-hide'); Chris@0: } Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Ajax command for triggering preview. Chris@0: * Chris@0: * @param {Drupal.Ajax} [ajax] Chris@0: * An Ajax object. Chris@0: * @param {object} [response] Chris@0: * The Ajax response. Chris@0: * @param {number} [status] Chris@0: * The HTTP status code. Chris@0: */ Chris@17: Drupal.AjaxCommands.prototype.viewsTriggerPreview = function( Chris@17: ajax, Chris@17: response, Chris@17: status, Chris@17: ) { Chris@0: if ($('input#edit-displays-live-preview').is(':checked')) { Chris@0: $('#preview-submit').trigger('click'); Chris@0: } Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Ajax command to replace the title of a page. Chris@0: * Chris@0: * @param {Drupal.Ajax} [ajax] Chris@0: * An Ajax object. Chris@0: * @param {object} response Chris@0: * The Ajax response. Chris@0: * @param {string} response.siteName Chris@0: * The site name. Chris@0: * @param {string} response.title Chris@0: * The new page title. Chris@0: * @param {number} [status] Chris@0: * The HTTP status code. Chris@0: */ Chris@17: Drupal.AjaxCommands.prototype.viewsReplaceTitle = function( Chris@17: ajax, Chris@17: response, Chris@17: status, Chris@17: ) { Chris@0: const doc = document; Chris@0: // For the element, make a best-effort attempt to replace the page Chris@0: // title and leave the site name alone. If the theme doesn't use the site Chris@0: // name in the <title> element, this will fail. Chris@0: const oldTitle = doc.title; Chris@0: // Escape the site name, in case it has special characters in it, so we can Chris@0: // use it in our regex. Chris@17: const escapedSiteName = response.siteName.replace( Chris@17: /[-[\]{}()*+?.,\\^$|#\s]/g, Chris@17: '\\$&', Chris@17: ); Chris@0: const re = new RegExp(`.+ (.) ${escapedSiteName}`); Chris@17: doc.title = oldTitle.replace( Chris@17: re, Chris@17: `${response.title} $1 ${response.siteName}`, Chris@17: ); Chris@0: Chris@0: $('h1.page-title').text(response.title); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Get rid of irritating tabledrag messages. Chris@0: * Chris@0: * @return {Array} Chris@0: * An array of messages. Always empty array, to get rid of the messages. Chris@0: */ Chris@17: Drupal.theme.tableDragChangedWarning = function() { Chris@0: return []; Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Trigger preview when the "live preview" checkbox is checked. Chris@0: * Chris@0: * @type {Drupal~behavior} Chris@0: * Chris@0: * @prop {Drupal~behaviorAttach} attach Chris@0: * Attaches behavior to trigger live preview if the live preview option is Chris@0: * checked. Chris@0: */ Chris@0: Drupal.behaviors.livePreview = { Chris@0: attach(context) { Chris@17: $('input#edit-displays-live-preview', context) Chris@17: .once('views-ajax') Chris@17: .on('click', function() { Chris@17: if ($(this).is(':checked')) { Chris@17: $('#preview-submit').trigger('click'); Chris@17: } Chris@17: }); Chris@0: }, Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sync preview display. Chris@0: * Chris@0: * @type {Drupal~behavior} Chris@0: * Chris@0: * @prop {Drupal~behaviorAttach} attach Chris@0: * Attaches behavior to sync the preview display when needed. Chris@0: */ Chris@0: Drupal.behaviors.syncPreviewDisplay = { Chris@0: attach(context) { Chris@17: $('#views-tabset a') Chris@17: .once('views-ajax') Chris@17: .on('click', function() { Chris@17: const href = $(this).attr('href'); Chris@17: // Cut of #views-tabset. Chris@17: const displayId = href.substr(11); Chris@17: // Set the form element. Chris@17: $('#views-live-preview #preview-display-id').val(displayId); Chris@17: }); Chris@0: }, Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Ajax behaviors for the views_ui module. Chris@0: * Chris@0: * @type {Drupal~behavior} Chris@0: * Chris@0: * @prop {Drupal~behaviorAttach} attach Chris@0: * Attaches ajax behaviors to the elements with the classes in question. Chris@0: */ Chris@0: Drupal.behaviors.viewsAjax = { Chris@0: collapseReplaced: false, Chris@0: attach(context, settings) { Chris@14: const baseElementSettings = { Chris@0: event: 'click', Chris@0: progress: { type: 'fullscreen' }, Chris@0: }; Chris@0: // Bind AJAX behaviors to all items showing the class. Chris@17: $('a.views-ajax-link', context) Chris@17: .once('views-ajax') Chris@17: .each(function() { Chris@17: const elementSettings = baseElementSettings; Chris@17: elementSettings.base = $(this).attr('id'); Chris@17: elementSettings.element = this; Chris@17: // Set the URL to go to the anchor. Chris@17: if ($(this).attr('href')) { Chris@17: elementSettings.url = $(this).attr('href'); Chris@17: } Chris@17: Drupal.ajax(elementSettings); Chris@17: }); Chris@0: Chris@0: $('div#views-live-preview a') Chris@17: .once('views-ajax') Chris@17: .each(function() { Chris@0: // We don't bind to links without a URL. Chris@0: if (!$(this).attr('href')) { Chris@0: return true; Chris@0: } Chris@0: Chris@14: const elementSettings = baseElementSettings; Chris@0: // Set the URL to go to the anchor. Chris@14: elementSettings.url = $(this).attr('href'); Chris@17: if ( Chris@17: Drupal.Views.getPath(elementSettings.url).substring(0, 21) !== Chris@17: 'admin/structure/views' Chris@17: ) { Chris@0: return true; Chris@0: } Chris@0: Chris@14: elementSettings.wrapper = 'views-preview-wrapper'; Chris@14: elementSettings.method = 'replaceWith'; Chris@14: elementSettings.base = $(this).attr('id'); Chris@14: elementSettings.element = this; Chris@14: Drupal.ajax(elementSettings); Chris@0: }); Chris@0: Chris@0: // Within a live preview, make exposed widget form buttons re-trigger the Chris@0: // Preview button. Chris@0: // @todo Revisit this after fixing Views UI to display a Preview outside Chris@0: // of the main Edit form. Chris@0: $('div#views-live-preview input[type=submit]') Chris@17: .once('views-ajax') Chris@17: .each(function(event) { Chris@17: $(this).on('click', function() { Chris@0: this.form.clk = this; Chris@0: return true; Chris@0: }); Chris@14: const elementSettings = baseElementSettings; Chris@0: // Set the URL to go to the anchor. Chris@14: elementSettings.url = $(this.form).attr('action'); Chris@17: if ( Chris@17: Drupal.Views.getPath(elementSettings.url).substring(0, 21) !== Chris@17: 'admin/structure/views' Chris@17: ) { Chris@0: return true; Chris@0: } Chris@0: Chris@14: elementSettings.wrapper = 'views-preview-wrapper'; Chris@14: elementSettings.method = 'replaceWith'; Chris@14: elementSettings.event = 'click'; Chris@14: elementSettings.base = $(this).attr('id'); Chris@14: elementSettings.element = this; Chris@0: Chris@14: Drupal.ajax(elementSettings); Chris@0: }); Chris@0: }, Chris@0: }; Chris@17: })(jQuery, Drupal, drupalSettings);