mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 13:32:45 +00:00 
			
		
		
		
	LibWeb: Support :active pseudo-class for hyperlinks, :focus possibly
Adds support for the :active pseudo-class for hyperlinks (<a> tags only). Also, since it was very similar to :focus and an element having a focused state was already implemented, I went ahead and implemented that pseudo-class too, although I cannot come up with a working example to validate it.
This commit is contained in:
		
							parent
							
								
									457edaa4d2
								
							
						
					
					
						commit
						5eb65286b6
					
				
					 10 changed files with 39 additions and 2 deletions
				
			
		|  | @ -563,6 +563,8 @@ public: | |||
|                 simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Link; | ||||
|             } else if (pseudo_name.equals_ignoring_case("visited")) { | ||||
|                 simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Visited; | ||||
|             } else if (pseudo_name.equals_ignoring_case("active")) { | ||||
|                 simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Active; | ||||
|             } else if (pseudo_name.equals_ignoring_case("hover")) { | ||||
|                 simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Hover; | ||||
|             } else if (pseudo_name.equals_ignoring_case("focus")) { | ||||
|  |  | |||
|  | @ -200,6 +200,8 @@ Vector<CSS::Selector::ComplexSelector> Parser::parse_selectors(Vector<String> pa | |||
|                 simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Link; | ||||
|             } else if (pseudo_name.equals_ignoring_case("visited")) { | ||||
|                 simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Visited; | ||||
|             } else if (pseudo_name.equals_ignoring_case("active")) { | ||||
|                 simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Active; | ||||
|             } else if (pseudo_name.equals_ignoring_case("hover")) { | ||||
|                 simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Hover; | ||||
|             } else if (pseudo_name.equals_ignoring_case("focus")) { | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ public: | |||
|             Enabled, | ||||
|             Checked, | ||||
|             Not, | ||||
|             Active, | ||||
|         }; | ||||
|         PseudoClass pseudo_class { PseudoClass::None }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -44,13 +44,18 @@ static bool matches(const CSS::Selector::SimpleSelector& component, const DOM::E | |||
|     case CSS::Selector::SimpleSelector::PseudoClass::Visited: | ||||
|         // FIXME: Maybe match this selector sometimes?
 | ||||
|         return false; | ||||
|     case CSS::Selector::SimpleSelector::PseudoClass::Active: | ||||
|         if (!element.is_active()) | ||||
|             return false; | ||||
|         break; | ||||
|     case CSS::Selector::SimpleSelector::PseudoClass::Hover: | ||||
|         if (!matches_hover_pseudo_class(element)) | ||||
|             return false; | ||||
|         break; | ||||
|     case CSS::Selector::SimpleSelector::PseudoClass::Focus: | ||||
|         // FIXME: Implement matches_focus_pseudo_class(element)
 | ||||
|         if (!element.is_focused()) | ||||
|             return false; | ||||
|         break; | ||||
|     case CSS::Selector::SimpleSelector::PseudoClass::FirstChild: | ||||
|         if (element.previous_element_sibling()) | ||||
|             return false; | ||||
|  |  | |||
|  | @ -876,6 +876,17 @@ void Document::set_focused_element(Element* element) | |||
|         m_layout_root->set_needs_display(); | ||||
| } | ||||
| 
 | ||||
| void Document::set_active_element(Element* element) | ||||
| { | ||||
|     if (m_active_element == element) | ||||
|         return; | ||||
| 
 | ||||
|     m_active_element = element; | ||||
| 
 | ||||
|     if (m_layout_root) | ||||
|         m_layout_root->set_needs_display(); | ||||
| } | ||||
| 
 | ||||
| void Document::set_ready_state(const String& ready_state) | ||||
| { | ||||
|     m_ready_state = ready_state; | ||||
|  |  | |||
|  | @ -208,6 +208,10 @@ public: | |||
| 
 | ||||
|     void set_focused_element(Element*); | ||||
| 
 | ||||
|     const Element* active_element() const { return m_active_element; } | ||||
| 
 | ||||
|     void set_active_element(Element*); | ||||
| 
 | ||||
|     bool created_for_appropriate_template_contents() const { return m_created_for_appropriate_template_contents; } | ||||
|     void set_created_for_appropriate_template_contents(bool value) { m_created_for_appropriate_template_contents = value; } | ||||
| 
 | ||||
|  | @ -323,6 +327,7 @@ private: | |||
|     bool m_editable { false }; | ||||
| 
 | ||||
|     WeakPtr<Element> m_focused_element; | ||||
|     WeakPtr<Element> m_active_element; | ||||
| 
 | ||||
|     bool m_created_for_appropriate_template_contents { false }; | ||||
|     RefPtr<Document> m_associated_inert_template_document; | ||||
|  |  | |||
|  | @ -327,6 +327,11 @@ bool Element::is_focused() const | |||
|     return document().focused_element() == this; | ||||
| } | ||||
| 
 | ||||
| bool Element::is_active() const | ||||
| { | ||||
|     return document().active_element() == this; | ||||
| } | ||||
| 
 | ||||
| NonnullRefPtr<HTMLCollection> Element::get_elements_by_tag_name(FlyString const& tag_name) | ||||
| { | ||||
|     // FIXME: Support "*" for tag_name
 | ||||
|  |  | |||
|  | @ -86,6 +86,8 @@ public: | |||
|     bool is_focused() const; | ||||
|     virtual bool is_focusable() const { return false; } | ||||
| 
 | ||||
|     bool is_active() const; | ||||
| 
 | ||||
|     NonnullRefPtr<HTMLCollection> get_elements_by_tag_name(FlyString const&); | ||||
|     NonnullRefPtr<HTMLCollection> get_elements_by_class_name(FlyString const&); | ||||
| 
 | ||||
|  |  | |||
|  | @ -341,6 +341,9 @@ void dump_selector(StringBuilder& builder, const CSS::Selector& selector) | |||
|             case CSS::Selector::SimpleSelector::PseudoClass::Visited: | ||||
|                 pseudo_class_description = "Visited"; | ||||
|                 break; | ||||
|             case CSS::Selector::SimpleSelector::PseudoClass::Active: | ||||
|                 pseudo_class_description = "Active"; | ||||
|                 break; | ||||
|             case CSS::Selector::SimpleSelector::PseudoClass::None: | ||||
|                 pseudo_class_description = "None"; | ||||
|                 break; | ||||
|  |  | |||
|  | @ -237,6 +237,7 @@ bool EventHandler::handle_mousedown(const Gfx::IntPoint& position, unsigned butt | |||
|                 auto anchor = href.substring_view(1, href.length() - 1); | ||||
|                 m_frame.scroll_to_anchor(anchor); | ||||
|             } else { | ||||
|                 document->set_active_element(link); | ||||
|                 if (m_frame.is_top_level()) { | ||||
|                     if (auto* page = m_frame.page()) | ||||
|                         page->client().page_did_click_link(url, link->target(), modifiers); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Paul Irwin
						Paul Irwin