### Eclipse Workspace Patch 1.0 #P drupal 7 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 17 May 2010 21:14:08 -0000 @@ -299,23 +299,25 @@ return { 'start': element.selectionStart, 'end': element.selectionEnd }; }; -/** - * Checks if position:fixed is supported. - * - * @return - * Boolean indicating whether or not position:fixed is supported. - * - * @see http://yura.thinkweb2.com/cft/#IS_POSITION_FIXED_SUPPORTED - */ -Drupal.positionFixedSupported = function () { - if (this._positionFixedSupported === undefined) { - var el = $('
').appendTo(document.body); - this._positionFixedSupported = el[0].offsetTop === 10; - el.remove(); - } - - return this._positionFixedSupported; -}; +if (!$.support.positionFixed) { + /** + * Checks if position:fixed is supported. + * + * @return + * Boolean indicating whether or not position:fixed is supported. + * + * @see http://yura.thinkweb2.com/cft/#IS_POSITION_FIXED_SUPPORTED + */ + $.support.positionFixed = function () { + if (this._positionFixed === undefined) { + var el = $('').appendTo(document.body); + this._positionFixed = el[0].offsetTop === 10; + el.remove(); + } + + return this._positionFixed; + }; +} /** * Build an error message from an AJAX response. 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 17 May 2010 21:14:07 -0000 @@ -13,34 +13,62 @@ * "displace-top" to that element, and to position it to the bottom of the view- * port add the class "displace-bottom". * + * To position an element absolute at the top of the viewport add beside the + * "displace-top" or "displace-bottom" also the class "displace-absolute". + * * When a browser doesn't support position:fixed (like IE6) the element gets * positioned absolutely by default, but this can be overridden by using the * "displace-unsupported" class. */ -/** - * Attaches the displace behavior. - */ Drupal.behaviors.displace = { + /** + * Attaches the displace behavior. + */ attach: function (context, settings) { // Test for position:fixed support. - if (!Drupal.positionFixedSupported()) { + if (!$.support.positionFixed()) { $(document.documentElement).addClass('displace-unsupported'); } - $(document.body).once('displace', function () { - $(window).bind('resize.drupal-displace', function () { - Drupal.displace.clearCache(); + Drupal.displace.clearCache(true); - $(document.body).css({ - paddingTop: Drupal.displace.getDisplacement('top'), - paddingBottom: Drupal.displace.getDisplacement('bottom') - }); - }); + if (Drupal.displace.getDisplacedElements('top') || Drupal.displace.getDisplacedElements('bottom')) { + var events = 'resize.drupal-displace'; + // If there are both absolute and fixed displaced elements also add + // a scroll event handler. + if (Drupal.displace.mixedDisplacement('top') || Drupal.displace.mixedDisplacement('bottom')) { + events += ' scroll.drupal-displace'; + } + $(window) + .bind(events, Drupal.displace.eventhandlerDisplaceBody) + .bind('drupalDisplaceAnchor.drupal-displace', Drupal.displace.eventhandlerDisplaceAnchor) + .bind('drupalDisplaceFocus.drupal-displace', Drupal.displace.eventhandlerDisplaceFocus); + } + // Unbind any previously bound event handlers as there are no displaced + // elements to be taken into account. + else { + $(window).unbind('.drupal-displace'); + } + + $(document.body).once('displace', function () { + // Detect when an anchor is being scrolled into view. + $(window).bind('scroll.drupal-displace-anchor', Drupal.displace.eventhandlerDetectAnchorScrolling); + // Detect when the focus is being set to an element. + $(document).bind('focusin.drupal-displace-focus', Drupal.displace.eventhandlerDetectFocusMovement); }); - Drupal.displace.clearCache(true); - $(window).triggerHandler('resize'); + $(window).triggerHandler('resize.drupal-displace'); + $(window).triggerHandler('scroll.drupal-displace-anchor'); + }, + + /** + * Detaches the displace behavior. + */ + detach: function (context, settings, trigger) { + if (trigger == 'unload' || trigger == 'move') { + Drupal.displace.clearCache(true); + } } }; @@ -50,6 +78,7 @@ Drupal.displace = Drupal.displace || {}; Drupal.displace.elements = []; +Drupal.displace.mixed = []; Drupal.displace.displacement = []; /** @@ -69,6 +98,23 @@ }; /** + * Checks whether there are both absolute and fixed displaced elements. + * + * @param region + * Region name. Either "top" or "bottom". + * + * @return + * TRUE if there are both absolute and fixed displaced elements in given + * region, FALSE otherwise. + */ +Drupal.displace.mixedDisplacement = function (region) { + if (!this.mixed[region]) { + this.mixed[region] = Drupal.displace.getDisplacedElements(region).is('.displace-absolute') && Drupal.displace.getDisplacedElements(region).is(':not(.displace-absolute)'); + } + return this.mixed[region]; +}; + +/** * Get the total displacement of given region. * * @param region @@ -81,14 +127,28 @@ if (!this.displacement[region]) { var offset = 0; var height = 0; + var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; this.getDisplacedElements(region).each(function () { offset = offset + height; height = $(this).css(region, offset).outerHeight(); + // Make sure absolute and fixed displaced elements work together. + if (Drupal.displace.mixedDisplacement(region) && $(this).hasClass('displace-absolute')) { + if (scrollTop < offset + height) { + $(this).addClass('displace-absolute-fixed'); + } + // Skip this absolute displaced element as it is outside the viewport. + else { + $(this).removeClass('displace-absolute-fixed'); + height = 0; + } + } + // 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; + height = Math.max(0, height); } }); @@ -108,8 +168,103 @@ Drupal.displace.clearCache = function (selectorCache) { if (selectorCache) { this.elements = []; + this.mixed = []; } this.displacement = []; }; +/** + * Creates an event object containing position data. + * + * @param type + * Describes the nature of the event. + * @param target + * The DOM element that initiated the event. + */ +Drupal.displace.createEvent = function (type, target) { + var event = jQuery.Event(type); + var $target = $(target); + var targetOffset = $target.offset(); + + event.target = target; + event.$target = $target; + // The amount of pixels the entire document has been scrolled. + event.pageXOffset = $(window).scrollLeft(); + event.pageYOffset = $(window).scrollTop(); + // The position of the target element relative to the document. + event.pageX = Math.round(targetOffset.left); + event.pageY = Math.round(targetOffset.top); + // The position of the target element relative to the viewport. + event.clientX = event.pageX - event.pageXOffset; + event.clientY = event.pageY - event.pageYOffset; + + return event; +}; + +/** + * Resize/scroll event handler: makes sure there is enough space for displaced + * elements at the top and bottom of the document. + */ +Drupal.displace.eventhandlerDisplaceBody = function (event) { + Drupal.displace.clearCache(); + + $(document.body).css({ + paddingTop: Drupal.displace.getDisplacement('top'), + paddingBottom: Drupal.displace.getDisplacement('bottom') + }); +}; + +/** + * DrupalDisplaceAnchor event handler: makes sure the anchor being scrolled into + * view is not hidden beneath any displaced elements. Adjusts the scrollTop if + * it does. + */ +Drupal.displace.eventhandlerDisplaceAnchor = function (event) { + window.scrollBy(0, -Drupal.displace.getDisplacement('top')); +}; + +/** + * DrupalDisplaceFocus event handler: makes sure the element being focused is + * not hidden beneath any displaced elements. Adjusts the scrollTop if it does. + */ +Drupal.displace.eventhandlerDisplaceFocus = function (event) { + if (event.clientY < Drupal.displace.getDisplacement('top')) { + window.scrollBy(0, -(Drupal.displace.getDisplacement('top') - event.clientY)); + } +}; + +/** + * Scroll event handler: detects when an anchor is being scrolled into view. + */ +Drupal.displace.eventhandlerDetectAnchorScrolling = function (event) { + if (location.hash && location.hash != '#') { + // Delay the timeout as long as events are triggered. + clearTimeout(Drupal.displace.displaceAnchorTimeout); + Drupal.displace.displaceAnchorTimeout = setTimeout(function () { + var $anchor = $(location.hash); + if ($anchor.length && Math.round($anchor.offset().top) == $(window).scrollTop()) { + $(window).trigger(Drupal.displace.createEvent('drupalDisplaceAnchor', $anchor[0])); + } + }, 100); + } +}; + +/** + * Focusin event handler: detects when the focus is being set to an element. + */ +Drupal.displace.eventhandlerDetectFocusMovement = function (event) { + if (event.target.nodeType === 1) { + // Make sure target element is not fixed positioned. + var offsetParent = $(event.target).offsetParent(); + while (offsetParent.length && offsetParent[0] !== document.body) { + if (offsetParent.css('position') == 'fixed') { + return; + } + offsetParent = $(offsetParent[0]).offsetParent(); + } + + $(window).trigger(Drupal.displace.createEvent('drupalDisplaceFocus', event.target)); + } +}; + })(jQuery); Index: modules/system/system.css =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.css,v retrieving revision 1.76 diff -u -r1.76 system.css --- modules/system/system.css 14 May 2010 07:45:54 -0000 1.76 +++ modules/system/system.css 17 May 2010 21:14:08 -0000 @@ -263,12 +263,18 @@ width: 100%; } .displace-processed .displace-top, -.displace-processed .displace-bottom { +.displace-processed .displace-bottom, +.displace-processed .displace-absolute.displace-absolute-fixed { position: fixed; + z-index: 600; width: auto; left: 0; right: 0; } +.displace-processed .displace-absolute { + position: absolute; + z-index: 500; +} .displace-unsupported .displace-top, .displace-unsupported .displace-bottom { position: absolute;