Bug 886646 - Part 3: Compute sticky positioning offsets for getComputedStyle(). r=heycam

This commit is contained in:
Corey Ford 2013-08-15 17:31:32 -07:00
parent a6ff6cfd81
commit 7850f5f462
5 changed files with 212 additions and 0 deletions

View File

@ -3708,6 +3708,8 @@ nsComputedDOMStyle::GetOffsetWidthFor(mozilla::css::Side aSide)
return GetStaticOffset(aSide);
case NS_STYLE_POSITION_RELATIVE:
return GetRelativeOffset(aSide);
case NS_STYLE_POSITION_STICKY:
return GetStickyOffset(aSide);
case NS_STYLE_POSITION_ABSOLUTE:
case NS_STYLE_POSITION_FIXED:
return GetAbsoluteOffset(aSide);
@ -3808,6 +3810,36 @@ nsComputedDOMStyle::GetRelativeOffset(mozilla::css::Side aSide)
return val;
}
CSSValue*
nsComputedDOMStyle::GetStickyOffset(mozilla::css::Side aSide)
{
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
const nsStylePosition* positionData = StylePosition();
nsStyleCoord coord = positionData->mOffset.Get(aSide);
NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
coord.GetUnit() == eStyleUnit_Percent ||
coord.GetUnit() == eStyleUnit_Auto ||
coord.IsCalcUnit(),
"Unexpected unit");
if (coord.GetUnit() == eStyleUnit_Auto) {
val->SetIdent(eCSSKeyword_auto);
return val;
}
PercentageBaseGetter baseGetter;
if (aSide == NS_SIDE_LEFT || aSide == NS_SIDE_RIGHT) {
baseGetter = &nsComputedDOMStyle::GetScrollFrameContentWidth;
} else {
baseGetter = &nsComputedDOMStyle::GetScrollFrameContentHeight;
}
val->SetAppUnits(StyleCoordToNSCoord(coord, baseGetter, 0, false));
return val;
}
CSSValue*
nsComputedDOMStyle::GetStaticOffset(mozilla::css::Side aSide)
@ -4126,6 +4158,50 @@ nsComputedDOMStyle::GetCBContentHeight(nscoord& aHeight)
return true;
}
bool
nsComputedDOMStyle::GetScrollFrameContentWidth(nscoord& aWidth)
{
if (!mOuterFrame) {
return false;
}
AssertFlushedPendingReflows();
nsIScrollableFrame* scrollableFrame =
nsLayoutUtils::GetNearestScrollableFrame(mOuterFrame->GetParent(),
nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
if (!scrollableFrame) {
return false;
}
aWidth =
scrollableFrame->GetScrolledFrame()->GetContentRectRelativeToSelf().width;
return true;
}
bool
nsComputedDOMStyle::GetScrollFrameContentHeight(nscoord& aHeight)
{
if (!mOuterFrame) {
return false;
}
AssertFlushedPendingReflows();
nsIScrollableFrame* scrollableFrame =
nsLayoutUtils::GetNearestScrollableFrame(mOuterFrame->GetParent(),
nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
if (!scrollableFrame) {
return false;
}
aHeight =
scrollableFrame->GetScrolledFrame()->GetContentRectRelativeToSelf().height;
return true;
}
bool
nsComputedDOMStyle::GetFrameBorderRectWidth(nscoord& aWidth)
{

View File

@ -125,6 +125,8 @@ private:
mozilla::dom::CSSValue* GetRelativeOffset(mozilla::css::Side aSide);
mozilla::dom::CSSValue* GetStickyOffset(mozilla::css::Side aSide);
mozilla::dom::CSSValue* GetStaticOffset(mozilla::css::Side aSide);
mozilla::dom::CSSValue* GetPaddingWidthFor(mozilla::css::Side aSide);
@ -491,6 +493,8 @@ private:
bool GetCBContentWidth(nscoord& aWidth);
bool GetCBContentHeight(nscoord& aWidth);
bool GetScrollFrameContentWidth(nscoord& aWidth);
bool GetScrollFrameContentHeight(nscoord& aHeight);
bool GetFrameBoundsWidthForTransform(nscoord &aWidth);
bool GetFrameBoundsHeightForTransform(nscoord &aHeight);
bool GetFrameBorderRectWidth(nscoord& aWidth);

View File

@ -137,6 +137,8 @@ MOCHITEST_FILES = test_acid3_test46.html \
test_parser_diagnostics_unprintables.html \
test_pixel_lengths.html \
test_pointer-events.html \
file_position_sticky.html \
test_position_sticky.html \
test_property_database.html \
test_priority_preservation.html \
test_property_syntax_errors.html \

View File

@ -0,0 +1,88 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=886646
-->
<head>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<style type="text/css">
#scroller {
width: 100px;
height: 100px;
padding: 10px;
border: 10px solid black;
margin: 10px;
overflow: hidden;
}
#container {
width: 50px;
height: 50px;
}
#sticky {
position: sticky;
width: 10px;
height: 10px;
overflow: hidden;
}
</style>
</head>
<body>
<div id="display">
<div id="scroller">
<div id="container">
<div id="sticky"></div>
</div>
</div>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 886646 - sticky positioning offsets **/
// Use "is()", "ok()", and "todo()" from parent document.
var is = parent.is;
var ok = parent.ok;
var todo = parent.todo;
// Test that percentage sticky offsets are computed in terms of the
// scroll container's content box
var offsets = {
"top": 10,
"left": 20,
"bottom": 30,
"right": 40,
};
var scroller = document.getElementById("scroller");
var container = document.getElementById("container");
var sticky = document.getElementById("sticky");
var cs = getComputedStyle(sticky, "");
for (var prop in offsets) {
sticky.style[prop] = offsets[prop] + "%";
is(cs[prop], offsets[prop] + "px");
}
// ... even in the presence of scrollbars
scroller.style.overflow = "scroll";
container.style.width = "100%";
container.style.height = "100%";
var ccs = getComputedStyle(container, "");
function isApproximatelyEqual(a, b) {
return Math.abs(a - b) < 0.001;
}
for (var prop in offsets) {
sticky.style[prop] = offsets[prop] + "%";
var basis = parseFloat(ccs[prop == "left" || prop == "right" ?
"width" : "height"]) / 100;
ok(isApproximatelyEqual(parseFloat(cs[prop]), offsets[prop] * basis));
}
parent.finish();
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=886646
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 886646</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=886646">Mozilla Bug 886646</a>
<div id="display">
<iframe id="iframe" style="height: 200px; width: 200px"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 886646 - sticky positioning offsets **/
/*
* This mochitest runs in an iframe so that we can selectively turn on the
* sticky about:config pref before its document is instantiated.
*
* See the iframe's source ("file_position_sticky.html") for the actual
* test code and for more documentation.
*/
SimpleTest.waitForExplicitFinish();
SpecialPowers.setBoolPref("layout.css.sticky.enabled", true);
document.getElementById("iframe").src = "file_position_sticky.html";
function finish() {
SpecialPowers.clearUserPref("layout.css.sticky.enabled");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>