mirror of
https://github.com/servo/servo.git
synced 2025-08-08 06:55:31 +01:00
script: Implement scrollIntoView
(#38230)
This is an implementation for `scrollIntoView`. For now, it is called when a certain element gains focus. Testing: Existing WPT tests Fixes: #24059 Signed-off-by: abdelrahman1234567 <abdelrahman.hossameldin.awadalla@huawei.com>
This commit is contained in:
parent
dcb90bb85e
commit
17a269a8ad
34 changed files with 492 additions and 318 deletions
|
@ -58,6 +58,7 @@ use percent_encoding::percent_decode;
|
|||
use profile_traits::ipc as profile_ipc;
|
||||
use profile_traits::time::TimerMetadataFrameType;
|
||||
use regex::bytes::Regex;
|
||||
use script_bindings::codegen::GenericBindings::ElementBinding::ElementMethods;
|
||||
use script_bindings::interfaces::DocumentHelpers;
|
||||
use script_bindings::script_runtime::JSContext;
|
||||
use script_traits::{ConstellationInputEvent, DocumentActivity, ProgressiveWebMetricType};
|
||||
|
@ -93,6 +94,9 @@ use crate::dom::bindings::codegen::Bindings::BeforeUnloadEventBinding::BeforeUnl
|
|||
use crate::dom::bindings::codegen::Bindings::DocumentBinding::{
|
||||
DocumentMethods, DocumentReadyState, DocumentVisibilityState, NamedPropertyValue,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::ElementBinding::{
|
||||
ScrollIntoViewContainer, ScrollIntoViewOptions, ScrollLogicalPosition,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElement_Binding::HTMLIFrameElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
|
||||
|
@ -105,12 +109,13 @@ use crate::dom::bindings::codegen::Bindings::PermissionStatusBinding::Permission
|
|||
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::TouchBinding::TouchMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::{
|
||||
FrameRequestCallback, ScrollBehavior, WindowMethods,
|
||||
FrameRequestCallback, ScrollBehavior, ScrollOptions, WindowMethods,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::XPathEvaluatorBinding::XPathEvaluatorMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::XPathNSResolverBinding::XPathNSResolver;
|
||||
use crate::dom::bindings::codegen::UnionTypes::{
|
||||
NodeOrString, StringOrElementCreationOptions, TrustedHTMLOrString,
|
||||
BooleanOrScrollIntoViewOptions, NodeOrString, StringOrElementCreationOptions,
|
||||
TrustedHTMLOrString,
|
||||
};
|
||||
use crate::dom::bindings::domname::{
|
||||
self, is_valid_attribute_local_name, is_valid_element_local_name, namespace_from_domstring,
|
||||
|
@ -1384,6 +1389,18 @@ impl Document {
|
|||
DeviceIntRect::from_untyped(&rect.to_box2d()),
|
||||
));
|
||||
}
|
||||
// Scroll operation to happen after element gets focus.
|
||||
// This is needed to ensure that the focused element is visible.
|
||||
elem.ScrollIntoView(BooleanOrScrollIntoViewOptions::ScrollIntoViewOptions(
|
||||
ScrollIntoViewOptions {
|
||||
parent: ScrollOptions {
|
||||
behavior: ScrollBehavior::Smooth,
|
||||
},
|
||||
block: ScrollLogicalPosition::Center,
|
||||
inline: ScrollLogicalPosition::Center,
|
||||
container: ScrollIntoViewContainer::All,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ use selectors::sink::Push;
|
|||
use servo_arc::Arc;
|
||||
use style::applicable_declarations::ApplicableDeclarationBlock;
|
||||
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
|
||||
use style::computed_values::position::T as Position;
|
||||
use style::context::QuirksMode;
|
||||
use style::invalidation::element::restyle_hints::RestyleHint;
|
||||
use style::media_queries::MediaList;
|
||||
|
@ -73,7 +74,7 @@ use crate::dom::bindings::cell::{DomRefCell, Ref, RefMut};
|
|||
use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::ElementBinding::{
|
||||
ElementMethods, GetHTMLOptions, ShadowRootInit,
|
||||
ElementMethods, GetHTMLOptions, ScrollIntoViewContainer, ScrollLogicalPosition, ShadowRootInit,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
||||
|
@ -85,7 +86,8 @@ use crate::dom::bindings::codegen::Bindings::WindowBinding::{
|
|||
ScrollBehavior, ScrollToOptions, WindowMethods,
|
||||
};
|
||||
use crate::dom::bindings::codegen::UnionTypes::{
|
||||
NodeOrString, TrustedHTMLOrNullIsEmptyString, TrustedHTMLOrString, TrustedScriptURLOrUSVString,
|
||||
BooleanOrScrollIntoViewOptions, NodeOrString, TrustedHTMLOrNullIsEmptyString,
|
||||
TrustedHTMLOrString, TrustedScriptURLOrUSVString,
|
||||
};
|
||||
use crate::dom::bindings::conversions::DerivedFrom;
|
||||
use crate::dom::bindings::domname::{
|
||||
|
@ -262,6 +264,20 @@ impl FromStr for AdjacentPosition {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents a scrolling box that can be either an element or the viewport
|
||||
/// <https://drafts.csswg.org/cssom-view/#scrolling-box>
|
||||
enum ScrollingBox {
|
||||
Element(DomRoot<Element>),
|
||||
Viewport(DomRoot<Document>),
|
||||
}
|
||||
|
||||
/// Represents a scroll position with x and y coordinates
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct ScrollPosition {
|
||||
x: f64,
|
||||
y: f64,
|
||||
}
|
||||
|
||||
//
|
||||
// Element methods
|
||||
//
|
||||
|
@ -852,6 +868,377 @@ impl Element {
|
|||
let result = media_list.evaluate(document.window().layout().device(), quirks_mode);
|
||||
result
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/cssom-view/#scroll-a-target-into-view>
|
||||
fn scroll_into_view_with_options(
|
||||
&self,
|
||||
behavior: ScrollBehavior,
|
||||
block: ScrollLogicalPosition,
|
||||
inline: ScrollLogicalPosition,
|
||||
container: Option<&Element>,
|
||||
) {
|
||||
let target_document = self.upcast::<Node>().owner_doc();
|
||||
|
||||
// Step 1: For each ancestor element or viewport that establishes a scrolling box,
|
||||
// in order of innermost to outermost scrolling box
|
||||
let mut out_of_bound = false;
|
||||
self.upcast::<Node>()
|
||||
.inclusive_ancestors(ShadowIncluding::Yes)
|
||||
.skip(1) // Skip self
|
||||
.filter(|node| self.establishes_scroll_box(node))
|
||||
.map_while(|node| {
|
||||
if out_of_bound {
|
||||
return None;
|
||||
}
|
||||
let scrolling_box = if node.is::<Document>() {
|
||||
let document = node.downcast::<Document>().unwrap();
|
||||
ScrollingBox::Viewport(DomRoot::from_ref(document))
|
||||
} else {
|
||||
let element = node.downcast::<Element>().unwrap();
|
||||
ScrollingBox::Element(DomRoot::from_ref(element))
|
||||
};
|
||||
|
||||
// Step 1.4: Check container stopping condition
|
||||
if let Some(container) = container {
|
||||
// If container is not null and either scrolling box is a
|
||||
// shadow-including inclusive ancestor of container or is a viewport
|
||||
// whose document is a shadow-including inclusive ancestor of
|
||||
// container, abort the rest of these steps.
|
||||
let stop_condition = match scrolling_box {
|
||||
ScrollingBox::Element(ref element) => {
|
||||
// Check if the scrolling box element is a shadow-including inclusive ancestor of container
|
||||
element
|
||||
.upcast::<Node>()
|
||||
.is_shadow_including_inclusive_ancestor_of(
|
||||
container.upcast::<Node>(),
|
||||
)
|
||||
},
|
||||
ScrollingBox::Viewport(ref document) => {
|
||||
// Check if the viewport's document is a shadow-including inclusive ancestor of container
|
||||
document
|
||||
.upcast::<Node>()
|
||||
.is_shadow_including_inclusive_ancestor_of(
|
||||
container.upcast::<Node>(),
|
||||
)
|
||||
},
|
||||
};
|
||||
if stop_condition {
|
||||
out_of_bound = true;
|
||||
}
|
||||
}
|
||||
Some(scrolling_box)
|
||||
})
|
||||
.for_each(|scrolling_box| {
|
||||
match scrolling_box {
|
||||
ScrollingBox::Element(ref element) => {
|
||||
// Step 1.1: Check same origin
|
||||
let scrolling_box_document = element.upcast::<Node>().owner_doc();
|
||||
if !target_document
|
||||
.origin()
|
||||
.same_origin(scrolling_box_document.origin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 1.2: Determine scroll position
|
||||
let position = self.determine_scroll_into_view_position(
|
||||
element.upcast::<Node>(),
|
||||
block,
|
||||
inline,
|
||||
);
|
||||
// Step 1.3: Check if scroll is needed
|
||||
// TODO: check if scrolling box has an ongoing smooth scroll
|
||||
let current_scroll_x = element.ScrollLeft();
|
||||
let current_scroll_y = element.ScrollTop();
|
||||
if position.x != current_scroll_x || position.y != current_scroll_y {
|
||||
// Step 1.3.1: If scrolling box is associated with an element:
|
||||
// Perform a scroll of the element’s scrolling box to position,
|
||||
// with the element as the associated element and behavior as the scroll behavior.
|
||||
let window = target_document.window();
|
||||
window.scroll_an_element(element, position.x, position.y, behavior);
|
||||
}
|
||||
},
|
||||
ScrollingBox::Viewport(ref viewport) => {
|
||||
// Step 1.1: Check same origin (viewport is always same origin with target)
|
||||
// Step 1.2: Determine scroll position
|
||||
let position = self.determine_scroll_into_view_position(
|
||||
viewport.upcast::<Node>(),
|
||||
block,
|
||||
inline,
|
||||
);
|
||||
// Step 1.3: Check if scroll is needed
|
||||
let window = viewport.window();
|
||||
let current_scroll_x = window.ScrollX() as f64;
|
||||
let current_scroll_y = window.ScrollY() as f64;
|
||||
if position.x != current_scroll_x || position.y != current_scroll_y {
|
||||
// Step 1.3.2: Perform a scroll of the viewport to position, with root
|
||||
// element as the associated element
|
||||
window.scroll(position.x, position.y, behavior);
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Check if an element establishes a scrolling box
|
||||
fn establishes_scroll_box(&self, node: &Node) -> bool {
|
||||
if node.is::<Document>() {
|
||||
true // Document's viewport is always a scrolling box
|
||||
} else if node.is::<Element>() {
|
||||
let element: &Element = node.downcast::<Element>().unwrap();
|
||||
if let Some(style) = element.style() {
|
||||
let overflow_x = style.get_box().clone_overflow_x();
|
||||
let overflow_y = style.get_box().clone_overflow_y();
|
||||
return overflow_x.is_scrollable() || overflow_y.is_scrollable();
|
||||
} else {
|
||||
false // Element without style is not a scrolling box
|
||||
}
|
||||
} else {
|
||||
false // Shadow roots and other nodes are not scrolling boxes
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/cssom-view/#element-scrolling-members>
|
||||
fn determine_scroll_into_view_position(
|
||||
&self,
|
||||
scrolling_node: &Node,
|
||||
block: ScrollLogicalPosition,
|
||||
inline: ScrollLogicalPosition,
|
||||
) -> ScrollPosition {
|
||||
let target_bounding_box = self.upcast::<Node>().bounding_content_box_or_zero();
|
||||
|
||||
let device_pixel_ratio = self
|
||||
.upcast::<Node>()
|
||||
.owner_doc()
|
||||
.window()
|
||||
.device_pixel_ratio()
|
||||
.get();
|
||||
|
||||
// Target element bounds
|
||||
let element_left = target_bounding_box
|
||||
.origin
|
||||
.x
|
||||
.to_nearest_pixel(device_pixel_ratio) as f64;
|
||||
let element_top = target_bounding_box
|
||||
.origin
|
||||
.y
|
||||
.to_nearest_pixel(device_pixel_ratio) as f64;
|
||||
let element_width = target_bounding_box
|
||||
.size
|
||||
.width
|
||||
.to_nearest_pixel(device_pixel_ratio) as f64;
|
||||
let element_height = target_bounding_box
|
||||
.size
|
||||
.height
|
||||
.to_nearest_pixel(device_pixel_ratio) as f64;
|
||||
let element_right = element_left + element_width;
|
||||
let element_bottom = element_top + element_height;
|
||||
|
||||
let (target_x, target_y) = if scrolling_node.is::<Document>() {
|
||||
// Handle document-specific scrolling
|
||||
// Viewport bounds and current scroll position
|
||||
let owner_doc = self.upcast::<Node>().owner_doc();
|
||||
let window = owner_doc.window();
|
||||
let viewport_width = window.InnerWidth() as f64;
|
||||
let viewport_height = window.InnerHeight() as f64;
|
||||
let current_scroll_x = window.ScrollX() as f64;
|
||||
let current_scroll_y = window.ScrollY() as f64;
|
||||
|
||||
// For viewport scrolling, we need to add current scroll to get document-relative positions
|
||||
let document_element_left = element_left + current_scroll_x;
|
||||
let document_element_top = element_top + current_scroll_y;
|
||||
let document_element_right = element_right + current_scroll_x;
|
||||
let document_element_bottom = element_bottom + current_scroll_y;
|
||||
|
||||
(
|
||||
self.calculate_scroll_position_one_axis(
|
||||
inline,
|
||||
document_element_left,
|
||||
document_element_right,
|
||||
element_width,
|
||||
viewport_width,
|
||||
current_scroll_x,
|
||||
),
|
||||
self.calculate_scroll_position_one_axis(
|
||||
block,
|
||||
document_element_top,
|
||||
document_element_bottom,
|
||||
element_height,
|
||||
viewport_height,
|
||||
current_scroll_y,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
// Handle element-specific scrolling
|
||||
// Scrolling box bounds and current scroll position
|
||||
let scrolling_box = scrolling_node.bounding_content_box_or_zero();
|
||||
let scrolling_left = scrolling_box.origin.x.to_nearest_pixel(device_pixel_ratio) as f64;
|
||||
let scrolling_top = scrolling_box.origin.y.to_nearest_pixel(device_pixel_ratio) as f64;
|
||||
let scrolling_width = scrolling_box
|
||||
.size
|
||||
.width
|
||||
.to_nearest_pixel(device_pixel_ratio) as f64;
|
||||
let scrolling_height = scrolling_box
|
||||
.size
|
||||
.height
|
||||
.to_nearest_pixel(device_pixel_ratio) as f64;
|
||||
|
||||
let current_scroll_x = scrolling_node.downcast::<Element>().unwrap().ScrollLeft();
|
||||
let current_scroll_y = scrolling_node.downcast::<Element>().unwrap().ScrollTop();
|
||||
|
||||
// Calculate element position in scroller's content coordinate system
|
||||
// Element's viewport position relative to scroller, then add scroll offset to get content position
|
||||
let viewport_relative_left = element_left - scrolling_left;
|
||||
let viewport_relative_top = element_top - scrolling_top;
|
||||
let viewport_relative_right = element_right - scrolling_left;
|
||||
let viewport_relative_bottom = element_bottom - scrolling_top;
|
||||
|
||||
// For absolutely positioned elements, we need to account for the positioning context
|
||||
// If the element is positioned relative to an ancestor that's within the scrolling container,
|
||||
// we need to adjust coordinates accordingly
|
||||
let (
|
||||
adjusted_relative_left,
|
||||
adjusted_relative_top,
|
||||
adjusted_relative_right,
|
||||
adjusted_relative_bottom,
|
||||
) = {
|
||||
// Check if this element has a positioned ancestor between it and the scrolling container
|
||||
let mut current_node = self.upcast::<Node>().GetParentNode();
|
||||
let mut final_coords = (
|
||||
viewport_relative_left,
|
||||
viewport_relative_top,
|
||||
viewport_relative_right,
|
||||
viewport_relative_bottom,
|
||||
);
|
||||
|
||||
while let Some(node) = current_node {
|
||||
// Stop if we reach the scrolling container
|
||||
if &*node == scrolling_node {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if this node establishes a positioning context and has position relative/absolute
|
||||
if let Some(element) = node.downcast::<Element>() {
|
||||
if let Some(computed_style) = element.style() {
|
||||
let position = computed_style.get_box().position;
|
||||
|
||||
if matches!(position, Position::Relative | Position::Absolute) {
|
||||
// If this element establishes a positioning context,
|
||||
// Get its bounding box to calculate the offset
|
||||
let positioning_box = node.bounding_content_box_or_zero();
|
||||
let positioning_left = positioning_box
|
||||
.origin
|
||||
.x
|
||||
.to_nearest_pixel(device_pixel_ratio)
|
||||
as f64;
|
||||
let positioning_top = positioning_box
|
||||
.origin
|
||||
.y
|
||||
.to_nearest_pixel(device_pixel_ratio)
|
||||
as f64;
|
||||
|
||||
// Calculate the offset of the positioning context relative to the scrolling container
|
||||
let offset_left = positioning_left - scrolling_left;
|
||||
let offset_top = positioning_top - scrolling_top;
|
||||
|
||||
// Adjust the coordinates by subtracting the positioning context offset
|
||||
final_coords = (
|
||||
viewport_relative_left - offset_left,
|
||||
viewport_relative_top - offset_top,
|
||||
viewport_relative_right - offset_left,
|
||||
viewport_relative_bottom - offset_top,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current_node = node.GetParentNode();
|
||||
}
|
||||
|
||||
final_coords
|
||||
};
|
||||
|
||||
let content_element_left = adjusted_relative_left + current_scroll_x;
|
||||
let content_element_top = adjusted_relative_top + current_scroll_y;
|
||||
let content_element_right = adjusted_relative_right + current_scroll_x;
|
||||
let content_element_bottom = adjusted_relative_bottom + current_scroll_y;
|
||||
|
||||
(
|
||||
self.calculate_scroll_position_one_axis(
|
||||
inline,
|
||||
content_element_left,
|
||||
content_element_right,
|
||||
element_width,
|
||||
scrolling_width,
|
||||
current_scroll_x,
|
||||
),
|
||||
self.calculate_scroll_position_one_axis(
|
||||
block,
|
||||
content_element_top,
|
||||
content_element_bottom,
|
||||
element_height,
|
||||
scrolling_height,
|
||||
current_scroll_y,
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
ScrollPosition {
|
||||
x: target_x,
|
||||
y: target_y,
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_scroll_position_one_axis(
|
||||
&self,
|
||||
alignment: ScrollLogicalPosition,
|
||||
element_start: f64,
|
||||
element_end: f64,
|
||||
element_size: f64,
|
||||
container_size: f64,
|
||||
current_scroll_offset: f64,
|
||||
) -> f64 {
|
||||
match alignment {
|
||||
// Step 1 & 5: If inline is "start", then align element start edge with scrolling box start edge.
|
||||
ScrollLogicalPosition::Start => element_start,
|
||||
// Step 2 & 6: If inline is "end", then align element end edge with
|
||||
// scrolling box end edge.
|
||||
ScrollLogicalPosition::End => element_end - container_size,
|
||||
// Step 3 & 7: If inline is "center", then align the center of target bounding
|
||||
// border box with the center of scrolling box in scrolling box’s inline base direction.
|
||||
ScrollLogicalPosition::Center => element_start + (element_size - container_size) / 2.0,
|
||||
// Step 4 & 8: If inline is "nearest",
|
||||
ScrollLogicalPosition::Nearest => {
|
||||
let viewport_start = current_scroll_offset;
|
||||
let viewport_end = current_scroll_offset + container_size;
|
||||
|
||||
// Step 4.2 & 8.2: If element start edge is outside scrolling box start edge and element
|
||||
// size is less than scrolling box size or If element end edge is outside
|
||||
// scrolling box end edge and element size is greater than scrolling box size:
|
||||
// Align element start edge with scrolling box start edge.
|
||||
if (element_start < viewport_start && element_size <= container_size) ||
|
||||
(element_end > viewport_end && element_size >= container_size)
|
||||
{
|
||||
element_start
|
||||
}
|
||||
// Step 4.3 & 8.3: If element end edge is outside scrolling box start edge and element
|
||||
// size is greater than scrolling box size or If element start edge is outside
|
||||
// scrolling box end edge and element size is less than scrolling box size:
|
||||
// Align element end edge with scrolling box end edge.
|
||||
else if (element_end > viewport_end && element_size < container_size) ||
|
||||
(element_start < viewport_start && element_size > container_size)
|
||||
{
|
||||
element_end - container_size
|
||||
}
|
||||
// Step 4.1 & 8.1: If element start edge and element end edge are both outside scrolling
|
||||
// box start edge and scrolling box end edge or an invalid situation: Do nothing.
|
||||
else {
|
||||
current_scroll_offset
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#valid-shadow-host-name>
|
||||
|
@ -3219,7 +3606,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
|
|||
win.scroll_an_element(self, self.ScrollLeft(), y, behavior);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-scrolltop
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-scrollleft
|
||||
fn ScrollLeft(&self) -> f64 {
|
||||
let node = self.upcast::<Node>();
|
||||
|
||||
|
@ -3316,6 +3703,52 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
|
|||
win.scroll_an_element(self, x, self.ScrollTop(), behavior);
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/cssom-view/#dom-element-scrollintoview>
|
||||
fn ScrollIntoView(&self, arg: BooleanOrScrollIntoViewOptions) {
|
||||
let (behavior, block, inline, container) = match arg {
|
||||
// If arg is true:
|
||||
BooleanOrScrollIntoViewOptions::Boolean(true) => (
|
||||
ScrollBehavior::Auto, // Step 1: Let behavior be "auto".
|
||||
ScrollLogicalPosition::Start, // Step 2: Let block be "start".
|
||||
ScrollLogicalPosition::Nearest, // Step 3: Let inline be "nearest".
|
||||
None, // Step 4: Let container be null.
|
||||
),
|
||||
// Step 5: If arg is a ScrollIntoViewOptions dictionary, set its properties
|
||||
// to the corresponding values in the dictionary.
|
||||
BooleanOrScrollIntoViewOptions::ScrollIntoViewOptions(options) => (
|
||||
options.parent.behavior,
|
||||
options.block,
|
||||
options.inline,
|
||||
// Step 5.4: If the container dictionary member of options is "nearest",
|
||||
// set container to the element.
|
||||
if options.container == ScrollIntoViewContainer::Nearest {
|
||||
Some(self)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
),
|
||||
// Step 6: Otherwise, if arg is false, then set block to "end".
|
||||
BooleanOrScrollIntoViewOptions::Boolean(false) => (
|
||||
ScrollBehavior::Auto,
|
||||
ScrollLogicalPosition::End,
|
||||
ScrollLogicalPosition::Nearest,
|
||||
None,
|
||||
),
|
||||
};
|
||||
|
||||
// Step 7: If the element does not have any associated box, or is not
|
||||
// available to user-agent features, then return.
|
||||
if !self.has_css_layout_box() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 8: Scroll the element into view with behavior, block, inline, and container.
|
||||
self.scroll_into_view_with_options(behavior, block, inline, container);
|
||||
|
||||
// Step 9: Optionally perform some other action that brings the
|
||||
// element to the user’s attention.
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth
|
||||
fn ScrollWidth(&self) -> i32 {
|
||||
self.upcast::<Node>().scroll_area().size.width
|
||||
|
|
|
@ -102,6 +102,7 @@ partial interface Element {
|
|||
[NewObject]
|
||||
DOMRect getBoundingClientRect();
|
||||
|
||||
undefined scrollIntoView(optional (boolean or ScrollIntoViewOptions) arg = {});
|
||||
undefined scroll(optional ScrollToOptions options = {});
|
||||
undefined scroll(unrestricted double x, unrestricted double y);
|
||||
|
||||
|
@ -134,6 +135,16 @@ dictionary GetHTMLOptions {
|
|||
sequence<ShadowRoot> shadowRoots = [];
|
||||
};
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dictdef-scrollintoviewoptions
|
||||
dictionary ScrollIntoViewOptions : ScrollOptions {
|
||||
ScrollLogicalPosition block = "start";
|
||||
ScrollLogicalPosition inline = "nearest";
|
||||
ScrollIntoViewContainer container = "all";
|
||||
};
|
||||
|
||||
enum ScrollLogicalPosition { "start", "center", "end", "nearest" };
|
||||
enum ScrollIntoViewContainer { "all", "nearest" };
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#api
|
||||
partial interface Element {
|
||||
Promise<undefined> requestFullscreen();
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[position-sticky-fixed-ancestor-iframe.html]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[position-sticky-input-box-gets-focused-after-scroll.html]
|
||||
[Focusing on visible sticky input box should reset the scroll to unshifted sticky position.]
|
||||
expected: FAIL
|
|
@ -1,4 +1,5 @@
|
|||
[elementFromPoint.html]
|
||||
expected: CRASH
|
||||
[SVG element at x,y]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -266,9 +266,6 @@
|
|||
[Element interface: document.createElement("div") must inherit property "scrollIntoView([object Object\],[object Object\])" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: calling scrollIntoView(optional (boolean or ScrollIntoViewOptions)) on document.createElement("img") with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: document.createElement("img") must inherit property "convertQuadFromNode(DOMQuadInit, GeometryNode, optional ConvertCoordinateOptions)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -278,9 +275,6 @@
|
|||
[CSSPseudoElement interface: operation convertPointFromNode(DOMPointInit, GeometryNode, optional ConvertCoordinateOptions)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: document.createElementNS("x", "y") must inherit property "scrollIntoView(optional (boolean or ScrollIntoViewOptions))" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: document.createElement("img") must inherit property "getBoxQuads(optional BoxQuadOptions)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -401,15 +395,6 @@
|
|||
[Text interface: calling getBoxQuads(optional BoxQuadOptions) on document.createTextNode("x") with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: calling scrollIntoView(optional (boolean or ScrollIntoViewOptions)) on document.createElement("div") with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: document.createElement("img") must inherit property "scrollIntoView(optional (boolean or ScrollIntoViewOptions))" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: operation scrollIntoView(optional (boolean or ScrollIntoViewOptions))]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: document must inherit property "convertPointFromNode(DOMPointInit, GeometryNode, optional ConvertCoordinateOptions)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -422,12 +407,6 @@
|
|||
[CSSPseudoElement interface: operation getBoxQuads(optional BoxQuadOptions)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: calling scrollIntoView(optional (boolean or ScrollIntoViewOptions)) on document.createElementNS("x", "y") with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: document.createElement("div") must inherit property "scrollIntoView(optional (boolean or ScrollIntoViewOptions))" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: document.createElementNS("x", "y") must inherit property "convertRectFromNode(DOMRectReadOnly, GeometryNode, optional ConvertCoordinateOptions)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -35,15 +35,6 @@
|
|||
[Element with smooth scroll-behavior ; scrollBy() with smooth behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Element with auto scroll-behavior ; scrollIntoView() with default behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Element with auto scroll-behavior ; scrollIntoView() with auto behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Element with auto scroll-behavior ; scrollIntoView() with instant behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Element with auto scroll-behavior ; scrollIntoView() with smooth behavior]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -53,9 +44,6 @@
|
|||
[Element with smooth scroll-behavior ; scrollIntoView() with auto behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Element with smooth scroll-behavior ; scrollIntoView() with instant behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Element with smooth scroll-behavior ; scrollIntoView() with smooth behavior]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -35,15 +35,6 @@
|
|||
[Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Main frame with auto scroll-behavior ; scrollIntoView() with default behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Main frame with auto scroll-behavior ; scrollIntoView() with auto behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Main frame with auto scroll-behavior ; scrollIntoView() with instant behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Main frame with auto scroll-behavior ; scrollIntoView() with smooth behavior]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -53,9 +44,6 @@
|
|||
[Main frame with smooth scroll-behavior ; scrollIntoView() with auto behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Main frame with smooth scroll-behavior ; scrollIntoView() with instant behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Main frame with smooth scroll-behavior ; scrollIntoView() with smooth behavior]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
[scroll-behavior-smooth-positions.html]
|
||||
[Scroll positions when performing smooth scrolling from (0, 500) to (500, 250) using scrollIntoView() ]
|
||||
expected: FAIL
|
||||
|
||||
[Scroll positions when performing smooth scrolling from (1000, 500) to (500, 250) using scrollIntoView() ]
|
||||
expected: FAIL
|
||||
|
||||
[Scroll positions when performing smooth scrolling from (0, 0) to (500, 250) using scrollIntoView() ]
|
||||
expected: FAIL
|
||||
|
||||
[Scroll positions when performing smooth scrolling from (1000, 0) to (500, 250) using scrollIntoView() ]
|
||||
expected: FAIL
|
||||
|
||||
[Make sure the page is ready for animation.]
|
||||
expected: FAIL
|
||||
expected: FAIL
|
|
@ -35,15 +35,6 @@
|
|||
[Subframe with smooth scroll-behavior ; scrollBy() with smooth behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Subframe with auto scroll-behavior ; scrollIntoView() with default behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Subframe with auto scroll-behavior ; scrollIntoView() with auto behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Subframe with auto scroll-behavior ; scrollIntoView() with instant behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Subframe with auto scroll-behavior ; scrollIntoView() with smooth behavior]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -53,9 +44,6 @@
|
|||
[Subframe with smooth scroll-behavior ; scrollIntoView() with auto behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Subframe with smooth scroll-behavior ; scrollIntoView() with instant behavior]
|
||||
expected: FAIL
|
||||
|
||||
[Subframe with smooth scroll-behavior ; scrollIntoView() with smooth behavior]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[scrollIntoView-align-scrollport-covering-child.html]
|
||||
[scrollIntoView scrolls scrollport-covering child in both axes]
|
||||
expected: FAIL
|
|
@ -1,15 +0,0 @@
|
|||
[scrollIntoView-container.html]
|
||||
[scrollIntoView() defaults to scrolling ancestors]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({container: 'all'}) scrolls ancestors]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({container: 'nearest'}) only scrolls nearest scroll container]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({container: 'nearest'}) doesn't stop at itself]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({container: 'nearest'}) doesn't propagate to outer frames]
|
||||
expected: FAIL
|
|
@ -1,4 +0,0 @@
|
|||
[scrollIntoView-horizontal-partially-visible.html]
|
||||
[scrollIntoView scrolls partially-visible child in both axes]
|
||||
expected: FAIL
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
[scrollIntoView-horizontal-tb-writing-mode.html]
|
||||
[scrollIntoView({"block":"center","inline":"center"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"end","inline":"start"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"start","inline":"center"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"center","inline":"start"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"start","inline":"start"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"end","inline":"center"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"end","inline":"end"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"start","inline":"end"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"center","inline":"end"})]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[scrollIntoView-inline-image.html]
|
||||
[Scrolling an inline element with a large line height uses the bounding rect]
|
||||
expected: FAIL
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
[scrollIntoView-multiple-nested.html]
|
||||
expected: TIMEOUT
|
||||
[Simultaneous smooth scrollIntoViews run to completion]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Simultaneous smooth,instant scrollIntoViews run to completion]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Simultaneous instant,smooth scrollIntoViews run to completion]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Simultaneous instant scrollIntoViews run to completion]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
[scrollIntoView-multiple.html]
|
||||
expected: TIMEOUT
|
||||
[Simultaneous smooth scrollIntoViews run to completion]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Simultaneous smooth,instant scrollIntoViews run to completion]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Simultaneous instant,smooth scrollIntoViews run to completion]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Simultaneous instant scrollIntoViews run to completion]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[scrollIntoView-shadow.html]
|
||||
[scrollIntoView should behave correctly if applies to shadow dom elements]
|
||||
expected: FAIL
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
[scrollIntoView-smooth.html]
|
||||
expected: TIMEOUT
|
||||
[Smooth scrollIntoView should scroll the element to the 'center' position]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Smooth scrollIntoView should scroll the element to the 'end' position]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Smooth scrollIntoView should scroll the element to the 'nearest' position]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Smooth scrollIntoView should scroll the element to the 'start' position]
|
||||
expected: FAIL
|
||||
|
||||
expected: NOTRUN
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
[scrollIntoView-vertical-lr-writing-mode.html]
|
||||
[scrollIntoView({"block":"center","inline":"center"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"end","inline":"start"})]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -11,18 +8,11 @@
|
|||
[scrollIntoView({"block":"center","inline":"start"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"start","inline":"start"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"end","inline":"center"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"end","inline":"end"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"start","inline":"end"})]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({"block":"center","inline":"end"})]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[scrollintoview-containingblock-chain.html]
|
||||
[scrollIntoView should not scroll ancestor overflow:scroll elements that are not containing block ancestors]
|
||||
expected: FAIL
|
|
@ -1,121 +0,0 @@
|
|||
[scrollintoview.html]
|
||||
[scrollIntoView(null) starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "start", inline: "start"}) starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "nearest", inline: "nearest"}) starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(false) starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "end", inline: "end"}) starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView() starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(undefined) starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(false) starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({}) starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "end", inline: "end"}) starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView() starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "nearest", inline: "nearest"}) starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(undefined) starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(true) starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "start", inline: "start"}) starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "center", inline: "center"}) starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "end", inline: "end"}) starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(true) starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "center", inline: "center"}) starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(true) starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "nearest", inline: "nearest"}) starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(false) starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({}) starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "center", inline: "center"}) starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(false) starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView() starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(undefined) starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({}) starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "end", inline: "end"}) starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(null) starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(null) starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "start", inline: "start"}) starting at right,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "center", inline: "center"}) starting at left,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "nearest", inline: "nearest"}) starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(null) starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({block: "start", inline: "start"}) starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(true) starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView(undefined) starting at right,top]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView() starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
||||
[scrollIntoView({}) starting at left,bottom]
|
||||
expected: FAIL
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
[focus-centers-element.html]
|
||||
[Element.focus() center in both directions]
|
||||
expected: FAIL
|
|
@ -1,4 +0,0 @@
|
|||
[scroll-matches-focus.html]
|
||||
expected: TIMEOUT
|
||||
[:focus applies before scrolling into view]
|
||||
expected: TIMEOUT
|
|
@ -1,2 +1,2 @@
|
|||
[hidden-until-found-001.html]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[preventScroll-nested-scroll-elements.html]
|
||||
[focus(options) - preventScroll on nested scroll elements]
|
||||
expected: FAIL
|
3
tests/wpt/meta/html/interaction/focus/processing-model/preventScroll-textarea.html.ini
vendored
Normal file
3
tests/wpt/meta/html/interaction/focus/processing-model/preventScroll-textarea.html.ini
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[preventScroll-textarea.html]
|
||||
[preventScroll: true on a textarea element]
|
||||
expected: FAIL
|
|
@ -1,18 +1,3 @@
|
|||
[preventScroll.html]
|
||||
[Sanity test]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus() without arguments]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus(undefined)]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus(null)]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus({})]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus({preventScroll: false})]
|
||||
[elm.focus({preventScroll: true})]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[textarea-scroll-selection.html]
|
||||
[programatic focus() scrolls selection into view including ancestors]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
[iframe-loading-lazy.html]
|
||||
expected: ERROR
|
||||
[Below-viewport srcdoc iframes load lazily]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[move-element-and-scroll.html]
|
||||
expected: ERROR
|
||||
[Test that <img> below viewport is not loaded when moved to another document and then scrolled to]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[remove-element-and-scroll.html]
|
||||
expected: ERROR
|
||||
[Test that <img> below viewport is not loaded when removed from the document and then scrolled to]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[scrolling-below-viewport-image-lazy-loading-in-iframe.html]
|
||||
[Scrolling a lazy loaded image into view in an iframe]
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue