1

I have a form, I would like to dynamically build, such that each product that has a help text gets a tooltip. This is a Product. It extends BaseProduct:

class BaseProduct {
    constructor(name, helpText = null) {
        this.name = name;
        this.helpText = helpText;
    }

    label() {
        if (this.helpText) {
            return `
                <label class="tooltip">
                    ${this.name}
                    <div class="right">${this.helpText}</div>
                </label>`;
        }
        return `<label for="not-important">${this.name}</label>`;
    }
}

class Product extends BaseProduct {
    constructor(name, price, helpText = null) {
        super(name, helpText);
        this.price = price;
    }

    toHtml() {
        let inner = `
            <input type="checkbox" name="not-important"
                id="not-important" value="not-important" />
            ${super.label()}
            <span class="price">${this.price}</span>`;
        return `
            <p class="item-row">
                ${inner}
            </p>`;
    }
}

You can check it out here: https://jsfiddle.net/whoru74c/10/

There is one example that is not dynamic, showing what it is supposed to look like. The other Product gets dynamically added.

The strange part about the Product is that I can print the result of calling Product.toHtml() or super.label() and it looks like expected:

<label class="tooltip">
    Product Name
    <div class="right">[Product help text]</div>
</label>

But when I insert it into the DOM tree, using insert(), it gets split up, so that the <div class="right"> comes after </label>:

<p class="item-row">
    <input type="checkbox" name="not-important" id="not-important" value="not-important">
    <label class="tooltip">
        Product Name
    </label>
    <!-- 1 -->
</p>
<!-- The following should be in 1 -->
<div class="right">[Product help text]</div>
<span class="price">123</span>
<p></p>

Furthermore, a random empty <p>-tag gets added, and I cannot figure out why.

Asger Skov Velling
  • 173
  • 2
  • 2
  • 11
  • 3
    [Mayhap because `div` are not allowed in `label`](https://stackoverflow.com/questions/18609554/is-div-inside-label-block-correct). – Lain Nov 02 '22 at 14:57
  • 1
    Please show a version that inserts. If you inspect the generated HTML, you will likely see the label is closed and then the div is AFTER the label – mplungjan Nov 02 '22 at 14:58
  • 1
    Also paragraph elements can't contain block elements - and browsers will terminate paragraphs if it encounters blocks before their end-paragraph tags. I had some success by changing the `
    ` tags inside the `
    – traktor Nov 02 '22 at 16:16
  • Thank you guys. It makes sense now that it wouldn't work. – Asger Skov Velling Nov 03 '22 at 11:57

1 Answers1

0

Here is a quick recap of what Lain and traktor pointed out, for anyone that might experience a similar problem.

According to the HTML spec, a <div> is not allowed inside of a <label>. Therefore, it gets pushed out of the element.

Changing the <div> inside <label> to a <span> seems to work fine. It might affect the layout though, so now you know where to look if that happens.

Rendered HTML before changing <div> to <span>:

<p class="item-row">
    <input type="checkbox" name="not-important" id="not-important" value="not-important">
    <label class="tooltip">
        Product Name
    </label>
</p>
<div class="right">[Product help text]</div>
<span class="price">123</span>
<p></p>

After:

<p class="item-row">
    <input type="checkbox" name="not-important" id="not-important" value="not-important">
    <label class="tooltip">
        Product Name
        <span class="right">[Product help text]</span>
    </label>
    <span class="price">123</span>
</p>
Asger Skov Velling
  • 173
  • 2
  • 2
  • 11