Setting step Value for input field from other html table column in same row with jQuery

Viewed 39

thanks a lot to the community for so much things I have learned here. So here is my first own question:

I need to set a step value for an input field ( input[title="Menge"] ) in a html table. The value must be taken from another table-column in the same row ( dd.variation-Verpackung p ) (There are different step values in each table row)

Here is my html:

<tbody>
    <tr class="cart_item">
        <td class="product-name">
                <a href="/products/druckluftarmaturen/kegeltuelle-mit-o-ring-dichtung/?attribute_pa_hose-id=6-mm&amp;attribute_pa_cone=13&amp;attribute_pa_package=10">Kegeltülle DIN 20033 mit O-Ring Dichtung </a>
                    <div class="cat">Druckluftarmaturen</div>                           
                    <dl class="variation">
                        <dt class="variation-HoseID">Hose ID:</dt>
                        <dd class="variation-HoseID"><p>6 mm</p></dd>
                        <dt class="variation-Cone">Cone:</dt>
                        <dd class="variation-Cone"><p>1:3</p></dd>
                        <dt class="variation-Verpackung">Verpackung:</dt>
                        <dd class="variation-Verpackung">
                            <p>10</p>
                        </dd>
                    </dl>
                    <dl class="variation">
                        <dt>Bestell-Nr.</dt>
                        <dd>034-0006v</dd>
                    </dl>
        </td>
        <td class="product-quantity">
            <div class="quantity">
                <label class="screen-reader-text" for="">Anzahl</label>
                <input type="number" id="" class="" step="1" min="0" max="" name="cart[11c4b4d2c3c1a853d0f4d2c31573e914][qty]" value="11" title="Menge" size="4" placeholder="" inputmode="">
            </div>
        </td>
        <td class="product-remove">
            <a href="/anfrageliste/?remove_item=11c4b4d2c3c1a853d0f4d2c31573e914&amp;_wpnonce=e47b3633ba" class="remove" title="Dieses Produkt entfernen">×</a>
        </td>
    </tr>
    <tr class="cart_item">
        <td class="product-name">
                <a href="/products/druckluftarmaturen/kegeltuelle-mit-o-ring-dichtung/?attribute_pa_hose-id=6-mm&amp;attribute_pa_cone=13&amp;attribute_pa_package=10">Kegeltülle DIN 20033 mit O-Ring Dichtung </a>
                    <div class="cat">Druckluftarmaturen</div>                           
                    <dl class="variation">
                        <dt class="variation-HoseID">Hose ID:</dt>
                        <dd class="variation-HoseID"><p>6 mm</p></dd>
                        <dt class="variation-Cone">Cone:</dt>
                        <dd class="variation-Cone"><p>1:3</p></dd>
                        <dt class="variation-Verpackung">Verpackung:</dt>
                        <dd class="variation-Verpackung">
                            <p>1</p>
                        </dd>
                    </dl>
                    <dl class="variation">
                        <dt>Bestell-Nr.</dt>
                        <dd>034-0006v</dd>
                    </dl>
        </td>
        <td class="product-quantity">
            <div class="quantity">
                <label class="screen-reader-text" for="">Anzahl</label>
                <input type="number" id="" class="" step="1" min="0" max="" name="cart[11c4b4d2c3c1a853d0f4d2c31573e914][qty]" value="11" title="Menge" size="4" placeholder="" inputmode="">
            </div>
        </td>
        <td class="product-remove">
            <a href="/anfrageliste/?remove_item=11c4b4d2c3c1a853d0f4d2c31573e914&amp;_wpnonce=e47b3633ba" class="remove" title="Dieses Produkt entfernen">×</a>
        </td>
    </tr>
</tbody>    

                    

Here is my jQuery :

jQuery( document ).ready(function() {
   var vpc = jQuery(".woocommerce-cart .quantity input").closest(".cart_item").find("dd.variation-Verpackung p").html();
   jQuery(this).closest(".woocommerce-cart .quantity input").attr('step', vpc);
});

What I am doing wrong?

Best regards and thanks for your help Pascal

1 Answers

So here's a few assumptions.

  • I believe the '.woocommerce-cart' class is assigned in some ancestor of your copied part of HTML. I'm in no way experienced with woocommerce so do tell me otherwise.
  • Your copied HTML is wrapped in <table> tags. If not, it's essentially invalid, since the <tbody> tag isn't valid according to schema. The page will probably work despite that, but jQuery for example won't be able to index that part of document, and selectors won't work for the most part.

Next, returning to your code

jQuery( document ).ready(function() {
   var vpc = jQuery(".woocommerce-cart .quantity input").closest(".cart_item").find("dd.variation-Verpackung p").html();
   jQuery(this).closest(".woocommerce-cart .quantity input").attr('step', vpc);
});

First you save the 'step' inside vpc variable. The second part I'm not so sure about in $(document).ready() context, 'this' refers to the 'window' element, and since .closest() is a function that crawls up the hierarchy, you're not really arriving anywhere.

Now, if you were to resolve the second expression, you'd still face an issue, and that being, every cart item has its own step. By calling .html(), you get "the HTML contents of first element found". So you would be assigning the step value of first item to all items below.

The last thing which is more of a suggestion is trying to find a way to make the jQueries as simple as possible. jQuery is fairly slow, which is to be expected considering how selectors work, and although this isn't an issue in your case due to the expected low number of items overall, it also helps with readability.

So, to put this all together, you might do something as follows:

jQuery(document).ready(function() {
    $('.woocommerce-cart tr.cart_item').each(function(_, item) {
        let stepValue = parseInt($('.variation-Verpackung p', item).text());
        $('.quantity input', item).attr('step', stepValue);
    });
});

Note several things in here.

  • 90% of the time you can achieve what you want with simple selectors and some looping.
  • in jQuery selector, you can add optional second argument called 'context', which can be HTMLElement, jQuery object or another selector. That one stands for 'look only inside here'. That way you can essentially run the code and say you don't want it to touch other cart items.
  • since you don't need HTML content, only simple text, prefer text() to .html(). Again doesn't matter in your code, but it can get messy sometimes as seen in in example in jQuery docs. And of course, readability again comes first.
  • finally, calling parseInt() is again great for readability, and also saves you from headaches when you try to add 1 + "10".

Working fiddle here.

Related