Multiply second value from array to dropdown selected

I have created a row of dropdowns with each option having its own value, as usual.

But what I need to do is multiply a second value per dropdown to the options values.

I understand the process of whats needs to be done, but I dont know where or how to add this extra figure in.

Her is it in action in this fiddle - http://jsfiddle.net/c9r48/8/

In the first dropdown for instance it has a label of ‘label 1’ the options values of:


label: 'Label 1',
value: '400',
options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }

Then you have that other value in this case 400.

What needs to happen is either the 400 is multiplied straight away to the 12, 6, 4 and 0 or the 400 is multiplied to the selected value, but I cant work out where it goes.

I have used the code below but like I said without much luck -


Math.round(parseInt( x * 100,10)* y)/100;

I have gathered those values here


var sFigure = selectInfo.value;

All the code


var selects = [
    {
        label: 'Label 1',
  value: '400',
        options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }
    },
    {
        label: 'Label 2',
  value: '300',
        options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }
    },
 {
        label: 'Label 3',
  value: '320',
        options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }
    },
 {
        label: 'Label 4',
  value: '330',
        options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }
    },
 {
        label: 'Label 5',
  value: '340',
        options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }
    },
 {
        label: 'Label 6',
  value: '350',
        options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }
    },
 {
        label: 'Label 7',
  value: '360',
        options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }
    },
 {
        label: 'Label 8',
  value: '370',
        options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }
    },
 {
        label: 'Label 9',
  value: '380',
        options: { '12': 'Monthly', '6': 'Bi-Monthly', '4': 'Quarterly', '0': 'N/A' }
    },
]


$(function () {
    $(".addRow").click(addRow)
})
function sum($els) {
    var sum = 0;
    $els.each(function () {
        sum += +$(this).val()
    })
    return sum
}
function addRow() {
    var fieldset = $('<fieldset></fieldset>').appendTo("#test");
 var wrapper = $("<div class='formWrapper'></div>").prependTo(fieldset);
    var sumDiv = $("<div class='sum'>total £<span>0</span></div>").appendTo(wrapper)
 
$.each(selects, function (index, selectInfo) {
 var label = $("<label class='label'>"+ selectInfo.label +"</label>").prependTo(wrapper);
 var sFigure = selectInfo.value;
 var select = $("<select class='selectD' name='select" + selectInfo.options +"'></select>").appendTo(label),
optionValues = sortOptions(selectInfo.options);
$.each(optionValues, function (index, value) {
var key = selectInfo.options[value];
$("<option></option>", {
value: value,
text: key
}).appendTo(select)
})
select.change(function () {
fieldset.find("span").text(sum($("select", fieldset)))
$(".sumTotal").find("span").text(sum($("#test select")))
}).change()
});
function sortOptions(options) {
    var optionValues = [];
 
    $.each(options, function (value, key) {
        optionValues.push(value);
    });
    function numbersDecreasing(a, b) {
        return b - a;
    }
    optionValues.sort(numbersDecreasing);
 return optionValues;
 
}
}

Before I go much further with this, I’m going to use http://jsbeautifier.org/ to tidy up the worst of the formatting issues, and http://jslint.com/ (which is built in to my text editor) to weed out the worst of bad practices.

With that distraction out of the way, the labels can be placed in their proper order by using appendTo instead of prependTo, and the value of the select options can be multipled by the approprate value.


label = $("<label class='label'>" + selectInfo.label + "</label>").appendTo(wrapper),
...
$("<option></option>", {
    value: selectInfo.value * value,
    text: key
}).appendTo(select);

You’ll notice a few of other adjustments, but they’re mostly to keep my jslint sensibilities intact, such as when .each() functions have an unused first property, in which case the properties aren’t needed at all and the this keyword can be used instead, cached to a suitable variable.


