Skip to content

Commit

Permalink
Shadow: define slotchange event
Browse files Browse the repository at this point in the history
Shadow: define slotchange event

Fixes WICG/webcomponents#288.

This defines the slotchange event in response to remove/insert operations, changes to a slot’s name attribute, and changes to an element’s slot attribute.

This also introduces the assigned nodes concept for slots, and assigned slot concept for slotables.

Slotables now also have a name, rather than a “get name”.

The slotchange event dispatches just after mutation observers have their callbacks invoked. The slotchange event is not yet marked scoped as scoped events are not yet defined in the DOM Standard.

Note: although the original issue did not mention it, this also suppresses signaling when slots are removed from a tree. Not just when they are inserted.
  • Loading branch information
annevk committed Apr 19, 2016
1 parent cb7c16b commit 81566a3
Show file tree
Hide file tree
Showing 2 changed files with 296 additions and 34 deletions.
178 changes: 161 additions & 17 deletions dom.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1518,27 +1518,78 @@ itself.</p>
<p>A <a>slot</a> has an associated <dfn export for=slot>name</dfn> (a string). Unless stated
otherwise it is the empty string.</p>

<p>Use these <a>attribute change steps</a> to update a <a>slot</a>'s <a for=slot>name</a>:

<ol>
<li>
<p>If <var>element</var> is a <a>slot</a>, <var>localName</var> is <code>name</code>, and
<var>namespace</var> is null, then:

<ol>
<li><p>If <var>value</var> is <var>oldValue</var>, then return.

<li><p>If <var>value</var> is null and <var>oldValue</var> is the empty string, then return.

<li><p>If <var>value</var> is the empty string and <var>oldValue</var> is null, then return.

<li><p>If <var>value</var> is null or the empty string, then set <var>element</var>'s
<a for=slot>name</a> to the empty string.

<li><p>Otherwise, set <var>element</var>'s <a for=slot>name</a> to <var>value</var>.

<li><p>Run <a>assign slotables for a tree</a> with <var>element</var>'s <a>tree</a>.
</ol>
</ol>

<p class="note">The first <a>slot</a> in a <a>shadow tree</a>, in <a>tree order</a>, whose
<a for=slot>name</a> is the empty string, is sometimes known as the "default slot".</p>

<p>A <a>slot</a> has an associated <dfn export for=slot>assigned nodes</dfn> (a list of
<a>slotables</a>). Unless stated otherwise it is empty.</p>

<h5 id=light-tree-slotables>Slotables</h5>

<p>{{Element}} and {{Text}} <a>nodes</a> are
<dfn export id=concept-slotable lt=slotable>slotables</dfn>.</p>

<p>A <a>slotable</a> has a <dfn for=slotable>get name</dfn> algorithm, which runs these steps:</p>
<p class="note">A <a>slot</a> can be a <a>slotable</a>.

<p>A <a>slotable</a> has an associated <dfn export for=slotable>name</dfn> (a string). Unless stated
otherwise it is the empty string.</p>

<p>Use these <a>attribute change steps</a> to update a <a>slotable</a>'s <a for=slotable>name</a>:

<ol>
<li><p>If <a>context object</a> is a {{Text}} <a>node</a>, then return the empty string.</p></li>
<li>
<p>If <var>localName</var> is <code>slot</code> and <var>namespace</var> is null, then:

<li><p>Return the result of running <a>get an attribute value</a> given <a>context object</a> and
"<code>slot</code>".</p></li>
<ol>
<li><p>If <var>value</var> is <var>oldValue</var>, then return.

<li><p>If <var>value</var> is null and <var>oldValue</var> is the empty string, then return.

<li><p>If <var>value</var> is the empty string and <var>oldValue</var> is null, then return.

<li><p>If <var>value</var> is null or the empty string, then set <var>element</var>'s
<a for=slotable>name</a> to the empty string.

<li><p>Otherwise, set <var>element</var>'s <a for=slotable>name</a> to <var>value</var>.

<li><p>If <var>element</var>'s <a for=slotable>assigned slot</a> is non-null, then run
<a>assign slotables</a> for <var>element</var>'s <a for=slotable>assigned slot</a>.

<li><p>Run <a>assign a slot</a> for <var>element</var>.
</ol>
</ol>

<p>A <a>slotable</a> has an associated <dfn export for=slotable>assigned slot</dfn> (null or a
<a>slot</a>). Unless stated otherwise it is null.</p>

<h5 id=finding-slots-and-slotables>Finding slots and slotables</h5>

<p>To <dfn>find a slot</dfn> for a given <a>slotable</a> <var>slotable</var> and an optional
<i>open flag</i> (unset unless stated otherwise), run these steps:</p>
<p>To <dfn lt="find a slot|finding a slot">find a slot</dfn> for a given <a>slotable</a>
<var>slotable</var> and an optional <i>open flag</i> (unset unless stated otherwise), run these
steps:</p>

