2020-01-18 11:38:21 +03:00
/*
2022-03-10 01:53:41 +03:00
* Copyright ( c ) 2018 - 2022 , Andreas Kling < kling @ serenityos . org >
2020-01-18 11:38:21 +03:00
*
2021-04-22 11:24:48 +03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 11:38:21 +03:00
*/
2020-11-11 12:46:53 +03:00
# include <AK/StringBuilder.h>
2023-01-29 01:23:16 +03:00
# include <LibWeb/ARIA/Roles.h>
2023-02-15 21:18:58 +03:00
# include <LibWeb/Bindings/ExceptionOrUtils.h>
2020-11-11 12:46:53 +03:00
# include <LibWeb/DOM/Document.h>
2022-02-16 22:43:24 +03:00
# include <LibWeb/DOM/IDLEventListener.h>
2022-10-02 23:42:47 +03:00
# include <LibWeb/DOM/ShadowRoot.h>
2022-02-06 20:46:26 +03:00
# include <LibWeb/HTML/BrowsingContext.h>
2022-10-08 13:25:01 +03:00
# include <LibWeb/HTML/DOMStringMap.h>
2021-02-04 00:47:50 +03:00
# include <LibWeb/HTML/EventHandler.h>
2022-11-05 17:30:49 +03:00
# include <LibWeb/HTML/Focus.h>
2020-11-22 00:53:18 +03:00
# include <LibWeb/HTML/HTMLAnchorElement.h>
2022-10-02 23:42:47 +03:00
# include <LibWeb/HTML/HTMLAreaElement.h>
2023-06-18 18:22:10 +03:00
# include <LibWeb/HTML/HTMLBaseElement.h>
2021-04-15 20:48:55 +03:00
# include <LibWeb/HTML/HTMLBodyElement.h>
2020-07-26 16:08:16 +03:00
# include <LibWeb/HTML/HTMLElement.h>
2022-12-12 14:20:02 +03:00
# include <LibWeb/HTML/NavigableContainer.h>
2022-10-02 23:42:47 +03:00
# include <LibWeb/HTML/VisibilityState.h>
2022-03-08 01:08:26 +03:00
# include <LibWeb/HTML/Window.h>
2023-06-18 18:22:10 +03:00
# include <LibWeb/Infra/CharacterTypes.h>
# include <LibWeb/Infra/Strings.h>
2021-09-30 02:35:19 +03:00
# include <LibWeb/Layout/Box.h>
2021-01-01 20:55:47 +03:00
# include <LibWeb/Layout/BreakNode.h>
2020-11-22 17:53:01 +03:00
# include <LibWeb/Layout/TextNode.h>
2022-03-11 01:13:37 +03:00
# include <LibWeb/Painting/PaintableBox.h>
2021-02-04 00:47:50 +03:00
# include <LibWeb/UIEvents/EventNames.h>
2022-02-07 02:04:10 +03:00
# include <LibWeb/UIEvents/FocusEvent.h>
2022-03-15 03:50:19 +03:00
# include <LibWeb/UIEvents/MouseEvent.h>
2022-09-25 19:28:46 +03:00
# include <LibWeb/WebIDL/DOMException.h>
2022-09-25 19:03:42 +03:00
# include <LibWeb/WebIDL/ExceptionOr.h>
2019-09-29 12:59:38 +03:00
2020-07-28 19:20:36 +03:00
namespace Web : : HTML {
2020-03-07 12:27:02 +03:00
2022-02-18 23:00:52 +03:00
HTMLElement : : HTMLElement ( DOM : : Document & document , DOM : : QualifiedName qualified_name )
2021-02-07 13:20:15 +03:00
: Element ( document , move ( qualified_name ) )
2019-09-29 12:59:38 +03:00
{
}
2022-03-14 22:21:51 +03:00
HTMLElement : : ~ HTMLElement ( ) = default ;
2020-03-07 12:27:02 +03:00
2023-08-07 09:41:28 +03:00
void HTMLElement : : initialize ( JS : : Realm & realm )
2022-09-03 19:49:56 +03:00
{
2023-08-07 09:41:28 +03:00
Base : : initialize ( realm ) ;
2023-01-10 14:28:20 +03:00
set_prototype ( & Bindings : : ensure_web_prototype < Bindings : : HTMLElementPrototype > ( realm , " HTMLElement " ) ) ;
2023-08-13 14:05:26 +03:00
m_dataset = DOMStringMap : : create ( * this ) ;
2022-09-03 19:49:56 +03:00
}
2022-08-28 14:42:07 +03:00
void HTMLElement : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( m_dataset . ptr ( ) ) ;
}
2022-11-05 04:56:42 +03:00
// https://html.spec.whatwg.org/multipage/dom.html#dom-dir
2022-12-04 21:02:33 +03:00
DeprecatedString HTMLElement : : dir ( ) const
2022-11-05 04:56:42 +03:00
{
2023-09-03 05:58:18 +03:00
auto dir = deprecated_attribute ( HTML : : AttributeNames : : dir ) ;
2022-11-05 04:56:42 +03:00
# define __ENUMERATE_HTML_ELEMENT_DIR_ATTRIBUTE(keyword) \
2023-03-10 10:48:54 +03:00
if ( dir . equals_ignoring_ascii_case ( # keyword # # sv ) ) \
2022-11-05 04:56:42 +03:00
return # keyword # # sv ;
ENUMERATE_HTML_ELEMENT_DIR_ATTRIBUTES
# undef __ENUMERATE_HTML_ELEMENT_DIR_ATTRIBUTE
return { } ;
}
2022-12-04 21:02:33 +03:00
void HTMLElement : : set_dir ( DeprecatedString const & dir )
2022-11-05 04:56:42 +03:00
{
MUST ( set_attribute ( HTML : : AttributeNames : : dir , dir ) ) ;
}
2020-08-03 04:57:28 +03:00
bool HTMLElement : : is_editable ( ) const
{
2023-05-15 11:08:13 +03:00
switch ( m_content_editable_state ) {
2020-08-03 04:57:28 +03:00
case ContentEditableState : : True :
return true ;
case ContentEditableState : : False :
return false ;
case ContentEditableState : : Inherit :
return parent ( ) & & parent ( ) - > is_editable ( ) ;
default :
2021-02-23 22:42:32 +03:00
VERIFY_NOT_REACHED ( ) ;
2020-08-03 04:57:28 +03:00
}
}
2022-12-04 21:02:33 +03:00
DeprecatedString HTMLElement : : content_editable ( ) const
2020-08-03 04:57:28 +03:00
{
2023-05-15 11:08:13 +03:00
switch ( m_content_editable_state ) {
2020-08-03 04:57:28 +03:00
case ContentEditableState : : True :
return " true " ;
case ContentEditableState : : False :
return " false " ;
case ContentEditableState : : Inherit :
return " inherit " ;
default :
2021-02-23 22:42:32 +03:00
VERIFY_NOT_REACHED ( ) ;
2020-08-03 04:57:28 +03:00
}
}
2021-02-20 02:43:08 +03:00
// https://html.spec.whatwg.org/multipage/interaction.html#contenteditable
2022-12-04 21:02:33 +03:00
WebIDL : : ExceptionOr < void > HTMLElement : : set_content_editable ( DeprecatedString const & content_editable )
2020-08-03 04:57:28 +03:00
{
2023-03-10 10:48:54 +03:00
if ( content_editable . equals_ignoring_ascii_case ( " inherit " sv ) ) {
2020-08-03 04:57:28 +03:00
remove_attribute ( HTML : : AttributeNames : : contenteditable ) ;
2021-02-20 02:43:08 +03:00
return { } ;
2020-08-03 04:57:28 +03:00
}
2023-03-10 10:48:54 +03:00
if ( content_editable . equals_ignoring_ascii_case ( " true " sv ) ) {
2022-10-30 20:50:04 +03:00
MUST ( set_attribute ( HTML : : AttributeNames : : contenteditable , " true " ) ) ;
2021-02-20 02:43:08 +03:00
return { } ;
2020-08-03 04:57:28 +03:00
}
2023-03-10 10:48:54 +03:00
if ( content_editable . equals_ignoring_ascii_case ( " false " sv ) ) {
2022-10-30 20:50:04 +03:00
MUST ( set_attribute ( HTML : : AttributeNames : : contenteditable , " false " ) ) ;
2021-02-20 02:43:08 +03:00
return { } ;
2020-08-03 04:57:28 +03:00
}
2022-09-26 01:38:21 +03:00
return WebIDL : : SyntaxError : : create ( realm ( ) , " Invalid contentEditable value, must be 'true', 'false', or 'inherit' " ) ;
2020-08-03 04:57:28 +03:00
}
2020-11-11 12:46:53 +03:00
void HTMLElement : : set_inner_text ( StringView text )
{
remove_all_children ( ) ;
2022-10-30 20:50:04 +03:00
MUST ( append_child ( document ( ) . create_text_node ( text ) ) ) ;
2020-11-11 12:46:53 +03:00
set_needs_style_update ( true ) ;
}
2022-12-04 21:02:33 +03:00
DeprecatedString HTMLElement : : inner_text ( )
2020-11-11 12:46:53 +03:00
{
StringBuilder builder ;
// innerText for element being rendered takes visibility into account, so force a layout and then walk the layout tree.
2020-12-14 12:39:39 +03:00
document ( ) . update_layout ( ) ;
2020-11-11 12:46:53 +03:00
if ( ! layout_node ( ) )
return text_content ( ) ;
2022-04-01 20:58:27 +03:00
Function < void ( Layout : : Node const & ) > recurse = [ & ] ( auto & node ) {
2020-11-11 12:46:53 +03:00
for ( auto * child = node . first_child ( ) ; child ; child = child - > next_sibling ( ) ) {
2021-01-01 20:55:47 +03:00
if ( is < Layout : : TextNode > ( child ) )
2021-06-24 20:53:42 +03:00
builder . append ( verify_cast < Layout : : TextNode > ( * child ) . text_for_rendering ( ) ) ;
2021-01-01 20:55:47 +03:00
if ( is < Layout : : BreakNode > ( child ) )
2020-11-11 12:46:53 +03:00
builder . append ( ' \n ' ) ;
recurse ( * child ) ;
}
} ;
recurse ( * layout_node ( ) ) ;
2022-12-06 04:12:49 +03:00
return builder . to_deprecated_string ( ) ;
2020-11-11 12:46:53 +03:00
}
2021-09-30 02:35:19 +03:00
// // https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsettop
int HTMLElement : : offset_top ( ) const
2021-04-15 20:48:55 +03:00
{
2022-09-17 17:10:08 +03:00
// NOTE: Ensure that layout is up-to-date before looking at metrics.
const_cast < DOM : : Document & > ( document ( ) ) . update_layout ( ) ;
2021-04-15 20:48:55 +03:00
if ( is < HTML : : HTMLBodyElement > ( this ) | | ! layout_node ( ) | | ! parent_element ( ) | | ! parent_element ( ) - > layout_node ( ) )
return 0 ;
auto position = layout_node ( ) - > box_type_agnostic_position ( ) ;
auto parent_position = parent_element ( ) - > layout_node ( ) - > box_type_agnostic_position ( ) ;
2023-06-12 21:37:35 +03:00
return position . y ( ) . to_int ( ) - parent_position . y ( ) . to_int ( ) ;
2021-04-15 20:48:55 +03:00
}
2021-09-30 02:35:19 +03:00
// https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetleft
int HTMLElement : : offset_left ( ) const
2021-04-15 20:48:55 +03:00
{
2022-09-17 17:10:08 +03:00
// NOTE: Ensure that layout is up-to-date before looking at metrics.
const_cast < DOM : : Document & > ( document ( ) ) . update_layout ( ) ;
2021-04-15 20:48:55 +03:00
if ( is < HTML : : HTMLBodyElement > ( this ) | | ! layout_node ( ) | | ! parent_element ( ) | | ! parent_element ( ) - > layout_node ( ) )
return 0 ;
auto position = layout_node ( ) - > box_type_agnostic_position ( ) ;
auto parent_position = parent_element ( ) - > layout_node ( ) - > box_type_agnostic_position ( ) ;
2023-06-12 21:37:35 +03:00
return position . x ( ) . to_int ( ) - parent_position . x ( ) . to_int ( ) ;
2021-04-15 20:48:55 +03:00
}
2021-09-30 02:35:19 +03:00
// https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetwidth
int HTMLElement : : offset_width ( ) const
{
2022-04-10 21:38:16 +03:00
// NOTE: Ensure that layout is up-to-date before looking at metrics.
const_cast < DOM : : Document & > ( document ( ) ) . update_layout ( ) ;
// 1. If the element does not have any associated CSS layout box return zero and terminate this algorithm.
2023-04-20 18:01:16 +03:00
if ( ! paintable_box ( ) )
2022-04-10 21:38:16 +03:00
return 0 ;
// 2. Return the width of the axis-aligned bounding box of the border boxes of all fragments generated by the element’ s principal box,
// ignoring any transforms that apply to the element and its ancestors.
// FIXME: Account for inline boxes.
2023-06-12 21:37:35 +03:00
return paintable_box ( ) - > border_box_width ( ) . to_int ( ) ;
2021-09-30 02:35:19 +03:00
}
// https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetheight
int HTMLElement : : offset_height ( ) const
{
2022-04-10 21:38:16 +03:00
// NOTE: Ensure that layout is up-to-date before looking at metrics.
const_cast < DOM : : Document & > ( document ( ) ) . update_layout ( ) ;
// 1. If the element does not have any associated CSS layout box return zero and terminate this algorithm.
2023-04-20 18:01:16 +03:00
if ( ! paintable_box ( ) )
2022-04-10 21:38:16 +03:00
return 0 ;
// 2. Return the height of the axis-aligned bounding box of the border boxes of all fragments generated by the element’ s principal box,
// ignoring any transforms that apply to the element and its ancestors.
// FIXME: Account for inline boxes.
2023-06-12 21:37:35 +03:00
return paintable_box ( ) - > border_box_height ( ) . to_int ( ) ;
2021-09-30 02:35:19 +03:00
}
2022-09-18 11:29:53 +03:00
// https://html.spec.whatwg.org/multipage/links.html#cannot-navigate
2020-11-22 00:53:18 +03:00
bool HTMLElement : : cannot_navigate ( ) const
{
2022-09-18 11:29:53 +03:00
// An element element cannot navigate if one of the following is true:
// - element's node document is not fully active
if ( ! document ( ) . is_fully_active ( ) )
return true ;
// - element is not an a element and is not connected.
2020-11-22 00:53:18 +03:00
return ! is < HTML : : HTMLAnchorElement > ( this ) & & ! is_connected ( ) ;
}
2023-07-03 18:08:37 +03:00
void HTMLElement : : attribute_changed ( DeprecatedFlyString const & name , DeprecatedString const & value )
2021-02-04 00:47:50 +03:00
{
2023-07-03 18:08:37 +03:00
Element : : attribute_changed ( name , value ) ;
2021-02-04 00:47:50 +03:00
2023-05-15 11:08:13 +03:00
if ( name = = HTML : : AttributeNames : : contenteditable ) {
2023-07-03 18:31:17 +03:00
if ( value . is_null ( ) ) {
2023-05-15 11:08:13 +03:00
m_content_editable_state = ContentEditableState : : Inherit ;
2023-07-03 18:31:17 +03:00
} else {
if ( value . is_empty ( ) | | value . equals_ignoring_ascii_case ( " true " sv ) ) {
// "true", an empty string or a missing value map to the "true" state.
m_content_editable_state = ContentEditableState : : True ;
} else if ( value . equals_ignoring_ascii_case ( " false " sv ) ) {
// "false" maps to the "false" state.
m_content_editable_state = ContentEditableState : : False ;
} else {
// Having no such attribute or an invalid value maps to the "inherit" state.
m_content_editable_state = ContentEditableState : : Inherit ;
}
2023-05-15 11:08:13 +03:00
}
}
2021-10-14 20:03:08 +03:00
// 1. If namespace is not null, or localName is not the name of an event handler content attribute on element, then return.
// FIXME: Add the namespace part once we support attribute namespaces.
2021-02-04 00:47:50 +03:00
# undef __ENUMERATE
2023-04-09 10:52:27 +03:00
# define __ENUMERATE(attribute_name, event_name) \
if ( name = = HTML : : AttributeNames : : attribute_name ) { \
element_event_handler_attribute_changed ( event_name , String : : from_deprecated_string ( value ) . release_value ( ) ) ; \
2021-02-04 00:47:50 +03:00
}
ENUMERATE_GLOBAL_EVENT_HANDLERS ( __ENUMERATE )
# undef __ENUMERATE
}
2022-02-06 20:46:26 +03:00
// https://html.spec.whatwg.org/multipage/interaction.html#dom-focus
void HTMLElement : : focus ( )
{
// 1. If the element is marked as locked for focus, then return.
if ( m_locked_for_focus )
return ;
// 2. Mark the element as locked for focus.
m_locked_for_focus = true ;
// 3. Run the focusing steps for the element.
run_focusing_steps ( this ) ;
// FIXME: 4. If the value of the preventScroll dictionary member of options is false,
// then scroll the element into view with scroll behavior "auto",
// block flow direction position set to an implementation-defined value,
// and inline base direction position set to an implementation-defined value.
// 5. Unmark the element as locked for focus.
m_locked_for_focus = false ;
}
2022-02-15 02:25:51 +03:00
2022-02-25 22:45:19 +03:00
// https://html.spec.whatwg.org/multipage/webappapis.html#fire-a-synthetic-pointer-event
2023-04-09 12:26:59 +03:00
bool HTMLElement : : fire_a_synthetic_pointer_event ( FlyString const & type , DOM : : Element & target , bool not_trusted )
2022-02-25 22:45:19 +03:00
{
// 1. Let event be the result of creating an event using PointerEvent.
// 2. Initialize event's type attribute to e.
// FIXME: Actually create a PointerEvent!
2023-08-13 14:05:26 +03:00
auto event = UIEvents : : MouseEvent : : create ( realm ( ) , type ) ;
2022-02-25 22:45:19 +03:00
// 3. Initialize event's bubbles and cancelable attributes to true.
event - > set_bubbles ( true ) ;
event - > set_cancelable ( true ) ;
// 4. Set event's composed flag.
event - > set_composed ( true ) ;
// 5. If the not trusted flag is set, initialize event's isTrusted attribute to false.
if ( not_trusted ) {
event - > set_is_trusted ( false ) ;
}
// FIXME: 6. Initialize event's ctrlKey, shiftKey, altKey, and metaKey attributes according to the current state
// of the key input device, if any (false for any keys that are not available).
// FIXME: 7. Initialize event's view attribute to target's node document's Window object, if any, and null otherwise.
// FIXME: 8. event's getModifierState() method is to return values appropriately describing the current state of the key input device.
// 9. Return the result of dispatching event at target.
2023-02-15 00:43:17 +03:00
return target . dispatch_event ( event ) ;
2022-02-25 22:45:19 +03:00
}
2022-02-15 02:25:51 +03:00
// https://html.spec.whatwg.org/multipage/interaction.html#dom-click
void HTMLElement : : click ( )
{
// FIXME: 1. If this element is a form control that is disabled, then return.
// 2. If this element's click in progress flag is set, then return.
if ( m_click_in_progress )
return ;
// 3. Set this element's click in progress flag.
m_click_in_progress = true ;
// FIXME: 4. Fire a synthetic pointer event named click at this element, with the not trusted flag set.
2023-04-09 12:26:59 +03:00
fire_a_synthetic_pointer_event ( HTML : : EventNames : : click , * this , true ) ;
2022-02-15 02:25:51 +03:00
// 5. Unset this element's click in progress flag.
m_click_in_progress = false ;
}
2022-10-02 23:42:47 +03:00
// https://html.spec.whatwg.org/multipage/interaction.html#dom-blur
void HTMLElement : : blur ( )
{
// The blur() method, when invoked, should run the unfocusing steps for the element on which the method was called.
run_unfocusing_steps ( this ) ;
// User agents may selectively or uniformly ignore calls to this method for usability reasons.
}
2023-01-29 01:23:16 +03:00
Optional < ARIA : : Role > HTMLElement : : default_role ( ) const
2022-11-29 02:58:13 +03:00
{
// https://www.w3.org/TR/html-aria/#el-article
if ( local_name ( ) = = TagNames : : article )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : article ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-aside
if ( local_name ( ) = = TagNames : : aside )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : complementary ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-b
if ( local_name ( ) = = TagNames : : b )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-bdi
if ( local_name ( ) = = TagNames : : bdi )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-bdo
if ( local_name ( ) = = TagNames : : bdo )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-code
if ( local_name ( ) = = TagNames : : code )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : code ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-dfn
if ( local_name ( ) = = TagNames : : dfn )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : term ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-em
if ( local_name ( ) = = TagNames : : em )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : emphasis ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-figure
if ( local_name ( ) = = TagNames : : figure )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : figure ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-footer
if ( local_name ( ) = = TagNames : : footer ) {
// TODO: If not a descendant of an article, aside, main, nav or section element, or an element with role=article, complementary, main, navigation or region then role=contentinfo
// Otherwise, role=generic
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
}
// https://www.w3.org/TR/html-aria/#el-header
if ( local_name ( ) = = TagNames : : header ) {
// TODO: If not a descendant of an article, aside, main, nav or section element, or an element with role=article, complementary, main, navigation or region then role=banner
// Otherwise, role=generic
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
}
// https://www.w3.org/TR/html-aria/#el-hgroup
if ( local_name ( ) = = TagNames : : hgroup )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-i
if ( local_name ( ) = = TagNames : : i )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-main
if ( local_name ( ) = = TagNames : : main )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : main ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-nav
if ( local_name ( ) = = TagNames : : nav )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : navigation ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-samp
if ( local_name ( ) = = TagNames : : samp )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-section
if ( local_name ( ) = = TagNames : : section ) {
// TODO: role=region if the section element has an accessible name
// Otherwise, no corresponding role
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : region ;
2022-11-29 02:58:13 +03:00
}
// https://www.w3.org/TR/html-aria/#el-small
if ( local_name ( ) = = TagNames : : small )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-strong
if ( local_name ( ) = = TagNames : : strong )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : strong ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-sub
if ( local_name ( ) = = TagNames : : sub )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : subscript ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-summary
if ( local_name ( ) = = TagNames : : summary )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : button ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-sup
if ( local_name ( ) = = TagNames : : sup )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : superscript ;
2022-11-29 02:58:13 +03:00
// https://www.w3.org/TR/html-aria/#el-u
if ( local_name ( ) = = TagNames : : u )
2023-01-29 01:23:16 +03:00
return ARIA : : Role : : generic ;
2022-11-29 02:58:13 +03:00
return { } ;
}
2023-06-18 18:22:10 +03:00
// https://html.spec.whatwg.org/multipage/semantics.html#get-an-element's-target
DeprecatedString HTMLElement : : get_an_elements_target ( ) const
{
// To get an element's target, given an a, area, or form element element, run these steps:
// 1. If element has a target attribute, then return that attribute's value.
if ( has_attribute ( AttributeNames : : target ) )
2023-09-03 05:58:18 +03:00
return deprecated_attribute ( AttributeNames : : target ) ;
2023-06-18 18:22:10 +03:00
// FIXME: 2. If element's node document contains a base element with a
// target attribute, then return the value of the target attribute of the
// first such base element.
// 3. Return the empty string.
return DeprecatedString : : empty ( ) ;
}
// https://html.spec.whatwg.org/multipage/links.html#get-an-element's-noopener
TokenizedFeature : : NoOpener HTMLElement : : get_an_elements_noopener ( StringView target ) const
{
// To get an element's noopener, given an a, area, or form element element and a string target:
2023-09-03 05:58:18 +03:00
auto rel = deprecated_attribute ( HTML : : AttributeNames : : rel ) . to_lowercase ( ) ;
2023-06-18 18:22:10 +03:00
auto link_types = rel . view ( ) . split_view_if ( Infra : : is_ascii_whitespace ) ;
// 1. If element's link types include the noopener or noreferrer keyword, then return true.
if ( link_types . contains_slow ( " noopener " sv ) | | link_types . contains_slow ( " noreferrer " sv ) )
return TokenizedFeature : : NoOpener : : Yes ;
// 2. If element's link types do not include the opener keyword and
// target is an ASCII case-insensitive match for "_blank", then return true.
if ( ! link_types . contains_slow ( " opener " sv ) & & Infra : : is_ascii_case_insensitive_match ( target , " _blank " sv ) )
return TokenizedFeature : : NoOpener : : Yes ;
// 3. Return false.
return TokenizedFeature : : NoOpener : : No ;
}
2020-03-07 12:27:02 +03:00
}