Built-in page elements Reference

Standard HTML elements

Some of the standard HTML elements need special handling, therefore they have corresponding classes defined in pagelems.

Otherwise, any other elements will be matched verbatim

class DHtmlObject(tag: <html>)

Consume the <html> element as top-level site page

As expected, may only have a <head> and a <body> .

class DHeadElement(tag: <head>)

HTML head only supports parsing-related elements

Currently, only <link>s and <template>s are allowed in <head>

class DLinkObject(tag: <link>)

Links are used to include other pagelem templates

class DBodyElement(tag: <body>)

Defines, matches the HTML <body>

class ScriptElement(tag: <script>)

Scripts are NOT allowed so far

class InputElement(tag: <input>)

Model an <input> element

Inputs are special and a bit weird. They are points of interaction with the remote side, also volatile, so must be exposed into DOM components. When this is specified, inputs become components as usual. Otherwise they become attributes of the parent components.

Therefore <input> elements MUST have this, an id or a name.

When ‘type’ is specified at this pagelem node, it helps choose the right descriptor class for the value of this input. If not, it may be auto-detected IF this is used OR name=’*’ performs wildcard detection of input elements.

If ‘pe-name’ attribute is specified, it overrides the ‘name’ one as the name to be used under the component, but does NOT need to match remote attribute(s).

Example:

<input pe-name="submit" type="submit">

will match any submit button and assign it to ‘submit’ name, even if the remote <input> element has no more attributes.

Note that setting both ‘this’ and ‘pe-name’ makes no sense, since a component-ized <input> element will not need a name.

class TextAreaObj(tag: <textarea>)

Textarea is handled just like <input>

class GHtmlObject(tag: <html> * in gallery)

Handle the <html> element of a gallery file

Gallery files can only contain <template> elements in their <head> or <body>, no other HTML.

Templates and slots

Templates and slots are defined in HTML5. This concept is re-used in pagelems, but as a means of parsing. See: Templates and Slots

class DTemplateElement(tag: <template>)

A template defines reusable DOM that is not normally rendered/scanned

See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template

Likewise, the template will be re-used in this parser, match remote DOM and generate same proxy elements, under their caller.

id="name"

Mandatory attribute, needed to register this template in the local scope.

class DUseTemplateElem(tag: <use-template>)

Calls a <template> in its place

Example:

<use-template id="chapter">
    <div slot="extra" class="remark" this="remark"> ... </div>
</use-template>
id="name"

refers to a <template> to use

class DSlotElement(tag: <slot>)

The contents of a <slot> are replaced by parent scope, if available

This resembles the official W3C definition of slots in the browser, meant to be a placeholder for content that can be customized within a template.

name="slot-name"

Slots must have a name, so that implementations can attach to them.

class DSlotContentElement(tag: <pe-slotcontent>)

Jump back to the content of calling ‘<slot>’ element

Example:

<div class="slot">
    <slot name="foo">
        <div class="content">
        </div>
    </slot>
</div>

<div slot="foo" class="bar">
    <middle>
        <pe-slotcontent/>
    </middle>
</div>

Should be equivalent to:

<div class="slot">
    <div class="bar">
        <middle>
            <div class="content"></div>
        </middle>
    </div>
</div>
This is inspired by Jinja2 ‘caller’ concept:
http://jinja.pocoo.org/docs/2.10/templates/#call

Pagelem flow elements

class DeepContainObj(tag: <pe-deep>)

Match contained elements at any level deep inside the DOM

Example:

<body>
    <pe-deep> <div class="content"></div> </pe-deep>
</body>

will match:

<body>
    <main>
        <div class="section">
            <div class="content"> ... </div>
        </div>
    </main>
</body>

Equivalent of using ‘pe-deep’ as an attribute.

Example (alt):

<body>
    <div pe-deep class="content"></div>
</body>
class RootAgainElem(tag: <pe-root>)

Reset to root element (of DOM), keep component deep in tree

Useful for overlays, where the modal part is attached to the <body> instead of that element itself, but logically linked to that inner component.

class RepeatObj(tag: <pe-repeat>)

Locate multiple components, from one template

In its simpler form, it allows explicit iterations, where the inner component wouldn’t.

Example:

<pe-repeat>
    <div class="chapter" this="chapter> ...</div>
</pe-repeat>

this would match all <div class=”chapter”> , assigning them to components like chapter1 , chapter2 etc.

But also useful for any controlled iteration. Supports min and max limits of how many components to match.

