Issue #1847084 by jessebeach, trawekp, LewisNyman, nod_, tarekdj: Fixed Vertical toolbar doesn't work with overlay (measure/track displacing elements better + provide change events for them).
parent
57669aabf1
commit
8aedb8ba85
|
@ -0,0 +1,179 @@
|
|||
/**
|
||||
* Manages elements that can offset the size of the viewport.
|
||||
*/
|
||||
(function ($, Drupal, debounce) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var offsets = {
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers a resize hanlder on the window.
|
||||
*/
|
||||
Drupal.behaviors.drupalDisplace = {
|
||||
attach: function () {
|
||||
// Do not process the window of the overlay.
|
||||
if (parent.Drupal.overlay && parent.Drupal.overlay.iframeWindow === window) {
|
||||
return;
|
||||
}
|
||||
// Mark this behavior as processed on the first pass.
|
||||
if (this.displaceProcessed) {
|
||||
return;
|
||||
}
|
||||
this.displaceProcessed = true;
|
||||
|
||||
$(window).on('resize.drupalDisplace', debounce(displace, 200));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Informs listeners of the current offset dimensions.
|
||||
*
|
||||
* @param {boolean} broadcast
|
||||
* (optional) When true or undefined, causes the recalculated offsets values to be
|
||||
* broadcast to listeners.
|
||||
*
|
||||
* @return {object}
|
||||
* An object whose keys are the for sides an element -- top, right, bottom
|
||||
* and left. The value of each key is the viewport displacement distance for
|
||||
* that edge.
|
||||
*/
|
||||
function displace (broadcast) {
|
||||
offsets = Drupal.displace.offsets = calculateOffsets();
|
||||
if (typeof broadcast === 'undefined' || broadcast) {
|
||||
$(document).trigger('drupalViewportOffsetChange', offsets);
|
||||
}
|
||||
return offsets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the viewport offsets.
|
||||
*
|
||||
* @return {object}
|
||||
* An object whose keys are the for sides an element -- top, right, bottom
|
||||
* and left. The value of each key is the viewport displacement distance for
|
||||
* that edge.
|
||||
*/
|
||||
function calculateOffsets () {
|
||||
return {
|
||||
top: calculateOffset('top'),
|
||||
right: calculateOffset('right'),
|
||||
bottom: calculateOffset('bottom'),
|
||||
left: calculateOffset('left')
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a specific edge's offset.
|
||||
*
|
||||
* Any element with the attribute data-offset-{edge} e.g. data-offset-top will
|
||||
* be considered in the viewport offset calculations. If the attribute has a
|
||||
* numeric value, that value will be used. If no value is provided, one will
|
||||
* be calculated using the element's dimensions and placement.
|
||||
*
|
||||
* @param {string} edge
|
||||
* The name of the edge to calculate. Can be 'top', 'right',
|
||||
* 'bottom' or 'left'.
|
||||
*
|
||||
* @return {number}
|
||||
* The viewport displacement distance for the requested edge.
|
||||
*/
|
||||
function calculateOffset (edge) {
|
||||
var edgeOffset = 0;
|
||||
var displacingElements = document.querySelectorAll('[data-offset-' + edge + ']');
|
||||
for (var i = 0, n = displacingElements.length; i < n; i++) {
|
||||
var el = displacingElements[i];
|
||||
// If the element is not visble, do consider its dimensions.
|
||||
if (el.style.display === 'none') {
|
||||
continue;
|
||||
}
|
||||
// If the offset data attribute contains a displacing value, use it.
|
||||
var displacement = parseInt(el.getAttribute('data-offset-' + edge), 10);
|
||||
// If the element's offset data attribute exits
|
||||
// but is not a valid number then get the displacement
|
||||
// dimensions directly from the element.
|
||||
if (isNaN(displacement)) {
|
||||
displacement = getRawOffset(el, edge);
|
||||
}
|
||||
// If the displacement value is larger than the current value for this
|
||||
// edge, use the displacement value.
|
||||
edgeOffset = Math.max(edgeOffset, displacement);
|
||||
}
|
||||
|
||||
return edgeOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates displacement for element based on its dimensions and placement.
|
||||
*
|
||||
* @param {jQuery} $el
|
||||
* The jQuery element whose dimensions and placement will be measured.
|
||||
*
|
||||
* @param {string} edge
|
||||
* The name of the edge of the viewport that the element is associated
|
||||
* with.
|
||||
*
|
||||
* @return {number}
|
||||
* The viewport displacement distance for the requested edge.
|
||||
*/
|
||||
function getRawOffset (el, edge) {
|
||||
var $el = $(el);
|
||||
var documentElement = document.documentElement;
|
||||
var displacement = 0;
|
||||
var horizontal = (edge === 'left' || edge === 'right');
|
||||
// Get the offset of the element itself.
|
||||
var placement = $el.offset()[ horizontal ? 'left' : 'top'];
|
||||
// Subtract scroll distance from placement to get the distance
|
||||
// to the edge of the viewport.
|
||||
placement -= window['scroll' + (horizontal ? 'X' : 'Y')] || document.documentElement['scroll' + (horizontal) ? 'Left' : 'Top'] || 0;
|
||||
// Find the displacement value according to the edge.
|
||||
switch (edge) {
|
||||
// Left and top elements displace as a sum of their own offset value
|
||||
// plus their size.
|
||||
case 'top':
|
||||
// Total displacment is the sum of the elements placement and size.
|
||||
displacement = placement + $el.outerHeight();
|
||||
break;
|
||||
|
||||
case 'left':
|
||||
// Total displacment is the sum of the elements placement and size.
|
||||
displacement = placement + $el.outerWidth();
|
||||
break;
|
||||
|
||||
// Right and bottom elements displace according to their left and
|
||||
// top offset. Their size isn't important.
|
||||
case 'bottom':
|
||||
displacement = documentElement.clientHeight - placement;
|
||||
break;
|
||||
|
||||
case 'right':
|
||||
displacement = documentElement.clientWidth - placement;
|
||||
break;
|
||||
|
||||
default:
|
||||
displacement = 0;
|
||||
}
|
||||
return displacement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign the displace function to a property of the Drupal global object.
|
||||
*/
|
||||
Drupal.displace = displace;
|
||||
$.extend(Drupal.displace, {
|
||||
/**
|
||||
* Expose offsets to other scripts to avoid having to recalculate offsets
|
||||
*/
|
||||
offsets: offsets,
|
||||
/**
|
||||
* Expose method to compute a single edge offsets.
|
||||
*/
|
||||
calculateOffset: calculateOffset
|
||||
});
|
||||
|
||||
})(jQuery, Drupal, Drupal.debounce);
|
|
@ -1,4 +1,4 @@
|
|||
(function ($, Drupal) {
|
||||
(function ($, Drupal, displace) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
@ -39,16 +39,14 @@ function tableHeaderOnScrollHandler(e) {
|
|||
forTables('onScroll');
|
||||
}
|
||||
|
||||
function tableHeaderOffsetChangeHandler(e) {
|
||||
// Compute the new offset value.
|
||||
TableHeader.computeOffsetTop();
|
||||
forTables('stickyPosition', TableHeader.offsetTop);
|
||||
function tableHeaderOffsetChangeHandler(e, offsets) {
|
||||
forTables('stickyPosition', offsets.top);
|
||||
}
|
||||
|
||||
// Bind event that need to change all tables.
|
||||
$(window).on({
|
||||
/**
|
||||
* When resizing table width and offset top can change, recalculate everything.
|
||||
* When resizing table width can change, recalculate everything.
|
||||
*/
|
||||
'resize.TableHeader': tableHeaderResizeHandler,
|
||||
|
||||
|
@ -66,9 +64,9 @@ $(document).on({
|
|||
'columnschange.TableHeader': tableHeaderResizeHandler,
|
||||
|
||||
/**
|
||||
* Offset value vas changed by a third party script.
|
||||
* Recalculate TableHeader.topOffset when viewport is resized
|
||||
*/
|
||||
'offsettopchange.TableHeader': tableHeaderOffsetChangeHandler
|
||||
'drupalViewportOffsetChange.TableHeader': tableHeaderOffsetChangeHandler
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -77,9 +75,6 @@ $(document).on({
|
|||
* TableHeader will make the current table header stick to the top of the page
|
||||
* if the table is very long.
|
||||
*
|
||||
* Fire a custom "topoffsetchange" event to make TableHeader compute the
|
||||
* new offset value from the "data-offset-top" attributes of relevant elements.
|
||||
*
|
||||
* @param table
|
||||
* DOM object for the table to add a sticky header to.
|
||||
*
|
||||
|
@ -119,28 +114,7 @@ $.extend(TableHeader, {
|
|||
*
|
||||
* @type {Array}
|
||||
*/
|
||||
tables: [],
|
||||
|
||||
/**
|
||||
* Cache of computed offset value.
|
||||
*
|
||||
* @type {Number}
|
||||
*/
|
||||
offsetTop: 0,
|
||||
|
||||
/**
|
||||
* Sum all [data-offset-top] values and cache it.
|
||||
*/
|
||||
computeOffsetTop: function () {
|
||||
var $offsets = $('[data-offset-top]');
|
||||
var value, sum = 0;
|
||||
for (var i = 0, il = $offsets.length; i < il; i++) {
|
||||
value = parseInt($offsets[i].getAttribute('data-offset-top'), 10);
|
||||
sum += !isNaN(value) ? value : 0;
|
||||
}
|
||||
this.offsetTop = sum;
|
||||
return sum;
|
||||
}
|
||||
tables: []
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -211,7 +185,7 @@ $.extend(TableHeader.prototype, {
|
|||
*/
|
||||
checkStickyVisible: function () {
|
||||
var scrollTop = scrollValue('scrollTop');
|
||||
var tableTop = this.tableOffset.top - TableHeader.offsetTop;
|
||||
var tableTop = this.tableOffset.top - displace.offsets.top;
|
||||
var tableBottom = tableTop + this.tableHeight;
|
||||
var visible = false;
|
||||
|
||||
|
@ -248,9 +222,9 @@ $.extend(TableHeader.prototype, {
|
|||
this.tableHeight = this.$originalTable[0].clientHeight;
|
||||
|
||||
// Update offset top.
|
||||
TableHeader.computeOffsetTop();
|
||||
displace.offsets.top = displace.calculateOffset('top');
|
||||
this.tableOffset = this.$originalTable.offset();
|
||||
this.stickyPosition(TableHeader.offsetTop);
|
||||
this.stickyPosition(displace.offsets.top, scrollValue('scrollLeft'));
|
||||
|
||||
// Update columns width.
|
||||
var $that = null;
|
||||
|
@ -277,4 +251,4 @@ $.extend(TableHeader.prototype, {
|
|||
// Expose constructor in the public space.
|
||||
Drupal.TableHeader = TableHeader;
|
||||
|
||||
}(jQuery, Drupal));
|
||||
}(jQuery, Drupal, window.parent.Drupal.displace));
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* RTL styling for Overlay child pages.
|
||||
|
@ -12,26 +11,13 @@ html {
|
|||
float: right;
|
||||
left: auto;
|
||||
}
|
||||
#overlay {
|
||||
padding: 0.2em;
|
||||
padding-left: 26px;
|
||||
}
|
||||
#overlay-close-wrapper {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
#overlay-close,
|
||||
#overlay-close:hover {
|
||||
background: transparent url(images/close.png) no-repeat;
|
||||
border-top-right-radius: 0;
|
||||
|
||||
-webkit-border-top-left-radius: 12px;
|
||||
-webkit-border-bottom-left-radius: 12px;
|
||||
-moz-border-radius-topleft: 12px;
|
||||
-moz-border-radius-bottomleft: 12px;
|
||||
border-top-left-radius: 12px;
|
||||
border-bottom-left-radius: 12px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Basic styling for the Overlay child pages.
|
||||
|
@ -16,15 +15,15 @@
|
|||
}
|
||||
|
||||
#overlay {
|
||||
display: table;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 80em;
|
||||
max-width: 80rem;
|
||||
min-height: 100px;
|
||||
min-width: 700px;
|
||||
position: relative;
|
||||
padding: .2em;
|
||||
padding-bottom: 2em;
|
||||
padding-right: 26px; /* LTR */
|
||||
width: 88%;
|
||||
padding: 2em 40px;
|
||||
width: 100%;
|
||||
}
|
||||
#overlay-titlebar {
|
||||
padding: 0 20px;
|
||||
|
@ -68,8 +67,8 @@
|
|||
}
|
||||
#overlay-close,
|
||||
#overlay-close:hover {
|
||||
background: transparent url(images/close.png) no-repeat; /* LTR */
|
||||
border-top-left-radius: 0; /* LTR */
|
||||
background: #ffffff url(images/close.png) no-repeat;
|
||||
border-radius: 0 12px 12px 0; /* LTR */
|
||||
display: block;
|
||||
height: 26px;
|
||||
margin: 0;
|
||||
|
@ -77,14 +76,6 @@
|
|||
/* Replace with position:fixed to get a scrolling close button. */
|
||||
position: absolute;
|
||||
width: 26px;
|
||||
|
||||
-webkit-border-top-right-radius: 12px;
|
||||
-webkit-border-bottom-right-radius: 12px;
|
||||
-moz-border-radius-topright: 12px;
|
||||
-moz-border-radius-bottomright: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
border-bottom-right-radius: 12px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -179,11 +179,13 @@ Drupal.overlayChild.behaviors.shortcutAddLink = function (context, settings) {
|
|||
});
|
||||
};
|
||||
|
||||
// Workaround because of the way jQuery events works.
|
||||
// jQuery from the parent frame needs to be used to catch this event.
|
||||
parent.jQuery(document).bind('offsettopchange', function () {
|
||||
// Fires an event that the child iframe can listen to.
|
||||
$(document).trigger('offsettopchange');
|
||||
});
|
||||
Drupal.overlayChild.behaviors.bindDrupalViewportOffsetChangeEvent = function (context, settings) {
|
||||
// Workaround because of the way jQuery events works.
|
||||
// jQuery from the parent frame needs to be used to catch this event.
|
||||
parent.jQuery(parent.document).on('drupalViewportOffsetChange', function (event, offsets) {
|
||||
// Fires an event that the child iframe can listen to.
|
||||
$(document).trigger('drupalViewportOffsetChange', offsets);
|
||||
});
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Attaches the behaviors for the Overlay parent pages.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
(function ($, Drupal, displace) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
@ -106,6 +106,10 @@ Drupal.overlay.open = function (url) {
|
|||
* Create the underlying markup and behaviors for the overlay.
|
||||
*/
|
||||
Drupal.overlay.create = function () {
|
||||
// Update offsets values on the page.
|
||||
displace(false);
|
||||
|
||||
// Build the overlay container.
|
||||
this.$container = $(Drupal.theme('overlayContainer'))
|
||||
.appendTo(document.body);
|
||||
|
||||
|
@ -131,6 +135,7 @@ Drupal.overlay.create = function () {
|
|||
$(window)
|
||||
.bind('resize' + eventClass, $.proxy(this, 'eventhandlerOuterResize'));
|
||||
$(document)
|
||||
.bind('drupalViewportOffsetChange' + eventClass, $.proxy(this, 'eventhandlerViewportOffsetChange'))
|
||||
.bind('drupalOverlayLoad' + eventClass, $.proxy(this, 'eventhandlerOuterResize'))
|
||||
.bind('drupalOverlayReady' + eventClass +
|
||||
' drupalOverlayClose' + eventClass, $.proxy(this, 'eventhandlerSyncURLFragment'))
|
||||
|
@ -139,11 +144,9 @@ Drupal.overlay.create = function () {
|
|||
' drupalOverlayBeforeLoad' + eventClass +
|
||||
' drupalOverlayResize' + eventClass, $.proxy(this, 'eventhandlerDispatchEvent'));
|
||||
|
||||
if ($('.overlay-displace-top, .overlay-displace-bottom').length) {
|
||||
$(document)
|
||||
.bind('drupalOverlayResize' + eventClass, $.proxy(this, 'eventhandlerAlterDisplacedElements'))
|
||||
.bind('drupalOverlayClose' + eventClass, $.proxy(this, 'eventhandlerRestoreDisplacedElements'));
|
||||
}
|
||||
$(document)
|
||||
.bind('drupalOverlayResize' + eventClass, $.proxy(this, 'eventhandlerAlterDisplacedElements'))
|
||||
.bind('drupalOverlayClose' + eventClass, $.proxy(this, 'eventhandlerRestoreDisplacedElements'));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -397,6 +400,22 @@ Drupal.overlay.isExternalLink = function (url) {
|
|||
return re.test(url);
|
||||
};
|
||||
|
||||
/**
|
||||
* Responds to the drupalViewportOffsetChange event.
|
||||
*
|
||||
* @param object event
|
||||
* A jQuery event object.
|
||||
*
|
||||
* @param object offsets
|
||||
* An object whose keys are the for sides an element -- top, right, bottom
|
||||
* and left. The value of each key is the viewport displacement distance for
|
||||
* that edge.
|
||||
*/
|
||||
Drupal.overlay.eventhandlerViewportOffsetChange = function (event, offsets) {
|
||||
// Allow other scripts to respond to this event.
|
||||
$(document).trigger('drupalOverlayResize');
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler: resizes overlay according to the size of the parent window.
|
||||
*
|
||||
|
@ -435,78 +454,29 @@ Drupal.overlay.eventhandlerAlterDisplacedElements = function (event) {
|
|||
return;
|
||||
}
|
||||
|
||||
$(this.iframeWindow.document.body).css({
|
||||
marginTop: Drupal.overlay.getDisplacement('top'),
|
||||
marginBottom: Drupal.overlay.getDisplacement('bottom')
|
||||
}).attr('data-offset-top', Drupal.overlay.getDisplacement('top'));
|
||||
var offsets = displace.offsets;
|
||||
|
||||
$(document).bind('offsettopchange', function () {
|
||||
var iframeDocument = Drupal.overlay.iframeWindow.document;
|
||||
$(iframeDocument.body).attr('data-offset-top', Drupal.overlay.getDisplacement('top'));
|
||||
$(iframeDocument).trigger('offsettopchange');
|
||||
// Move the body of the iframe contentDocument inward a sufficient distance
|
||||
// to prevent it from appearing underneath displacing elements like the
|
||||
// toolbar.
|
||||
var iframeBody = this.iframeWindow.document.body;
|
||||
$(iframeBody).css({
|
||||
'padding-top': offsets.top,
|
||||
'padding-right': offsets.right,
|
||||
'padding-bottom': offsets.bottom,
|
||||
'padding-left': offsets.left
|
||||
});
|
||||
// Trigger a repaint.
|
||||
iframeBody.style.display = 'none';
|
||||
var _tmp = iframeBody.offsetHeight;
|
||||
iframeBody.style.display = 'block';
|
||||
|
||||
var documentHeight = this.iframeWindow.document.body.clientHeight;
|
||||
var documentWidth = this.iframeWindow.document.body.clientWidth;
|
||||
// IE6 doesn't support maxWidth, use width instead.
|
||||
var maxWidthName = 'maxWidth';
|
||||
|
||||
if (Drupal.overlay.leftSidedScrollbarOffset === undefined && $(document.documentElement).attr('dir') === 'rtl') {
|
||||
// We can't use element.clientLeft to detect whether scrollbars are placed
|
||||
// on the left side of the element when direction is set to "rtl" as most
|
||||
// browsers dont't support it correctly.
|
||||
// http://www.gtalbot.org/BugzillaSection/DocumentAllDHTMLproperties.html
|
||||
// There seems to be absolutely no way to detect whether the scrollbar
|
||||
// is on the left side in Opera; always expect scrollbar to be on the left.
|
||||
if ($.browser.opera) {
|
||||
Drupal.overlay.leftSidedScrollbarOffset = document.documentElement.clientWidth - this.iframeWindow.document.documentElement.clientWidth + this.iframeWindow.document.documentElement.clientLeft;
|
||||
}
|
||||
else if (this.iframeWindow.document.documentElement.clientLeft) {
|
||||
Drupal.overlay.leftSidedScrollbarOffset = this.iframeWindow.document.documentElement.clientLeft;
|
||||
}
|
||||
else {
|
||||
var el1 = $('<div style="direction: rtl; overflow: scroll;"></div>').appendTo(document.body);
|
||||
var el2 = $('<div></div>').appendTo(el1);
|
||||
Drupal.overlay.leftSidedScrollbarOffset = parseInt(el2[0].offsetLeft - el1[0].offsetLeft, 10);
|
||||
el1.remove();
|
||||
}
|
||||
// Constrain the width of offsetting top and bottom elements, such as the
|
||||
// toolbar, so that a scroll in the overlay iframe won't be occluded.
|
||||
var iframeBodyWidth = iframeBody.clientWidth;
|
||||
if (iframeBodyWidth > 0 && iframeBodyWidth < document.documentElement.clientWidth) {
|
||||
$('[data-offset-top], [data-offset-bottom]').css('max-width', iframeBodyWidth);
|
||||
}
|
||||
|
||||
// Consider any element that should be visible above the overlay (such as
|
||||
// a toolbar).
|
||||
$('.overlay-displace-top, .overlay-displace-bottom').each(function () {
|
||||
var data = $(this).data();
|
||||
var maxWidth = documentWidth;
|
||||
// In IE, Shadow filter makes element to overlap the scrollbar with 1px.
|
||||
if (this.filters && this.filters.length && this.filters.item('DXImageTransform.Microsoft.Shadow')) {
|
||||
maxWidth -= 1;
|
||||
}
|
||||
|
||||
if (Drupal.overlay.leftSidedScrollbarOffset) {
|
||||
$(this).css('left', Drupal.overlay.leftSidedScrollbarOffset);
|
||||
}
|
||||
|
||||
// Prevent displaced elements overlapping window's scrollbar.
|
||||
var currentMaxWidth = parseInt($(this).css(maxWidthName), 10);
|
||||
if ((data.drupalOverlay && data.drupalOverlay.maxWidth) || isNaN(currentMaxWidth) || currentMaxWidth > maxWidth || currentMaxWidth <= 0) {
|
||||
$(this).css(maxWidthName, maxWidth);
|
||||
(data.drupalOverlay = data.drupalOverlay || {}).maxWidth = true;
|
||||
}
|
||||
|
||||
// Use a more rigorous approach if the displaced element still overlaps
|
||||
// window's scrollbar; clip the element on the right.
|
||||
var offset = $(this).offset();
|
||||
var offsetRight = offset.left + $(this).outerWidth();
|
||||
if ((data.drupalOverlay && data.drupalOverlay.clip) || offsetRight > maxWidth) {
|
||||
if (Drupal.overlay.leftSidedScrollbarOffset) {
|
||||
$(this).css('clip', 'rect(auto, auto, ' + (documentHeight - offset.top) + 'px, ' + (Drupal.overlay.leftSidedScrollbarOffset + 2) + 'px)');
|
||||
}
|
||||
else {
|
||||
$(this).css('clip', 'rect(auto, ' + (maxWidth - offset.left) + 'px, ' + (documentHeight - offset.top) + 'px, auto)');
|
||||
}
|
||||
(data.drupalOverlay = data.drupalOverlay || {}).clip = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -519,16 +489,7 @@ Drupal.overlay.eventhandlerAlterDisplacedElements = function (event) {
|
|||
* - event.currentTarget: any
|
||||
*/
|
||||
Drupal.overlay.eventhandlerRestoreDisplacedElements = function (event) {
|
||||
var $displacedElements = $('.overlay-displace-top, .overlay-displace-bottom');
|
||||
try {
|
||||
$displacedElements.css({ maxWidth: '', clip: '' });
|
||||
}
|
||||
// IE bug that doesn't allow unsetting style.clip (http://dev.jquery.com/ticket/6512).
|
||||
catch (err) {
|
||||
$displacedElements.attr('style', function (index, attr) {
|
||||
return attr.replace(/clip\s*:\s*rect\([^)]+\);?/i, '');
|
||||
});
|
||||
}
|
||||
$('[data-offset-top], [data-offset-bottom]').css('max-width', 'none');
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -828,7 +789,7 @@ Drupal.overlay.resetActiveClass = function(activePath) {
|
|||
var self = this;
|
||||
var windowDomain = window.location.protocol + window.location.hostname;
|
||||
|
||||
$('.overlay-displace-top, .overlay-displace-bottom')
|
||||
$('#toolbar-administration')
|
||||
.find('a[href]')
|
||||
// Remove active class from all links in displaced elements.
|
||||
.removeClass('active')
|
||||
|
@ -870,24 +831,6 @@ Drupal.overlay.getPath = function (link) {
|
|||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the total displacement of given region.
|
||||
*
|
||||
* @param region
|
||||
* Region name. Either "top" or "bottom".
|
||||
*
|
||||
* @return
|
||||
* The total displacement of given region in pixels.
|
||||
*/
|
||||
Drupal.overlay.getDisplacement = function (region) {
|
||||
var displacement = 0;
|
||||
var lastDisplaced = $('[data-offset-' + region + ']');
|
||||
if (lastDisplaced.length) {
|
||||
displacement = parseInt(lastDisplaced.attr('data-offset-' + region));
|
||||
}
|
||||
return displacement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes elements outside the overlay unreachable via the tab key.
|
||||
*
|
||||
|
@ -916,7 +859,7 @@ Drupal.overlay.makeDocumentUntabbable = function (context) {
|
|||
// If another element (like a div) has a tabindex, it's also tabbable.
|
||||
$tabbable = $tabbable.add($hasTabindex);
|
||||
// Leave links inside the overlay and toolbars alone.
|
||||
$overlay = $('.overlay-element, #overlay-container, .overlay-displace-top, .overlay-displace-bottom').find('*');
|
||||
$overlay = $('.overlay-element, #overlay-container, #toolbar-administration').find('*');
|
||||
$tabbable = $tabbable.not($overlay);
|
||||
// We now have a list of everything in the underlying document that could
|
||||
// possibly be reachable via the tab key. Make it all unreachable.
|
||||
|
@ -982,4 +925,4 @@ $.extend(Drupal.theme, {
|
|||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
})(jQuery, Drupal, Drupal.displace);
|
||||
|
|
|
@ -225,6 +225,7 @@ function overlay_library_info() {
|
|||
array('system', 'jquery'),
|
||||
array('system', 'drupal'),
|
||||
array('system', 'drupalSettings'),
|
||||
array('system', 'drupal.displace'),
|
||||
array('system', 'jquery.ui.core'),
|
||||
array('system', 'jquery.bbq'),
|
||||
),
|
||||
|
|
|
@ -1399,6 +1399,22 @@ function system_library_info() {
|
|||
),
|
||||
);
|
||||
|
||||
// A utility that measures and reports viewport offset dimensions from
|
||||
// elements like the toolbar that can potentially displace the positioning of
|
||||
// elements like the overlay.
|
||||
$libraries['drupal.displace'] = array(
|
||||
'title' => 'Drupal displace',
|
||||
'version' => VERSION,
|
||||
'js' => array(
|
||||
'core/misc/displace.js' => array('group' => JS_LIBRARY),
|
||||
),
|
||||
'dependencies' => array(
|
||||
array('system', 'jquery'),
|
||||
array('system', 'drupal'),
|
||||
array('system', 'drupal.debounce'),
|
||||
),
|
||||
);
|
||||
|
||||
// A utility function to limit calls to a function with a given time.
|
||||
$libraries['drupal.debounce'] = array(
|
||||
'title' => 'Drupal debounce',
|
||||
|
@ -2095,6 +2111,7 @@ function system_library_info() {
|
|||
array('system', 'drupal'),
|
||||
array('system', 'drupalSettings'),
|
||||
array('system', 'jquery.once'),
|
||||
array('system', 'drupal.displace'),
|
||||
),
|
||||
);
|
||||
$libraries['drupal.timezone'] = array(
|
||||
|
|
|
@ -91,7 +91,7 @@ html.js .toolbar {
|
|||
position: absolute;
|
||||
}
|
||||
.toolbar .tray {
|
||||
z-index: 250;
|
||||
z-index: 1200;
|
||||
}
|
||||
.toolbar .horizontal {
|
||||
width: 100%;
|
||||
|
|
|
@ -2,9 +2,18 @@
|
|||
* @file toolbar.theme-rtl.css
|
||||
*/
|
||||
|
||||
/**
|
||||
* Toolbar bar.
|
||||
*/
|
||||
.toolbar .bar {
|
||||
box-shadow: 1px 0 3px 1px rgba(0, 0, 0, 0.3333);
|
||||
}
|
||||
/**
|
||||
* Toolbar tray.
|
||||
*/
|
||||
.toolbar .horizontal {
|
||||
box-shadow: 2px 1px 3px 1px rgba(0, 0, 0, 0.3333);
|
||||
}
|
||||
.toolbar .horizontal > .lining {
|
||||
padding-right: 0;
|
||||
padding-left: 5em;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
*/
|
||||
.toolbar .bar {
|
||||
background-color: #0f0f0f;
|
||||
box-shadow: 0 0 3px 1px rgba(0, 0, 0, 0.3333);
|
||||
box-shadow: -1px 0 3px 1px rgba(0, 0, 0, 0.3333); /* LTR */
|
||||
color: #dddddd;
|
||||
}
|
||||
.toolbar .bar a {
|
||||
|
@ -66,7 +66,7 @@
|
|||
}
|
||||
.toolbar .horizontal {
|
||||
border-bottom: 1px solid #aaaaaa;
|
||||
box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.3333);
|
||||
box-shadow: -2px 1px 3px 1px rgba(0, 0, 0, 0.3333); /* LTR */
|
||||
}
|
||||
.toolbar .horizontal .tray {
|
||||
background-color: #f5f5f5;
|
||||
|
|
|
@ -81,12 +81,9 @@ Drupal.behaviors.toolbar = {
|
|||
changeOrientation((locked) ? 'vertical' : ((mql.wide.matches) ? 'horizontal' : 'vertical'), locked);
|
||||
// Render the main menu as a nested, collapsible accordion.
|
||||
$toolbar.find('.toolbar-menu-administration > .menu').toolbarMenu();
|
||||
// Call setHeight on screen resize. Wrap it in debounce to prevent
|
||||
// setHeight from being called too frequently.
|
||||
var setHeight = Drupal.debounce(Drupal.toolbar.setHeight, 200);
|
||||
// Attach behavior to the window.
|
||||
$(window)
|
||||
.on('resize.toolbar', setHeight);
|
||||
// Attach behaviors to the document.
|
||||
$(document)
|
||||
.on('drupalViewportOffsetChange.toolbar', Drupal.toolbar.adjustPlacement);
|
||||
// Attach behaviors to the toolbar.
|
||||
$toolbar
|
||||
.on('click.toolbar', '.bar a', Drupal.toolbar.toggleTray)
|
||||
|
@ -99,6 +96,8 @@ Drupal.behaviors.toolbar = {
|
|||
// Update the page and toolbar dimension indicators.
|
||||
updatePeripherals();
|
||||
}
|
||||
// Call displace to get the initial placement of offset elements.
|
||||
Drupal.displace();
|
||||
}
|
||||
},
|
||||
// Default options.
|
||||
|
@ -158,18 +157,22 @@ Drupal.toolbar.toggleTray = function (event) {
|
|||
// Set aria-pressed to false.
|
||||
.attr('aria-pressed', 'false');
|
||||
$toolbar.find('.tray').not($activateTray).removeClass('active');
|
||||
// Update the page and toolbar dimension indicators.
|
||||
updatePeripherals();
|
||||
}
|
||||
// Update the page and toolbar dimension indicators.
|
||||
updatePeripherals();
|
||||
};
|
||||
|
||||
/**
|
||||
* The height of the toolbar offsets the top of the page content.
|
||||
* Repositions trays and sets body padding according to the height of the bar.
|
||||
*
|
||||
* Page components can register with the offsettopchange event to know when
|
||||
* the height of the toolbar changes.
|
||||
* @param {Event} event
|
||||
* - jQuery Event object.
|
||||
*
|
||||
* @param {Object} offsets
|
||||
* - Contains for keys -- top, right, bottom and left -- that indicate the
|
||||
* viewport offset distances calculated by Drupal.displace().
|
||||
*/
|
||||
Drupal.toolbar.setHeight = function () {
|
||||
Drupal.toolbar.adjustPlacement = function (event, offsets) {
|
||||
// Set the top of the all the trays to the height of the bar.
|
||||
var barHeight = $toolbar.find('.bar').outerHeight();
|
||||
var height = barHeight;
|
||||
|
@ -181,20 +184,27 @@ Drupal.toolbar.setHeight = function () {
|
|||
tray.style.top = bhpx;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the height of the active tray and include it in the total
|
||||
* height of the toolbar.
|
||||
*/
|
||||
height += $trays.filter('.active.horizontal').outerHeight() || 0;
|
||||
// Indicate the height of the toolbar in the attribute data-offset-top.
|
||||
var offset = parseInt($toolbar.attr('data-offset-top'), 10);
|
||||
if (offset !== height) {
|
||||
$toolbar.attr('data-offset-top', height);
|
||||
// Alter the padding on the top of the body element.
|
||||
$('body').css('padding-top', height);
|
||||
$(document).trigger('offsettopchange', height);
|
||||
$(window).trigger('resize');
|
||||
}
|
||||
// Alter the padding on the top of the body element.
|
||||
$('body').css('padding-top', offsets.top);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the width of a vertical tray in a data attribute.
|
||||
*
|
||||
* If the width of the tray changed, Drupal.displace is called so that elements
|
||||
* can adjust to the placement of the tray.
|
||||
*/
|
||||
Drupal.toolbar.setTrayWidth = function () {
|
||||
var dir = document.documentElement.dir;
|
||||
var edge = (dir === 'rtl') ? 'right' : 'left';
|
||||
// Remove the left offset from the trays.
|
||||
$toolbar.find('.tray').removeAttr('data-offset-' + edge + ' data-offset-top');
|
||||
// If an active vertical tray exists, mark it as an offset element.
|
||||
$toolbar.find('.tray.vertical.active').attr('data-offset-' + edge, '');
|
||||
// If an active horizontal tray exists, mark it as an offset element.
|
||||
$toolbar.find('.tray.horizontal.active').attr('data-offset-top', '');
|
||||
// Trigger a recalculation of viewport displacing elements.
|
||||
Drupal.displace();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -294,8 +304,8 @@ function toggleOrientationToggle (orientation) {
|
|||
function updatePeripherals () {
|
||||
// Adjust the body to accommodate trays.
|
||||
setBodyState();
|
||||
// Adjust the height of the toolbar.
|
||||
Drupal.toolbar.setHeight();
|
||||
// Adjust the tray width for vertical trays.
|
||||
Drupal.toolbar.setTrayWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -93,7 +93,7 @@ function toolbar_element_info() {
|
|||
'id' => 'toolbar-administration',
|
||||
// The 'overlay-displace-top' class pushes the overlay down, so it appears
|
||||
// below the toolbar.
|
||||
'class' => array('toolbar', 'overlay-displace-top'),
|
||||
'class' => array('toolbar',),
|
||||
'role' => 'navigation',
|
||||
),
|
||||
// Metadata for the administration bar.
|
||||
|
@ -101,7 +101,8 @@ function toolbar_element_info() {
|
|||
'#heading' => t('Toolbar items'),
|
||||
'#attributes' => array(
|
||||
'id' => 'toolbar-bar',
|
||||
'class' => array('bar', 'overlay-displace-top', 'clearfix'),
|
||||
'class' => array('bar', 'clearfix',),
|
||||
'data-offset-top' => array(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -315,7 +316,6 @@ function toolbar_pre_render_item($element) {
|
|||
}
|
||||
$element['tray']['#wrapper_attributes'] += $attributes;
|
||||
$element['tray']['#wrapper_attributes']['class'][] = 'tray';
|
||||
$element['tray']['#wrapper_attributes']['class'][] = 'overlay-displace-top';
|
||||
|
||||
if (!isset($element['tray']['#theme_wrappers'])) {
|
||||
$element['tray']['#theme_wrappers'] = array();
|
||||
|
@ -631,6 +631,7 @@ function toolbar_library_info() {
|
|||
array('system', 'matchmedia'),
|
||||
array('system', 'jquery.once'),
|
||||
array('system', 'drupal.debounce'),
|
||||
array('system', 'drupal.displace'),
|
||||
array('toolbar', 'toolbar.menu'),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1622,7 +1622,7 @@ div.admin-panel .description {
|
|||
/**
|
||||
* Responsive tables.
|
||||
*/
|
||||
@media screen and (max-width:28.125em) { /* 450px */
|
||||
@media screen and (max-width: 37.5em) { /* 600px */
|
||||
th.priority-low,
|
||||
td.priority-low,
|
||||
th.priority-medium,
|
||||
|
@ -1630,7 +1630,7 @@ div.admin-panel .description {
|
|||
display: none;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width:45em) { /* 720px */
|
||||
@media screen and (max-width: 60em) { /* 920px */
|
||||
th.priority-low,
|
||||
td.priority-low {
|
||||
display: none;
|
||||
|
|
|
@ -522,7 +522,7 @@ table.system-status-report tr.error {
|
|||
/**
|
||||
* Responsive tables.
|
||||
*/
|
||||
@media screen and (max-width:28.125em) { /* 450px */
|
||||
@media screen and (max-width: 37.5em) { /* 600px */
|
||||
th.priority-low,
|
||||
td.priority-low,
|
||||
th.priority-medium,
|
||||
|
@ -530,7 +530,7 @@ table.system-status-report tr.error {
|
|||
display: none;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width:45em) { /* 720px */
|
||||
@media screen and (max-width: 60em) { /* 920px */
|
||||
th.priority-low,
|
||||
td.priority-low {
|
||||
display: none;
|
||||
|
|
Loading…
Reference in New Issue