2021-10-10 19:12:32 +02:00
/*
2024-10-04 13:19:50 +02:00
* Copyright ( c ) 2021 - 2022 , Andreas Kling < andreas @ ladybird . org >
2021-10-10 19:12:32 +02:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
# include <LibWeb/Bindings/Intrinsics.h>
2024-04-27 12:09:58 +12:00
# include <LibWeb/Bindings/SelectionPrototype.h>
2022-10-11 16:54:42 +02:00
# include <LibWeb/DOM/Document.h>
# include <LibWeb/DOM/Range.h>
2021-10-10 19:12:32 +02:00
# include <LibWeb/Selection/Selection.h>
namespace Web : : Selection {
2023-11-19 19:47:52 +01:00
JS_DEFINE_ALLOCATOR ( Selection ) ;
2023-08-13 13:05:26 +02:00
JS : : NonnullGCPtr < Selection > Selection : : create ( JS : : NonnullGCPtr < JS : : Realm > realm , JS : : NonnullGCPtr < DOM : : Document > document )
2021-10-10 19:12:32 +02:00
{
2023-08-13 13:05:26 +02:00
return realm - > heap ( ) . allocate < Selection > ( realm , realm , document ) ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
Selection : : Selection ( JS : : NonnullGCPtr < JS : : Realm > realm , JS : : NonnullGCPtr < DOM : : Document > document )
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
: PlatformObject ( realm )
2022-10-11 16:54:42 +02:00
, m_document ( document )
2022-09-04 13:20:53 +02:00
{
}
Selection : : ~ Selection ( ) = default ;
2023-08-07 08:41:28 +02:00
void Selection : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2023-08-07 08:41:28 +02:00
Base : : initialize ( realm ) ;
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( Selection ) ;
2023-01-10 06:28:20 -05:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dfn-empty
bool Selection : : is_empty ( ) const
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// Each selection can be associated with a single range.
// When there is no range associated with the selection, the selection is empty.
// The selection must be initially empty.
// NOTE: This function should not be confused with Selection.empty() which empties the selection.
return ! m_range ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
void Selection : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( m_range ) ;
visitor . visit ( m_document ) ;
}
// https://w3c.github.io/selection-api/#dfn-anchor
JS : : GCPtr < DOM : : Node > Selection : : anchor_node ( )
{
if ( ! m_range )
return nullptr ;
if ( m_direction = = Direction : : Forwards )
return m_range - > start_container ( ) ;
return m_range - > end_container ( ) ;
}
// https://w3c.github.io/selection-api/#dfn-anchor
2021-10-10 19:12:32 +02:00
unsigned Selection : : anchor_offset ( )
{
2022-10-11 16:54:42 +02:00
if ( ! m_range )
return 0 ;
if ( m_direction = = Direction : : Forwards )
return m_range - > start_offset ( ) ;
return m_range - > end_offset ( ) ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dfn-focus
JS : : GCPtr < DOM : : Node > Selection : : focus_node ( )
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
if ( ! m_range )
return nullptr ;
if ( m_direction = = Direction : : Forwards )
return m_range - > end_container ( ) ;
return m_range - > start_container ( ) ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dfn-focus
2021-10-10 19:12:32 +02:00
unsigned Selection : : focus_offset ( ) const
{
2022-10-11 16:54:42 +02:00
if ( ! m_range )
return 0 ;
if ( m_direction = = Direction : : Forwards )
return m_range - > end_offset ( ) ;
return m_range - > start_offset ( ) ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-iscollapsed
2021-10-10 19:12:32 +02:00
bool Selection : : is_collapsed ( ) const
{
2022-10-11 16:54:42 +02:00
// The attribute must return true if and only if the anchor and focus are the same
// (including if both are null). Otherwise it must return false.
2024-10-12 02:42:55 +02:00
if ( ! m_range )
return true ;
return const_cast < Selection * > ( this ) - > anchor_node ( ) = = const_cast < Selection * > ( this ) - > focus_node ( )
& & m_range - > start_offset ( ) = = m_range - > end_offset ( ) ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-rangecount
2021-10-10 19:12:32 +02:00
unsigned Selection : : range_count ( ) const
{
2022-10-11 16:54:42 +02:00
if ( m_range )
return 1 ;
return 0 ;
2021-10-10 19:12:32 +02:00
}
2023-08-26 16:39:52 +12:00
String Selection : : type ( ) const
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
if ( ! m_range )
2023-08-26 16:39:52 +12:00
return " None " _string ;
2022-10-11 16:54:42 +02:00
if ( m_range - > collapsed ( ) )
2023-08-26 16:39:52 +12:00
return " Caret " _string ;
return " Range " _string ;
2021-10-10 19:12:32 +02:00
}
2024-10-13 14:38:25 +11:00
String Selection : : direction ( ) const
{
if ( ! m_range | | m_direction = = Direction : : Directionless )
return " none " _string ;
if ( m_direction = = Direction : : Forwards )
return " forward " _string ;
return " backward " _string ;
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-getrangeat
WebIDL : : ExceptionOr < JS : : GCPtr < DOM : : Range > > Selection : : get_range_at ( unsigned index )
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// The method must throw an IndexSizeError exception if index is not 0, or if this is empty.
if ( index ! = 0 | | is_empty ( ) )
2024-10-12 20:56:21 +02:00
return WebIDL : : IndexSizeError : : create ( realm ( ) , " Selection.getRangeAt() on empty Selection or with invalid argument " _string ) ;
2022-10-11 16:54:42 +02:00
// Otherwise, it must return a reference to (not a copy of) this's range.
return m_range ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-addrange
void Selection : : add_range ( JS : : NonnullGCPtr < DOM : : Range > range )
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// 1. If the root of the range's boundary points are not the document associated with this, abort these steps.
if ( & range - > start_container ( ) - > root ( ) ! = m_document . ptr ( ) )
return ;
// 2. If rangeCount is not 0, abort these steps.
if ( range_count ( ) ! = 0 )
return ;
// 3. Set this's range to range by a strong reference (not by making a copy).
2023-01-11 19:48:53 +01:00
set_range ( range ) ;
2024-10-13 14:39:02 +11:00
// AD-HOC: WPT selection/removeAllRanges.html and selection/addRange.htm expect this
m_direction = Direction : : Forwards ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-removerange
WebIDL : : ExceptionOr < void > Selection : : remove_range ( JS : : NonnullGCPtr < DOM : : Range > range )
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// The method must make this empty by disassociating its range if this's range is range.
if ( m_range = = range ) {
2023-01-11 19:48:53 +01:00
set_range ( nullptr ) ;
2022-10-11 16:54:42 +02:00
return { } ;
}
// Otherwise, it must throw a NotFoundError.
2024-10-12 20:56:21 +02:00
return WebIDL : : NotFoundError : : create ( realm ( ) , " Selection.removeRange() with invalid argument " _string ) ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-removeallranges
2021-10-10 19:12:32 +02:00
void Selection : : remove_all_ranges ( )
{
2022-10-11 16:54:42 +02:00
// The method must make this empty by disassociating its range if this has an associated range.
2023-01-11 19:48:53 +01:00
set_range ( nullptr ) ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-empty
2021-10-10 19:12:32 +02:00
void Selection : : empty ( )
{
2022-10-11 16:54:42 +02:00
// The method must be an alias, and behave identically, to removeAllRanges().
remove_all_ranges ( ) ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-collapse
2022-12-09 21:57:10 +01:00
WebIDL : : ExceptionOr < void > Selection : : collapse ( JS : : GCPtr < DOM : : Node > node , unsigned offset )
2021-10-10 19:12:32 +02:00
{
2022-12-09 21:57:10 +01:00
// 1. If node is null, this method must behave identically as removeAllRanges() and abort these steps.
if ( ! node ) {
remove_all_ranges ( ) ;
return { } ;
}
// 2. The method must throw an IndexSizeError exception if offset is longer than node's length and abort these steps.
if ( offset > node - > length ( ) ) {
2024-10-12 20:56:21 +02:00
return WebIDL : : IndexSizeError : : create ( realm ( ) , " Selection.collapse() with offset longer than node's length " _string ) ;
2022-12-09 21:57:10 +01:00
}
2024-09-02 14:03:45 +02:00
// 3. If document associated with this is not a shadow-including inclusive ancestor of node, abort these steps.
if ( ! m_document - > is_shadow_including_inclusive_ancestor_of ( * node ) )
2022-12-09 21:57:10 +01:00
return { } ;
// 4. Otherwise, let newRange be a new range.
2023-08-13 13:05:26 +02:00
auto new_range = DOM : : Range : : create ( * m_document ) ;
2022-12-09 21:57:10 +01:00
// 5. Set the start the start and the end of newRange to (node, offset).
TRY ( new_range - > set_start ( * node , offset ) ) ;
// 6. Set this's range to newRange.
2023-01-11 19:48:53 +01:00
set_range ( new_range ) ;
2022-12-09 21:57:10 +01:00
return { } ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-setposition
2022-12-09 21:57:10 +01:00
WebIDL : : ExceptionOr < void > Selection : : set_position ( JS : : GCPtr < DOM : : Node > node , unsigned offset )
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// The method must be an alias, and behave identically, to collapse().
2022-12-09 21:57:10 +01:00
return collapse ( node , offset ) ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-collapsetostart
2022-12-09 22:08:16 +01:00
WebIDL : : ExceptionOr < void > Selection : : collapse_to_start ( )
2021-10-10 19:12:32 +02:00
{
2022-12-09 22:08:16 +01:00
// 1. The method must throw InvalidStateError exception if the this is empty.
if ( ! m_range ) {
2024-10-12 20:56:21 +02:00
return WebIDL : : InvalidStateError : : create ( realm ( ) , " Selection.collapse_to_start() on empty range " _string ) ;
2022-12-09 22:08:16 +01:00
}
// 2. Otherwise, it must create a new range
2023-08-13 13:05:26 +02:00
auto new_range = DOM : : Range : : create ( * m_document ) ;
2022-12-09 22:08:16 +01:00
// 3. Set the start both its start and end to the start of this's range
TRY ( new_range - > set_start ( * anchor_node ( ) , m_range - > start_offset ( ) ) ) ;
TRY ( new_range - > set_end ( * anchor_node ( ) , m_range - > start_offset ( ) ) ) ;
// 4. Then set this's range to the newly-created range.
2023-01-11 19:48:53 +01:00
set_range ( new_range ) ;
2022-12-09 22:08:16 +01:00
return { } ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-collapsetoend
2022-12-09 22:09:03 +01:00
WebIDL : : ExceptionOr < void > Selection : : collapse_to_end ( )
2021-10-10 19:12:32 +02:00
{
2022-12-09 22:09:03 +01:00
// 1. The method must throw InvalidStateError exception if the this is empty.
if ( ! m_range ) {
2024-10-12 20:56:21 +02:00
return WebIDL : : InvalidStateError : : create ( realm ( ) , " Selection.collapse_to_end() on empty range " _string ) ;
2022-12-09 22:09:03 +01:00
}
// 2. Otherwise, it must create a new range
2023-08-13 13:05:26 +02:00
auto new_range = DOM : : Range : : create ( * m_document ) ;
2022-12-09 22:09:03 +01:00
// 3. Set the start both its start and end to the start of this's range
TRY ( new_range - > set_start ( * anchor_node ( ) , m_range - > end_offset ( ) ) ) ;
TRY ( new_range - > set_end ( * anchor_node ( ) , m_range - > end_offset ( ) ) ) ;
// 4. Then set this's range to the newly-created range.
2023-01-11 19:48:53 +01:00
set_range ( new_range ) ;
2022-12-09 22:09:03 +01:00
return { } ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-extend
WebIDL : : ExceptionOr < void > Selection : : extend ( JS : : NonnullGCPtr < DOM : : Node > node , unsigned offset )
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// 1. If node's root is not the document associated with this, abort these steps.
if ( & node - > root ( ) ! = m_document . ptr ( ) )
return { } ;
// 2. If this is empty, throw an InvalidStateError exception and abort these steps.
if ( ! m_range ) {
2024-10-12 20:56:21 +02:00
return WebIDL : : InvalidStateError : : create ( realm ( ) , " Selection.extend() on empty range " _string ) ;
2022-10-11 16:54:42 +02:00
}
// 3. Let oldAnchor and oldFocus be the this's anchor and focus, and let newFocus be the boundary point (node, offset).
auto & old_anchor_node = * anchor_node ( ) ;
auto old_anchor_offset = anchor_offset ( ) ;
auto & new_focus_node = node ;
auto new_focus_offset = offset ;
// 4. Let newRange be a new range.
2023-08-13 13:05:26 +02:00
auto new_range = DOM : : Range : : create ( * m_document ) ;
2022-10-11 16:54:42 +02:00
// 5. If node's root is not the same as the this's range's root, set the start newRange's start and end to newFocus.
if ( & node - > root ( ) ! = & m_range - > start_container ( ) - > root ( ) ) {
2022-10-30 17:50:04 +00:00
TRY ( new_range - > set_start ( new_focus_node , new_focus_offset ) ) ;
2022-10-11 16:54:42 +02:00
}
// 6. Otherwise, if oldAnchor is before or equal to newFocus, set the start newRange's start to oldAnchor, then set its end to newFocus.
else if ( old_anchor_node . is_before ( new_focus_node ) | | & old_anchor_node = = new_focus_node . ptr ( ) ) {
2022-10-30 17:50:04 +00:00
TRY ( new_range - > set_end ( new_focus_node , new_focus_offset ) ) ;
2022-10-11 16:54:42 +02:00
}
// 7. Otherwise, set the start newRange's start to newFocus, then set its end to oldAnchor.
else {
2022-10-30 17:50:04 +00:00
TRY ( new_range - > set_start ( new_focus_node , new_focus_offset ) ) ;
TRY ( new_range - > set_end ( old_anchor_node , old_anchor_offset ) ) ;
2022-10-11 16:54:42 +02:00
}
// 8. Set this's range to newRange.
2023-01-11 19:48:53 +01:00
set_range ( new_range ) ;
2022-10-11 16:54:42 +02:00
// 9. If newFocus is before oldAnchor, set this's direction to backwards. Otherwise, set it to forwards.
if ( new_focus_node - > is_before ( old_anchor_node ) ) {
m_direction = Direction : : Backwards ;
} else {
m_direction = Direction : : Forwards ;
}
return { } ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-setbaseandextent
2022-12-09 19:00:18 +00:00
WebIDL : : ExceptionOr < void > Selection : : set_base_and_extent ( JS : : NonnullGCPtr < DOM : : Node > anchor_node , unsigned anchor_offset , JS : : NonnullGCPtr < DOM : : Node > focus_node , unsigned focus_offset )
2021-10-10 19:12:32 +02:00
{
2022-12-09 19:00:18 +00:00
// 1. If anchorOffset is longer than anchorNode's length or if focusOffset is longer than focusNode's length, throw an IndexSizeError exception and abort these steps.
if ( anchor_offset > anchor_node - > length ( ) )
2024-10-12 20:56:21 +02:00
return WebIDL : : IndexSizeError : : create ( realm ( ) , " Anchor offset points outside of the anchor node " _string ) ;
2022-12-09 19:00:18 +00:00
if ( focus_offset > focus_node - > length ( ) )
2024-10-12 20:56:21 +02:00
return WebIDL : : IndexSizeError : : create ( realm ( ) , " Focus offset points outside of the focus node " _string ) ;
2022-12-09 19:00:18 +00:00
2024-07-02 10:21:06 +01:00
// 2. If document associated with this is not a shadow-including inclusive ancestor of anchorNode or focusNode, abort these steps.
2024-07-19 16:39:34 +02:00
if ( ! m_document - > is_shadow_including_inclusive_ancestor_of ( anchor_node ) | | ! m_document - > is_shadow_including_inclusive_ancestor_of ( focus_node ) )
2022-12-09 19:00:18 +00:00
return { } ;
// 3. Let anchor be the boundary point (anchorNode, anchorOffset) and let focus be the boundary point (focusNode, focusOffset).
// 4. Let newRange be a new range.
2023-08-13 13:05:26 +02:00
auto new_range = DOM : : Range : : create ( * m_document ) ;
2022-12-09 19:00:18 +00:00
// 5. If anchor is before focus, set the start the newRange's start to anchor and its end to focus. Otherwise, set the start them to focus and anchor respectively.
auto position_of_anchor_relative_to_focus = DOM : : position_of_boundary_point_relative_to_other_boundary_point ( anchor_node , anchor_offset , focus_node , focus_offset ) ;
if ( position_of_anchor_relative_to_focus = = DOM : : RelativeBoundaryPointPosition : : Before ) {
TRY ( new_range - > set_start ( anchor_node , anchor_offset ) ) ;
TRY ( new_range - > set_end ( focus_node , focus_offset ) ) ;
} else {
TRY ( new_range - > set_start ( focus_node , focus_offset ) ) ;
TRY ( new_range - > set_end ( anchor_node , anchor_offset ) ) ;
}
// 6. Set this's range to newRange.
2023-01-11 19:48:53 +01:00
set_range ( new_range ) ;
2022-12-09 19:00:18 +00:00
// 7. If focus is before anchor, set this's direction to backwards. Otherwise, set it to forwards
// NOTE: "Otherwise" can be seen as "focus is equal to or after anchor".
if ( position_of_anchor_relative_to_focus = = DOM : : RelativeBoundaryPointPosition : : After )
m_direction = Direction : : Backwards ;
else
m_direction = Direction : : Forwards ;
return { } ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-selectallchildren
WebIDL : : ExceptionOr < void > Selection : : select_all_children ( JS : : NonnullGCPtr < DOM : : Node > node )
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// 1. If node's root is not the document associated with this, abort these steps.
if ( & node - > root ( ) ! = m_document . ptr ( ) )
return { } ;
// 2. Let newRange be a new range and childCount be the number of children of node.
2023-08-13 13:05:26 +02:00
auto new_range = DOM : : Range : : create ( * m_document ) ;
2022-10-11 16:54:42 +02:00
auto child_count = node - > child_count ( ) ;
// 3. Set newRange's start to (node, 0).
TRY ( new_range - > set_start ( node , 0 ) ) ;
// 4. Set newRange's end to (node, childCount).
TRY ( new_range - > set_end ( node , child_count ) ) ;
// 5. Set this's range to newRange.
2023-01-11 19:48:53 +01:00
set_range ( new_range ) ;
2022-10-11 16:54:42 +02:00
// 6. Set this's direction to forwards.
m_direction = Direction : : Forwards ;
return { } ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-deletefromdocument
WebIDL : : ExceptionOr < void > Selection : : delete_from_document ( )
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// The method must invoke deleteContents() on this's range if this is not empty.
// Otherwise the method must do nothing.
if ( ! is_empty ( ) )
return m_range - > delete_contents ( ) ;
return { } ;
2021-10-10 19:12:32 +02:00
}
2022-10-11 16:54:42 +02:00
// https://w3c.github.io/selection-api/#dom-selection-containsnode
bool Selection : : contains_node ( JS : : NonnullGCPtr < DOM : : Node > node , bool allow_partial_containment ) const
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// The method must return false if this is empty or if node's root is not the document associated with this.
if ( ! m_range )
return false ;
if ( & node - > root ( ) ! = m_document . ptr ( ) )
return false ;
// Otherwise, if allowPartialContainment is false, the method must return true if and only if
// start of its range is before or visually equivalent to the first boundary point in the node
// and end of its range is after or visually equivalent to the last boundary point in the node.
if ( ! allow_partial_containment ) {
auto start_relative_position = DOM : : position_of_boundary_point_relative_to_other_boundary_point (
* m_range - > start_container ( ) ,
m_range - > start_offset ( ) ,
node ,
0 ) ;
auto end_relative_position = DOM : : position_of_boundary_point_relative_to_other_boundary_point (
* m_range - > end_container ( ) ,
m_range - > end_offset ( ) ,
node ,
node - > length ( ) ) ;
return ( start_relative_position = = DOM : : RelativeBoundaryPointPosition : : Before | | start_relative_position = = DOM : : RelativeBoundaryPointPosition : : Equal )
& & ( end_relative_position = = DOM : : RelativeBoundaryPointPosition : : Equal | | end_relative_position = = DOM : : RelativeBoundaryPointPosition : : After ) ;
}
// If allowPartialContainment is true, the method must return true if and only if
// start of its range is before or visually equivalent to the last boundary point in the node
// and end of its range is after or visually equivalent to the first boundary point in the node.
auto start_relative_position = DOM : : position_of_boundary_point_relative_to_other_boundary_point (
* m_range - > start_container ( ) ,
m_range - > start_offset ( ) ,
node ,
node - > length ( ) ) ;
auto end_relative_position = DOM : : position_of_boundary_point_relative_to_other_boundary_point (
* m_range - > end_container ( ) ,
m_range - > end_offset ( ) ,
node ,
0 ) ;
return ( start_relative_position = = DOM : : RelativeBoundaryPointPosition : : Before | | start_relative_position = = DOM : : RelativeBoundaryPointPosition : : Equal )
& & ( end_relative_position = = DOM : : RelativeBoundaryPointPosition : : Equal | | end_relative_position = = DOM : : RelativeBoundaryPointPosition : : After ) ;
2021-10-10 19:12:32 +02:00
}
2023-08-26 16:39:52 +12:00
String Selection : : to_string ( ) const
2021-10-10 19:12:32 +02:00
{
2022-10-11 16:54:42 +02:00
// FIXME: This needs more work to be compatible with other engines.
// See https://www.w3.org/Bugs/Public/show_bug.cgi?id=10583
if ( ! m_range )
2023-08-26 16:39:52 +12:00
return String { } ;
2023-08-26 16:46:33 +12:00
return m_range - > to_string ( ) ;
2021-10-10 19:12:32 +02:00
}
2023-01-11 19:48:53 +01:00
JS : : NonnullGCPtr < DOM : : Document > Selection : : document ( ) const
{
return m_document ;
}
2023-01-11 19:45:03 +01:00
JS : : GCPtr < DOM : : Range > Selection : : range ( ) const
{
return m_range ;
}
2023-01-11 19:48:53 +01:00
void Selection : : set_range ( JS : : GCPtr < DOM : : Range > range )
{
if ( m_range = = range )
return ;
if ( m_range )
m_range - > set_associated_selection ( { } , nullptr ) ;
m_range = range ;
if ( m_range )
m_range - > set_associated_selection ( { } , this ) ;
}
2021-10-10 19:12:32 +02:00
}