// $.each(selects, function (index, selectInfo) {
$.each(selects, function () {
    var selectInfo = this,

Is one better than the other? That’s debatable. Does my eye-twitch increase when my live linter shows problems such as unused variables in the code? You betcha!

Here’s the full code:


/*globals $ */
var selects = [
    {
        label: 'Label 1',
        value: '400',
        options: {
            '12': 'Monthly',
            '6': 'Bi-Monthly',
            '4': 'Quarterly',
            '0': 'N/A'
        }
    },
    {
        label: 'Label 2',
        value: '300',
        options: {
            '12': 'Monthly',
            '6': 'Bi-Monthly',
            '4': 'Quarterly',
            '0': 'N/A'
        }
    },
    {
        label: 'Label 3',
        value: '320',
        options: {
            '12': 'Monthly',
            '6': 'Bi-Monthly',
            '4': 'Quarterly',
            '0': 'N/A'
        }
    },
    {
        label: 'Label 4',
        value: '330',
        options: {
            '12': 'Monthly',
            '6': 'Bi-Monthly',
            '4': 'Quarterly',
            '0': 'N/A'
        }
    },
    {
        label: 'Label 5',
        value: '340',
        options: {
            '12': 'Monthly',
            '6': 'Bi-Monthly',
            '4': 'Quarterly',
            '0': 'N/A'
        }
    },
    {
        label: 'Label 6',
        value: '350',
        options: {
            '12': 'Monthly',
            '6': 'Bi-Monthly',
            '4': 'Quarterly',
            '0': 'N/A'
        }
    },
    {
        label: 'Label 7',
        value: '360',
        options: {
            '12': 'Monthly',
            '6': 'Bi-Monthly',
            '4': 'Quarterly',
            '0': 'N/A'
        }
    },
    {
        label: 'Label 8',
        value: '370',
        options: {
            '12': 'Monthly',
            '6': 'Bi-Monthly',
            '4': 'Quarterly',
            '0': 'N/A'
        }
    },
    {
        label: 'Label 9',
        value: '380',
        options: {
            '12': 'Monthly',
            '6': 'Bi-Monthly',
            '4': 'Quarterly',
            '0': 'N/A'
        }
    }
];

$(function () {
    "use strict";

    function sum($els) {
        var total = 0;
        $els.each(function () {
            total += Number($(this).val());
        });
        return total;
    }

    function sortOptions(options) {
        var optionValues = [];

        $.each(options, function (value) {
            optionValues.push(value);
        });

        function numbersDecreasing(a, b) {
            return b - a;
        }
        optionValues.sort(numbersDecreasing);
        return optionValues;

    }

    function addRow() {
        var fieldset = $('<fieldset></fieldset>').appendTo("#test"),
            wrapper = $("<div class='formWrapper'></div>").prependTo(fieldset),
            sumDiv = $("<div class='sum'>total £<span>0</span></div>");

        $.each(selects, function () {
            var selectInfo = this,
                label = $("<label class='label'>" + selectInfo.label + "</label>").appendTo(wrapper),
                select = $("<select class='selectD' name='select" + selectInfo.options + "'></select>").appendTo(label),
                optionValues = sortOptions(selectInfo.options);
            $.each(optionValues, function () {
                var value = this,
                    key = selectInfo.options[value];
                $("<option></option>", {
                    value: selectInfo.value * value,
                    text: key
                }).appendTo(select);
            });
            select.change(function () {
                fieldset.find("span").text(sum($("select", fieldset)));
                $(".sumTotal").find("span").text(sum($("#test select")));
            }).change();
        });

        sumDiv.appendTo(wrapper);
    }

    $(".addRow").click(addRow);
});

Quite a lot of repetition can now be seen in the data structure. The month periods should rightly be removed out to a separate array, which leaves us with just a simple array of multiplier values.


var monthlyPeriods = [
    {'12': 'Monthly'},
    {'6': 'Bi-Monthly'},
    {'4': 'Quarterly'},
    {'0': 'N/A'}
],
selects = [
    {
        label: 'Label 1',
        value: '400'
    },
    {
        label: 'Label 2',
        value: '300'
    },
    ...
$.each(monthlyPeriods, function () {
    var value = Object.keys(this)[0],
    key = this[value];

You can even make the label values simpler too, by reducing the data structure even further:


selects = [
    {'Label 1': '400'},
    {'Label 2': '300'},
    {'Label 3': '320'},
    {'Label 4': '330'},
    {'Label 5': '340'},
    {'Label 6': '350'},
    {'Label 7': '360'},
    {'Label 8': '370'},
    {'Label 9': '380'}
];
...
$.each(selects, function (index, selectInfo) {
    var selectLabel = Object.keys(selectInfo)[0],
        selectValue = selectInfo[selectValue],
        label = $("<label class='label'>" + selectLabel + "</label>").appendTo(wrapper),
        select = $("<select class='selectD' name='select" + index + "'></select>").appendTo(label);
...
            value: selectValue * value,

I’ve also fixed the name above too, for in earlier code it was undefined.

Here’s the code for that variation:


/*globals $ */
var selects = [
        {'Label 1': '400'},
        {'Label 2': '300'},
        {'Label 3': '320'},
        {'Label 4': '330'},
        {'Label 5': '340'},
        {'Label 6': '350'},
        {'Label 7': '360'},
        {'Label 8': '370'},
        {'Label 9': '380'}
    ],
    monthlyPeriods = [
        {'12': 'Monthly'},
        {'6': 'Bi-Monthly'},
        {'4': 'Quarterly'},
        {'0': 'N/A'}
    ];

$(function () {
    "use strict";

    function sum($els) {
        var total = 0;
        $els.each(function () {
            total += Number($(this).val());
        });
        return total;
    }

    function sortOptions(options) {
        var optionValues = [];

        $.each(options, function (value) {
            optionValues.push(value);
        });

        function numbersDecreasing(a, b) {
            return b - a;
        }
        optionValues.sort(numbersDecreasing);
        return optionValues;

    }

    function addRow() {
        var fieldset = $('<fieldset></fieldset>').appendTo("#test"),
            wrapper = $("<div class='formWrapper'></div>").prependTo(fieldset),
            sumDiv = $("<div class='sum'>total £<span>0</span></div>");

$.each(selects, function (index, selectInfo) {
    var selectLabel = Object.keys(selectInfo)[0],
        selectValue = selectInfo[selectValue],
        label = $("<label class='label'>" + selectLabel + "</label>").appendTo(wrapper),
        select = $("<select class='selectD' name='select" + index + "'></select>").appendTo(label);
            $.each(monthlyPeriods, function () {
                var value = Object.keys(this)[0],
                    key = this[value];
                $("<option></option>", {
                    value: selectValue * value,
                    text: key
                }).appendTo(select);
            });
            select.change(function () {
                fieldset.find("span").text(sum($("select", fieldset)));
                $(".sumTotal").find("span").text(sum($("#test select")));
            }).change();
        });

        sumDiv.appendTo(wrapper);
    }

    $(".addRow").click(addRow);
});

Morning Paul,

Talking about twitches, thats how my eye goes when I see code changes like that, all very useful stuff though, but takes me a little while to read it through.

I’m still on the first reply you sent yesterday and it works so well, but one little thing the each row value comes out as ‘0’ on load when it should be the total value of the dropdowns before any change is made.

Thank you very much Paul, it takes me a little while but I do eventually start to understand it.

As the only developer here Im jumping between jquery, asp, php, html5, mysql, sql and so on and so dont get the continuity on one code to learn it thoroughly.

I know there a few things that are needed to take this further, but not sure exactly what they are yet, so will see this afternoon i expect, but they going to be very happy with this

http://www.accend4web.co.uk/OCalculator/design.php

To rectify this in my way which is why I’m asking you as its not your way (correct way), I added the append back on as below

sumDiv = $(“<div class=‘sum’>This £<span>0</span></div>”).appendTo(wrapper)

and took away from the bottom of the function.


$(function () {
    "use strict";
 
    function sum($els) {
        var total = 0;
        $els.each(function () {
            total += Number($(this).val());
        });
        return total;
    }
 
    function sortOptions(options) {
        var optionValues = [];
 
        $.each(options, function (value) {
            optionValues.push(value);
        });
 
        function numbersDecreasing(a, b) {
            return b - a;
        }
        optionValues.sort(numbersDecreasing);
        return optionValues;
 
    }
 
    function addRow() {
        var fieldset = $('<fieldset></fieldset>').appendTo("#test"),
            wrapper = $("<div class='formWrapper'></div>").prependTo(fieldset),
            sumDiv = $("<div class='sum'>This £<span>0</span></div>").appendTo(wrapper)
 
        $.each(selects, function () {
            var selectInfo = this,
                label = $("<label class='label'>" + selectInfo.label + "</label>").appendTo(wrapper),
                select = $("<select class='selectD' name='select" + selectInfo.options + "'></select>").appendTo(label),
                optionValues = sortOptions(selectInfo.options);
            $.each(optionValues, function () {
                var value = this,
                    key = selectInfo.options[value];
                $("<option></option>", {
                    value: selectInfo.value * value,
                    text: key
                }).appendTo(select);
            });
            select.change(function () {
                fieldset.find("span").text(sum($("select", fieldset)));
                $(".sumTotal").find("span").text(sum($("#test select")));
            }).change();
        });
 
    }
 
    $(".addRow").click(addRow);
});


What you think Paul.

So long as it works and you’re happy with it, there are no problems.

With bigger projects though it’s preferable to do all of the work off the page, and to then attach the finished result to the page. This results in only one page update occurring, instead of multiple ones when each on-page change occurs. It’s a small detail though that doesn’t have any impact on what you’re doing here.

It’s great to see that you’ve succeeded in achieving what you’re wanting to do here.

Thanks Paul,

Yes Im about to show this now to the managers, and I will find out what they wont from it next, I think to connect the array data to a database, so will have a look at that.

Thanks again for all the help.