Value change on drop down or check box Part 2

#23

This is what I understand →

function selecWooPriceOption() {
     var SelectDropDown = document.getElementById('license_type');

     for(var i=0; i < SelectDropDown.length; i++)
     {
       alert(SelectDropDown.value) 
   }

I have updated the ID and JS function on the same codepen also.

0 Likes

#24

What seems to be missing there is getting the options.

That is achieved by using SelectDropDown.options, most easily by assigning it to a local variable.
That gives you an array-like container that contains each option.

2 Likes

#25

Finally I come up with this →

function selecWooPriceOption() {
     var SelectDropDown= document.getElementById("license_type");	 
	 for(i=0; i<SelectDropDown.options.length;i++){
		 console.log(SelectDropDown.options[i].value);
	 }
}

I hope this is now correct. Previously I was also not accounting for that [i] loop.

0 Likes

#26

It’s a good idea to assign SelectDropDown.options[i] to a separate variable inside of the loop, because you will be using that a few times inside there to access information.

1 Like

#27

Like this →

function selecWooPriceOption() {
     var SelectDropDown= document.getElementById("license_type");
	 var ov = SelectDropDown.options;
	 for(i=0; i<ov.length;i++){
		 console.log(ov[i].value);
	 }
}

Sir, What is the next step now. what and where should I proceed?

0 Likes

#28

Not quite, but we can work with that.

Next up is inside of the for loop to get the dataset information and assign that to a local variable, also inside of the for loop, so that we can then work with that dataset information.

1 Like

#29

I have put data-set like this in options →

<select class="license_type" name="license_type" id="license_type">
<option value="license_one" data-1="500">Single Site License</option>
<option value="license_two" data-2="700">5 Site License</option>
<option value="license_three" data-3="1400">Developers License</option>
</select>

Finally, I come up with something like this →

function selecWooPriceOption() {
     var SelectDropDown= document.getElementById("license_type");
	 var ov = SelectDropDown.options;
	 for(i=0; i<ov.length;i++){
		 var capture[i] = SelectDropDown.options[SelectDropDown.selectedIndex].dataset.[i];
	 }
}

dataset.[i]
where I will be 1, 2, or 3?

According to my understanding, this will generate 3 different variables:

var capture[i] =

  1. var capture1
  2. var capture2
  3. var capture3
0 Likes

#31

And does it?

0 Likes

#32

No it is actually generating an error at line# 72 =

0 Likes

#33

Let’s simplify things, as I was wanting you to do so earlier.

Remove the contents of the for loop.
All you need to do at first in there is to assign the dataset to a variable, so that you can use console.log to show that variable.

Further progress can then occur from there.

1 Like

#34

I ended up simply making something like this →

var proPrice= document.getElementById("license_type");
    var proPrice1 = proPrice.options[0].getAttribute('data-one');
    var proPrice2 = proPrice.options[1].getAttribute('data-two');
    var proPrice3 = proPrice.options[2].getAttribute('data-three');

the script is also working, including console generating.

Please have a look here →

is this how you wanted me to do? Or i am still deviating?

0 Likes

#35

I was going to work towards how to make it capable of handing a wider variety of situations, but if your options aren’t going to change their data attribute names, there’s not much reason to improve things beyond what you currently have.

Other than the screaming of my inner code-quality inspector of course :slight_smile:

1 Like

#36

For the sake of learning would it be possible if you can write the subtle version of the code that can handle a multitude of options?

You are very experienced and Pro so that is quite obvious.

In the final Wordpress version →

<option value="l_one" data-one="500">License 1</option>

Here 500 will be coming from the PHP code →

data-one="<?php some code to deliver those numerical values ?>" and so on. This is because every woocommerce product will have a different price. (for example)

I think that will still make the code remain the same. I was just informing you how it is going to be work later on.

0 Likes

#37

Sure. I haven’t tested the following code for completeness, but the main idea is there.
We can output information to the console as we go along, to help ensure that we are getting meaningful results.

I’ll also comment out old lines of code to help show how the code changes occur.

Get dataset info

First, we get the dataset information from each option. Here I’m assigning each option to a local variable, to help make the code easier to understand. I’ll also rename ov to options because when I look back at code after not using it for six months or more, I need all the help that I can get.

// var ov = SelectDropDown.options;
var options = SelectDropDown.options;
for(i=0; i<ov.length;i++){
    // var option = ov[i];
    var option = options[i];
    var dataInfo = option.dataset;
    console.log(dataInfo); // {one: "59"} {two: "245"} {three: "1569"}
}

That gives a useful start to things:

Use forEach instead of a for loop

JavaScript has supported an improved technique instead of for loops for a long time, and that is the forEach method.

The above function can instead be done in the following manner, for which that option variable helps to make the transition easier to achieve:

options.forEach(function (option) {
    var dataInfo = option.dataset;
    console.log(dataInfo); // {one: "59"} {two: "245"} {three: "1569"}
});

Make the prices easier to retrieve

What happens from here depends on how we want to use the information. An effective thing to do from here is to put each price into an array, where the first of the select’s options is the first in the price array.

We want to end up with the following array of price values: [59, 245, 1569]

We can achieve that by adding a prices array, and adding each dataset value to it.
But how do we get each price from the dataset?

It would help if the data name was identical for each option, so I’m going to assume that you make that easy improvement to the dataset names on your HTML options:

<select class="license_type" name="license_type" id="license_type">
    <!--<option value="license_one" data-one="59">Single Site License</option>-->
    <option value="license_one" data-price="59">Single Site License</option>
    <!--<option value="license_two" data-two="245">5 Site License</option>-->
    <option value="license_two" data-price="245">5 Site License</option>
    <!--<option value="license_three" data-three="1569">Developers License</option>-->
    <option value="license_three" data-price="1569">Developers License</option>
</select>

Get the prices

With that, we can now easily add the prices to the array:

var prices = [];
options.forEach(function (option) {
    var dataInfo = option.dataset;
    prices.push(dataInfo.price);
});
console.log(prices); // ["59", "245", "1569"]

But that’s not yet done, because the array contains strings of the prices instead of number values.

We could make the forEach method more complex by updating the push line, but easier to understand results are obtained by using the map method on the array instead.

var prices = [];
options.forEach(function (option) {
    var dataInfo = option.dataset;
    prices.push(dataInfo.price);
});
prices = prices.map(function (strPrice) {
    return Number(strPrice);
});
console.log(prices); // ["59", "245", "1569"]

Which gives us the following array: [59, 245, 1569]

Now that we’re getting the information that we need, we can work on improving the code.

Simplify code with filter, map, reduce

There’s a nice way to simply your code, for which many articles have been written including simply your code with filter, map, and reduce, where you filter information through several pipes until you end up with what you require.

For this example there’s nothing to filter. Map can be used to get the price from the data value, and I don’t think that reduce will even be needed either.

<Heavy sigh>: while editing I carried on to make lots of beneficial improvements to the code, before realizing that I can really simply things with the filter/map/reduce idea. This means of course deleting all that I had done rewriting things all over again. The quest for simplicity is not without its casualties.

Use map to get the prices

Instead of assigning an array to prices and using forEach to update it, we can instead use the map method to get the price. I’ll give names to the functions as well so it’s easier to understand what they do.

// var prices = [];
// options.forEach(function (option) {
var prices = options.map(function getPrice(option) {
    var dataInfo = option.dataset;
    // prices.push(dataInfo.price);
    return dataInfo.price;
});
prices = prices.map(function toNumber(strPrice) {
    return Number(strPrice);
});
console.log(prices); // [59, 245, 1569]

Bring common things together

We can now easily extract those functions, making it easier to understand how they’re used.

function getPrice(option) {
    var dataInfo = option.dataset;
    return dataInfo.price;
}
function toNumber(strPrice) {
    return Number(strPrice);
}
var prices = options.map(getPrice);
prices = prices.map(toNumber);
console.log(prices); // [59, 245, 1569]

And we can remove that reassignment at the end, by chaining on the .map method:

function getPrice(option) {
    var dataInfo = option.dataset;
    return dataInfo.price;
}
function toNumber(strPrice) {
    return Number(strPrice);
}
// var prices = options.map(getPrice);
// prices = prices.map(toNumber);
var prices = options.map(getPrice).map(toNumber);
console.log(prices); // [59, 245, 1569]

Arrow functions

If we make that getPrice function a simple one-liner, we can simplify those functions even further.

function getPrice(option) {
    // var dataInfo = option.dataset;
    // return dataInfo.price;
    return option.dataset.price;
}
function toNumber(strPrice) {
    return Number(strPrice);
}
var prices = options.map(getPrice).map(toNumber);
console.log(prices); // [59, 245, 1569]

Now that they’re simple one-liners, we can easily turn them into arrow functions. I’ll also rename var to const when doing this, to help make it crystal clear that we’re using ES6 techniques here instead.

// function getPrice(option) {
//     return option.dataset.price;
// }
const getPrice = (option) => option.dataset.price;
// function toNumber(strPrice) {
//     return Number(strPrice);
// }
const toNumber = (strPrice) => Number(strPrice);
// var prices = options.map(getPrice).map(toNumber);
const prices = options.map(getPrice).map(toNumber);
console.log(prices); // [59, 245, 1569]

Conclusion

That’s about as simple as the code normally gets.

The following code is all you need to get the prices from the data attributes of the options, however reading through the above content gives you access to much more information about how code is easily modified to achieve a different range of benefits.

const getPrice = (option) => option.dataset.price;
const toNumber = (strPrice) => Number(strPrice);
const prices = options.map(getPrice).map(toNumber);
console.log(prices); // [59, 245, 1569]

Hopefully some useful and meaningful information was learned along the way as well.

3 Likes

#38

Hi there @Paul_Wilkins

In a compact way, you have written a whole tutorial. It will take some time for me to dive, research all the details that you have provided. Thank you so much. I will get back to this.

You have set things in the motion :airplane:

1 Like

#39

Because this was written without testing, there is a detail that didn’t get in there.

The options can be acquired with querySelectorAll which gives you a nodeList, but you can’t map over that as that’s for arrays instead.

As a result, we need to use Array.from when getting the options.

var options = Array.from(document.querySelectorAll(...));

2 Likes

#40

This is the best code cutting.

Previously there we 3 X [0 + 1 + 2 + 3] = 3 X 6 = 18

But now there are 1 X [0 + 1 + 2 + 3] = 6 Combinations.

(There are also 3 checkboxes for additional possible services.)

0 Likes

#41

"officersIds " → Array

What is “officers” or “officer”? From where they have come and how are they working w/o defining them before.

0 Likes

#42

officers is an array that contains a range of items.

The function that you use with the forEach method, receives each item as the first parameter of the function. In this case, the name of officer has been chosen to make it easier to understand what’s happening there.

It’s entirely possible for officer to be renamed to r_3KtW_iYF and the code will still work in exactly the same way. But, that doesn’t help you, the person looking at the code, to understand what it’s supposed to achieve.

1 Like

#43

Thanks got it.

Officers was actually defined above in that example in the link shared by you. so the data is been fetched from that array.

// What you have
var officers = [
  { id: 20, name: 'Captain Piett' },
  { id: 24, name: 'General Veers' },
  { id: 56, name: 'Admiral Ozzel' },
  { id: 88, name: 'Commander Jerjerrod' }
];
// What you need
[20, 24, 56, 88]

so finally this will
var officersIds = [];

be →

var officersIds = [20, 24, 56, 88];

0 Likes