mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Auto merge of #6662 - tschneidereit:client-geometry, r=glennw,pcwatson
Implement Element.client{Top,Left,Width,Height} This isn't done, but contains a working implementation of at least `clientTop`. Feedback would be much appreciated: it's probably far from ideal. Implementing `clientLeft` is straight-forward, I think, but `clientWidth` and `clientHeight` require accessing the `border_box` - and I don't know how that works, yet. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6662) <!-- Reviewable:end -->
This commit is contained in:
commit
e0bd80f807
8 changed files with 217 additions and 1 deletions
|
@ -53,7 +53,7 @@ use net_traits::{load_bytes_iter, PendingAsyncLoad};
|
||||||
use net_traits::image_cache_task::{ImageCacheTask, ImageCacheResult, ImageCacheChan};
|
use net_traits::image_cache_task::{ImageCacheTask, ImageCacheResult, ImageCacheChan};
|
||||||
use script::dom::bindings::js::LayoutJS;
|
use script::dom::bindings::js::LayoutJS;
|
||||||
use script::dom::node::{LayoutData, Node};
|
use script::dom::node::{LayoutData, Node};
|
||||||
use script::layout_interface::{Animation, ContentBoxResponse, ContentBoxesResponse};
|
use script::layout_interface::{Animation, ContentBoxResponse, ContentBoxesResponse, NodeGeometryResponse};
|
||||||
use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC, MouseOverResponse};
|
use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC, MouseOverResponse};
|
||||||
use script::layout_interface::{NewLayoutTaskInfo, Msg, Reflow, ReflowGoal, ReflowQueryType};
|
use script::layout_interface::{NewLayoutTaskInfo, Msg, Reflow, ReflowGoal, ReflowQueryType};
|
||||||
use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress};
|
use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress};
|
||||||
|
@ -70,6 +70,7 @@ use std::sync::mpsc::{channel, Sender, Receiver, Select};
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
use style::computed_values::{filter, mix_blend_mode};
|
use style::computed_values::{filter, mix_blend_mode};
|
||||||
use style::media_queries::{MediaType, MediaQueryList, Device};
|
use style::media_queries::{MediaType, MediaQueryList, Device};
|
||||||
|
use style::properties::style_structs;
|
||||||
use style::selector_matching::Stylist;
|
use style::selector_matching::Stylist;
|
||||||
use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt};
|
use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -126,6 +127,9 @@ pub struct LayoutTaskData {
|
||||||
/// A queued response for the content boxes of a node.
|
/// A queued response for the content boxes of a node.
|
||||||
pub content_boxes_response: Vec<Rect<Au>>,
|
pub content_boxes_response: Vec<Rect<Au>>,
|
||||||
|
|
||||||
|
/// A queued response for the client {top, left, width, height} of a node in pixels.
|
||||||
|
pub client_rect_response: Rect<i32>,
|
||||||
|
|
||||||
/// The list of currently-running animations.
|
/// The list of currently-running animations.
|
||||||
pub running_animations: Vec<Animation>,
|
pub running_animations: Vec<Animation>,
|
||||||
|
|
||||||
|
@ -368,6 +372,7 @@ impl LayoutTask {
|
||||||
generation: 0,
|
generation: 0,
|
||||||
content_box_response: Rect::zero(),
|
content_box_response: Rect::zero(),
|
||||||
content_boxes_response: Vec::new(),
|
content_boxes_response: Vec::new(),
|
||||||
|
client_rect_response: Rect::zero(),
|
||||||
running_animations: Vec::new(),
|
running_animations: Vec::new(),
|
||||||
visible_rects: Arc::new(HashMap::with_hash_state(Default::default())),
|
visible_rects: Arc::new(HashMap::with_hash_state(Default::default())),
|
||||||
new_animations_receiver: new_animations_receiver,
|
new_animations_receiver: new_animations_receiver,
|
||||||
|
@ -850,6 +855,16 @@ impl LayoutTask {
|
||||||
rw_data.content_boxes_response = iterator.rects;
|
rw_data.content_boxes_response = iterator.rects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn process_node_geometry_request<'a>(&'a self,
|
||||||
|
requested_node: TrustedNodeAddress,
|
||||||
|
layout_root: &mut FlowRef,
|
||||||
|
rw_data: &mut RWGuard<'a>) {
|
||||||
|
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||||
|
let mut iterator = FragmentLocatingFragmentIterator::new(requested_node);
|
||||||
|
sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
|
||||||
|
rw_data.client_rect_response = iterator.client_rect;
|
||||||
|
}
|
||||||
|
|
||||||
fn compute_abs_pos_and_build_display_list<'a>(&'a self,
|
fn compute_abs_pos_and_build_display_list<'a>(&'a self,
|
||||||
data: &Reflow,
|
data: &Reflow,
|
||||||
layout_root: &mut FlowRef,
|
layout_root: &mut FlowRef,
|
||||||
|
@ -1044,6 +1059,9 @@ impl LayoutTask {
|
||||||
ReflowQueryType::ContentBoxesQuery(node) => {
|
ReflowQueryType::ContentBoxesQuery(node) => {
|
||||||
self.process_content_boxes_request(node, &mut root_flow, &mut rw_data)
|
self.process_content_boxes_request(node, &mut root_flow, &mut rw_data)
|
||||||
}
|
}
|
||||||
|
ReflowQueryType::NodeGeometryQuery(node) => {
|
||||||
|
self.process_node_geometry_request(node, &mut root_flow, &mut rw_data)
|
||||||
|
}
|
||||||
ReflowQueryType::NoQuery => {}
|
ReflowQueryType::NoQuery => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1283,6 +1301,14 @@ impl LayoutRPC for LayoutRPCImpl {
|
||||||
ContentBoxesResponse(rw_data.content_boxes_response.clone())
|
ContentBoxesResponse(rw_data.content_boxes_response.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_geometry(&self) -> NodeGeometryResponse {
|
||||||
|
let &LayoutRPCImpl(ref rw_data) = self;
|
||||||
|
let rw_data = rw_data.lock().unwrap();
|
||||||
|
NodeGeometryResponse {
|
||||||
|
client_rect: rw_data.client_rect_response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Requests the node containing the point of interest.
|
/// Requests the node containing the point of interest.
|
||||||
fn hit_test(&self, _: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()> {
|
fn hit_test(&self, _: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()> {
|
||||||
let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y));
|
let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y));
|
||||||
|
@ -1400,6 +1426,40 @@ impl FragmentBorderBoxIterator for CollectingFragmentBorderBoxIterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FragmentLocatingFragmentIterator {
|
||||||
|
node_address: OpaqueNode,
|
||||||
|
client_rect: Rect<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FragmentLocatingFragmentIterator {
|
||||||
|
fn new(node_address: OpaqueNode) -> FragmentLocatingFragmentIterator {
|
||||||
|
FragmentLocatingFragmentIterator {
|
||||||
|
node_address: node_address,
|
||||||
|
client_rect: Rect::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FragmentBorderBoxIterator for FragmentLocatingFragmentIterator {
|
||||||
|
fn process(&mut self, fragment: &Fragment, border_box: &Rect<Au>) {
|
||||||
|
let style_structs::Border {
|
||||||
|
border_top_width: top_width,
|
||||||
|
border_right_width: right_width,
|
||||||
|
border_bottom_width: bottom_width,
|
||||||
|
border_left_width: left_width,
|
||||||
|
..
|
||||||
|
} = *fragment.style.get_border();
|
||||||
|
self.client_rect.origin.y = top_width.to_px();
|
||||||
|
self.client_rect.origin.x = left_width.to_px();
|
||||||
|
self.client_rect.size.width = (border_box.size.width - left_width - right_width).to_px();
|
||||||
|
self.client_rect.size.height = (border_box.size.height - top_width - bottom_width).to_px();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_process(&mut self, fragment: &Fragment) -> bool {
|
||||||
|
fragment.node == self.node_address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The default computed value for background-color is transparent (see
|
// The default computed value for background-color is transparent (see
|
||||||
// http://dev.w3.org/csswg/css-backgrounds/#background-color). However, we
|
// http://dev.w3.org/csswg/css-backgrounds/#background-color). However, we
|
||||||
// need to propagate the background color from the root HTML/Body
|
// need to propagate the background color from the root HTML/Body
|
||||||
|
|
|
@ -1317,6 +1317,26 @@ impl<'a> ElementMethods for &'a Element {
|
||||||
rect.origin.x + rect.size.width)
|
rect.origin.x + rect.size.width)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ClientTop(self) -> i32 {
|
||||||
|
let node = NodeCast::from_ref(self);
|
||||||
|
node.get_client_rect().origin.y
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ClientLeft(self) -> i32 {
|
||||||
|
let node = NodeCast::from_ref(self);
|
||||||
|
node.get_client_rect().origin.x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ClientWidth(self) -> i32 {
|
||||||
|
let node = NodeCast::from_ref(self);
|
||||||
|
node.get_client_rect().size.width
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ClientHeight(self) -> i32 {
|
||||||
|
let node = NodeCast::from_ref(self);
|
||||||
|
node.get_client_rect().size.height
|
||||||
|
}
|
||||||
|
|
||||||
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML
|
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML
|
||||||
fn GetInnerHTML(self) -> Fallible<DOMString> {
|
fn GetInnerHTML(self) -> Fallible<DOMString> {
|
||||||
//XXX TODO: XML case
|
//XXX TODO: XML case
|
||||||
|
|
|
@ -492,6 +492,7 @@ pub trait NodeHelpers {
|
||||||
|
|
||||||
fn get_bounding_content_box(self) -> Rect<Au>;
|
fn get_bounding_content_box(self) -> Rect<Au>;
|
||||||
fn get_content_boxes(self) -> Vec<Rect<Au>>;
|
fn get_content_boxes(self) -> Vec<Rect<Au>>;
|
||||||
|
fn get_client_rect(self) -> Rect<i32>;
|
||||||
|
|
||||||
fn before(self, nodes: Vec<NodeOrString>) -> ErrorResult;
|
fn before(self, nodes: Vec<NodeOrString>) -> ErrorResult;
|
||||||
fn after(self, nodes: Vec<NodeOrString>) -> ErrorResult;
|
fn after(self, nodes: Vec<NodeOrString>) -> ErrorResult;
|
||||||
|
@ -794,6 +795,10 @@ impl<'a> NodeHelpers for &'a Node {
|
||||||
window_from_node(self).r().content_boxes_query(self.to_trusted_node_address())
|
window_from_node(self).r().content_boxes_query(self.to_trusted_node_address())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_client_rect(self) -> Rect<i32> {
|
||||||
|
window_from_node(self).r().client_rect_query(self.to_trusted_node_address())
|
||||||
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-childnode-before
|
// https://dom.spec.whatwg.org/#dom-childnode-before
|
||||||
fn before(self, nodes: Vec<NodeOrString>) -> ErrorResult {
|
fn before(self, nodes: Vec<NodeOrString>) -> ErrorResult {
|
||||||
match self.parent_node.get() {
|
match self.parent_node.get() {
|
||||||
|
|
|
@ -59,6 +59,11 @@ interface Element : Node {
|
||||||
partial interface Element {
|
partial interface Element {
|
||||||
DOMRectList getClientRects();
|
DOMRectList getClientRects();
|
||||||
DOMRect getBoundingClientRect();
|
DOMRect getBoundingClientRect();
|
||||||
|
|
||||||
|
readonly attribute long clientTop;
|
||||||
|
readonly attribute long clientLeft;
|
||||||
|
readonly attribute long clientWidth;
|
||||||
|
readonly attribute long clientHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://domparsing.spec.whatwg.org/#extensions-to-the-element-interface
|
// https://domparsing.spec.whatwg.org/#extensions-to-the-element-interface
|
||||||
|
|
|
@ -540,6 +540,7 @@ pub trait WindowHelpers {
|
||||||
fn layout(&self) -> &LayoutRPC;
|
fn layout(&self) -> &LayoutRPC;
|
||||||
fn content_box_query(self, content_box_request: TrustedNodeAddress) -> Rect<Au>;
|
fn content_box_query(self, content_box_request: TrustedNodeAddress) -> Rect<Au>;
|
||||||
fn content_boxes_query(self, content_boxes_request: TrustedNodeAddress) -> Vec<Rect<Au>>;
|
fn content_boxes_query(self, content_boxes_request: TrustedNodeAddress) -> Vec<Rect<Au>>;
|
||||||
|
fn client_rect_query(self, node_geometry_request: TrustedNodeAddress) -> Rect<i32>;
|
||||||
fn handle_reflow_complete_msg(self, reflow_id: u32);
|
fn handle_reflow_complete_msg(self, reflow_id: u32);
|
||||||
fn set_fragment_name(self, fragment: Option<String>);
|
fn set_fragment_name(self, fragment: Option<String>);
|
||||||
fn steal_fragment_name(self) -> Option<String>;
|
fn steal_fragment_name(self) -> Option<String>;
|
||||||
|
@ -771,6 +772,13 @@ impl<'a> WindowHelpers for &'a Window {
|
||||||
rects
|
rects
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn client_rect_query(self, node_geometry_request: TrustedNodeAddress) -> Rect<i32> {
|
||||||
|
self.reflow(ReflowGoal::ForScriptQuery,
|
||||||
|
ReflowQueryType::NodeGeometryQuery(node_geometry_request),
|
||||||
|
ReflowReason::Query);
|
||||||
|
self.layout_rpc.node_geometry().client_rect
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_reflow_complete_msg(self, reflow_id: u32) {
|
fn handle_reflow_complete_msg(self, reflow_id: u32) {
|
||||||
let last_reflow_id = self.last_reflow_id.get();
|
let last_reflow_id = self.last_reflow_id.get();
|
||||||
if last_reflow_id == reflow_id {
|
if last_reflow_id == reflow_id {
|
||||||
|
@ -1077,6 +1085,7 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason:
|
||||||
ReflowQueryType::NoQuery => "\tNoQuery",
|
ReflowQueryType::NoQuery => "\tNoQuery",
|
||||||
ReflowQueryType::ContentBoxQuery(_n) => "\tContentBoxQuery",
|
ReflowQueryType::ContentBoxQuery(_n) => "\tContentBoxQuery",
|
||||||
ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
|
ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
|
||||||
|
ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
|
||||||
});
|
});
|
||||||
|
|
||||||
debug_msg.push_str(match *reason {
|
debug_msg.push_str(match *reason {
|
||||||
|
|
|
@ -95,6 +95,8 @@ pub trait LayoutRPC {
|
||||||
fn content_box(&self) -> ContentBoxResponse;
|
fn content_box(&self) -> ContentBoxResponse;
|
||||||
/// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
|
/// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
|
||||||
fn content_boxes(&self) -> ContentBoxesResponse;
|
fn content_boxes(&self) -> ContentBoxesResponse;
|
||||||
|
/// Requests the geometry of this node. Used by APIs such as `clientTop`.
|
||||||
|
fn node_geometry(&self) -> NodeGeometryResponse;
|
||||||
/// Requests the node containing the point of interest
|
/// Requests the node containing the point of interest
|
||||||
fn hit_test(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()>;
|
fn hit_test(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()>;
|
||||||
fn mouse_over(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<MouseOverResponse, ()>;
|
fn mouse_over(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<MouseOverResponse, ()>;
|
||||||
|
@ -102,6 +104,9 @@ pub trait LayoutRPC {
|
||||||
|
|
||||||
pub struct ContentBoxResponse(pub Rect<Au>);
|
pub struct ContentBoxResponse(pub Rect<Au>);
|
||||||
pub struct ContentBoxesResponse(pub Vec<Rect<Au>>);
|
pub struct ContentBoxesResponse(pub Vec<Rect<Au>>);
|
||||||
|
pub struct NodeGeometryResponse {
|
||||||
|
pub client_rect: Rect<i32>,
|
||||||
|
}
|
||||||
pub struct HitTestResponse(pub UntrustedNodeAddress);
|
pub struct HitTestResponse(pub UntrustedNodeAddress);
|
||||||
pub struct MouseOverResponse(pub Vec<UntrustedNodeAddress>);
|
pub struct MouseOverResponse(pub Vec<UntrustedNodeAddress>);
|
||||||
|
|
||||||
|
@ -120,6 +125,7 @@ pub enum ReflowQueryType {
|
||||||
NoQuery,
|
NoQuery,
|
||||||
ContentBoxQuery(TrustedNodeAddress),
|
ContentBoxQuery(TrustedNodeAddress),
|
||||||
ContentBoxesQuery(TrustedNodeAddress),
|
ContentBoxesQuery(TrustedNodeAddress),
|
||||||
|
NodeGeometryQuery(TrustedNodeAddress),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information needed for a reflow.
|
/// Information needed for a reflow.
|
||||||
|
|
|
@ -287,6 +287,12 @@
|
||||||
"url": "/_mozilla/mozilla/child_reparenting.html"
|
"url": "/_mozilla/mozilla/child_reparenting.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"mozilla/client-top-left-height-width.html": [
|
||||||
|
{
|
||||||
|
"path": "mozilla/client-top-left-height-width.html",
|
||||||
|
"url": "/_mozilla/mozilla/client-top-left-height-width.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"mozilla/collections.html": [
|
"mozilla/collections.html": [
|
||||||
{
|
{
|
||||||
"path": "mozilla/collections.html",
|
"path": "mozilla/collections.html",
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: 'ahem';
|
||||||
|
src: url(../css/fonts/ahem/ahem.ttf);
|
||||||
|
}
|
||||||
|
#no-border {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
#with-border {
|
||||||
|
border: 10px solid black;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
#with-border-and-padding {
|
||||||
|
border: 10px solid black;
|
||||||
|
padding: 10px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
#abs1 {
|
||||||
|
position: absolute;
|
||||||
|
background-color: red;
|
||||||
|
top: 45px;
|
||||||
|
left: 155px;
|
||||||
|
width: 100px;
|
||||||
|
height: 120px;
|
||||||
|
}
|
||||||
|
#abs2 {
|
||||||
|
position: absolute;
|
||||||
|
background-color: green;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
#abs3 {
|
||||||
|
position: absolute;
|
||||||
|
background-color: blue;
|
||||||
|
top: 12px;
|
||||||
|
left: 14px;
|
||||||
|
width: 48px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
#span1 {
|
||||||
|
font-family: 'ahem';
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
#rotated {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: blue;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
#inline-block {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: green;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
#display-none {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: green;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="no-border">my div</div>
|
||||||
|
<div id="with-border">my div</div>
|
||||||
|
<div id="with-border-and-padding">my div</div>
|
||||||
|
<div id="abs1">
|
||||||
|
<span id="span1">X</span>
|
||||||
|
</div>
|
||||||
|
<div id='rotated'>rotated</div>
|
||||||
|
<div id='inline-block'>inline-block</div>
|
||||||
|
<div id='display-none'>display-none</div>
|
||||||
|
<script>
|
||||||
|
function test_rect(name, left, top, height, width) {
|
||||||
|
var div = document.getElementById(name);
|
||||||
|
var rect = div.getBoundingClientRect();
|
||||||
|
|
||||||
|
assert_equals(div.clientLeft, left);
|
||||||
|
assert_equals(div.clientTop, top);
|
||||||
|
assert_equals(div.clientHeight, height);
|
||||||
|
assert_equals(div.clientWidth, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(function() { test_rect('no-border', 0, 0, 100, 100); }, 'Block without border');
|
||||||
|
test(function() { test_rect('with-border', 10, 10, 100, 100); }, 'Block with border');
|
||||||
|
test(function() { test_rect('with-border-and-padding', 10, 10, 120, 120); }, 'Block without border and padding');
|
||||||
|
test(function() { test_rect('abs1', 0, 0, 120, 100); }, 'Absolutely positioned block');
|
||||||
|
test(function() { test_rect('rotated', 0, 0, 100, 100); }, 'Rotated block');
|
||||||
|
test(function() { test_rect('span1', 0, 0, 0, 0); }, 'Span');
|
||||||
|
test(function() { test_rect('inline-block', 0, 0, 100, 100); }, 'Inline block');
|
||||||
|
test(function() { test_rect('display-none', 0, 0, 0, 0); }, 'display: none');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue