uncaught type error: undefined is not a function

I get the error "uncaught type error: undefined is not a function" when a function is called. The function is called in one javascript file but is defined in another. I don't think that is the problem because even when I move the function call to the same page as it is defined, it still gives the same error, and there are no variable or function name duplications between the two files. Here is the function definition inside of javascript2.js
function getDeliveries(){
    $.get("driverDeliveries.aspx").find("ul").each(function () {
        var liElems = $(this).find('li');
        alert(liElems[1].text());
        geocoder = new google.maps.Geocoder();
        geocoder.geocode({ 'address': liElems[1].text() }, function (results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                var marker = new google.maps.Marker({ map: map, position: results[0].geometry.location });
                map.fitBounds(results[0].geometry.viewport);
                
            }
        });
    });
}

Open in new window


It is immediately called (executed) when javascript1 loads. In the html, javascript 2 is loaded in the head tag. Javascript 1 is loaded right before the closing of the body tag. It does not even make it to the alert message, and I looked in the dev tools, and the page request ($.get) is returning exactly what is expected.
LVL 9
BobHavertyComhAsked:
Who is Participating?
 
Robert SchuttSoftware EngineerCommented:
You've combined a couple of things in a manner that's not the way it should be:
$("<div>" + data + "</div>").find("ul").each(function (textStatus, jqXHR) {

Open in new window

"textStatus, jqXHR" are optional arguments to the callback function you pass to get() on the line above, the each() call has its own arguments that are an index and the current object being iterated. In fact that second one is better used than 'this' to get the <LI>s, although in this particular situation they are the same. You have to be careful using 'this' though when using callback functions and such.

New code: (although the map didn't work for me as I'm probably missing some references, the returned data seemed ok)
function getDeliveries() {
    var msg = encodeURI("driverDeliveries.aspx");
    $.get(msg, function (data) { // this is the asynchronous callback function processing the html data
        $("<div>" + data + "</div>").find("ul").each(function (intIndex, objUL) { // this is the iterator function
            //alert(data);
            var liElems = $(objUL).find('li');
            geocoder = new google.maps.Geocoder();
            // note below I added an extra $() because the text() function is defined on the jQuery object but not directly on a JavaScript DOM object
            geocoder.geocode({ 'address': $(liElems[1]).text() }, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    var dmarker = new google.maps.Marker({ map: map, position: results[0].geometry.location });
                    /*map.fitBounds(results[0].geometry.viewport);*/
                
                }
                else {
                    alert("Could Not Geocode Address");
                }
            });
        });
    });
}

Open in new window


It can really help if you get comfortable with the developer tools that every modern browser offers (F12), giving you a console and debugger and lots of other tools. You can set a breakpoint in the code and examine variables. Here's a screen capture of how I checked the new code.
captureOn the left you can see where I have set a breakpoint and on the right I added a watch to check the value of the expression from your code: results[0].geometry.location
0
 
Robert SchuttSoftware EngineerCommented:
The various ways to handle the returned data from $.get() are explained here.

So the data is not the return value of the get function, but rather the data is passed as the first argument to a function that is called asynchronously when the response is received. That function can be an argument to the get() function or set on the return object.

Here is the code, note that I took out the geocoder bit for now.
function getDeliveries(){
    $.get("driverDeliveries.html", function (data, textStatus, jqXHR) {
        $("<div>" + data + "</div>").find("ul").each(function () {
            var liElems = $(this).find('li');
            alert($(liElems[1]).text());
            /*
            geocoder = new google.maps.Geocoder();
            geocoder.geocode({ 'address': liElems[1].text() }, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    var marker = new google.maps.Marker({ map: map, position: results[0].geometry.location });
                    map.fitBounds(results[0].geometry.viewport);
                    
                }
            });
            */
        });
    });
}

Open in new window


Also note that in my example, the <ul> was on the first level in the returned document so I had to add a container <div> because find() only looks inside tags in the body.

Live example here, using test document driverDeliveries.html
0
 
BobHavertyComhAuthor Commented:
Hi Robert, thanks for your answer. I changed the code as you said. I did think it was kind of odd to just use a find on data, but data does indeed return the exact tags I expect when I use an alert to print it out.
function getDeliveries() {
    var msg = encodeURI("driverDeliveries.aspx");
    $.get(msg, function (data, textStatus, jqXHR) {
        $("<div>" + data + "</div>").find("ul").each(function () {
            alert(data);
            var liElems = $(this).find('li');
            geocoder = new google.maps.Geocoder();
            geocoder.geocode({ 'address': liElems[1].text() }, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    var dmarker = new google.maps.Marker({ map: map, position: results[0].geometry.location });
                    /*map.fitBounds(results[0].geometry.viewport);*/
                
                }
                else {
                    alert("Could Not Geocode Address");
                }
            });
        });
    });

Open in new window


Thanks for the heads up about jqXHR. I didn't know about that and didn't know it was needed for chaining. I'm positive what it still does not like, but I'm not positive why.

This,
"var liElems = $(this).find('li');"

does not return anything, so it causes the call to geocode where it is used, to bomb.

Since alert(data) returns exactly what I expect all info is making it to that line of code correctly.
0
 
BobHavertyComhAuthor Commented:
This works. Now I have to figure out why I am getting back ZERO_RESULTS from my geocode attempt. Thanks a bunch!
0
 
Robert SchuttSoftware EngineerCommented:
Great!

Have you checked what's in $(liElems[1]).text()?
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.