WebKit Bugzilla
Attachment 346421 Details for
Bug 188279
: Range APIs do not construct / move trees in tree order (observable by custom elements)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
The test page mentioned in the bug.
rangeOrdering.html (text/html), 5.19 KB, created by
Russell Bicknell
on 2018-08-02 15:15:39 PDT
(
hide
)
Description:
The test page mentioned in the bug.
Filename:
MIME Type:
Creator:
Russell Bicknell
Created:
2018-08-02 15:15:39 PDT
Size:
5.19 KB
patch
obsolete
><!doctype html> > ><template id="original"> > <c-e> > (root) > <c-e> > (root-0) > <c-e> > (root-0-0) > <c-e>(root-0-0-0)</c-e> > <c-e>(root-0-0-1......<span class="start"></span>.....)</c-e> > <c-e>(root-0-0-2)</c-e> > </c-e> > <c-e> > (root-0-1) > <c-e>(root-0-1-0)</c-e> > <c-e>(root-0-1-1)</c-e> > <c-e>(root-0-1-2)</c-e> > </c-e> > </c-e> > <c-e>(root-1)</c-e> > <c-e> > (root-2) > <c-e> > (root-2-0) > <c-e>(root-2-0-0)</c-e> > <c-e>(root-2-0-1)</c-e> > <c-e>(root-2-0-2)</c-e> > </c-e> > <c-e> > (root-2-1) > <c-e>(root-2-1-0)</c-e> > <c-e>(root-2-1-1.....<span class="end"></span>....)</c-e> > <c-e>(root-2-1-2)</c-e> > </c-e> > </c-e> > </c-e> ></template> > ><h1>Choose events to log:</h1> ><table> > <thead> > <tr> > <td>enable</td> > <td colspan="2">legend</td> > </tr> > </thead> > <tbody> > <tr> > <td><input type="checkbox" id="logConstructor" checked></td> > <td>#<var>n</var></td> > <td>constructor called at step <var>n</var></td> > </tr> > <tr> > <td><input type="checkbox" id="logNew" checked></td> > <td>NEW</td> > <td>created during the range operation</td> > </tr> > <tr> > <td><input type="checkbox" id="logConnected"></td> > <td>C<var>n</var></td> > <td><code>connectedCallback</code> called at step <var>n</var></td> > </tr> > <tr> > <td><input type="checkbox" id="logDisconnected"></td> > <td>D<var>n</var></td> > <td><code>disconnectedCallback</code> called at step <var>n</var></td> > </tr> > </tbody> ></table> > ><hr> > ><h1>1. Create the source tree:</h1> ><button id="createSourceTree">create source</button> > ><div id="input"></div> > ><h1>2. Perform a range operation:</h1> ><button id="extract" disabled>extract</button> ><button id="clone" disabled>clone</button> > ><div id="output"></div> > ><script> >"use strict"; > > >// A custom element that logs based on the checkboxes in this page. > >let annotation = ''; >let order = 0; >class CE extends HTMLElement { > constructor() { > super(); > this.attachShadow({mode: 'open'}).innerHTML = ` > [<span id="log"></span>] <slot></slot> > `; > if (logConstructor.checked) { > this._log(`#${order++}`); > } > if (logNew.checked && annotation !== '') { > this._log(` ${annotation}`); > } > } > > connectedCallback() { > if (logConnected.checked) { > this._log(`, C${order++}`); > } > } > > disconnectedCallback() { > if (logDisconnected.checked) { > this._log(`, D${order++}`); > } > } > > _log(text) { > this.shadowRoot.querySelector('#log').appendChild(new Text(text)); > } >} >customElements.define('c-e', CE); > > >// checkboxes >const logConstructor = document.getElementById('logConstructor'); >const logNew = document.getElementById('logNew'); >const logConnected = document.getElementById('logConnected'); >const logDisconnected = document.getElementById('logDisconnected'); > >// buttons >const createSourceTreeButton = document.getElementById('createSourceTree'); >const extractButton = document.getElementById('extract'); >const cloneButton = document.getElementById('clone'); > > >createSourceTreeButton.addEventListener('click', () => { > const template = document.getElementById('original'); > const input = document.getElementById('input'); > > // Use `innerHTML` so that these elements are created by the parser. > input.innerHTML = template.innerHTML; > > // Disable / enable controls for next step. > createSourceTreeButton.disabled = true; > cloneButton.disabled = false; > extractButton.disabled = false; >}); > > >function getRange() { > const range = new Range(); > const start = document.querySelector('#input .start'); > const end = document.querySelector('#input .end'); > range.setStart(start.parentNode, Array.from(start.parentNode.childNodes).indexOf(start)); > range.setEnd(end.parentNode, Array.from(end.parentNode.childNodes).indexOf(end) + 1); > return range; >} > > >cloneButton.addEventListener('click', () => { > annotation = 'NEW'; > > // Get the range, clone it, append the resulting fragment to the output div. > document.getElementById('output').appendChild( > getRange().cloneContents() > ); > > // Disable controls. > cloneButton.disabled = true; > extractButton.disabled = true; >}); > >extractButton.addEventListener('click', () => { > annotation = 'NEW'; > > // Get the range, extract it, append the resulting fragment to the output div. > document.getElementById('output').appendChild( > getRange().extractContents() > ); > > // Disable controls. > cloneButton.disabled = true; > extractButton.disabled = true; >}); ></script> > ><style> >body { > font-family: sans-serif; >} > >h1 { > font-size: 1rem; >} > >#input, #output { > margin: 4px; > border-width: 4px; > border-style: dashed; > padding: 4px; >} > >#input { > border-color: blue; >} > >#output { > border-color: orange; >} > >c-e { > display: block; > margin: 2px; > border: 1px solid gray; > padding: 2px; >} > >c-e c-e { > margin-left: 2ch; >} > >.start::before { > content: 'START'; > background-color: #0f0; >} > >.end::before { > content: 'END'; > background-color: #f00; >} > >table { > border-spacing: 0px; >} > >table td { > padding: 2px; >} > >thead td { > border-bottom: 1px solid #ccc; >} > >td:not(:last-of-type) { > border-right: 1px solid #ccc; >} ></style>
<!doctype html> <template id="original"> <c-e> (root) <c-e> (root-0) <c-e> (root-0-0) <c-e>(root-0-0-0)</c-e> <c-e>(root-0-0-1......<span class="start"></span>.....)</c-e> <c-e>(root-0-0-2)</c-e> </c-e> <c-e> (root-0-1) <c-e>(root-0-1-0)</c-e> <c-e>(root-0-1-1)</c-e> <c-e>(root-0-1-2)</c-e> </c-e> </c-e> <c-e>(root-1)</c-e> <c-e> (root-2) <c-e> (root-2-0) <c-e>(root-2-0-0)</c-e> <c-e>(root-2-0-1)</c-e> <c-e>(root-2-0-2)</c-e> </c-e> <c-e> (root-2-1) <c-e>(root-2-1-0)</c-e> <c-e>(root-2-1-1.....<span class="end"></span>....)</c-e> <c-e>(root-2-1-2)</c-e> </c-e> </c-e> </c-e> </template> <h1>Choose events to log:</h1> <table> <thead> <tr> <td>enable</td> <td colspan="2">legend</td> </tr> </thead> <tbody> <tr> <td><input type="checkbox" id="logConstructor" checked></td> <td>#<var>n</var></td> <td>constructor called at step <var>n</var></td> </tr> <tr> <td><input type="checkbox" id="logNew" checked></td> <td>NEW</td> <td>created during the range operation</td> </tr> <tr> <td><input type="checkbox" id="logConnected"></td> <td>C<var>n</var></td> <td><code>connectedCallback</code> called at step <var>n</var></td> </tr> <tr> <td><input type="checkbox" id="logDisconnected"></td> <td>D<var>n</var></td> <td><code>disconnectedCallback</code> called at step <var>n</var></td> </tr> </tbody> </table> <hr> <h1>1. Create the source tree:</h1> <button id="createSourceTree">create source</button> <div id="input"></div> <h1>2. Perform a range operation:</h1> <button id="extract" disabled>extract</button> <button id="clone" disabled>clone</button> <div id="output"></div> <script> "use strict"; // A custom element that logs based on the checkboxes in this page. let annotation = ''; let order = 0; class CE extends HTMLElement { constructor() { super(); this.attachShadow({mode: 'open'}).innerHTML = ` [<span id="log"></span>] <slot></slot> `; if (logConstructor.checked) { this._log(`#${order++}`); } if (logNew.checked && annotation !== '') { this._log(` ${annotation}`); } } connectedCallback() { if (logConnected.checked) { this._log(`, C${order++}`); } } disconnectedCallback() { if (logDisconnected.checked) { this._log(`, D${order++}`); } } _log(text) { this.shadowRoot.querySelector('#log').appendChild(new Text(text)); } } customElements.define('c-e', CE); // checkboxes const logConstructor = document.getElementById('logConstructor'); const logNew = document.getElementById('logNew'); const logConnected = document.getElementById('logConnected'); const logDisconnected = document.getElementById('logDisconnected'); // buttons const createSourceTreeButton = document.getElementById('createSourceTree'); const extractButton = document.getElementById('extract'); const cloneButton = document.getElementById('clone'); createSourceTreeButton.addEventListener('click', () => { const template = document.getElementById('original'); const input = document.getElementById('input'); // Use `innerHTML` so that these elements are created by the parser. input.innerHTML = template.innerHTML; // Disable / enable controls for next step. createSourceTreeButton.disabled = true; cloneButton.disabled = false; extractButton.disabled = false; }); function getRange() { const range = new Range(); const start = document.querySelector('#input .start'); const end = document.querySelector('#input .end'); range.setStart(start.parentNode, Array.from(start.parentNode.childNodes).indexOf(start)); range.setEnd(end.parentNode, Array.from(end.parentNode.childNodes).indexOf(end) + 1); return range; } cloneButton.addEventListener('click', () => { annotation = 'NEW'; // Get the range, clone it, append the resulting fragment to the output div. document.getElementById('output').appendChild( getRange().cloneContents() ); // Disable controls. cloneButton.disabled = true; extractButton.disabled = true; }); extractButton.addEventListener('click', () => { annotation = 'NEW'; // Get the range, extract it, append the resulting fragment to the output div. document.getElementById('output').appendChild( getRange().extractContents() ); // Disable controls. cloneButton.disabled = true; extractButton.disabled = true; }); </script> <style> body { font-family: sans-serif; } h1 { font-size: 1rem; } #input, #output { margin: 4px; border-width: 4px; border-style: dashed; padding: 4px; } #input { border-color: blue; } #output { border-color: orange; } c-e { display: block; margin: 2px; border: 1px solid gray; padding: 2px; } c-e c-e { margin-left: 2ch; } .start::before { content: 'START'; background-color: #0f0; } .end::before { content: 'END'; background-color: #f00; } table { border-spacing: 0px; } table td { padding: 2px; } thead td { border-bottom: 1px solid #ccc; } td:not(:last-of-type) { border-right: 1px solid #ccc; } </style>
View Attachment As Raw
Actions:
View
Attachments on
bug 188279
: 346421