layout_builder_ipe-1.0.x-dev/js/ipe.js
js/ipe.js
/**
* @file
*/
(function ($, Drupal) {
Drupal.LB_IPE = {};
if (typeof $.fn.processLayoutBuilderToolbar == 'undefined') {
$.fn.processLayoutBuilderToolbar = function() {
Drupal.toolbar.ToolbarVisualView.updateToolbarHeight();
}
}
/**
* Attaches the IPE behaviors.
*/
Drupal.behaviors.lb_ipe_attach_behaviors = {
attach: function (context, settings) {
var editing = false;
let ipe_settings = settings.layout_builder_ipe != 'undefined' ? settings.layout_builder_ipe : null;
let hide_local_tasks = ipe_settings && ipe_settings.hasOwnProperty('hide_local_tasks') && ipe_settings.hide_local_tasks;
let enhance_ui = ipe_settings && ipe_settings.hasOwnProperty('enhance_ui') && ipe_settings.enhance_ui;
let $ajax_link = null;
let $body = $('body');
if ($body && ipe_settings && ipe_settings.hasOwnProperty('links') && !$('.layout-builder-ipe-actions').length) {
// Setup the link container.
let $link_container = $('<div>');
$link_container.addClass('layout-builder-ipe-actions');
// Setup the links.
for (var key in ipe_settings.links) {
let $link = $(ipe_settings.links[key]);
$link.addClass('layout-builder-ipe--link')
.addClass('layout-builder-ipe--link-' + key)
.addClass('inline-block-create-button');
$link_container.append($link);
}
// Add the built links container to the page.
$body.append($link_container);
$body.addClass('has-layout-builder-ipe-actions');
// We need to attach the behaviors for this new container.
Drupal.attachBehaviors($body.find('.layout-builder-ipe-actions')[0], settings);
let link_container_height = $body.find('.layout-builder-ipe-actions').outerHeight();
$body.css('padding-bottom', link_container_height + 'px');
// Add error handling to the customize button.
$ajax_link = $(Drupal.ajax.instances).filter(function () {
return $(this.element).hasClass('layout-builder-ipe--link-customize');
});
if ($ajax_link.length) {
// We must overwrite the error handling for this ajax link, otherwise
// there will be an uncaught error and the tests will fail.
$ajax_link.get(0).error = function error(xmlhttprequest, uri, customMessage) {
// Just do the same as in Drupal.Ajax.prototype.error except the
// error throwing at the end.
if (this.progress.element) {
$(this.progress.element).remove();
}
if (this.progress.object) {
this.progress.object.stopMonitoring();
}
$(this.wrapper).show();
$(this.element).prop('disabled', false);
if (this.$form && document.body.contains(this.$form.get(0))) {
var settings = this.settings || drupalSettings;
Drupal.attachBehaviors(this.$form.get(0), settings);
}
// Done.
}
// Now to our own error handling, where we get the access denied
// message and show it in a modal, together with a button to break
// the lock if that applies.
$ajax_link.get(0).options.error = function(xmlhttprequest) {
$ajax_link.get(0).ajaxing = false;
let response = JSON.parse(xmlhttprequest.responseJSON.message);
if (typeof response == 'object' && response.hasOwnProperty('reason') && response.reason == 'locked') {
buttons = [
{
text: Drupal.t('Ok'),
class: 'glb-button glb-button--primary',
click() {
Drupal.dialog($(this).get(0)).close();
// Attach behaviors so that the #drupal-module DOM element
// can be re-added.
Drupal.attachBehaviors();
},
}
];
if (response.break_lock_url) {
buttons.push({
text: Drupal.t('Break lock'),
class: 'glb-button',
click() {
// Break the log
Drupal.ajax({
url: response.break_lock_url,
}).execute();
}
});
}
$('#drupal-modal').append('<div>' + response.message + '</div>');
let dialog = Drupal.dialog($('#drupal-modal').get(0), {
title: Drupal.t('Content is locked'),
dialogClass: 'locked-message',
buttons: buttons,
// Prevent this modal from being closed without the user making a choice
// as per http://stackoverflow.com/a/5438771.
closeOnEscape: false,
create() {
$(this).parent().find('.ui-dialog-titlebar-close').remove();
},
beforeClose: false,
});
dialog.showModal();
}
}
}
// Content wrapper.
let $wrapper = $('<div>')
.attr('id', 'layout-builder-ipe-wrapper');
$(ipe_settings.entity_selector).wrapAll($wrapper);
}
// Wrap the toolbar and, if present, the secondary toolbar so that we can
// replace them together in BaseController::ajaxResponse().
if (($('body').hasClass('gin--horizontal-toolbar') || $('body').hasClass('gin--vertical-toolbar')) && !$('#gin-toolbar-wrapper').length) {
$('#toolbar-administration, #toolbar-administration ~ .gin-secondary-toolbar').wrapAll('<div id="gin-toolbar-wrapper">');
Drupal.attachBehaviors($('#gin-toolbar-wrapper').get(0));
}
if (enhance_ui) {
$('body').addClass('layout-builder-ipe--enhance-ui');
}
if ($(context).attr('id') == 'layout-builder-ipe-wrapper') {
editing = $(context).hasClass('edit-layout');
$('body').toggleClass('layout-builder-ipe-editing', editing ? true : false);
if (hide_local_tasks) {
$('body').find('.block-local-tasks-block').toggle(editing ? false : true);
}
}
$('body.layout-builder-ipe-editing .layout-builder__region').each(function () {
let has_blocks = $(this).find('.layout-builder-block').length > 0;
if (has_blocks && enhance_ui) {
$(this).children('.layout-builder__add-block').hide().removeAttr('data-layout-builder-highlight-id');
$('a.layout-builder__link--add.link-before, a.layout-builder__link--add.link-after', this).on('click', function () {
$('.layout-builder-block.is-layout-builder-active .active-link').removeClass('active-link');
$('.layout-builder-block.is-layout-builder-active').removeClass('is-layout-builder-active');
$(this).parents('.layout-builder-block').addClass('is-layout-builder-active');
$(this).addClass('active-link');
});
$(window).on('dialog:afterclose', function (event, dialog, $element) {
$('.is-layout-builder-active .active-link').removeClass('active-link');
$('.is-layout-builder-active').removeClass('is-layout-builder-active');
});
}
});
let toolbar = typeof Drupal.toolbar !== 'undefined' ? Drupal.toolbar : null;
let toolbar_view = toolbar && typeof toolbar.views.toolbarVisualView != 'undefined' ? toolbar.views.toolbarVisualView : null;
if (editing && toolbar_view) {
toolbar_view.updateToolbarHeight();
}
else if (!editing) {
$('body').css({
'padding-top': 0,
});
}
// Check if the editing interface should be automatically opened.
let query = new URLSearchParams(location.search);
if (query.has('openIpe') && !editing && $ajax_link && $ajax_link.length) {
$ajax_link.get(0).execute();
}
}
}
})(jQuery, Drupal);
