0

I have been trying to solve the following problem for the last week or so, and after many searches around the internet, and on here, haven't found an exact solution for what I am trying to achieve.

This is my first post on here, and decided to post here as this forum has saved my bacon several times!

This is what I would like to happen:

User selects the number of scouts and leaders from the dropdowns. The first tshirts (small) is populated with the number of leaders + scouts total.

if the user selects a lesser amount from the small dropdown, then the remaining amount is used to populate the medium select list, and so on upto XXL.

The following bit of code is how far I have got so far, but it seems a bit buggy, the option values append again and again if the user changes their mind, and the medium box is showing the total options rather that total - amount of small selected.

I don't know if this is the best way or if there are any better solutions?

Here goes

<form method='post' id="wawBooking" action='processWAWBooking.php' >
    <div id="groupDetails" >
        <fieldset>
            <legend>Group Details</legend>
            <label for="noScouts">Number of scouts:</label>
            <select id='noScouts' name="noScouts"></select><br />
            <label for="noLeaders">Number of leaders:</label>
            <select id='noLeaders' name="noLeaders"></select><br />
        </fieldset>
    </div>
    <div style="clear: both;"></div>
    <div id="tshirts">
        <fieldset style="height: auto;">
            <legend>T-Shirts</legend>
            Total: <span id='totalTshirts'></span><br />
            Amount left (Total - current total): <span id='amountLeft'></span><br />
            Sum of Selected: <span id='liveTotal'></span><br />
            <label for='s'>Small</label>
            <select id='s'></select><br />
            <label for='m'>Medium</label>
            <select id='m'> </select><br />
            <label for='l'>Large</label>
            <select id='l'></select><br />
            <label for='xl'>X-Large</label>
            <select id='xl'></select><br />
            <label for='xxl'>XX-Large</label>
            <select id='xxl'></select><br />
        </fieldset>
    </div>
    <input type="reset" value="Reset Form" id="reset" style="float: left;"/>
    <input type="button" value="Order t-shirts" id="tshirtOrder" style="float: right;"/>
    <input type="submit" value="Submit Booking" style="float: right;"/>
</form>
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script> 
<script type="text/javascript">
    var scouts = 20;
    var leaders = 30;

    // ignore this bit - using just to demonstrate
    for (a = 0; a <= leaders; a++) {
        $('#noScouts').append("<option value='" + a + "'>" + a + "</option>");
    }
    for (b = 0; b <= scouts; b++) {
        $('#noLeaders').append("<option value='" + b + "'>" + b + "</option>");
    }
    // end of ignore section!

    $('#wawBooking').change(function(){
        var totalTshirts = parseInt($('#noLeaders').val()) + parseInt($('#noScouts').val());
        var liveTotal = parseInt($('#s').val())
                      + parseInt($('#m').val()) 
                      + parseInt($('#l').val()) 
                      + parseInt($('#xl').val()) 
                      + parseInt($('#xxl').val());
        if ($('#noScouts').val() && $('#noLeaders').val() > 0) {
            $('#totalTshirts').empty().append(totalTshirts);
            $('#liveTotal').empty().append(liveTotal);
            for (i = 0; i <= totalTshirts; i++) {
                $('#s').append('<option value="' + i + '">' + i + '</option>')
            }
            if ($('#s').val() > 0 && $('#s').val() < totalTshirts) {
                var subSmallMinusTotal = parseInt(totalTshirts) - parseInt($('#s').val());
                for (k = 0; k <= subSmallMinusTotal; k++) {
                    $('#m').append('<option value="' + k + '">' + k  + '</option>')
                }           
            }
        } 
    });

</script>

Any suggestions or tips?

Many thanks in advance

Chris

Jaak Kütt
  • 2,239
  • 4
  • 26
  • 37
Chris
  • 387
  • 6
  • 20
  • where's your javascript? – slashingweapon Nov 06 '12 at 02:43
  • Not sure I follow... The JavaScript is at the end of the html, although I just noticed that I have forgotten the body tags etc! I took the liberty of adding it to a JsFiddle which can be found here(http://jsfiddle.net/j3RKs/) – Chris Nov 06 '12 at 09:40

1 Answers1

0

Here's a possible solution. You might be able to tweak it to be more generic and generate the lists off a collection, but I think it'll get you started.

Example (JsFiddle)

HTML

<label for="noScouts">Number of scouts:</label>
<select id='noScouts' name="noScouts"></select><br />
<label for="noLeaders">Number of leaders:</label>
<select id='noLeaders' name="noLeaders"></select><br />
<label for="noSmall">s:</label>
<select id='noSmall' name="noSmall"></select>
<label for="noMed">m:</label>
<select id='noMed' name="noMed"></select>
<label for="noLarge">l:</label>
<select id='noLarge' name="noLarge"></select>
<label for="noXLarge">xl:</label>
<select id='noXLarge' name="noXLarge"></select>
<label for="noXXLarge">xxl:</label>
<select id='noXXLarge' name="noXXLarge"></select>

JS

var sizes = $('#sizes'); 
var numScouts = new selectRange('#noScouts', { max: 30 }); 
var numLeaders = new selectRange('#noLeaders', { max: 20 }); 

var total = new watchVal(0); 
var small = new selectRange('#noSmall', { max: 0 }); 
var med = new selectRange('#noMed', { max: 0 }); 
var large = new selectRange('#noLarge', { max: 0 }); 
var xlarge = new selectRange('#noXLarge', { max: 0 }); 
var xxlarge = new selectRange('#noXXLarge', { max: 0 }); 

numScouts.change(zSetTotal); 
numLeaders.change(zSetTotal); 


total.change(function(e, total){
    small.setMax(total); 
}); 

small.change(function(){
   med.setMax(total.value() - small.value());
});

med.change(function(){
   large.setMax(total.value() - med.value() - small.value());
});

large.change(function(){
   xlarge.setMax(total.value() - med.value() - small.value() - large.value());
});

xlarge.change(function(){
   xxlarge.setMax(total.value() - med.value() - small.value() - large.value() - xlarge.value());
});

function zSetTotal(){
    total.value(numScouts.value() + numLeaders.value()); 
}

function watchVal(initVal){
    var _val = initVal; 
    var $_ctx = $(this); 
    $_ctx.value = function(newVal){
        if(newVal){
            _val = newVal;   
            $_ctx.trigger('change', _val);            
        }else{
            return _val;    
        }
    }    
    return $_ctx;         
}

function selectRange(selector, options){
    var _config = {
        max: 10               
    };
    var _select = null; 
    var _ctx = this; 

    function zInit(){
        $.extend(_config, options); 
        if($(selector).is('select')){
            _select = $(selector); 
        }else{
            _select = $('<select />'); 
            _select.appendTo(selector); 
        }
        _ctx.repaint(); 
    }            

    this.setMax = function(max){
        _config.max = max;       
        this.repaint();     
        _select.trigger('change');
    };

    this.repaint = function(){
        var prevPos = _select.find('> option:selected').index();         
        _select.empty(); 
        for (var i = 0; i <= _config.max; i++) {
            var option = $("<option />", {
                'value': i,
                'text': i        
            });

            _select.append(option); 
            if(i === prevPos){
                option.prop('selected', true);                   
            }
        }
    };

    this.value = function(){
        return parseInt(_select.val(), 10);             
    };

    this.change = function(fun){
        _select.change(fun);         
    };

    zInit(); 
}
​
Brandon Boone
  • 15,271
  • 4
  • 69
  • 93