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?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
jQuery

From novice to tech pro — start learning today.