From fa50f04ee4d55bf6e6098d088a6de86b149dd54d Mon Sep 17 00:00:00 2001 From: Dries Buytaert Date: Fri, 14 May 2010 07:45:54 +0000 Subject: - Patch #787940 by casey: generic approach for position:fixed elements like toolbar. --- misc/displace.js | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++ misc/tableheader.js | 2 +- 2 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 misc/displace.js (limited to 'misc') diff --git a/misc/displace.js b/misc/displace.js new file mode 100644 index 000000000..6345ff2c1 --- /dev/null +++ b/misc/displace.js @@ -0,0 +1,122 @@ +// $Id$ +(function ($) { + +/** + * Provides a generic method to position elements fixed to the viewport. + * + * Fixed positioning (CSS declaration position:fixed) is done relatively to the + * viewport. This makes it hard to position multiple fixed positioned element + * relative to each other (e.g. multiple toolbars should come after each other, + * not on top of each other). + * + * To position an element fixed at the top of the viewport add the class + * "displace-top" to that element, and to position it to the bottom of the view- + * port add the class "displace-bottom". + * + * When a browser doesn't support position:fixed (like IE6) the element gets + * positioned absolutely by default, but this can be overriden by using the + * "displace-unsupported" class. + */ + +/** + * Attaches the displace behavior. + */ +Drupal.behaviors.displace = { + attach: function (context, settings) { + // Test for position:fixed support as IE6 does not. + // http://yura.thinkweb2.com/cft/#IS_POSITION_FIXED_SUPPORTED + if (this.supported === undefined) { + var el = $('
').appendTo(document.body); + this.supported = el[0].offsetTop === 10; + el.remove(); + + if (!this.supported) { + $(document.documentElement).addClass('displace-unsupported'); + } + } + + $(document.body).once('displace', function () { + $(window).bind('resize.drupal-displace', function () { + Drupal.displace.clearCache(); + + $(document.body).css({ + paddingTop: Drupal.displace.getDisplacement('top'), + paddingBottom: Drupal.displace.getDisplacement('bottom') + }); + }); + }); + + Drupal.displace.clearCache(true); + $(window).triggerHandler('resize'); + } +}; + +/** + * The displace object. + */ +Drupal.displace = Drupal.displace || {}; + +Drupal.displace.elements = []; +Drupal.displace.displacement = []; + +/** + * Get all displaced elements of given region. + * + * @param region + * Region name. Either "top" or "bottom". + * + * @return + * jQuery object containing all displaced elements of given region. + */ +Drupal.displace.getDisplacedElements = function (region) { + if (!this.elements[region]) { + this.elements[region] = $('.displace-' + region); + } + return this.elements[region]; +}; + +/** + * 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.displace.getDisplacement = function (region) { + if (!this.displacement[region]) { + var offset = 0; + var height = 0; + this.getDisplacedElements(region).each(function () { + offset = offset + height; + height = $(this).css(region, offset).outerHeight(); + + // In IE, Shadow filter adds some extra height, so we need to remove it + // from the returned height. + if (this.filters && this.filters.length && this.filters.item('DXImageTransform.Microsoft.Shadow')) { + height -= this.filters.item('DXImageTransform.Microsoft.Shadow').strength; + } + }); + + // Use offset of latest displaced element as the total displacement. + this.displacement[region] = offset + height; + } + + return this.displacement[region]; +}; + +/** + * Clear cache. + * + * @param selectorCache + * Boolean whether to also clear the selector cache. + */ +Drupal.displace.clearCache = function (selectorCache) { + if (selectorCache) { + this.elements = []; + } + this.displacement = []; +}; + +})(jQuery); diff --git a/misc/tableheader.js b/misc/tableheader.js index 4efe26a43..daae1924d 100644 --- a/misc/tableheader.js +++ b/misc/tableheader.js @@ -42,7 +42,7 @@ Drupal.behaviors.tableHeader = { // Track positioning and visibility. function tracker(e) { // Reset top position of sticky table headers to the current top offset. - var topOffset = Drupal.settings.tableHeaderOffset ? eval(Drupal.settings.tableHeaderOffset + '()') : 0; + var topOffset = Drupal.displace ? Drupal.displace.getDisplacement('top') : 0; $('.sticky-header').css('top', topOffset + 'px'); // Save positioning data. var viewHeight = document.documentElement.scrollHeight || document.body.scrollHeight; -- cgit v1.2.3