Then, <pe-repeat> can have this attribute, assigning the list of produced components as one component. This is useful even when iteration is not desired, rather a component that does not consume its corresponding DOM (parent) element.

class PeChoiceElement(tag: <pe-choice>)

Matches the first child of this element (at least)

Using pe-choice means that at least one of its children shall match the remote, any others can fail.

Example:

<pe-choice>
    <div class="chapter" this="chapter">...</div>
    <div class="footer" this="footer">...</div>
    <section class="index" this="index"> ... </section>
</pe-choice>

the above would succeed if any of these three patterns match, but could also emit /all/ of them, if these can be found.

Note that the output of <pe-choice> is ordered by the options given inside pe-choice, NOT the order that elements are in the remote DOM. This is due to the XPath implementation.

class PeGroupElement(tag: <pe-group>)

Trivial group, DOM-less container of many elements

Implements all-or-nothing logic, will never produce partial components* from its childen.

By default, unordered behaviour. Can specify ‘ordered’ to enforce that children sub-elements are matched in strict order.

* unless the group’s children have optional logic with <pe-choice> or <pe-repeat>.

class PeMatchIDElement(tag: <pe-matchid>)

Jump to an element that matches by id

It is a compact shorthand for taking an element’s attribute, resolving it and then searching the root of the DOM for that id.

Example:

<input this="input" role="combobox"
       aria-owns='[owns]'>
<pe-matchid id="root['input'].owns" this="panel" pe-optional>
    ...
</pe-matchid>

would resolve the aria-owns attribute of the <input> , then look for any element with that id in the tree, assign it to the dropdown panel.

Pagelem match elements

class AnyElement(tag: <pe-any>)

Match any HTML element

This would match any element in the remote DOM, but also serves as a baseclass for matching particular tags.

Useful for matching a particular element by attribute, rather than HTML tag.

Offers some standard attributes and rich syntax for matching remote DOM element properties.

this="name"

Exposes the element as a component under that name

slot="name"

Attaches this element into a <slot> of a <template>

Only valid within <use-template> blocks

pe-deep

Matches that element at any nested level under the parent. Equivalent of puting that element within a <pe-deep> tag

pe-optional

Makes matching optional, this element and any children may not exist.

pe-controller="some.controller"

Uses some.controller to complement functionality of this component.

pe-ctrl

Synonym of pe-controller

class PeNotElement(tag: <pe-not>)

Negative-match element: check that element does NOT contain others

Negative-match will invert the meaning of contained matches, thus not selecting parents that contain specified patterns.

Example:

<div class="eggs">
    <pe-not><div class="spam"></div>
    </pe-not>
</div>

Meaning that it will match a div@class=eggs that does NOT contain a spam div .

When multiple children elements are specified inside pe-not, then all of them should be present for parent to mis-match. Having any of the children but not all, will allow the parent to match.

The other logic, failing the parent if any children exist, is possible by using multiple <pe-not> elements.

Do not use named elements (with this) or logic of pe-choice, pe-repeat or pe-optional elements inside a pe-not. As it will never create components, such logic is pointless.

class RegexElement(tag: <pe-regex>)

Match text of remote DOM element, parse with regex into attribute(s)

If this regex contains (?P<name>...) named groups, these will be exposed as name attributes.

Otherwise, if this attribute is defined, expose all matched string under this name.

Note

text inside this element can contain ‘<’ and ‘>’, no need to escape these.

Example:

<div class="header" this="chapter">
    <pe-regex>Chapter (?P<number>[0-9]+): (?P<title>.*)</pe-regex>
</div>

This one would match DOM like this:

<div class="header">Chapter 4: Getting there</div>

and produce a component like:

chapter: number="4" title="Getting there"

Pagelem data elements

class PeDataElement(tag: <pe-data>)

Define arbitrary data as a component attribute

This supports two modes: with a value= attribute or using inner JSON data.

When using the value= attribute, the data will be a plain string. When using inner JSON, it can be any of the simple types that JSON supports.

Example:

<div class="chapter" this="chapter">
    <pe-data name="lang" value="en"/>
    <pe-data name="difficulty">0.8</pe-data>
    ...
</div>
would produce a component like:
chapter: lang=”en” difficulty=0.8

Note that difficulty is parsed as JSON, and therefore becomes a native float, rather than a string.

class PEScopeDataElement(tag: <pe-scopedata>)

Attach arbitrary data as a scope attribute

WARNING: this data will only work if the component containing this tag is ‘discovered’, ie. attached to that scope.