diff --git a/CHANGELOG b/CHANGELOG index 1a98cf8..66fc485 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Ensure positionedOffset properly considers "position: fixed" elements. Also ensures IE reports offsets correctly by triggering hasLayout when a "static" element has a "fixed" element as an offset parent. Closes #10644. [heygrady, kangax, Andrew Dupont] + * Roll back the fix for #9609, since it does not work in Opera. Instead, avoid using "valueOf" or "toString" as field names in forms. * Prevent DOM node expandos _countedByPrototype and _prototypeEventID from being serialized into (inner|outer)HTML in IE. Closes #10909. [dcpedit, Tobie Langel, Andrew Dupont] diff --git a/src/dom.js b/src/dom.js index e0a3c2c..2a2be6f 100644 --- a/src/dom.js +++ b/src/dom.js @@ -519,7 +519,7 @@ Element.Methods = { if (element) { if (element.tagName == 'BODY') break; var p = Element.getStyle(element, 'position'); - if (p == 'relative' || p == 'absolute') break; + if (p !== 'static') break; } } while (element); return Element._returnOffset(valueL, valueT); @@ -712,12 +712,31 @@ if (Prototype.Browser.Opera) { } else if (Prototype.Browser.IE) { - $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { + // IE doesn't report offsets correctly for static elements, so we change them + // to "relative" to get the values, then change them back. + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { Element.Methods[method] = Element.Methods[method].wrap( function(proceed, element) { element = $(element); var position = element.getStyle('position'); - if (position != 'static') return proceed(element); + if (position !== 'static') return proceed(element); + // Trigger hasLayout on the offset parent so that IE6 reports + // accurate offsetTop and offsetLeft values for position: fixed. + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); element.setStyle({ position: 'relative' }); var value = proceed(element); element.setStyle({ position: position }); @@ -725,7 +744,7 @@ else if (Prototype.Browser.IE) { } ); }); - + Element.Methods.getStyle = function(element, style) { element = $(element); style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); diff --git a/test/unit/dom.html b/test/unit/dom.html index ab64a46..e596cf8 100644 --- a/test/unit/dom.html +++ b/test/unit/dom.html @@ -367,7 +367,10 @@
testtest
XYZ
- +
+ foo + bar +
@@ -1091,13 +1094,11 @@ assert($('grand-child').descendantOf('child'), 'grand-child < child'); assert($('great-grand-child').descendantOf('child'), 'great-grand-child < child'); - window.debug = true; assert($('sibling').descendantOf('ancestor'), 'sibling < ancestor'); assert($('grand-sibling').descendantOf('sibling'), 'grand-sibling < sibling'); assert($('grand-sibling').descendantOf('ancestor'), 'grand-sibling < ancestor'); assert($('grand-sibling').descendantOf(document.body), 'grand-sibling < body'); - window.debug = false; assert(!$('great-grand-child').descendantOf('great-grand-child'), 'great-grand-child < great-grand-child'); assert(!$('great-grand-child').descendantOf('sibling'), 'great-grand-child < sibling'); @@ -1105,7 +1106,7 @@ assert(!$('great-grand-child').descendantOf('not-in-the-family'), 'great-grand-child < not-in-the-family'); assert(!$('child').descendantOf('not-in-the-family'), 'child < not-in-the-family'); - assert(!$(document.body).descendantOf('great-grand-child')); + assert(!$(document.body).descendantOf('great-grand-child')); }}, testChildOf: function() {with(this) { @@ -1604,6 +1605,12 @@ $('absolute_relative').positionedOffset()); assertEnumEqual([0,10], $('absolute_relative_undefined').positionedOffset()); + assertEnumEqual([10,10], + $('absolute_fixed_absolute').positionedOffset()); + + var afu = $('absolute_fixed_undefined'); + assertEnumEqual([afu.offsetLeft, afu.offsetTop], + afu.positionedOffset()); }}, testViewportOffset: function() {with(this) {