<ol>
<li><p>If <var>slotable</var>'s <a>parent</a> is null, then return null.</p></li>
Expand All @@ -1551,14 +1602,12 @@ otherwise it is the empty string.</p>
<li><p>If the <i>open flag</i> is set and <var>shadow</var>'s <a for=ShadowRoot>mode</a> is
<em>not</em> "<code>open</code>", then return null.</p></li>

<li><p>Let <var>name</var> be the result of running <var>slotable</var>'s
<a for=slotable>get name</a>.</p></li>

<li><p>Return the first <a>slot</a> in <var>shadow</var>'s <a>tree</a> whose <a for=slot>name</a>
is <var>name</var>, if any, and null otherwise.</p></li>
is <var>slotable</var>'s <a for=slotable>name</a>, if any, and null otherwise.</p></li>
</ol>

<p>To <dfn>find slotables</dfn> for a given <a>slot</a> <var>slot</var>, run these steps:</p>
<p>To <dfn lt="find slotables|finding slotables">find slotables</dfn> for a given <a>slot</a>
<var>slot</var>, run these steps:</p>

<ol>
<li><p>Let <var>result</var> be an empty list.</p></li>
Expand All @@ -1574,7 +1623,7 @@ otherwise it is the empty string.</p>
<a>tree order</a>, run these substeps:</p>

<ol>
<li><p>Let <var>foundSlot</var> be the result of running <a>find a slot</a> given
<li><p>Let <var>foundSlot</var> be the result of <a>finding a slot</a> given
<var>slotable</var>.</p></li>

<li><p>If <var>foundSlot</var> is <var>slot</var>, then append <var>slotable</var> to
Expand All @@ -1585,13 +1634,14 @@ otherwise it is the empty string.</p>
<li><p>Return <var>result</var>.</p></li>
</ol>

<p>To <dfn>find distributed slotables</dfn> for a given <a>slot</a> <var>slot</var>, run these
steps:</p>
<p>To
<dfn lt="find flattened slotables|finding flattened slotables">find distributed slotables</dfn> for
a given <a>slot</a> <var>slot</var>, run these steps:</p>

<ol>
<li><p>Let <var>result</var> be an empty list.</p></li>

<li><p>Let <var>slotables</var> be the result of running <a>find slotables</a> given
<li><p>Let <var>slotables</var> be the result of <a>finding slotables</a> given
<var>slot</var>.</p></li>

<li><p>If <var>slotables</var> is the empty list, then append each <a>slotable</a>
Expand All @@ -1605,8 +1655,8 @@ steps:</p>
<p>If <var>node</var> is a <a>slot</a>, run these subsubsteps:</p>

<ol>
<li><p>Let <var>temporaryResult</var> be the result of running
<a>find distributed slotables</a> given <var>node</var>.</p></li>
<li><p>Let <var>temporaryResult</var> be the result of <a>finding flattened slotables</a> given
<var>node</var>.</p></li>

<li><p>Append each <a>slotable</a> in <var>temporaryResult</var>, in order, to
<var>result</var>.</p></li>
Expand All @@ -1619,6 +1669,66 @@ steps:</p>
<li><p>Return <var>result</var>.</p></li>
</ol>

<h5 id=assigning-slotables-and-slots>Assigning slotables and slots</h5>

<p>To <dfn>assign slotables</dfn>, for a <a>slot</a> <var>slot</var> with an optional
<var>suppress signaling flag</var> (unset unless stated otherwise), run these steps:

<ol>
<li><p>Let <var>slotables</var> be the result of <a>finding slotables</a> for <var>slot</var>.

<li><p>If <var>suppress signaling flag</var> is unset, and <var>slotables</var> and
<var>slot</var>'s <a>assigned nodes</a> are not identical, then run <a>signal a slot change</a> for
<var>slot</var>.

<li><p>Set <var>slot</var>'s <a>assigned nodes</a> to <var>slotables</var>.

<li><p>For each <var>slotable</var> in <var>slotables</var>, set <var>slotable</var>'s
<a>assigned slot</a> to <var>slot</var>.
</ol>

<p>To <dfn>assign slotables for a tree</dfn>, given a <a>tree</a> <var>tree</var> and an optional
set of <a>slots</a> <var>noSignalSlots</var> (empty unless stated otherwise), run these steps for
each <a>slot</a> <var>slot</var> in <var>tree</var>, in <a>tree order</a>:

<ol>
<li><p>Let <var>suppress signaling flag</var> be set, if <var>slot</var> is in
<var>noSignalSlots</var>, and unset otherwise.</p></li>

