annotate core/misc/dialog/off-canvas.es6.js @ 14:1fec387a4317

Update Drupal core to 8.5.2 via Composer
author Chris Cannam
date Mon, 23 Apr 2018 09:46:53 +0100
parents
children 129ea1e6d783
rev   line source
Chris@14 1 /**
Chris@14 2 * @file
Chris@14 3 * Drupal's off-canvas library.
Chris@14 4 */
Chris@14 5
Chris@14 6 (($, Drupal, debounce, displace) => {
Chris@14 7 /**
Chris@14 8 * Off-canvas dialog implementation using jQuery Dialog.
Chris@14 9 *
Chris@14 10 * Transforms the regular dialogs created using Drupal.dialog when the dialog
Chris@14 11 * element equals '#drupal-off-canvas' into an side-loading dialog.
Chris@14 12 *
Chris@14 13 * @namespace
Chris@14 14 */
Chris@14 15 Drupal.offCanvas = {
Chris@14 16
Chris@14 17 /**
Chris@14 18 * The minimum width to use body displace needs to match the width at which
Chris@14 19 * the tray will be 100% width. @see core/misc/dialog/off-canvas.css
Chris@14 20 *
Chris@14 21 * @type {Number}
Chris@14 22 */
Chris@14 23 minDisplaceWidth: 768,
Chris@14 24
Chris@14 25 /**
Chris@14 26 * Wrapper used to position off-canvas dialog.
Chris@14 27 *
Chris@14 28 * @type {jQuery}
Chris@14 29 */
Chris@14 30 $mainCanvasWrapper: $('[data-off-canvas-main-canvas]'),
Chris@14 31
Chris@14 32 /**
Chris@14 33 * Determines if an element is an off-canvas dialog.
Chris@14 34 *
Chris@14 35 * @param {jQuery} $element
Chris@14 36 * The dialog element.
Chris@14 37 *
Chris@14 38 * @return {bool}
Chris@14 39 * True this is currently an off-canvas dialog.
Chris@14 40 */
Chris@14 41 isOffCanvas($element) {
Chris@14 42 return $element.is('#drupal-off-canvas');
Chris@14 43 },
Chris@14 44
Chris@14 45 /**
Chris@14 46 * Remove off-canvas dialog events.
Chris@14 47 *
Chris@14 48 * @param {jQuery} $element
Chris@14 49 * The target element.
Chris@14 50 */
Chris@14 51 removeOffCanvasEvents($element) {
Chris@14 52 $element.off('.off-canvas');
Chris@14 53 $(document).off('.off-canvas');
Chris@14 54 $(window).off('.off-canvas');
Chris@14 55 },
Chris@14 56
Chris@14 57 /**
Chris@14 58 * Handler fired before an off-canvas dialog has been opened.
Chris@14 59 *
Chris@14 60 * @param {Object} settings
Chris@14 61 * Settings related to the composition of the dialog.
Chris@14 62 *
Chris@14 63 * @return {undefined}
Chris@14 64 */
Chris@14 65 beforeCreate({ settings, $element }) {
Chris@14 66 // Clean up previous dialog event handlers.
Chris@14 67 Drupal.offCanvas.removeOffCanvasEvents($element);
Chris@14 68
Chris@14 69 $('body').addClass('js-off-canvas-dialog-open');
Chris@14 70 // @see http://api.jqueryui.com/position/
Chris@14 71 settings.position = {
Chris@14 72 my: 'left top',
Chris@14 73 at: `${Drupal.offCanvas.getEdge()} top`,
Chris@14 74 of: window,
Chris@14 75 };
Chris@14 76
Chris@14 77 /**
Chris@14 78 * Applies initial height to dialog based on window height.
Chris@14 79 * @see http://api.jqueryui.com/dialog for all dialog options.
Chris@14 80 */
Chris@14 81 settings.height = $(window).height();
Chris@14 82 },
Chris@14 83
Chris@14 84 /**
Chris@14 85 * Handler fired after an off-canvas dialog has been closed.
Chris@14 86 *
Chris@14 87 * @return {undefined}
Chris@14 88 */
Chris@14 89 beforeClose({ $element }) {
Chris@14 90 $('body').removeClass('js-off-canvas-dialog-open');
Chris@14 91 // Remove all *.off-canvas events
Chris@14 92 Drupal.offCanvas.removeOffCanvasEvents($element);
Chris@14 93
Chris@14 94 Drupal.offCanvas.$mainCanvasWrapper.css(`padding-${Drupal.offCanvas.getEdge()}`, 0);
Chris@14 95 },
Chris@14 96
Chris@14 97 /**
Chris@14 98 * Handler fired when an off-canvas dialog has been opened.
Chris@14 99 *
Chris@14 100 * @param {jQuery} $element
Chris@14 101 * The off-canvas dialog element.
Chris@14 102 * @param {Object} settings
Chris@14 103 * Settings related to the composition of the dialog.
Chris@14 104 *
Chris@14 105 * @return {undefined}
Chris@14 106 */
Chris@14 107 afterCreate({ $element, settings }) {
Chris@14 108 const eventData = { settings, $element, offCanvasDialog: this };
Chris@14 109
Chris@14 110 $element
Chris@14 111 .on('dialogContentResize.off-canvas', eventData, Drupal.offCanvas.handleDialogResize)
Chris@14 112 .on('dialogContentResize.off-canvas', eventData, Drupal.offCanvas.bodyPadding);
Chris@14 113
Chris@14 114 Drupal.offCanvas.getContainer($element).attr(`data-offset-${Drupal.offCanvas.getEdge()}`, '');
Chris@14 115
Chris@14 116 $(window)
Chris@14 117 .on('resize.off-canvas', eventData, debounce(Drupal.offCanvas.resetSize, 100))
Chris@14 118 .trigger('resize.off-canvas');
Chris@14 119 },
Chris@14 120
Chris@14 121 /**
Chris@14 122 * Toggle classes based on title existence.
Chris@14 123 * Called with Drupal.offCanvas.afterCreate.
Chris@14 124 *
Chris@14 125 * @param {Object} settings
Chris@14 126 * Settings related to the composition of the dialog.
Chris@14 127 *
Chris@14 128 * @return {undefined}
Chris@14 129 */
Chris@14 130 render({ settings }) {
Chris@14 131 $('.ui-dialog-off-canvas, .ui-dialog-off-canvas .ui-dialog-titlebar').toggleClass('ui-dialog-empty-title', !settings.title);
Chris@14 132 },
Chris@14 133
Chris@14 134 /**
Chris@14 135 * Adjusts the dialog on resize.
Chris@14 136 *
Chris@14 137 * @param {jQuery.Event} event
Chris@14 138 * The event triggered.
Chris@14 139 * @param {object} event.data
Chris@14 140 * Data attached to the event.
Chris@14 141 */
Chris@14 142 handleDialogResize(event) {
Chris@14 143 const $element = event.data.$element;
Chris@14 144 const $container = Drupal.offCanvas.getContainer($element);
Chris@14 145
Chris@14 146 const $offsets = $container.find('> :not(#drupal-off-canvas, .ui-resizable-handle)');
Chris@14 147 let offset = 0;
Chris@14 148
Chris@14 149 // Let scroll element take all the height available.
Chris@14 150 $element.css({ height: 'auto' });
Chris@14 151 const modalHeight = $container.height();
Chris@14 152
Chris@14 153 $offsets.each((i, e) => {
Chris@14 154 offset += $(e).outerHeight();
Chris@14 155 });
Chris@14 156
Chris@14 157 // Take internal padding into account.
Chris@14 158 const scrollOffset = $element.outerHeight() - $element.height();
Chris@14 159 $element.height(modalHeight - offset - scrollOffset);
Chris@14 160 },
Chris@14 161
Chris@14 162 /**
Chris@14 163 * Resets the size of the dialog.
Chris@14 164 *
Chris@14 165 * @param {jQuery.Event} event
Chris@14 166 * The event triggered.
Chris@14 167 * @param {object} event.data
Chris@14 168 * Data attached to the event.
Chris@14 169 */
Chris@14 170 resetSize(event) {
Chris@14 171 const offsets = displace.offsets;
Chris@14 172 const $element = event.data.$element;
Chris@14 173 const container = Drupal.offCanvas.getContainer($element);
Chris@14 174
Chris@14 175 const topPosition = (offsets.top !== 0 ? `+${offsets.top}` : '');
Chris@14 176 const adjustedOptions = {
Chris@14 177 // @see http://api.jqueryui.com/position/
Chris@14 178 position: {
Chris@14 179 my: `${Drupal.offCanvas.getEdge()} top`,
Chris@14 180 at: `${Drupal.offCanvas.getEdge()} top${topPosition}`,
Chris@14 181 of: window,
Chris@14 182 },
Chris@14 183 };
Chris@14 184
Chris@14 185 container.css({
Chris@14 186 position: 'fixed',
Chris@14 187 height: `${$(window).height() - (offsets.top + offsets.bottom)}px`,
Chris@14 188 });
Chris@14 189
Chris@14 190 $element
Chris@14 191 .dialog('option', adjustedOptions)
Chris@14 192 .trigger('dialogContentResize.off-canvas');
Chris@14 193 },
Chris@14 194
Chris@14 195 /**
Chris@14 196 * Adjusts the body padding when the dialog is resized.
Chris@14 197 *
Chris@14 198 * @param {jQuery.Event} event
Chris@14 199 * The event triggered.
Chris@14 200 * @param {object} event.data
Chris@14 201 * Data attached to the event.
Chris@14 202 */
Chris@14 203 bodyPadding(event) {
Chris@14 204 if ($('body').outerWidth() < Drupal.offCanvas.minDisplaceWidth) {
Chris@14 205 return;
Chris@14 206 }
Chris@14 207 const $element = event.data.$element;
Chris@14 208 const $container = Drupal.offCanvas.getContainer($element);
Chris@14 209 const $mainCanvasWrapper = Drupal.offCanvas.$mainCanvasWrapper;
Chris@14 210
Chris@14 211 const width = $container.outerWidth();
Chris@14 212 const mainCanvasPadding = $mainCanvasWrapper.css(`padding-${Drupal.offCanvas.getEdge()}`);
Chris@14 213 if (width !== mainCanvasPadding) {
Chris@14 214 $mainCanvasWrapper.css(`padding-${Drupal.offCanvas.getEdge()}`, `${width}px`);
Chris@14 215 $container.attr(`data-offset-${Drupal.offCanvas.getEdge()}`, width);
Chris@14 216 displace();
Chris@14 217 }
Chris@14 218 },
Chris@14 219
Chris@14 220 /**
Chris@14 221 * The HTML element that surrounds the dialog.
Chris@14 222 * @param {HTMLElement} $element
Chris@14 223 * The dialog element.
Chris@14 224 *
Chris@14 225 * @return {HTMLElement}
Chris@14 226 * The containing element.
Chris@14 227 */
Chris@14 228 getContainer($element) {
Chris@14 229 return $element.dialog('widget');
Chris@14 230 },
Chris@14 231
Chris@14 232 /**
Chris@14 233 * The edge of the screen that the dialog should appear on.
Chris@14 234 *
Chris@14 235 * @return {string}
Chris@14 236 * The edge the tray will be shown on, left or right.
Chris@14 237 */
Chris@14 238 getEdge() {
Chris@14 239 return document.documentElement.dir === 'rtl' ? 'left' : 'right';
Chris@14 240 },
Chris@14 241 };
Chris@14 242
Chris@14 243 /**
Chris@14 244 * Attaches off-canvas dialog behaviors.
Chris@14 245 *
Chris@14 246 * @type {Drupal~behavior}
Chris@14 247 *
Chris@14 248 * @prop {Drupal~behaviorAttach} attach
Chris@14 249 * Attaches event listeners for off-canvas dialogs.
Chris@14 250 */
Chris@14 251 Drupal.behaviors.offCanvasEvents = {
Chris@14 252 attach: () => {
Chris@14 253 $(window).once('off-canvas').on({
Chris@14 254 'dialog:beforecreate': (event, dialog, $element, settings) => {
Chris@14 255 if (Drupal.offCanvas.isOffCanvas($element)) {
Chris@14 256 Drupal.offCanvas.beforeCreate({ dialog, $element, settings });
Chris@14 257 }
Chris@14 258 },
Chris@14 259 'dialog:aftercreate': (event, dialog, $element, settings) => {
Chris@14 260 if (Drupal.offCanvas.isOffCanvas($element)) {
Chris@14 261 Drupal.offCanvas.render({ dialog, $element, settings });
Chris@14 262 Drupal.offCanvas.afterCreate({ $element, settings });
Chris@14 263 }
Chris@14 264 },
Chris@14 265 'dialog:beforeclose': (event, dialog, $element) => {
Chris@14 266 if (Drupal.offCanvas.isOffCanvas($element)) {
Chris@14 267 Drupal.offCanvas.beforeClose({ dialog, $element });
Chris@14 268 }
Chris@14 269 },
Chris@14 270 });
Chris@14 271 },
Chris@14 272 };
Chris@14 273 })(jQuery, Drupal, Drupal.debounce, Drupal.displace);