Constraint the effect of JQuery Code

I was trying to enhance the functionality: the whole new code is here →

<script type="text/javascript">
		$(document).ready(function() {
			var max_fields      = 10; //maximum input boxes allowed
			var wrapper   		= $(".html_js"); //Fields wrapper
			var add_button      = $(".buttonjs"); //Add button ID
			var sem_button      = $(".sembutton"); //Add button ID

			$(add_button).click(function(e){ //on add input button click
			e.preventDefault();
				var count = $(this).parent().find( "div").length;
				if(count !=10) {
					$('<div class="htmljs"><label for=""><h3>Subject<span class="csscounter"></span></h3></label> <input type="text" name="" value=""><input type="text" name="" value=""></div>').insertBefore(this);
				}
			});

			$(sem_button).click(function(e){ //on add input button click
			e.preventDefault();
				var semcount = 3;
				if(semcount < max_fields){
					semcount++;
					$('<div class="semester"><div class="class1"><h2>Semester 3</h2></div><div class="class2"><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><button type="button" name="button" class="buttonjs">Add subjects</button></div></div>').insertBefore(this);
				}
			});
		});
</script>

The semesters are adding but the cap that i wanted to put was maximum 10 semesters should be allowed. that cao is not working, but semsters are adding indefinitely+

The new semesters added doesn’t have additional subjects adding.

			var semcount = 3;
			if(semcount < max_fields){

Well, how do you expect those two lines to interact when they’re directly next to each other?

You click the button.
Set semcount to 3.
if (semcount (3) is less than max_fields (10)) { [True]
set semcount to 4.
do an addline.
End button click.

You click the button again.
Set semcount to 3.
if (semcount (3) is less than max_fields (10)) { [True]
set semcount to 4.
do an addline.
End button click.

… repeat ad infinitum.

1 Like

Got it. Fixed, but now why the subjects are not incrementing for the newly added semesters.

The short answer is because of when you bind the event, and how you bind the event.

Event Delegation is a large topic, and i’d suggest reading what jQuery has to say on the matter.

You’ll need to change your click binds to reflect this methodology.

1 Like

I read this and I tried changing the bind with so many examples that i cam through. I even used delegate(), but of no success. Can you guide me from here onwards, please.

A good first step is to convert your existing click events, to on events instead. I like to give the function a suitable name too.

// $(add_button).click(function(e){
$(add_button).on("click", function addbuttonClickHandler(e){

A benefit of using named functions, is that you can then easily make them separate, which can then help to make it easier to understand the code, or use that function from somewhere else instead.

function addbuttonClickHandler(e){
    ...
}
$(add_button).on("click", addbuttonClickHandler);

That assigns the event to every matching add button, but can’t do anything about other add buttons that are added in the future.

One solution to that is to separately add the event when you add the new add button.

        $('<div class="semester">...<div class="class1">' +
            ...
            '<button type="button" name="button" class="buttonjs">Add subjects</button>' +
            '</div></div>').insertBefore(this);
        $('.buttonjs', this.parent()).on("click", addbuttonClickHandler);

Instead of doing it separately though, you can instead place a click event on the document object, and have it trigger when a matching element is used.

$(document).on("click", '.buttonjs', addbuttonClickHandler);
// $(add_button).on("click", addbuttonClickHandler);
    ...
    // $('.buttonjs', this.parent()).on("click", addbuttonClickHandler);

And because you already have that class selector assigned to the add_button variable, you can use that instead too.

var add_button = $(".buttonjs");
...
// $(document).on("click", '.buttonjs', addbuttonClickHandler);
$(document).on("click", add_button, addbuttonClickHandler);

Which in words means, from the document watch for a click, and when it matches the add_button selector use the addbuttonClickHandler.

1 Like

Hi there @Paul_Wilkins,

Thank you for providing the insight and helping me.

I am getting slightly confused. what part of the previous or the would be new code will go inside this function?

From this excerpt, where I’ve just added a name to the function:

    $(add_button).click(function addbuttonClickHandler(e){ //on add input button click
        e.preventDefault();
        var count = $(this).parent().find( "div").length;
        if (count != 10) {
            $('<div class="htmljs"><label for=""><h3>Subject<span class="csscounter"></span></h3></label> <input type="text" name="" value=""><input type="text" name="" value=""></div>').insertBefore(this);
        }
    });

You can move the function out of the click statement, leaving just the name of the function in its place.

    function addbuttonClickHandler(e){ //on add input button click
        e.preventDefault();
        var count = $(this).parent().find( "div").length;
        if (count != 10) {
            $('<div class="htmljs"><label for=""><h3>Subject<span class="csscounter"></span></h3></label> <input type="text" name="" value=""><input type="text" name="" value=""></div>').insertBefore(this);
        }
    }

    $(add_button).click(addbuttonClickHandler);
1 Like

Hi there,

There are two areas where I am confused.

This is the older version of the full code:

<script type="text/javascript">
$(document).ready(function() {
	var max_fields      = 10; //maximum input boxes allowed
	var wrapper   		= $(".html_js"); //Fields wrapper
	var add_button      = $(".buttonjs"); //Add button ID
	var sem_button      = $(".sembutton"); //Add button ID

	$(add_button).click(function(e){ //on add input button click
	e.preventDefault();
		var count = $(this).parent().find( "div").length;
		if(count !=10) {
			$('<div class="htmljs"><label for=""><h3>Subject<span class="csscounter"></span></h3></label> <input type="text" name="" value=""><input type="text" name="" value=""></div>').insertBefore(this);
		}
	});

	var semcount = 3;
	$(sem_button).click(function(e){ //on add input button click
	e.preventDefault();
		if(semcount < max_fields){
			semcount++;
	$('<div class="semester"><div class="class1"><h2>Semester <span class="csscounter2"></span></h2></div><div class="class2"><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><button type="button" name="button" class="buttonjs">Add subjects</button></div></div>').insertBefore(this);
		}
	});
});
</script>

Now the modified code will be:

<script type="text/javascript">
		$(document).ready(function() {
			var max_fields      = 10; //maximum input boxes allowed
			var wrapper   		= $(".html_js"); //Fields wrapper
			var add_button      = $(".buttonjs"); //Add button ID
			var sem_button      = $(".sembutton"); //Add button ID

			$(add_button).click(function addbuttonClickHandler(e){ //on add input button click

			});

			var semcount = 3;
			$(sem_button).click(function(e){ //on add input button click
			e.preventDefault();
				if(semcount < max_fields){
					semcount++;
			$('<div class="semester"><div class="class1"><h2>Semester <span class="csscounter2"></span></h2></div><div class="class2"><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><button type="button" name="button" class="buttonjs">Add subjects</button></div></div>').insertBefore(this);
				}
			});

			function addbuttonClickHandler(e) {
				e.preventDefault();
					var count = $(this).parent().find( "div").length;
					if(count !=10) {
						$('<div class="htmljs"><label for=""><h3>Subject<span class="csscounter"></span></h3></label> <input type="text" name="" value=""><input type="text" name="" value=""></div>').insertBefore(this);
					}
			}
			$(add_button).click(addbuttonClickHandler);
		});
		</script>

Confusion #1
This part of the code is empty than what was the use in making that →

$(add_button).click(function addbuttonClickHandler(e){ //on add input button click

});

Confusion #2
where will this part of the code so that newly added semester subjects can also be increased:

$(document).on("click", add_button, addbuttonClickHandler);

Re: #1: That part should be removed.
Re: #2: I’m… not sure what you’re asking about here? How it binds to newly added elements? That was covered by the jQuery page I linked before.

1 Like

Where should I put this in the current code:

$(document).on("click", add_button, addbuttonClickHandler);

Thanks.

Make it easy: Replace the thing in #1 with the thing in #2.

1 Like

Done!

Final code:

<script type="text/javascript">
		$(document).ready(function() {
			var max_fields      = 10; //maximum input boxes allowed
			var wrapper   		= $(".html_js"); //Fields wrapper
			var add_button      = $(".buttonjs"); //Add button ID
			var sem_button      = $(".sembutton"); //Add button ID

			$(document).on("click", add_button, addbuttonClickHandler);
			var semcount = 3;
			$(sem_button).click(function(e){ //on add input button click
			e.preventDefault();
				if(semcount < max_fields){
					semcount++;
			$('<div class="semester"><div class="class1"><h2>Semester <span class="csscounter2"></span></h2></div><div class="class2"><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><div class="htmljs"><label for=""><h3>Subject <span class="csscounter"></span></h3></label> <input type="text" name="" value=""> <input type="text" name="" value=""></div><button type="button" name="button" class="buttonjs">Add subjects</button></div></div>').insertBefore(this);
				}
			});

			function addbuttonClickHandler(e) {
				e.preventDefault();
					var count = $(this).parent().find( "div").length;
					if(count !=10) {
						$('<div class="htmljs"><label for=""><h3>Subject<span class="csscounter"></span></h3></label> <input type="text" name="" value=""><input type="text" name="" value=""></div>').insertBefore(this);
					}
			}
			$(add_button).click(addbuttonClickHandler);
		});
		</script>

still in newly added sems subjects cant be added.

Try this instead:
$(document).on("click", ".buttonjs", addbuttonClickHandler);

1 Like

image

Hi there,

var totsub = $(‘.htmljs’).parent().find( “input”).length;

This is fetching all the inputs length, but I want in real time only nonempty inputs should be calculated.

When does real time differ from when the totsub line is executed?

Actually initially all divs input are empty:
http://html.trafficopedia.com/cgpa/

This numbers should increase as soon as CGPA are entered.

The ntire new script that i have added is:

$(document).on("keyup", ".cgpatot", function() {
				var totsub = $('.htmljs').parent().find( "input:not(:empty)").length;
			    var sum = 0;
			    $(".cgpatot").each(function(){
			        sum += +$(this).val();
			    });
				var finalcgpa = sum/totsub;
			    $(".total").val(totsub);
			});

You might want to use filter instead, and use find in that filter method.

Can you please guide me sir. How?