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.
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.
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. :^)
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! :^)