• More-or-Less panel (web component)

    From luserdroog@21:1/5 to All on Thu Jul 6 08:34:43 2023
    I'm trying to factor out some of the disparate functionality in my app.
    This one seemed to peel out rather nicely, only I'm somehow not able
    to successfully send it a custom "redraw" event. In my application I'm
    having to trigger a redraw by peeking into the shadow dom and calling
    .click() twice on the toggle.

    A <more-panel></more-panel> works like a div that can be in either
    of two states: a 'more' state where the clickable word says "(less)"
    and the panel hides contents with the class of "less" and shows
    contents with the class of "more; and a 'less' state where the clickable
    word says "(more)" and the panel hides contents with the class of
    "more" and shows contents with the class of "less". Contents without
    either of these classes is simply passed through unmolested.
    Contents with both classes will be shown in both states.

    The more-panel itself can be instantiated with or without the "more"
    class to specify its initial state.

    Any critiques or comments welcome.

    more.js:
    const morePanelTemplate = document.createElement("template"); morePanelTemplate.innerHTML = `
    <style>
    .content{
    border: 1px solid;
    border-radius: 5px;
    }
    #toggle{
    font-size: small;
    text-decoration: underline;
    cursor: pointer;
    }
    </style>
    <div class="content">
    <span id=toggle></span>
    <slot></slot>
    </div>
    `;

    class MorePanel extends HTMLElement {

    constructor() {
    super();
    this.attachShadow( {mode:"open"} );
    this.shadowRoot.appendChild( morePanelTemplate.content.cloneNode(true) );
    let content = this.shadowRoot.querySelector(".content");
    this.showStuff();
    }

    showStuff() {
    if( this.classList.contains( "more" ) )
    this.showMore();
    else
    this.showLess();
    }

    connectedCallback() {
    this.shadowRoot.querySelector("#toggle").addEventListener( "click", ()=>{
    this.classList.toggle( "more" );
    this.showStuff();
    });
    self.addEventListener( "redraw", (event) => this.showStuff() );
    }

    disconnectedCallback() {
    this.shadowRoot.querySelector("#toggle").removeEventListener();
    }

    showMore() {
    this.shadowRoot.querySelector("#toggle").textContent="(less)";
    this.querySelectorAll(".less").forEach( el => el.style.display = 'none' );
    this.querySelectorAll(".more").forEach( el => el.style.display = '' );
    }

    showLess() {
    this.shadowRoot.querySelector("#toggle").textContent="(more)";
    this.querySelectorAll(".more").forEach( el => el.style.display = 'none' );
    this.querySelectorAll(".less").forEach( el => el.style.display = '' );
    }
    }

    window.customElements.define( "more-panel", MorePanel );



    more.html:
    <!DOCTYPE html>
    <meta http-equiv="content-type" content="text/html" charset="UTF-8">
    <meta name="viewport" content="width=device-width">
    <html>
    <title></title>
    <style>
    </style>
    <body>
    <more-panel class="more">
    <div class="more">This div</div>
    <span>the span</span>
    </more-panel>
    </body>
    <script src="more.js"></script>
    <script>
    </script>
    </html>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Haufe (TNO)@21:1/5 to luserdroog on Mon Jul 10 10:46:29 2023
    On Thursday, July 6, 2023 at 10:34:49 AM UTC-5, luserdroog wrote:
    I'm trying to factor out some of the disparate functionality in my app.
    This one seemed to peel out rather nicely, only I'm somehow not able
    to successfully send it a custom "redraw" event. In my application I'm having to trigger a redraw by peeking into the shadow dom and calling .click() twice on the toggle.

    A <more-panel></more-panel> works like a div that can be in either
    of two states: a 'more' state where the clickable word says "(less)"
    and the panel hides contents with the class of "less" and shows
    contents with the class of "more; and a 'less' state where the clickable word says "(more)" and the panel hides contents with the class of
    "more" and shows contents with the class of "less". Contents without
    either of these classes is simply passed through unmolested.
    Contents with both classes will be shown in both states.

    The more-panel itself can be instantiated with or without the "more"
    class to specify its initial state.

    Any critiques or comments welcome.
    [...]

    There is a native <details /> tag you can use now:

    <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details>

    Just style it as appropriate

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luserdroog@21:1/5 to All on Mon Jul 10 19:12:00 2023
    On Monday, July 10, 2023 at 12:46:36 PM UTC-5, Michael Haufe (TNO) wrote:
    On Thursday, July 6, 2023 at 10:34:49 AM UTC-5, luserdroog wrote:
    I'm trying to factor out some of the disparate functionality in my app. This one seemed to peel out rather nicely, only I'm somehow not able
    to successfully send it a custom "redraw" event. In my application I'm having to trigger a redraw by peeking into the shadow dom and calling .click() twice on the toggle.

    A <more-panel></more-panel> works like a div that can be in either
    of two states: a 'more' state where the clickable word says "(less)"
    and the panel hides contents with the class of "less" and shows
    contents with the class of "more; and a 'less' state where the clickable word says "(more)" and the panel hides contents with the class of
    "more" and shows contents with the class of "less". Contents without either of these classes is simply passed through unmolested.
    Contents with both classes will be shown in both states.

    The more-panel itself can be instantiated with or without the "more"
    class to specify its initial state.

    Any critiques or comments welcome.
    [...]

    There is a native <details /> tag you can use now:

    <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details>

    Just style it as appropriate

    Well, dang. I wish I'd noticed that earlier. Thanks. That does 90% of what
    I wanted. Ultimately, I found the extra flexibility very useful. Being able to toggle the "more" and "less" classes separately on the contents means
    I can pop up an important control into the abbreviated state by just
    adding "less" to it. I suppose I could accomplish similar with some js gymnastics upon a <details />.

    Anyway, good to know. I like mine better.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Haufe (TNO)@21:1/5 to luserdroog on Mon Jul 10 22:12:11 2023
    On Monday, July 10, 2023 at 9:12:05 PM UTC-5, luserdroog wrote:
    Just style it as appropriate
    Well, dang. I wish I'd noticed that earlier. Thanks. That does 90% of what
    I wanted. Ultimately, I found the extra flexibility very useful. Being able to
    toggle the "more" and "less" classes separately on the contents means
    I can pop up an important control into the abbreviated state by just
    adding "less" to it. I suppose I could accomplish similar with some js gymnastics upon a <details />.

    Anyway, good to know. I like mine better.

    Well, the open state of <details /> can be styled with: details[open].

    The JavaScript event is simply:

    details.addEventListener("toggle", (event) => {
    if (details.open) {
    /* the element was toggled open */
    } else {
    /* the element was toggled closed */
    }
    });

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luserdroog@21:1/5 to All on Tue Aug 8 21:19:38 2023
    On Tuesday, July 11, 2023 at 12:12:17 AM UTC-5, Michael Haufe (TNO) wrote:
    On Monday, July 10, 2023 at 9:12:05 PM UTC-5, luserdroog wrote:
    Just style it as appropriate
    Well, dang. I wish I'd noticed that earlier. Thanks. That does 90% of what I wanted. Ultimately, I found the extra flexibility very useful. Being able to
    toggle the "more" and "less" classes separately on the contents means
    I can pop up an important control into the abbreviated state by just adding "less" to it. I suppose I could accomplish similar with some js gymnastics upon a <details />.

    Anyway, good to know. I like mine better.
    Well, the open state of <details /> can be styled with: details[open].

    The JavaScript event is simply:

    details.addEventListener("toggle", (event) => {
    if (details.open) {
    /* the element was toggled open */
    } else {
    /* the element was toggled closed */
    }
    });

    This tidbit turned out incredibly valuable. I wanted to wrap them all up
    and disappear them with one click. But mine don't nest. sigh.
    Wrapping it all in a <details> got me out of the corner without stepping
    in the paint.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)