<li><p>Run <a>assign slotables</a> for <var>slot</var> with <var>suppress signaling flag</var>.
</ol>

<p>To <dfn>assign a slot</dfn>, given a <a>slotable</a> <var>slotable</var>, run these steps:

<ol>
<li><p>Let <var>slot</var> be the result of <a>finding a slot</a> with <var>slotable</var>.

<li><p>If <var>slot</var> is non-null, then run <a>assign slotables</a> for <var>slot</var>.
</ol>

<h5 id=signaling-slot-change>Signaling slot change</h5>

<p>Each <a>unit of related similar-origin browsing contexts</a> has a
<dfn export>signal slot list</dfn> (a list of <a>slots</a>). Unless stated otherwise it is empty.
[[!HTML]]

<p>To <dfn>signal a slot change</dfn>, for a <a>slot</a> <var>slot</var>, run these steps:

<ol>
<li><p>If <var>slot</var> is not in <a>unit of related similar-origin browsing contexts</a>'
<a>signal slot list</a>, append <var>slot</var> to
<a>unit of related similar-origin browsing contexts</a>' <a>signal slot list</a>.

<li><p>If <var>slot</var>'s <a>assigned slot</a> is non-null, then run <a>signal a slot change</a>
for <var>slot</var>'s <a>assigned slot</a>.

<li><p>Otherwise, if <var>slot</var>'s <a>parent</a> is a <a>slot</a> and <var>slot</var>'s
<a>parent</a>'s <a>assigned nodes</a> is the empty list, then run <a>signal a slot change</a> for
<var>slot</var>'s <a>parent</a>.

<li><p><a>Queue a mutation observer compound microtask</a>.
</ol>


<h4 id=mutation-algorithms>Mutation algorithms</h4>

Expand Down Expand Up @@ -1788,6 +1898,15 @@ into a <var>parent</var> before a <var>child</var>, with an optional
<li><p>Insert <var>node</var> into <var>parent</var> before <var>child</var> or at the end of
<var>parent</var> if <var>child</var> is null.

<li><p>If <var>parent</var>'s <a for=Element>shadow root</a> is non-null and <var>node</var> is a
<a>slotable</a>, then <a>assign a slot</a> for <var>node</var>.

<li><p>If <var>parent</var> is a <a>slot</a> whose <a>assigned nodes</a> is the empty list, then
run <a>signal a slot change</a> for <var>parent</var>.

<li><p>Run <a>assign slotables for a tree</a> with <var>node</var>'s <a>tree</a> and a set
containing each <a>inclusive descendant</a> of <var>node</var> that is a <a>slot</a>.

<li>
<p>For each <a>shadow-including inclusive descendant</a> <var>inclusiveDescendant</var> of
<var>node</var>, in <a>shadow-including tree order</a>, run these subsubsteps:
Expand Down Expand Up @@ -2059,6 +2178,21 @@ steps:

<li>Remove <var>node</var> from its <var>parent</var>.

<li><p>If <var>node</var>'s <a>assigned slot</a> is non-null, then run <a>assign slotables</a> for
<var>node</var>'s <a>assigned slot</a>.

<li><p>If <var>parent</var> is a <a>slot</a> whose <a>assigned nodes</a> is the empty list, then
run <a>signal a slot change</a> for <var>parent</var>.

<li><p>If <var>node</var> has an <a>inclusive descendant</a> that is a <a>slot</a>, then:

<ol>
<li><p>Run <a>assign slotables for a tree</a> with <var>parent</var>'s <a>tree</a>.

<li><p>Run <a>assign slotables for a tree</a> with <var>node</var>'s <a>tree</a> and a set
containing each <a>inclusive descendant</a> of <var>node</var> that is a <a>slot</a>.
</ol>

<li><p>Run the <a>removing steps</a> with <var>node</var> and <var>parent</var>.

<li>
Expand Down Expand Up @@ -2755,6 +2889,16 @@ To <dfn export>notify mutation observers</dfn>, run these steps:
<a>callback this value</a>. If this throws an exception,
<a>report the exception</a>.
</ol>

<li><p>Let <var>signalList</var> be a copy of
<a>unit of related similar-origin browsing contexts</a>' <a>signal slot list</a>.

<li><p>Empty <a>unit of related similar-origin browsing contexts</a>' <a>signal slot list</a>.

<li><p>For each <a>slot</a> <var>slot</var> in <var>signalList</var>, in order,
<a>fire an event</a> named <code>slotchange</code>, with its {{Event/bubbles}} attribute set to
true, at <var>slot</var>.
<!-- XXX scoped (change this while updating events for shadow trees) -->
</ol>

<hr>
Expand Down
Loading

0 comments on commit 81566a3

Please sign in to comment.