Show dropdown values in sum div when form is created

Hi,

What I am in the process of putting together is an online quote calculator that allows a consultant to go see a holtelier and they work out a contract value.

The idea in the link below, its in a very basic format at the moment, is that the consultant has this option in amongst the rest of the form, which when he clicks a button a form appears, and then if they have anymore hotels, they can click the button again and the same dropdowns appeara nd away tehy go again, each with a total, but every forms total will add up to a total total.

This is the link - http://www.accend4web.co.uk/OCalculator/design.php


function active_tiptip() {
var selects = [ 
{
 "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}];
    $('#test')
        .append('<form id="form1" name="form1"></form>');
    $.each(selects, function (i, v) {
        var select=$("<select id='select"+i+"'></select>").appendTo("#form1")
        console.log(i, v)
        $.each(v,function(value,key){
            $("<option></option>",{value:value,text:key}).appendTo(select)
        })
    })
    $("<div class='sum'></div>").appendTo("#form1")
        $("#form1").find("select").change(function(){
    var total=0
    $(this).prevUntil(".sum").add($(this).nextUntil(".sum")).each(function(){
    console.log(this)
    total+= +$(this).val();
    })
    $(this).nextAll('.sum:first').text('£' + total);
    })
}

$('#test')
.append("<div class='sumTotal'>Total Total in here</div>");

Im struggling with two things, the first being how do I get the id=sum to show the total values of each form on load, rather than having to wait until a change occurs, and then carrying on as is once a change has been selected and the sum changes. Its that load the value before having to wait for a change

The bit i have been working on today which also needed to be done was to add all the totals up and show it in the total total section, I have got it working in a way, but for some reason its not quite right as is all the calculations, as they dont seem to show the correct value.

What I mean by that is that obviously my main aim is to have the total of the dropdowns show when its created, but for the time being its showing when I make a selection, but they add up to 8, when there are 9 dropdowns and in the first instance they all have a value of 1, so it should be 9.

So there a few little issues which im struggling with.

link again - http://www.accend4web.co.uk/OCalculator/design.php


function active_tiptip() {
var selects = [ 
{
 "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}, {
    "1": "test 1",
        "2": "test 2"
}];
    $('#test')
        .append('<form id="form1" name="form1"></form>');
    $.each(selects, function (i, v) {
        var select=$("<select id='select"+i+"'></select>").appendTo("#form1")
        console.log(i, v)
        $.each(v,function(value,key){
            $("<option></option>",{value:value,text:key}).appendTo(select)
        })
    })
    $("<div class='sum'></div>").appendTo("#form1")
 var totalT=0
        $("#form1").find("select").change(function(){
    var total=0
    $(this).prevUntil(".sum").add($(this).nextUntil(".sum")).each(function(){
    console.log(this)
    total+= +$(this).val();
 totalT+= +$(this).val();
    })
    $(this).nextAll('.sum:first').text('£' + total);
 $('.sumTotal').text('£' + totalT);
    })
}
$('#test')
.append("<span style='color:#fff'>Total Total in here:</span> <div class='sumTotal'></div>");


What’s happening is that when you are picking up the select fields to add them, the first one called select0 is being missed out.

I would make it a bit clearer about what is happening and why, by adjusting things so that you collect the select fields within the form.


$("#form1 select").on('change', function () {
    var total = 0,
        form = this.form,
        $selects = $('select', form);

    $selects.each(function () {
        total += +$(this).val();
    });
    ...
});

Hi Paul,

Thanks for getting back to me, its sorted now and works really well.


var selects = [{
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "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 sumDiv = $("<div class='sum'>total £<span>0</span></div>").appendTo(fieldset)
    $.each(selects, function (i, v) {
        var select = $("<select name='select" + i + "'></select>").prependTo(fieldset)
        $.each(v, function (value, key) {
            $("<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()
    })
}

Could you help me with the next bit which im struggling with.

On each of those dropdowns I need to add a second value, and then multiply the second value with the value of the dropdown. So the second value could come from the label perhaps, as cant think of anything else, but each dropdowns second value will be different as they different prices per module.

This is why.

Each drop down at the moment is a module, and it has a set value which lets say is £400 for dropdown 1, then in the drop down there going to be 4 values such as
Monthly = 12
Bi-Monthly = 6
Quarterly = 4
N/A = 0

So to get the sum value from that drop down its £400 x by either (12,6,4,0)

Is this dooable, and can you help me get there, as I will then need to add that formula to all those dropdowns.

Thanks for the help again

It seems to me that a more important thing to work on is in regard to the form design, making it easily understandable to the people using it what information they need to provide. The manner in which scripting interacts with the form is secondary at best.

Also, with more information about the form in terms of other information that will be used with it, better scripting solutions can be provided too.

As such, my recommendation is to focus on making the form easily understandable by people first, before moving on with other scripting in regard to it.

Hi Paul,

This isnt a customer focused form, this is for a consultant to use whilst sitting with a client and its his job to basically get as high a contract as possible, so how it looks etc isnt so much of a problem really, as he will know what each drop down means, its the total total figure thats the important part for the customer to see.

Its sort of for internal use really.

You are right though Paul, it does have to look a bit betterm wbut what would be enough really is to include labels in and thats what gave me that idea to attach a value to them and then use that figure, but again adding those labels isnt straightforward.

Will give it a go but im sure i will be back.

Morning Paul,

I hope you dont mind me asking, but I have 3 problems which I am struggling with at the moment.

  1. I need to sort the dropdowns so that the highest value is at the top, displayed and counted on all the drop downs, so that the total’s on all the forms at the beginning are at this point 12 x 9 = £108 rather that 12 x N/A = £0

  2. Each dropdown needs a label with it with a different name, and ideally on top of the dropdown. (I have managed to add a label, but it aligned itself to the right, and I couldnt work out how to populate it with the correct name.

  3. To get that second value associated with each drodown, so that I can multiply that with that second value to then be added to the form total, and then add up in the total total.

If you could help that would be great, and thanks again anyway.


var selects = [{
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "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 sumDiv = $("<div class='sum'>total £<span>0</span></div>").appendTo(fieldset)
 
    $.each(selects, function (i, v) {
  var select = $("<select name='select" + i + "'></select>").prependTo(fieldset)
        $.each(v, function (value, key) {
            $("<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()
    })
}


http://quotation.csf.dcmanaged.com/design.php

Dropdowns normally require two clicks to use, whereas radio buttons only need one click.
Because you have so many dropdowns, are you sure that dropdowns are the best type of form field to use? Have you considered how radio buttons may improve the ability for people to use your form?

Even though it’s going to be internal - the easier it is to use the faster people can use it, and the more money that can be made.

Hi Paul,

Unfortunately it has to be dropdowns, as the design and the way it is meant to work has come from the CEO, so I havent got much say in the matter, and it has been discussed with the consultants and this is what they want.

Thanks for that though

i have been looking at the first one and I understand that sort is the way to do it, but the examples I’ve seen on other posts dont really fit with what I got, to get it working, I am trying as always

Sorting by numbers can be tricky, because JavaScript normally sorts alphabetically, so sorting “1”, “2”, “12” will end up with them being sorted as “1”, “12”, “2”

To sort an array numerically you can give the sort function a custom function, so that you can give it new instructions for when comparing numbers.

Details are at the Array.prototype.sort() page, but a numeric sort can be done using:


function compareNumbers(a, b) {
  return a - b;
}

var numbers = [4, 2, 5, 1, 3];
numbers.sort(compareNumbers);

print(numbers); // 1, 2, 3, 4, 5

Ah instead of using name: & value: I just have numbers.


var selects = [{
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}];
selects.sort(function (a, b) {
    if (a.name > b.name)
      return 1;
    if (a.name < b.name)
      return -1;
    // a must be equal to b
    return 0;
});

So I cant compare them using a,b if you like…

Then how do I pass on the ordering to the dropdowns

That’s fine, you can extract the numbers from the object and put them in to an array.

I’m not at a computer right now, but it could be something like this:


var array = [],
    key;
for (key in obj) {
    if (obj.hasOwnProperty(key)) {
        array[array.length] = Number(key);
    }
}

Brought to you by a big iPhone pretending to be a computer, my ipad.

LOL Paul,

I think i’ll have to wait until you got more time, as this is beating me now.

So do I not do it the way i started and instead go at it your way, which I didnt need to ask anyway, and then how do those changes fall into place with what I got when the dropdons are outputted…

Coming from a Welsh man pretending to be an programmer!

The place where the select data is used to build the options, is at this place of the code:


$.each(selects, function (i, v) {
    var select = $("<select name='select" + i + "'></select>").prependTo(fieldset)
    $.each(v, function (value, key) {

So that I can think clearly about this, I will rename the function properties to more meaningful names:


$.each(selects, function (index, options) {
    var select = $("<select name='select" + index + "'></select>").prependTo(fieldset)
    $.each(options, function (value, key) {

Instead of processing each of the options, you can instead create a sorted array of the option values, and then use that sorted array to choose which option to work on.


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;
}

Here’s how you could work it in to your existing code:


$.each(selects, function (index, options) {
    var select = $("<select name='select" + index + "'></select>"),
        optionValues = sortOptions(options);
    
    $.each(optionValues, function (index, value) {
        var key = options[value];
         ...
    });
});

Hi Paul,

Not good, I think I understand that the one is a outside function and we calling it in, and if thats correct then Im doing something wrong, and cant see it.

Why I know its wrong is because there no dropdowns showing, only the totals…


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

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;
}

$.each(selects, function (index, options) {
var select = $("<select name='select" + index + "'></select>"),
optionValues = sortOptions(options);
$.each(optionValues, function (index, value) {
var key = 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()
})
}


I’m sorry if I’m miles off Paul, Im not doing your help justice…

http://quotation.csf.dcmanaged.com/design.php

Things seem to be going well - the select element just needs to be added to the page.

Ah there you go,

I forgot to append it, thanks Paul.

Would you mind helping me with the other 2 too, so i can get it to the next point to show the manager and then can see what next needs to be done.

What I need now as you pointed out is to add labels to the top of each dropdown, and then if possible I really need to be able to associate a vale to each dropdown as a second value to multiply it with the selection of the dropdown, and each drop down will have its own second value like the label.

I’m htinking of maybe creating an array


var nameArray = [ "Food 1", "Food 2", "Food 3", "Food 4", "Food 5", "Food 6", "Food 7", "Food 8", "Food 9" ]; 
for ( var i = 0; i < nameArray.length; i = i + 1 ) {     
console.log( nameArray[ i ] ); 
}

Then somehow adding the name from the array with its position to a label above the dropdown.

Any good?

I’m trying to pinch the method off the other array, and i think the idea is there, im getting undefined back, but a label is appearing with the dropdown although to the right, but need to try and get the proper name in there


var nameArray = [ "Food 1", "Food 2", "Food 3", "Food 4", "Food 5", "Food 6", "Food 7", "Food 8", "Food 9" ]; 
for ( var i = 0; i < nameArray.length; i = i + 1 ) {     
console.log( nameArray[ i ] ); 
}
var selects = [{
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "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 sumDiv = $("<div class='sum'>total £<span>0</span></div>").appendTo(fieldset)
 
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;
}
$.each(selects, function (index, options) {
var label = $("<label>"+ nameArray[i] +"</label>").prependTo(fieldset);
var select = $("<select name='select" + index + "'></select>").prependTo(fieldset),
optionValues = sortOptions(options);
$.each(optionValues, function (index, value) {
var key = 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()
})
}


OK I have been able to generate the values from the area and created labels, but they are not attached to the dropdowns just started its own block to the right.

http://quotation.csf.dcmanaged.com/design.php


var nameArray = [ "Food 1", "Food 2", "Food 3", "Food 4", "Food 5", "Food 6", "Food 7", "Food 8", "Food 9" ]; 

var selects = [{
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "12": "Monthly",
        "6": "Bi-Monthly",
   "4": "Quarterly",
    "0": "N/A"
}, {
    "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 sumDiv = $("<div class='sum'>total £<span>0</span></div>").appendTo(fieldset)
 
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;
}

$.each(nameArray, function(index, value){
 var label = $("<label>"+ value +"</label>").prependTo(fieldset);
});

$.each(selects, function (index, options) {
var select = $("<select name='select" + index + "'></select>").prependTo(fieldset),
optionValues = sortOptions(options);
$.each(optionValues, function (index, value) {
var key = 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()
})
}