Age | Commit message (Collapse) | Author |
|
|
|
Instead of doing a forced layout synchronously whenever an element's
style is changed, use a zero-timer to do the forced relayout on next
event loop iteration.
This effectively coalesces a lot of layouts and makes many pages such
as GitHub spend way less time doing redundant layout work.
|
|
|
|
The StyleResolver can find the specified CSS values for the parent
element via the DOM. Forcing everyone to locate specified values for
their parent was completely unnecessary.
|
|
Layout nodes now only carry CSS computer values with them. The main
idea here is to give them only what they need to perform layout, and
leave the rest back in the DOM.
|
|
Instead of using the specified style stored on Layout::Node, use the
specified CSS values kept by the DOM::Element in more places.
|
|
This object represents the specified CSS values, so let's call it that.
|
|
|
|
|
|
|
|
Otherwise fetching stuff via LayoutNode::style() will have stale values
since we were only updating the specified_style() here.
LayoutNode::specified_style() should eventually go away since there's
no need to carry those uncooked values around with the layout tree.
|
|
|
|
This patch adds a simple, naive & inefficient class for document-wide
style invalidation, e.g. after element attribute updates. During
construction it collects a HashMap of a document's elements and their
matching rules, during destruction it does the same and then compares
the results; dirtying all elements that have a different number or order
of matching rules afterwards.
Much room for improvement, but it solves the problem of stale element
styling after attribute updates for now :^)
Fixes #4404.
|
|
|
|
Fixes #4403.
|
|
After you mark a node as needing new style, there's no situation in
which we don't want a style update to happen, so just take care of
scheduling it automatically.
|
|
Instead of invoking the CSS parser every time we compute the style for
an element that has a "style" attribute, we now cache the result of
parsing the inline style whenever the "style" attribute is set.
This is a nice boost to relayout performance since we no longer hit the
CSS parser at all.
|
|
|
|
Bring the names of various boxes closer to spec language. This should
hopefully make things easier to understand and hack on. :^)
Some notable changes:
- LayoutNode -> Layout::Node
- LayoutBox -> Layout::Box
- LayoutBlock -> Layout::BlockBox
- LayoutReplaced -> Layout::ReplacedBox
- LayoutDocument -> Layout::InitialContainingBlockBox
- LayoutText -> Layout::TextNode
- LayoutInline -> Layout::InlineNode
Note that this is not strictly a "box tree" as we also hang inline/text
nodes in the same tree, and they don't generate boxes. (Instead, they
contribute line box fragments to their containing block!)
|
|
|
|
|
|
Reading the property has a few warts (see FIXMEs in the included
tests), but with this the timestamps on http://45.33.8.238/
get localized :^)
Since the Date() constructor currently ignores all arguments,
they don't get localized correctly but are all set to the current
time, but hey, it's still progress from a certain point of view.
|
|
You can now cycle through focusable elements (currently only hyperlinks
are focusable) with the Tab key.
The focus outline is rendered in a new FocusOutline paint phase.
|
|
HTMLElement is the only interface that includes ElementContentEditable
in the HTML specification. This makes sense, as Element is also a base
class for elements in other specifications such as SVG,
which definitely shouldn't be editable.
Also adds a test for the attribute based on what Andreas did in the
video that added it.
|
|
|
|
We now respect the contenteditable HTML attribute and only let you
edit content inside explicitly editable elements.
|
|
|
|
|
|
|
|
LibWeb keeps growing and the Web namespace is filling up fast.
Let's put DOM stuff into Web::DOM, just like we already started doing
with SVG stuff in Web::SVG.
|
|
|
|
To prepare for fully qualified tag names, let's call this local_name.
Note that we still keep an Element::tag_name() around since that's what
the JS bindings end up calling into for the Element.tagName property.
|
|
|
|
|
|
This patch implements most of the HTML fragment parsing algorithm and
ports Element::set_inner_html() to it. This was the last remaining user
of the old HTML parser. :^)
|
|
To make this possible, I also had to give each LayoutNode a Document&
so it can resolve document-specific colors correctly. There's probably
ways to avoid having this extra member by resolving colors later, but
this works for now.
|
|
The display property is not interesting after we've built the layout
tree, so we don't have to move it into LayoutStyle.
|
|
Let's make way for a slightly-more-cooked style() that will eventually
replace the raw specified_style() for layout and paint purposes.
|
|
Not doing this was causing the wrong kind of LayoutNode to stay around
even though we had the final "display" value.
|
|
|
|
The only CSS property we care about for widgets is "display:none".
For everything else, we ignore it and use a native look & feel. :^)
|
|
This makes stuff inside <noscript> correctly not show up since we run
with scripting enabled.
In the future, we can add a way to disable scripting, but for now,
Document::is_scripting_enabled() just returns true.
|
|
This seems to have a higher chance of generating somewhat recognizable
content compared to inline layout. This problem will gradually go away
as we implement more display values.
|
|
Instead of string splitting every time you call Element::has_class(),
we now split the "class" attribute value when it changes, and cache
the individual classes as FlyStrings in Element::m_classes.
This makes has_class() significantly faster and moves the pain point
of selector matching somewhere else.
|
|
This display type is implemented using a LayoutBlock that is_inline().
Basically it behaves like a block internally, and its children are laid
out in the normal block layout fashion. Externally however, it behaves
like an atomic inline-level box.
Layout of inline-block boxes happens in three stages:
1. The outer dimensions of the block are computed during the recursive
normal layout pass. We skip positioning, but lay out children.
2. Later on, during line layout in the *containing block*, the inline
block now contributes a linebox fragment. When linebox fragments are
positioned, we learn the final position of the inline block. That's
when we set the inline block's position.
3. We re-layout the inline block's children once again. This is done to
make sure they end up in the right position. The layout tree doesn't
use relative offsets, so after we position the inline block in (2),
its children will not have its positions updated. Relayout moves
all children of inline blocks to the right place.
This is a rather naive approach but it does get the basic behavior into
place so we can iterate on it. :^)
|
|
Let's at least try to keep going and see what we can render.
|
|
Getting the innerHTML property will recurse through the subtree inside
the element and serialize it into a string as it goes.
Setting it will parse the set value as an HTML fragment. It will then
remove all current children of the element and replace them with all
the children inside the parsed fragment.
Setting element.innerHTML will currently force a complete rebuild of
the document's layout tree.
This is pretty neat! :^)
|
|
This makes selector matching a lot more efficient, and also reduces the
number of strings on the heap.
|
|
Attribute names occur again and again.
|
|
Let's rename this to LibWeb since it aims to provide more parts of the
web platform than just HTML. :^)
|