1

I currently have an array that is populated by changing the value/option of many select fields. E.g. If two select fields are in the dom and the options selected are 2 & 3 then the array would look like this - Array [ "2", "3" ]

Each select has a data attribute data-ticketprice which I would like to bind to each of the option values. So I can get the sum of both of the numbers e.g.

data attribute = 100
Select option value = 5
Sum = 100 x 5;

HTML -

<select class="ticket-qty" data-ticketprice="280.88" name="34">
 <option value="0">0 Tickets</option>
 <option value="1">1 Ticket</option>
 <option value="2">2 Tickets</option>
 <option value="3">3 Tickets</option>
 <option value="4">4 Tickets</option>
 <option value="5">5 Tickets</option>
</select>
<select class="ticket-qty" data-ticketprice="390" name="39">
 <option value="0">0 Tickets</option>
 <option value="1">1 Ticket</option>
 <option value="2">2 Tickets</option>
 <option value="3">3 Tickets</option>
 <option value="4">4 Tickets</option>
 <option value="5">5 Tickets</option>
</select>

Current jQuery -

//When select is changed update value to array
$('select.ticket-qty').on('change', function (e) {
 //Map the values for the array
 var arr = $('select.ticket-qty').map(function(){
 return this.value
 }).get()
 //This sums the all the select options (not what I want)
 var total = 0;
 for (var i = 0; i < arr.length; i++) {
 total += arr[i] << 0;
 }
 console.log(total);
});
asked Feb 21, 2018 at 16:21
4
  • Please consider using an MVC framework for this type of project. Vue JS is easy to get started with if you haven't done so before. Commented Feb 21, 2018 at 16:29
  • 2
    You don't need a big framework for every little problem. Commented Feb 21, 2018 at 16:34
  • If this is a school project, probably not. If he is really selling tickets to something, this will outgrow jQuery within a day. Commented Feb 21, 2018 at 16:44
  • @AdamLeggett I'm already using an MVC framework such as Laravel. I don't like VueJS because you end up with around 100 libraries. It's never just vue, its axios, vue routing etc.. This is a really basic application with almost no JS requirements. Commented Feb 21, 2018 at 17:16

4 Answers 4

2

You need to fill the array you build with map() with the selected quantity multiplied by the cost per item, which you can retrieve from the data attribute. From there you can use reduce() to sum up all values in the array. Something like this:

$('select.ticket-qty').on('change', function(e) {
 var arr = $('select.ticket-qty').map(function() {
 var cost = $(this).data('ticketprice');
 var qty = $(this).val();
 return cost * qty;
 }).get();
 
 var total = arr.reduce((a, b) => a + b, 0);
 console.log(total);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="ticket-qty" data-ticketprice="280.88" name="34">
 <option value="0">0 Tickets</option>
 <option value="1">1 Ticket</option>
 <option value="2">2 Tickets</option>
 <option value="3">3 Tickets</option>
 <option value="4">4 Tickets</option>
 <option value="5">5 Tickets</option>
</select>
<select class="ticket-qty" data-ticketprice="390" name="39">
 <option value="0">0 Tickets</option>
 <option value="1">1 Ticket</option>
 <option value="2">2 Tickets</option>
 <option value="3">3 Tickets</option>
 <option value="4">4 Tickets</option>
 <option value="5">5 Tickets</option>
</select>

You should note that this can all be done in a single loop, however I am assuming you're building the array of individual totals for use elsewhere in your UI.

answered Feb 21, 2018 at 16:27
Sign up to request clarification or add additional context in comments.

9 Comments

He will need a polyfill for reduce if he wishes to support IE9.
Unfortunately so. We can dream of a world without IE and Edge... one day.
Edge isn't that bad.
It's better than IE admittedly, but it's still a long way from where it should be. It's standards compliance is rather lacking. It'll be the new IE6 in 3-4 years time.
@AdamLeggett: IE9 supports most of ECMAScript 5, including .reduce().
|
0

So how far I understand is, you want to multiply the selected value with the given data attribute on Select?

Here is sample code for getting Array of All selected values. And how to calculate the value you posted.

var array = [];
var i =0;
$('select.ticket-qty').on('change', function (e) {
 // Get value of all selects in array.
 $('select.ticket-qty').each(function(){
 array[i] = $(this).val();
 i++;
 });
 //calculate Sum ?
 var data_attribute = $(this).data("ticketprice");
 SelectedOptionValue = = $(this).val();
 Sum = parseFloat(data_attribute)* parseInt(SelectedOptionValue);
});
answered Feb 21, 2018 at 16:30

Comments

0

Vanilla JS

const SELECTS = document.querySelectorAll('select.ticket-qty')
const LOG_SUM = e => {
 const ticketPrice = e.target.getAttribute('data-ticketPrice')
 const multiplier = e.target.value
 const SUM = (+ticketPrice * +multiplier)
 
 console.log(SUM)
}
SELECTS.forEach(select => {
 select.addEventListener('change', e => {
 LOG_SUM(e)
 })
})

jQuery

$('select.ticket-qty').on('change', e => {
 const ticketPrice = $(e.target).attr('data-ticketPrice')
 const multiplier = e.target.value
 const SUM = (+ticketPrice * +multiplier)
 
 console.log(SUM)
});

Notice how i prepend the + operator to the ticketPrice & multiplier constants... this is because attr && value are returning Strings and the + operator converts numbers of type String into numbers of type Number

answered Feb 21, 2018 at 16:34

Comments

0

You can use some jQuery plugins to populate and reduce the select boxes.

(function($) {
 $.reduce = function(arr, fn, initial) {
 initial = typeof initial === 'undefined' ? 0 : initial;
 $.each(arr, function(i, v) {
 initial = fn(initial, v, i);
 });
 return initial;
 };
 $.fn.reduce = function(fn, initial) {
 return $.reduce(this, fn, initial);
 };
 $.fn.populateCombo = function(opts) {
 let data = opts.data || Array.apply(null, {length: opts.range || 0}).map(Number.call, Number);
 return this.append(data.map(x => $('<option>')
 .text(opts.textFn ? opts.textFn(x) : x)
 .val(opts.valFn ? opts.valFn(x) : x)));
 };
})(jQuery);
$('.ticket-qty').each((i, combo) => $(combo).populateCombo({
 range : 6, textFn: v => v + ' Tickets'
}));
$('select.ticket-qty').on('change', function(e) {
 var total = $('select.ticket-qty').reduce(function(result, item) {
 return result + $(item).data('ticketprice') * $(item).val();
 }, 0);
 console.log('$' + total.toFixed(2));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="ticket-qty" data-ticketprice="280.88" name="34"></select>
<select class="ticket-qty" data-ticketprice="390" name="39"></select>

answered Feb 21, 2018 at 17:05

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.