-
Notifications
You must be signed in to change notification settings - Fork 12
t/173: Created various DOM utilities to allow the view document scroll to the selection #174
Conversation
…clusion of borders and scrollbars.
…ports in scroll.js.
src/dom/getborderwidths.js
Outdated
import global from './global'; | ||
|
||
/** | ||
* Returns an object containing CSS border withs of a specified `HTMLElement`. |
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.
widths*
HTML element
src/dom/getborderwidths.js
Outdated
left: computedStyles.borderLeftWidth | ||
}; | ||
|
||
for ( const width in borderWidths ) { |
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.
Just use parseInt()
above and return the object without iterating over it. That will be shorter and faster.
src/dom/rect.js
Outdated
@@ -234,21 +247,63 @@ export default class Rect { | |||
} | |||
|
|||
/** | |||
* Checks if all properties ({@link #top}, {@link #left}, {@link #right}, | |||
* {@link #bottom}, {@link #width} and {@link #height}) are the same as in the other `Rect`. |
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.
are the same -> equal? properties are "the same" has a bit different meaning than "values of these properties equal ...". It's a detail and shouldn't be confusing, but I found the wording a bit unusual.
src/dom/rect.js
Outdated
} | ||
|
||
/** | ||
* Checks whether a `Rect` fully contains another `Rect` instance. |
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 same issue as everywhere else – I don't think that it makes sense to abuse preformatted text and type names. IMO, this makes reading the descriptions harder because the text is less heterogeneous. Plus, it's semantically incorrect as well because you're not checking Rect
(type) here but a rect instance.
For me, it should be: "Checks whether this rect fully contains another rect instance."
The same applies to many other places in these docs.
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.
cc @AnnaTomanek
src/dom/rect.js
Outdated
contains( anotherRect ) { | ||
const intersectRect = this.getIntersection( anotherRect ); | ||
|
||
if ( !intersectRect || !intersectRect.isEqual( anotherRect ) ) { |
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.
return intersectRect && intersectRect.isEqual( anotherRect );
?
src/dom/rect.js
Outdated
*/ | ||
static getViewportRect() { | ||
static getViewportRect( options = {} ) { |
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.
Why does this method look like one big hack? There's something wrong with this method's constructor if you need to override stuff like _source
and call private methods once an instance was initialised.
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 removed the method and allowed new Rect( window )
. See the updated docs.
src/dom/rect.js
Outdated
rect._source = global.window; | ||
|
||
if ( options.excludeScrollbars ) { | ||
rect._excludeScrollbarsAndBorders(); |
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.
Couldn't this be a public method? It'd make more sense to call it manually, rather than add the options
param everywhere.
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 made a public method out of this thing.
src/dom/scroll.js
Outdated
* by keeping the `target` some distance from the edge of the viewport and thus making it easier to | ||
* read or edit by the user. | ||
*/ | ||
function scrollViewportToShowTarget( { target, viewportOffset = 0 } ) { |
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.
won't scrollViewportToShowTarget( { target } )
crash? It will leave viewportOffset
set to undefined or not? I can never remember;|
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.
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.
OK, the problems I remembered were with this notation: function x( a = { x: 1, y: 2 } )
.
// | ||
// To prevent this, we're checking the rects moved by the viewportOffset to cover | ||
// the upper/lower edge of the viewport. | ||
const rects = [ targetShiftedUpRect, targetShiftedDownRect ]; |
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.
Yyyy... Are you sure about this method's code? I don't want to analyse it :D
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 a pure magic 😄
src/dom/scroll.js
Outdated
} while ( ( parent = parent.parentNode ) ); | ||
} | ||
|
||
export default { |
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.
Why exporting this as an object? For testing purposes? Please explain it then. And in fact, it's better to expose these functions separately and then expose a test object with the two of them. So that object will be protected, while the functions will be nice and clean and exposed separately.
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 for testing purposes, e.g. to mock scrollAncestorsToShowTarget()
and check if scrollViewportToShowTarget()
always calls it first.
Without the mock, the test becomes ridiculously complex because both viewport and ancestors are to be scrolled and it's fairly obvious that scrollAncestorsToShowTarget()
is already tested extensively in the other place.
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.
OK, but you can still code this in a clearer way:
const module = { a, b };
export function a() {
module.b();
}
export function b() {
...
}
export { module as _test };
Thanks to the fact that a()
uses b()
through module
you can still mock the stuff.
/* global Node */ | ||
|
||
/** | ||
* @module utils/dom/scroll |
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.
Do I see correctly that there are no tests for this module?
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.
There are lots of them.
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.
OK, they got folded so I missed them.
I love the manual test :D The description is unclear (it's too complicated – it's hard to figure out what you're actually supposed to do) but you can play with these elements in various ways. I'd only do one change – make the squares borders' rounded. That will help in recognizing whether the entire square is visible. Something like 5px will be enough. You can also think about different style which might help. 1px border would also be good. |
…ct and replaced it with new Rect( window ). Introduced a new instance method #excludeScrollbarsAndBorders.
enumerable: false | ||
} ); | ||
|
||
if ( isElement( source ) ) { | ||
copyRectProperties( this, source.getBoundingClientRect() ); | ||
} else if ( isRange( source ) ) { | ||
copyRectProperties( this, Rect.getDomRangeRects( source )[ 0 ] ); | ||
} else if ( source === global.window ) { |
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 about other windows? Iframes will have their own. This deserves a followup.
PS. The next line is not optimal (you could use source
).
let scrollBarWidth, scrollBarHeight; | ||
|
||
if ( source === global.window ) { | ||
scrollBarWidth = global.window.innerWidth - global.document.documentElement.clientWidth; |
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.
Just like I commented above – depending on the main window and document is unsafe.
* @returns {Boolean} `true` if contains, `false` otherwise. | ||
*/ | ||
contains( anotherRect ) { | ||
const intersectRect = this.getIntersection( anotherRect ); |
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 about two rects next to each other?
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.
OK, nvmnd. I didn't ask :D
And here's the followup: https://github.com/ckeditor/ckeditor5-utils/issues/175. |
Suggested merge commit message (convention)
Feature: Created various DOM utilities to allow the view document scroll to the selection. Closes ckeditor/ckeditor5#4966.
BREAKING CHANGE: The static
Rect.getViewportRect
method has been removed. Usenew Rect( window )
instead.