-
Notifications
You must be signed in to change notification settings - Fork 3k
Add scrollOptions for Element.focus() #2787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Hi @jihyerish, as you can see from the Travis CI results, the build is failing. This makes it hard to review your changes. Can you fix the patch so that it compiles and builds, at least locally on your computer? Let us know if you need any help. |
You also seem to have made a lot of changes that revert recent work we've done on HTML. If you could please not do that, that would be ideal. |
@domenic Sorry! I didn't know that. I'll fix this. |
I had a quick question. Why don't we use the same options as ScrollIntoViewOptions in this case as well? Is there any attribute there that doesn't apply here? |
@NavidZ You're right. As ScrollIntoViewOptions, the scrollOptions specifies the scrolling behavior and the scrolling position, but there is From that point of view, ScrollIntoViewOptions may have |
Basically that is what I was suggesting. Instead of defining a new dictionary why not just reuse the ScrollIntoViewOption which also has other applicable options like inline and then somewhere add a none behavior and in the steps of the focus just call into ScrollIntoView or something. This way you don't even need to redefine all the behavior of values for the keys in ScrollIntoViewOptions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like @NavidZ's idea. If I am understanding that will require IDL like:
dictionary FocusOptions {
ScrollIntoViewOptions scroll;
};
Then the usage would be either .focus()
(equivalent to .focus({ scroll: undefined })
), or .focus({ scroll: { behavior: "smooth" } })
or similar.
This needs to be added to this spec patch, however; right now there are no IDL changes at all.
@@ -73384,14 +73384,16 @@ | |||
</dd> | |||
--> | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to update the IDL, around line 9871.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't we want to define something like this:
dictionary FocusOptions {
ScrollIntoViewOptions scroll;
};
and use that dictionary here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we could use ScrollIntoViewOptions here if the "none" value is added to it.
I made an issue about it in CSSOM - w3c/csswg-drafts#1608.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I specified the naming of the option for Element.focus() as "scrollOptions".
But there is already "ScrollOptions" in CSSOM.
I'll change "scrollOptions" to "focusOptions".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding the "none" value in the ScrollBehavior I don't think that will be the best option here. How about just relying on the scrolloptions
key in the FocusOptions
dictionary in your last patch? So the scrolloptions
is either undefined which we can interpret as no scrolling or it is a ScrollIntoViewOptions which then gets passed to the scrollIntoView algorithm. This way we do not need to add a "none" value to the "ScrollBehavior".
This is I believe what @domenic agreed to as well:
#2787 (review)
So if somebody calls .focus({ scrolloptions: undefined })
then we would not scroll (instead of adding "none" to ScrollBehavior
). If somebody calls focus() it is as if they call .focus({scrolloptions: {behavior: auto}}
) which is the current behavior of focus regarding scrolling. Also if they desire to pass a full scrolling options for focus they can do that as well.
btw shouldn't we use scrollOptions
instead of scrolloptions
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the IDL, around line 9939 and 9949.
source
Outdated
|
||
<p>If the element is a <span>browsing context container</span>, moves the focus to the <span>nested browsing context</span> instead.</p> | ||
|
||
<p>If the focused element is in a scrollable region and partially visible within the <span>viewport</span>, it may scroll into the <span>viewport</span>. The scroll behavior of is decided by <var>scrollOptions</var>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few issues:
- What does "in a scrollable region" mean? Is that term defined anywhere?
- What does "partially visible within the viewport" mean? Is that defined anywhere?
- You cannot use "may" inside non-normative text like this description. Probably this should be "can"? Or "will"?
- "The scroll behavior of is" should just be "The scroll behavior is"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does "in a scrollable region" mean? Is that term defined anywhere?
In the Focus section in HTML Standard, the term "scrollable regions" is used to describe the viewport of a box which an element can scroll into.
But there isn't any definition about it in the spec.
"scrolling area" in CSSOM is similar to "scrollable regions".
What does "partially visible within the viewport" mean? Is that defined anywhere?
It means that the entire area of an element isn't in the viewport.
The expression of "part of an element" is used in the spec, so I think it's better to change the sentence by using it.
You cannot use "may" inside non-normative text like this description.
Probably this should be "can"? Or "will"?
"The scroll behavior of is" should just be "The scroll behavior is"
Thanks for the correction! I'll fix those. : )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for helping me out here. "scrollable region" seems OK then, although maybe we should work in the future on updating to consolidate with CSSOM.
I'm OK with either of "part of an element" or "partially visible within the viewport". But I am still not sure I understand the meaning. Does this mean that if something is too far down the page to be visible, we won't scroll to it? Is that intentional? Why would we add such a restriction?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the first time, I thought controlling the scroll behavior for the invisible element within the viewport is unnecessary. So I considered only the visible elements to apply this feature.
But now I also think we don't need the restriction on the visibility of an element.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But now I also think we don't need the restriction on the visibility of an element.
If an element is entirely inside the viewport, we shouldn't scroll it, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@EiraGe Yes, it is. This will work as "scrollIntoView()".
source
Outdated
<li><p>Mark the element as <dfn>locked for focus</dfn>.</p></li> | ||
|
||
<li><p>Run the <span>focusing steps</span> for the element.</p></li> | ||
<li><p>If the element is in the scrollable region, take <var>scrollOptions</var> as the scroll behavior.</p></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted above "is in the scrollable region" doesn't seem to be defined.
Also, the statement "take scrollOptions as the scroll behavior" is meaningless. Probably this should be something like "scroll the element into view using scrollOptions"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it seems much better!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest not adding any conditions here and other places in this patch. We already have these conditions in the scroll steps. So just mentioning the call into the scroll function will take care of the cases that there are no scrollable boxes and whatnot.
The only condition needed here is if ScrollIntoViewOptions is null/false/undefined (whichever we decide for not scrolling) then do not call scroll function and effectively don't scroll. Otherwise call it and pass the options to it.
We also need to define the default value that doesn't interfere with not scrolling value and also indicates the current scroll behavior for that default which I believe is doing the scroll. Right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have these conditions in the scroll steps. So just mentioning the call into the scroll function will take care of the cases that there are no scrollable boxes and whatnot.
The scroll steps that you mentioned above is described in scrollIntoView function.
Does scrolling effect triggered by focus always call the scrollIntoView function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can call that out in the spec that focus calls into scrollIntoView. I don't see any reason not to.
source
Outdated
|
||
</ol> | ||
|
||
User agents may scroll the focused element if it is partially within the <span>viewport</span> of the scrollable region. The behavior of scroll is specified with <var>scrollOptions</var>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This algorithm is in general pretty confusing; it's not clear when it applies, and it takes no inputs or outputs. Probably we want to delegate to https://drafts.csswg.org/cssom-view/#scroll-an-element-into-view if at all possible instead.
If https://drafts.csswg.org/cssom-view/#scroll-an-element-into-view is not good, could you describe the intent of the algorithm first, and then we can work together on crafting the right text for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take the algorithm mentioned in https://drafts.csswg.org/cssom-view/#scroll-an-element-into-view as mush as possible. Thanks! : )
source
Outdated
<li><p>Mark the element as <dfn>locked for focus</dfn>.</p></li> | ||
|
||
<li><p>Run the <span>focusing steps</span> for the element.</p></li> | ||
<li><p>If the element is in the scrollable region, take <var>scrollOptions</var> as the scroll behavior.</p></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest not adding any conditions here and other places in this patch. We already have these conditions in the scroll steps. So just mentioning the call into the scroll function will take care of the cases that there are no scrollable boxes and whatnot.
The only condition needed here is if ScrollIntoViewOptions is null/false/undefined (whichever we decide for not scrolling) then do not call scroll function and effectively don't scroll. Otherwise call it and pass the options to it.
We also need to define the default value that doesn't interfere with not scrolling value and also indicates the current scroll behavior for that default which I believe is doing the scroll. Right?
@@ -73384,14 +73384,16 @@ | |||
</dd> | |||
--> | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't we want to define something like this:
dictionary FocusOptions {
ScrollIntoViewOptions scroll;
};
and use that dictionary here?
thank u |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated IDL in the commit 4bf4a2c
@domenic |
If someone calls
|
source
Outdated
[<span>CEReactions</span>] attribute [TreatNullAs=EmptyString] DOMString <span data-x="dom-innerText">innerText</span>; | ||
}; | ||
|
||
dictionary <dfn>FocusOptions</dfn> : <a href="https://drafts.csswg.org/cssom-view/#dictdef-scrollintoviewoptions">ScrollIntoViewOptions</a> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not inherit from ScrollIntoViewOptions, since it contains ScrollIntoViewOptions.
source
Outdated
}; | ||
|
||
dictionary <dfn>FocusOptions</dfn> : <a href="https://drafts.csswg.org/cssom-view/#dictdef-scrollintoviewoptions">ScrollIntoViewOptions</a> { | ||
<a href="https://drafts.csswg.org/cssom-view/#dictdef-scrollintoviewoptions">ScrollIntoViewOptions</a> scrolloptions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use <a href="">
inside IDL blocks. Instead, we use <span>ScrollIntoViewOptions</span>
, and add something to the "References" section. In this case it would be around line 3560.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your comment! I'll fix this.
source
Outdated
<li><p>Run the <span>focusing steps</span> for the element.</p></li> | ||
<li><p>If the element is in the scrollable region, take <var>options</var> as the scroll behavior.</p></li> | ||
|
||
<li><p>Run the <span>focusing steps</span> for the element with <var>options</var>.</p></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The focusing steps do not take options as an argument, so this doesn't work. It's like calling a function with arguments that it does not accept; it won't compile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's right. The option is irrelevant to the focusing steps.
I was under this impression that |
Oh, sorry for misunderstanding this; I was assuming it did not, without testing.
Yeah, that's not correct. In Web IDL, supplying undefined for a dictionary is the same as supplying a dictionary with all its values set to its defaults. (And
I think adding to ScrollBehavior is the best option, as it's much more clear for developers. If you're not willing to do that... perhaps we should take a step back and think about what API we want to present to developers, before getting into the IDL details. For example, one possibility I just came up with is: el.focus({ scroll: "auto" });
el.focus(); // same as above
el.focus({ scroll: "none" });
el.focus({ scroll: "instant" });
el.focus({ scroll: "smooth" });
el.focus({ scroll: "smooth", scrollOptions: { block: "start", inline: "end" }); Getting this properly integrated with the various underlying specs is difficult, but I'd be happy to help there. But first I think we should work on agreement on what API we want, regardless of how it integrates with other specs. |
My only concern for adding the "none" to ScrollBehavior is that it is a parameter to a function that its job is to scroll with different behaviors. So if one doesn't want to scroll they shouldn't even call into that function (i.e. scrollIntoView) in the first place rather than a parameter telling that function to do nothing. However, that was the only thing I had in mind which I agree it might not be the strongest point. So if we cannot come up with anything clean I certainly would be fine with adding One question regarding your suggestion:
Isn't |
My point was that we should not worry about the IDL; we should figure out what user-facing API we want. Thus this may involve creating new enumerations, dictionaries, or any of that so as to get the better experience for users. I'd like us to figure out what that experience is, before worrying about how it fits with existing or new IDL constructs. |
How about this: |
Hmm, that departs from JavaScript APIs in several ways that we should avoid:
Can we come up with an API that avoids these pitfalls? |
- Don't use dictionary member names to discuss options to the scroll into view algorithm - Move FocusOptions definition near focus()'s definition - Make the developer-facing documentation more explicit and don't mention spec-level concepts like dictionaries - Tag closing or whitespace tweaks especially to make the diff simpler
I did a review and decided to just push small tweaks for the editorial issues I found. Nothing major. I will switch my status to approved. What remains before we can merge this is web-platform-tests and interest from another browser implementer. I understand Chrome is interested; was there any word on others? |
@domenic Thanks for the review and approval! @smaug---- Am I understanding correctly? |
Ah, thank you, I forgot there was a corresponding issue thread. In that case all we need is tests! |
Wait, no, @zcorpan wrote tests!! web-platform-tests/wpt#7915 and web-platform-tests/wpt#7917 . I'll work on getting this all merged tomorrow then \o/ |
Yay, finally!! 😆 Thank you! |
ugh, the discussion is again nicely split to PR and Issue. But ok, initially there will be just a way to prevent scrolling, right and no other customizations? Sounds ok. |
@smaug---- Yes, for now only the option to prevent scrolling will be added. |
Add scrollOptions to Element.focus()
This option allows the author to define the scroll behavior triggered when a focused element is partially viewed within the viewport.
auto: A focused element scrolls into viewport instantly
none: A focused element doesn't scroll into viewport
smooth: A focused element scrolls into viewport smoothly
start: A focused element scrolls to the start (top) of the viewport.
end: A focused element scrolls to the end (bottom) of the viewport.
scrollOptions refers to the scrollIntoViewOptions of Element.scrollIntoView().
Closes #834