• four-state checkbox?

    From luserdroog@21:1/5 to All on Thu Aug 3 08:04:53 2023
    I want to make a control that looks like a checkbox but cycles through
    4 states: { blank, checkmark, X-mark, questionmark }. What's the best
    way to build such a thing. I'm thinking it wouldn't be too hard to make
    a web component that just controls a span and flips through
    { " ", "&#x...whatevers", ... "?" } strings.

    Is there an existing element that's closer, like an <option> I guess?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Haufe (TNO)@21:1/5 to luserdroog on Thu Aug 3 14:46:11 2023
    On Thursday, August 3, 2023 at 10:04:58 AM UTC-5, luserdroog wrote:
    I want to make a control that looks like a checkbox but cycles through
    4 states: { blank, checkmark, X-mark, questionmark }. What's the best
    way to build such a thing. I'm thinking it wouldn't be too hard to make
    a web component that just controls a span and flips through
    { "&nbsp;", "&#x...whatevers", ... "?" } strings.

    Is there an existing element that's closer, like an <option> I guess?

    My first suggestion is choose a different way to accomplish this instead of abusing checkboxes which are meant to be binary (though less directly support an indeterminate state).

    If you insist on using a checkbox for this, you can leverage a radio list and style it appropriately:

    https://stackoverflow.com/a/33455783/153209

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luserdroog@21:1/5 to luserdroog on Sat Aug 5 05:55:08 2023
    On Thursday, August 3, 2023 at 10:04:58 AM UTC-5, luserdroog wrote:
    I want to make a control that looks like a checkbox but cycles through
    4 states: { blank, checkmark, X-mark, questionmark }. What's the best
    way to build such a thing. I'm thinking it wouldn't be too hard to make
    a web component that just controls a span and flips through
    { "&nbsp;", "&#x...whatevers", ... "?" } strings.

    Is there an existing element that's closer, like an <option> I guess?

    Thanks Michael and Arno. Here's my idea for the interface a little more
    fleshed out:

    <click-box cycle
    states="empty checkmark xmark questionmark"
    empty=""
    checkmark="&x#..."
    xmark="&x#..."
    questionmark="?"></click-box>

    Specifying the "cycle" attribute selects the (currently only) behavior
    of cycling through states. The .value attribute/property of the
    component will be reported as one of the strings from the "states"
    attribute. If a state value itself is defined as an attribute then the
    value of that attribute will be used as the label for visual display, otherwise the value string will be used as the label.

    This seems like it covers what I need, allowing extension without too
    much YAGNI, and I can stick one in a <template> and then clone that
    around where I need it, I think. Maybe it should also offer a .textContent output.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Arno Welzel@21:1/5 to All on Sat Aug 5 14:19:15 2023
    luserdroog, 2023-08-03 17:04:

    I want to make a control that looks like a checkbox but cycles through
    4 states: { blank, checkmark, X-mark, questionmark }. What's the best

    A *checkbox* is there to show a *checked* or *unchecked* state.

    If you need 4 different states, then it is not a checkbox but just some
    element which shows 4 states. And in most cases a radio group is much
    better for this - then users can clearly see what options are available
    and can choose one of the options.

    way to build such a thing. I'm thinking it wouldn't be too hard to make
    a web component that just controls a span and flips through
    { "&nbsp;", "&#x...whatevers", ... "?" } strings.

    Is there an existing element that's closer, like an <option> I guess?

    No. You need to implement it on your own or check if Angular, React, Vue
    or Bootstrap have a component for that.

    --
    Arno Welzel
    https://arnowelzel.de

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From The Natural Philosopher@21:1/5 to Arno Welzel on Sat Aug 5 18:31:58 2023
    On 05/08/2023 13:19, Arno Welzel wrote:
    luserdroog, 2023-08-03 17:04:

    I want to make a control that looks like a checkbox but cycles through
    4 states: { blank, checkmark, X-mark, questionmark }. What's the best

    A *checkbox* is there to show a *checked* or *unchecked* state.

    If you need 4 different states, then it is not a checkbox but just some element which shows 4 states. And in most cases a radio group is much
    better for this - then users can clearly see what options are available
    and can choose one of the options.

    way to build such a thing. I'm thinking it wouldn't be too hard to make
    a web component that just controls a span and flips through
    { "&nbsp;", "&#x...whatevers", ... "?" } strings.

    Is there an existing element that's closer, like an <option> I guess?

    No. You need to implement it on your own or check if Angular, React, Vue
    or Bootstrap have a component for that.

    It's not hard to do in Javascript, simply have an onmousedown() event
    that rotates an internal variable round 4 states and updates an onscreen
    area with text, or selects e.g. a pseudo LED to light up to indicate the
    state of the control.
    I have long since given up using any HTML input controls. They look like
    shit and they are hard to get looking nice across browser variations.

    CSS styles the whole thing and javascript handles all user input. And
    ajax calls update the server.




    --
    In theory, there is no difference between theory and practice.
    In practice, there is.
    -- Yogi Berra

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Arno Welzel@21:1/5 to he would not have on Sun Aug 6 13:47:56 2023
    The Natural Philosopher, 2023-08-05 19:31:

    On 05/08/2023 13:19, Arno Welzel wrote:
    luserdroog, 2023-08-03 17:04:

    I want to make a control that looks like a checkbox but cycles through
    4 states: { blank, checkmark, X-mark, questionmark }. What's the best
    [...]
    Is there an existing element that's closer, like an <option> I guess?

    No. You need to implement it on your own or check if Angular, React, Vue
    or Bootstrap have a component for that.

    It's not hard to do in Javascript, simply have an onmousedown() event
    that rotates an internal variable round 4 states and updates an onscreen
    area with text, or selects e.g. a pseudo LED to light up to indicate the state of the control.

    If the OP would be able to do so, he would not have asked here.

    I have long since given up using any HTML input controls. They look like
    shit and they are hard to get looking nice across browser variations.

    CSS styles the whole thing and javascript handles all user input. And
    ajax calls update the server.

    And all this is *not* accessible. HTML input controls can be styled
    *and* you can override them with your own components. But not using them
    at all is often a very bad decision.

    --
    Arno Welzel
    https://arnowelzel.de

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Arno Welzel@21:1/5 to All on Sun Aug 6 13:50:56 2023
    luserdroog, 2023-08-05 14:55:

    On Thursday, August 3, 2023 at 10:04:58 AM UTC-5, luserdroog wrote:
    I want to make a control that looks like a checkbox but cycles through
    4 states: { blank, checkmark, X-mark, questionmark }. What's the best
    way to build such a thing. I'm thinking it wouldn't be too hard to make
    a web component that just controls a span and flips through
    { "&nbsp;", "&#x...whatevers", ... "?" } strings.

    Is there an existing element that's closer, like an <option> I guess?

    Thanks Michael and Arno. Here's my idea for the interface a little more fleshed out:

    <click-box cycle
    states="empty checkmark xmark questionmark"
    empty=""
    checkmark="&x#..."
    xmark="&x#..."
    questionmark="?"></click-box>

    Maybe you should consult this:

    <https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements>



    --
    Arno Welzel
    https://arnowelzel.de

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From JJ@21:1/5 to luserdroog on Mon Aug 7 12:04:03 2023
    On Sat, 5 Aug 2023 05:55:08 -0700 (PDT), luserdroog wrote:
    On Thursday, August 3, 2023 at 10:04:58 AM UTC-5, luserdroog wrote:
    I want to make a control that looks like a checkbox but cycles through
    4 states: { blank, checkmark, X-mark, questionmark }. What's the best
    way to build such a thing. I'm thinking it wouldn't be too hard to make
    a web component that just controls a span and flips through
    { "&nbsp;", "&#x...whatevers", ... "?" } strings.

    Is there an existing element that's closer, like an <option> I guess?

    Thanks Michael and Arno. Here's my idea for the interface a little more fleshed out:

    <click-box cycle
    states="empty checkmark xmark questionmark"
    empty=""
    checkmark="&x#..."
    xmark="&x#..."
    questionmark="?"></click-box>

    Specifying the "cycle" attribute selects the (currently only) behavior
    of cycling through states. The .value attribute/property of the
    component will be reported as one of the strings from the "states"
    attribute. If a state value itself is defined as an attribute then the
    value of that attribute will be used as the label for visual display, otherwise the value string will be used as the label.

    This seems like it covers what I need, allowing extension without too
    much YAGNI, and I can stick one in a <template> and then clone that
    around where I need it, I think. Maybe it should also offer a .textContent output.

    That would be a custom input interface element. e.g.

    https://jsbin.com/dixapihuto/1/edit?html,css,js,output

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luserdroog@21:1/5 to All on Mon Aug 7 07:56:22 2023
    On Monday, August 7, 2023 at 12:04:12 AM UTC-5, JJ wrote:
    On Sat, 5 Aug 2023 05:55:08 -0700 (PDT), luserdroog wrote:
    On Thursday, August 3, 2023 at 10:04:58 AM UTC-5, luserdroog wrote:
    I want to make a control that looks like a checkbox but cycles through
    4 states: { blank, checkmark, X-mark, questionmark }. What's the best
    way to build such a thing. I'm thinking it wouldn't be too hard to make >> a web component that just controls a span and flips through
    { "&nbsp;", "&#x...whatevers", ... "?" } strings.

    Is there an existing element that's closer, like an <option> I guess?

    Thanks Michael and Arno. Here's my idea for the interface a little more fleshed out:

    <click-box cycle
    states="empty checkmark xmark questionmark"
    empty=""
    checkmark="&x#..."
    xmark="&x#..."
    questionmark="?"></click-box>

    Specifying the "cycle" attribute selects the (currently only) behavior
    of cycling through states. The .value attribute/property of the
    component will be reported as one of the strings from the "states" attribute. If a state value itself is defined as an attribute then the value of that attribute will be used as the label for visual display, otherwise the value string will be used as the label.

    This seems like it covers what I need, allowing extension without too
    much YAGNI, and I can stick one in a <template> and then clone that
    around where I need it, I think. Maybe it should also offer a .textContent output.
    That would be a custom input interface element. e.g.

    https://jsbin.com/dixapihuto/1/edit?html,css,js,output

    Very nice. I took a slight peek while ironing out the creases in mine.
    I haven't quite figured out the next tweak where I want to convert
    the value to/from a string by doing a map/reverse-map through the
    label strings. Like, if this "clickbox" is a cell in a table I want to easily convert the table contents to/from a CSV text file. And for this type of
    cell it should read and write the unicode checkmark character and
    internally recognize/store the value as "checkmark".

    click.html:

    <html>
    <body>
    <click-box cycle
    states="empty checkmark xmark questionmark"
    empty=""
    checkmark="&check;"
    xmark="&#x2716;"
    questionmark="?"></click-box>
    </body>
    <script src="click.js"></script>
    </html>


    click.js:

    const clickBoxTemplate = document.createElement( "template" ); clickBoxTemplate.innerHTML = `
    <style>
    input{
    text-align: center;
    cursor: default;
    }
    </style>
    <input id="box" type="text" readonly>
    `;

    function max( x, y ){
    return y > x ? y : x;
    }

    class ClickBox extends HTMLElement {
    constructor() {
    super();
    this.attachShadow( {mode:"open"} );
    this.shadowRoot.appendChild( clickBoxTemplate.content.cloneNode(true) );
    if( this.hasAttribute( "cycle" ) ){
    this._states =
    ( this.hasAttribute("states") ?
    this.getAttribute("states") : "empty true false" ).split( " " );
    console.log( this._states );
    this._stateNumber = 0;
    this._state = this._states[ this._stateNumber ];
    let box = this.shadowRoot.querySelector("#box");
    let size = this._states.
    map(x=>this.hasAttribute(x)?this.getAttribute(x):x).
    map(x=>x.length).
    reduce( max );
    console.log( size );
    box.setAttribute( "size", size );
    }
    }
    increment() {
    this._stateNumber = (this._stateNumber + 1) % this._states.length;
    this._state = this._states[ this._stateNumber ];
    }
    draw() {
    let box = this.shadowRoot.querySelector("#box");
    console.log( box );
    this.value = this._state;
    console.log( this.value );
    box.toggleAttribute( "readonly" );
    if( this.hasAttribute( this.value ) ){
    box.value = this.getAttribute( this.value );
    } else {
    box.value = this.value;
    }
    box.toggleAttribute( "readonly" );
    box.blur();
    }
    click( event ){
    event.preventDefault();
    this.increment();
    this.draw();
    return;
    }
    connectedCallback() {
    this.shadowRoot.querySelector("#box").addEventListener( "click", (e)=>this.click(e) );
    }
    disconnectedCallback() {
    this.shadowRoot.querySelector("#box").removeEventListener();
    }
    }

    window.customElements.define( "click-box", ClickBox );

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