### Eclipse Workspace Patch 1.0 #P drupal 7 Index: misc/tableheader.js =================================================================== RCS file: /cvs/drupal/drupal/misc/tableheader.js,v retrieving revision 1.30 diff -u -r1.30 tableheader.js --- misc/tableheader.js 14 May 2010 07:45:53 -0000 1.30 +++ misc/tableheader.js 15 May 2010 14:54:34 -0000 @@ -1,118 +1,102 @@ // $Id: tableheader.js,v 1.30 2010/05/14 07:45:53 dries Exp $ (function ($) { -Drupal.tableHeaderDoScroll = function () { - if ($.isFunction(Drupal.tableHeaderOnScroll)) { - Drupal.tableHeaderOnScroll(); - } -}; - +/** + * Attaches sticky table headers. + */ Drupal.behaviors.tableHeader = { attach: function (context, settings) { - // This breaks in anything less than IE 7. Prevent it from running. - if ($.browser.msie && parseInt($.browser.version, 10) < 7) { + if (!Drupal.positionFixedSupported()) { return; } - $('table.sticky-enabled thead', context).once('tableheader', function () { - // Clone the table header so it inherits original jQuery properties. Hide - // the table to avoid a flash of the header clone upon page load. - var headerClone = $(this).clone(true).hide().insertBefore(this.parentNode).wrap('').parent().css({ - position: 'fixed', - top: '0px' - }); - - headerClone = $(headerClone)[0]; - - // Store parent table. - var table = $(this).parent('table')[0]; - headerClone.table = table; - // Finish initializing header positioning. - tracker(headerClone); - // We hid the header to avoid it showing up erroneously on page load; - // we need to unhide it now so that it will show up when expected. - $(headerClone).children('thead').show(); - - $(table).addClass('sticky-table'); + $('table.sticky-enabled', context).once('tableheader', function () { + $(this).data("drupal-tableheader", new Drupal.tableHeader(this)); }); + } +}; - // Define the anchor holding var. - var prevAnchor = ''; +/** + * Constructor for the tableHeader object. Provides sticky table headers. + * + * @param table + * DOM object for the table to add a sticky header to. + */ +Drupal.tableHeader = function (table) { + var self = this; + + this.originalTable = $(table); + this.originalHeader = $(table).children('thead'); + this.originalHeaderCells = this.originalHeader.find('> tr > th'); + + // Clone the table header so it inherits original jQuery properties. Hide + // the table to avoid a flash of the header clone upon page load. + this.stickyTable = $('') + .insertBefore(this.originalTable) + .css({ position: 'fixed', top: '0px' }); + this.stickyHeader = this.originalHeader.clone(true) + .hide() + .appendTo(this.stickyTable); + this.stickyHeaderCells = this.stickyHeader.find('> tr > th'); + + this.originalTable.addClass('sticky-table'); + var anchorUpdateDelay; + $(window) + .bind('scroll.drupal-tableheader', $.proxy(this, 'recalculate')) + .bind('resize.drupal-tableheader', { calculateWidth: true }, $.proxy(this, 'recalculate')) + .bind('drupalScrollToAnchor.drupal-tableheader', function () { + window.scrollBy(0, -self.stickyTable.outerHeight()); + }) + .triggerHandler('scroll.drupal-tableheader'); + + // We hid the header to avoid it showing up erroneously on page load; + // we need to unhide it now so that it will show up when expected. + this.stickyHeader.show(); +}; - // Track positioning and visibility. - function tracker(e) { - // Reset top position of sticky table headers to the current top offset. - 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; - if (e.viewHeight != viewHeight) { - e.viewHeight = viewHeight; - e.vPosition = $(e.table).offset().top - 4 - topOffset; - e.hPosition = $(e.table).offset().left; - e.vLength = e.table.clientHeight - 100; - // Resize header and its cell widths. - var parentCell = $('th', e.table); - $('th', e).each(function (index) { - var cellWidth = parentCell.eq(index).css('width'); - // Exception for IE7. - if (cellWidth == 'auto') { - cellWidth = parentCell.get(index).clientWidth + 'px'; - } - $(this).css('width', cellWidth); - }); - $(e).css('width', $(e.table).css('width')); - } +/** + * Recalculates position and visibility of the sticky table header. + * + * @param event + * Event object. + */ +Drupal.tableHeader.prototype.recalculate = function (event) { + var self = this; + var calculateWidth = event.data && event.data.calculateWidth; + + // Reset top position of sticky table headers to the current top offset. + var topOffset = Drupal.displace ? Drupal.displace.getDisplacement('top') : 0; + this.stickyTable.css('top', topOffset + 'px'); + + // Save positioning data. + var viewHeight = document.documentElement.scrollHeight || document.body.scrollHeight; + if (calculateWidth || this.viewHeight !== viewHeight) { + this.viewHeight = viewHeight; + this.vPosition = this.originalTable.offset().top - 4 - topOffset; + this.hPosition = this.originalTable.offset().left; + this.vLength = this.originalTable[0].clientHeight - 100; + calculateWidth = true; + } - // Track horizontal positioning relative to the viewport and set visibility. - var hScroll = document.documentElement.scrollLeft || document.body.scrollLeft; - var vOffset = (document.documentElement.scrollTop || document.body.scrollTop) - e.vPosition; - var visState = (vOffset > 0 && vOffset < e.vLength) ? 'visible' : 'hidden'; - $(e).css({ left: -hScroll + e.hPosition + 'px', visibility: visState }); - - // Check the previous anchor to see if we need to scroll to make room for the header. - // Get the height of the header table and scroll up that amount. - if (prevAnchor != location.hash) { - if (location.hash != '') { - var scrollLocation = $('td' + location.hash).offset().top - $(e).height(); - $('body, html').scrollTop(scrollLocation); - } - prevAnchor = location.hash; + // Track horizontal positioning relative to the viewport and set visibility. + var hScroll = document.documentElement.scrollLeft || document.body.scrollLeft; + var vOffset = (document.documentElement.scrollTop || document.body.scrollTop) - this.vPosition; + var visState = (vOffset > 0 && vOffset < this.vLength) ? 'visible' : 'hidden'; + this.stickyTable.css({ left: (-hScroll + this.hPosition) + 'px', visibility: visState }); + + // Only perform costly calculations if the sticky header is actually visible. + if (visState == 'visible' && (calculateWidth || !this.widthCalculated)) { + this.widthCalculated = true; + // Resize header and its cell widths. + this.stickyHeaderCells.each(function (index) { + var cellWidth = self.originalHeaderCells.eq(index).css('width'); + // Exception for IE7. + if (cellWidth == 'auto') { + cellWidth = self.originalHeaderCells.get(index).clientWidth + 'px'; } - } - - // Only attach to scrollbars once, even if Drupal.attachBehaviors is called - // multiple times. - $('body').once(function () { - $(window).scroll(Drupal.tableHeaderDoScroll); - $(document.documentElement).scroll(Drupal.tableHeaderDoScroll); + $(this).css('width', cellWidth); }); - - // Track scrolling. - Drupal.tableHeaderOnScroll = function () { - $('table.sticky-header').each(function () { - tracker(this); - }); - }; - - // Track resizing. - var time = null; - var resize = function () { - // Ensure minimum time between adjustments. - if (time) { - return; - } - time = setTimeout(function () { - $('table.sticky-header').each(function () { - // Force cell width calculation. - this.viewHeight = 0; - tracker(this); - }); - // Reset timer. - time = null; - }, 250); - }; - $(window).resize(resize); + this.stickyTable.css('width', this.originalTable.css('width')); } }; Index: misc/drupal.js =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.js,v retrieving revision 1.66 diff -u -r1.66 drupal.js --- misc/drupal.js 14 May 2010 16:44:37 -0000 1.66 +++ misc/drupal.js 15 May 2010 14:54:34 -0000 @@ -352,6 +352,22 @@ // Attach all behaviors. $(function () { Drupal.attachBehaviors(document, Drupal.settings); + + var scrollToAnchorDelay; + $(window) + .bind('scroll.drupal-anchor', function (event) { + if (location.hash && location.hash != '#') { + // Delay the timeout as long as events are triggered. + clearTimeout(scrollToAnchorDelay); + scrollToAnchorDelay = setTimeout(function () { + var $anchor = $(location.hash); + if ($anchor.length && Math.round($anchor.offset().top) == $(window).scrollTop()) { + $(window).trigger('drupalScrollToAnchor'); + } + }, 250); + } + }) + .triggerHandler('scroll.drupal-anchor'); }); /** Index: misc/displace.js =================================================================== RCS file: /cvs/drupal/drupal/misc/displace.js,v retrieving revision 1.2 diff -u -r1.2 displace.js --- misc/displace.js 14 May 2010 16:44:37 -0000 1.2 +++ misc/displace.js 15 May 2010 14:54:34 -0000 @@ -29,14 +29,18 @@ } $(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') + $(window) + .bind('resize.drupal-displace', function () { + Drupal.displace.clearCache(); + + $(document.body).css({ + paddingTop: Drupal.displace.getDisplacement('top'), + paddingBottom: Drupal.displace.getDisplacement('bottom') + }); + }) + .bind('drupalScrollToAnchor.drupal-displace', function () { + window.scrollBy(0, -Drupal.displace.getDisplacement('top')); }); - }); }); Drupal.displace.clearCache(true);