F.Fasser F.Fasser - 6 months ago 8
jQuery Question

Javascript problems with option.length

I wrote the function below to get the length of a

listbox
with the id
courselessons
. The problem when I comment the alert the function works only once.

When I uncomment the
alert
it works fine. But I don't wanna have an alert on every single click.

The
.options.length
shows only the first time the right content.

Can somebody helps me?

Greetings from switzerland

Javascript:

function changecheckbox() {
//alert("function called...");
var selOpts = document.getElementById("courselessons").length();
alert(selOpts);
if (selOpts > 0) {
$('#taskassignment').prop('disabled', false);
}
else {
$('#taskassignment').prop('disabled', true).prop("checked", false);
}
}

function addItem() {
if (seltask == undefined || seltask.length === 0) {
return;
}
var lessonsDropdown = $('#courselessons');
lessonsDropdown.empty();
$("#tasks option:selected").appendTo("#coursetasks");
$("#coursetasks option").attr("selected", false);
if (seltask.length > 0) {
cacheToken = new Date().getTime();
// retrieve data using a Url.Action() to construct url
$.getJSON('@Url.Action("AddTaskToCourse")', {
task: seltask,
lesson: lesson,
_: cacheToken
});
$.getJSON('@Url.Action("UpdateLessonInCourse")', {
_: cacheToken
}).done(function (data) {
//re-enable tasks drop down
//for each returned tasks
$.each(data, function (i, lessons) {
//Create new option
var test = $('<option />').html(lessons);
//append tasks taskss drop down
lessonsDropdown.append(test);
});
seltask = null;
});

}
changecheckbox();
}


HTML:

<button type="button" class="btn btn-default" id="btnAdd" onclick="addItem();"><i class="glyphicon glyphicon-arrow-right"></i></button><br />

Answer

The code inside addItem() is making a GET request to a resource asynchronously. This means the code which comes after this function to be execute will not wait for its execution to get complete.

When I uncomment the alert it works fine.

That is because as the alert() is built in, it halts the execution of script until user interaction. This gave the time addItem() needs and everything seems to work.

Fortunately, there are solutions available to handle this situation.

  1. Promise.
  2. Rearrange your code to work with callbacks.

Under the covers, $.getJSON is shorthand for making a GET request using ajax with datatype = 'json'and it returns a promise object which basically tells that please wait honey, i will give you something which could be a success or a failure but sometime later.

So yes, you can easily call the function inside the done().

NOTE: These things have been explained pretty well on web so i will not reinvent the wheel :)

Keeping the things simple...

function addItem() {

    // Rest of the code...

    if (seltask.length > 0) {
        cacheToken = new Date().getTime();
        // retrieve data using a Url.Action() to construct url
        $.getJSON('@Url.Action("AddTaskToCourse")', {
            task: seltask,
            lesson: lesson,
            _: cacheToken
        });
        $.getJSON('@Url.Action("UpdateLessonInCourse")', {
            _: cacheToken
        }).done(function (data) {
            //re-enable tasks drop down
            //for each returned tasks
            $.each(data, function (i, lessons) {
                //Create new option
                var test = $('<option />').html(lessons);
                //append tasks taskss drop down
                lessonsDropdown.append(test);
            });
            seltask = null;
            changecheckbox();
        });

    }        
}

After this setup, you should remove the changecheckbox() call from the button onclick otherwise it would make it execute twice.