Version 1
[yaffs-website] / web / core / modules / outside_in / js / off-canvas.js
diff --git a/web/core/modules/outside_in/js/off-canvas.js b/web/core/modules/outside_in/js/off-canvas.js
new file mode 100644 (file)
index 0000000..d7c8d90
--- /dev/null
@@ -0,0 +1,160 @@
+/**
+ * @file
+ * Drupal's off-canvas library.
+ *
+ * @todo This functionality should extracted into a new core library or a part
+ *  of the current drupal.dialog.ajax library.
+ *  https://www.drupal.org/node/2784443
+ */
+
+(function ($, Drupal, debounce, displace) {
+
+  'use strict';
+
+  // The minimum width to use body displace needs to match the width at which
+  // the tray will be %100 width. @see outside_in.module.css
+  var minDisplaceWidth = 768;
+
+  /**
+   * The edge of the screen that the dialog should appear on.
+   *
+   * @type {string}
+   */
+  var edge = document.documentElement.dir === 'rtl' ? 'left' : 'right';
+
+  var $mainCanvasWrapper = $('[data-off-canvas-main-canvas]');
+
+  /**
+   * Resets the size of the dialog.
+   *
+   * @param {jQuery.Event} event
+   *   The event triggered.
+   */
+  function resetSize(event) {
+    var offsets = displace.offsets;
+    var $element = event.data.$element;
+    var $widget = $element.dialog('widget');
+
+    var adjustedOptions = {
+      // @see http://api.jqueryui.com/position/
+      position: {
+        my: edge + ' top',
+        at: edge + ' top' + (offsets.top !== 0 ? '+' + offsets.top : ''),
+        of: window
+      }
+    };
+
+    $widget.css({
+      position: 'fixed',
+      height: ($(window).height() - (offsets.top + offsets.bottom)) + 'px'
+    });
+
+    $element
+      .dialog('option', adjustedOptions)
+      .trigger('dialogContentResize.off-canvas');
+  }
+
+  /**
+   * Adjusts the dialog on resize.
+   *
+   * @param {jQuery.Event} event
+   *   The event triggered.
+   */
+  function handleDialogResize(event) {
+    var $element = event.data.$element;
+    var $widget = $element.dialog('widget');
+
+    var $offsets = $widget.find('> :not(#drupal-off-canvas, .ui-resizable-handle)');
+    var offset = 0;
+    var modalHeight;
+
+    // Let scroll element take all the height available.
+    $element.css({height: 'auto'});
+    modalHeight = $widget.height();
+    $offsets.each(function () { offset += $(this).outerHeight(); });
+
+    // Take internal padding into account.
+    var scrollOffset = $element.outerHeight() - $element.height();
+    $element.height(modalHeight - offset - scrollOffset);
+  }
+
+  /**
+   * Adjusts the body padding when the dialog is resized.
+   *
+   * @param {jQuery.Event} event
+   *   The event triggered.
+   */
+  function bodyPadding(event) {
+    if ($('body').outerWidth() < minDisplaceWidth) {
+      return;
+    }
+    var $element = event.data.$element;
+    var $widget = $element.dialog('widget');
+
+    var width = $widget.outerWidth();
+    var mainCanvasPadding = $mainCanvasWrapper.css('padding-' + edge);
+    if (width !== mainCanvasPadding) {
+      $mainCanvasWrapper.css('padding-' + edge, width + 'px');
+      $widget.attr('data-offset-' + edge, width);
+      displace();
+    }
+  }
+
+  /**
+   * Attaches off-canvas dialog behaviors.
+   *
+   * @type {Drupal~behavior}
+   *
+   * @prop {Drupal~behaviorAttach} attach
+   *   Attaches event listeners for off-canvas dialogs.
+   */
+  Drupal.behaviors.offCanvasEvents = {
+    attach: function () {
+      $(window).once('off-canvas').on({
+        'dialog:aftercreate': function (event, dialog, $element, settings) {
+          if ($element.is('#drupal-off-canvas')) {
+            var eventData = {settings: settings, $element: $element};
+            $('.ui-dialog-off-canvas, .ui-dialog-off-canvas .ui-dialog-titlebar').toggleClass('ui-dialog-empty-title', !settings.title);
+
+            $element
+              .on('dialogresize.off-canvas', eventData, debounce(bodyPadding, 100))
+              .on('dialogContentResize.off-canvas', eventData, handleDialogResize)
+              .on('dialogContentResize.off-canvas', eventData, debounce(bodyPadding, 100))
+              .trigger('dialogresize.off-canvas');
+
+            $element.dialog('widget').attr('data-offset-' + edge, '');
+
+            $(window)
+              .on('resize.off-canvas scroll.off-canvas', eventData, debounce(resetSize, 100))
+              .trigger('resize.off-canvas');
+          }
+        },
+        'dialog:beforecreate': function (event, dialog, $element, settings) {
+          if ($element.is('#drupal-off-canvas')) {
+            $('body').addClass('js-tray-open');
+            // @see http://api.jqueryui.com/position/
+            settings.position = {
+              my: 'left top',
+              at: edge + ' top',
+              of: window
+            };
+            settings.dialogClass += ' ui-dialog-off-canvas';
+            // Applies initial height to dialog based on window height.
+            // See http://api.jqueryui.com/dialog for all dialog options.
+            settings.height = $(window).height();
+          }
+        },
+        'dialog:beforeclose': function (event, dialog, $element) {
+          if ($element.is('#drupal-off-canvas')) {
+            $('body').removeClass('js-tray-open');
+            // Remove all *.off-canvas events
+            $(document).off('.off-canvas');
+            $(window).off('.off-canvas');
+            $mainCanvasWrapper.css('padding-' + edge, 0);
+          }
+        }
+      });
+    }
+  };
+
+})(jQuery, Drupal, Drupal.debounce, Drupal.displace);