Question

I am trying to create a section of my webstore where the customer can 'build' their own bundle and choose any combination of 5 items.

I have a set of buttons which, when clicked, add their value to a Fieldset along with a button to remove it in case they misclicked or changed their mind.

All the components work fine, but I don't know how to limit the Fieldset to only five items. Is there a way to either count the lines, then stop accepting input after five or look for 'Remove' five times?

I'm still fairly new to coding and not too sure what is possible. This input will end up being submitted in a form.

Here is my Fiddle and below is my Javascript code which i have tried for it :

$(document).ready(function () {
    $(".buttons").click(function () {
        var intId = $().length + 1;
        var item = $(this).html();
        var fieldWrapper = $("<div class=\"fieldwrapper\" id=\"field" + intId + "\"/>");
        var removeButton = $("<input type=\"button\" class=\"remove\" value=\"Remove\" />");
        removeButton.click(function () {
            $(this).parent().remove();
        });
        fieldWrapper.append(size);
        fieldWrapper.append(removeButton);
        $("#buildyourkit").append(fieldWrapper);
    });
});
Was it helpful?

Solution

This will give you the current quantity of elements added to the . Just make sure that there is still room for another before appending a new one.

$("fieldset .fieldwrapper").length

I've forked your fiddle. Just look at the console while adding new items to the fieldset.

OTHER TIPS

You can have a global variable which will count up and disable all buttons if over 5 every time you add a field, and down and enable all buttons every time you remove a field.

Also, it is a bit nicer to just set a live handler listening for any remove buttons, rather than make a new function and bind a new listener for each button, so I demonstrated; but it is not obligatory (your way works, too, given it's just 5 elements).

$(document).ready(function () {
    var buttonMaxID = 0;
    var buttonCount = 0;
    $('$buildyourkit').on('click', '.remove', function () {
        $(this).parent().remove();
        if (buttonCount-- >= 5) {
            $('.buttons').prop('disabled', false);
        }
    });
    $(".buttons").click(function () {
        if (++buttonCount >= 5) {
            $('.buttons').prop('disabled', true);
        }
        var item = $(this).html();
        var fieldWrapper = $("<div class=\"fieldwrapper\" id=\"field" + (buttonMaxId++) + "\"/>");
        var removeButton = $("<input type=\"button\" class=\"remove\" value=\"Remove\" />");
        fieldWrapper.append(size);
        fieldWrapper.append(removeButton);
        $("#buildyourkit").append(fieldWrapper);
    });
});

What I propose is designing a manager class to maintain all functions/methods that must interact with the UI. This allows you to define your data set in one place, and keep the UI binds in one place. By doing so, you set yourself up with a cleaner code base, easy refactoring, and quickly make code modifications. Also, you get all this goodness without any global variables, another great bonus.

The code does look like its larger, but once you understand the simplicity of the manager you will see the possibilities I outlined above.

$(document).ready(function () {
    //Create a new Kit Manager
    var kitManager = new KitManager();

    $(".buttons").click(function () {
        kitManager.add(this);
    });

    $(".report").click(function () {
        kitManager.getKit();
    });
});

function KitManager()
{
    //Static amount of items to return
    var MAX_ITEMS = 5;
    //Where the items should be visually displayed on the UI
    var kitLegend = $("#buildyourkit");
    //Internal array for storing the items added
    var items = []

    function add(element)
    {       
        if(items.length < MAX_ITEMS)
        {
            var itemNumber = items.length + 1;         
            var item = $(element).html();
            var fieldWrapper = $("<div class=\"fieldwrapper\" id=\"field" + itemNumber + "\"/>");
            var removeButton = $("<input type=\"button\" class=\"remove\" value=\"Remove\" />"); 

            //Add item to the array collection
            items.push(item);

            //Bind a remove function to the newly created button
            removeButton.click(function () {
                kitLegend[0].removeChild(fieldWrapper[0]);
                items.splice(itemNumber, 1); 
            });

            //Append UI components to container
            fieldWrapper.append(item).append(removeButton);

            //Append to main legend
            kitLegend.append(fieldWrapper); 
        }
        else
        {
            //Simple alert to user
            alert('You\'ve Reached The Maximum Number of Items');
        }
    }
    //Simple function for demonstration of a reporting feature
    //or potential method for returning the stored items
    function getKit()
    {
        for(var i=0,length=items.length;i <length;i++)
        {
            console.log(items[i]);
        }
    }

    //Expose public method call
    return {
        add:add,
        getKit: getKit
    };
}

http://jsfiddle.net/x97S5/

I hope you find the solution acceptable, and if you have any further questions please ask.

For more information on the solution and technique proposed take a look at Key Principles of Maintainable JavaScript

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top