rockeypjb
rockeypjb

Reputation: 47

WooCommerce - jQuery - Show Title of Muliple Selected Swatches

I need to use jQuery to get the value of several selected objects and display the title of each object, separately...

I am using WooCommerce with the Variation Swatches and Photos plugin. When a swatch is selected I want to show that swatch name beside the attribute title. I found a partial solution, however I need the function to loop for each class since I have more than one swatch option.

The code from the Variation Swatches plugin is

<table class="variations-table" cellspacing="0">
        <tbody>
            <?php
            $loop = 0;
            foreach ($this->attributes as $name => $options) : $loop++;
                ?>
                <tr>
                    <td class="attribute_title_label"><label for="<?php echo sanitize_title($name); ?>"><?php echo wc_attribute_label($name); ?> : </label></td>
                </tr>
                <tr>
                    <td class="attributes_border">
                        <?php
                        if (isset($this->swatch_type_options[sanitize_title($name)])) {
                            $picker_type = $this->swatch_type_options[sanitize_title($name)]['type'];
                            if ($picker_type == 'default') {
                                $this->render_default(sanitize_title($name), $options);
                            } else {
                                $this->render_picker(sanitize_title($name), $options);
                            }
                        } else {
                            $this->render_default(sanitize_title($name), $options);
                        }
                        ?>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

The jQuery provided in the above solution is:

    (function($){
"use strict";
$('body').on('change', 'div.select', function(event){
var colorname = "";
var colorname = $(".selected a.swatch-anchor").attr('title');
if(colorname){
   $(".variations-table label").html('Color: ">'+colorname);
}else{
   $(".variations-table label").html("Please select a color");
}
});
})(jQuery);

That script works if you only have one swatch panel, but I will have several swatch options. So I would have colors, size, and orientation that are selected as swatches.

I know that I need to run a function on each class, but my attempts have been unsucessful. This is what I came up with:

$(function () {
 function changeName) {
     $("td.attributes_border").each(function(){
         
         var swatchname = "",
             swatchname = $(".selected a.swatch-anchor").attr('title');
        if(swatchname){
           $(".attribute_title_label label").html(+swatchname);
        }else{
           $(".attribute_title_label label").html("Please select an option");
        }
        });
$("div.select").on("change", changeName);
changeName();
});

I am sure this is very simple, but my javascript and jquery knowledge is very limited.

Thanks

Upvotes: 0

Views: 1128

Answers (1)

rockeypjb
rockeypjb

Reputation: 47

After many hours of trial and error I have found a solution to my problem.

First, I changed my table a bit. I removed the table row holding the title and changed it to a table cell (I only set it as row to have it on a separate line- which I fixed with CSS). This allowed me to have each loop contain only one table row, which I assigned a class "swatchcontainer". Second, I added a span with class "swatchname". This gave me a place holder for the returned value. Allowing me to use the default attribute title. This is the php:

    <table class="variations-table" cellspacing="0">
        <tbody>
            <?php
            $loop = 0;
            foreach ($this->attributes as $name => $options) : $loop++;
                ?>
                <tr class="swatchcontainer">
                    <td class="attribute_title_label"><label for="<?php echo sanitize_title($name); ?>"> <?php echo wc_attribute_label($name); ?> : <span class="swatchname"> </span></label>
                    </td>
                    <td class="attributes_border">
                        <?php
                        if (isset($this->swatch_type_options[sanitize_title($name)])) {
                            $picker_type = $this->swatch_type_options[sanitize_title($name)]['type'];
                            if ($picker_type == 'default') {
                                $this->render_default(sanitize_title($name), $options);
                            } else {
                                $this->render_picker(sanitize_title($name), $options);
                            }
                        } else {
                            $this->render_default(sanitize_title($name), $options);
                        }
                        ?>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

Next, the frustrating part, was to write a script which fulfilled my requirements. I knew that the issue was locating the selected value and applying it to the cell in the same row. I came up with:

jQuery('table').change(function(){  
    $('.swatchcontainer').each(function() {
    var swatchname = $(this).find("div.selected a.swatch-anchor").attr('title');
    if(swatchname){
        $(this).find("span.swatchname").html(swatchname);
    }else{
        $(this).find("span.swatchname").html("Please select an option");
    }
});
});
  1. My logic is that whenever there is a change to the table (either page load or the user clicks on a swatch, the function runs.
  2. I Then used .each for my tr class, so that it would loop though each tr.swatchcontainer.
  3. The swatchname variable was located using .find to locate the element within the tr the function is currently running ($(this))
  4. A simple if else statement is used if there is a value. Assigning the value using the same $(this).find, to make sure it is applied to the element in the current tr.

Hopefully that is correct or at least acceptable, but it does work.

Upvotes: 0

Related Questions