setApiKey not working

1,145 views
Skip to first unread message

Dan Zoll

unread,
Jan 25, 2013, 1:07:55 PM1/25/13
to google-api-jav...@googlegroups.com
I developed some Javascript code for programmatically adding an event to a Google calendar based on this:


It works perfectly. After adding the code to a large ASP page, I'm suddenly getting ' gapi.client is undefined' when I try to run setApiKey.

In both places, I'm loading the gapi library with:

<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>, and it's there in the page's source big as life.

I've tried moving the library line around, but it seems to make no difference. I had to change some things in the Javascript a bit to get info from the ASP page into the Javascript function, but nothing that I feel could be the cause of the problem.

Does anyone have any ideas what the cause could be? I could post the code, but I'm not sure how much help that would be.

Brendan

unread,
Jan 25, 2013, 1:39:11 PM1/25/13
to google-api-jav...@googlegroups.com
Without seeing your page, it's difficult to say what the exact problem is. But this is the exact symptom of trying to use the client library before it is ready. i.e. calling a gapi.client function before the handleClientLoad callback has fired.

I had to change some things in the Javascript a bit to get info from the ASP page into the Javascript function

If this is the only difference between your working and non-working case then it seems likely that something in these changes is the cause. Double check if you are calling gapi.client.setApiKey before handleClientLoad.

Brendan

Dan Zoll

unread,
Jan 25, 2013, 1:54:30 PM1/25/13
to google-api-jav...@googlegroups.com
Thanks for the reply. I know, I saw those posts. Supposedly adding '?onload=handleClientLoad' to the client Javascript load fixes the problem, but it doesn't in my case. I invoke the code from the ASP with this:

response.Write "<script>handleClientLoad('" &EventTitle &"','" &EventDescription &"','" &EventLocation &"','" &EventDate &"')</script>"

That section of the code looks like this:

<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>

<script type="text/javascript">
    var clientId = [whatever]
    var apiKey = '[whatever]';
    var EventTitle
    var EventDescription
    var EventLocation
    var EventDate
    function handleClientLoad(EventTitle,EventDescription,EventLocation,EventDate) {
        EventTitle = EventTitle;
        EventDescription = EventDescription;
        EventLocation = EventLocation;
        EventDate = EventDate;
        gapi.client.setApiKey(apiKey);
        window.setTimeout(checkAuth, 1);
        checkAuth();
    }
...

Brendan O'Brien

unread,
Jan 25, 2013, 2:11:32 PM1/25/13
to google-api-jav...@googlegroups.com
You shouldn't be calling handleClientLoad manually, that will cause the errors you are seeing. The JS Client library will execute it automatically when the library is ready to use. The function also takes no arguments. If you need to pass data to the loader function, I suggest putting them in global variables. Finally, the callback function needs to be defined before you reference it in the /js/client.js URL. I would suggest rewriting your code something like this:

<script type="text/javascript">
    var clientId = [whatever]
    var apiKey = '[whatever]';
    var EventTitle = *value inserted by ASP*;
    var EventDescription = *value inserted by ASP*;
    var EventLocation = *value inserted by ASP*;
    var EventDate = *value inserted by ASP*;
    function handleClientLoad() {
        gapi.client.setApiKey(apiKey);
        // setTimeout is no longer needed, just call checkAuth() directly.
        // window.setTimeout(checkAuth, 1);
        checkAuth(); 
    }
</script>
<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>



Brendan O'Brien | Software Engineer | obr...@google.com | 650.450.4134

Dan Zoll

unread,
Jan 25, 2013, 2:14:19 PM1/25/13
to google-api-jav...@googlegroups.com

Dan Zoll

unread,
Jan 25, 2013, 2:19:29 PM1/25/13
to google-api-jav...@googlegroups.com
The thing is, I can't have the function I wrote execute when the page loads. I have a form that gets submitted, and if I see a date in one of its variables, I need to add the event then. I think I have to kick off handleClientLoad manually.

Brendan O'Brien

unread,
Jan 25, 2013, 2:34:01 PM1/25/13
to google-api-jav...@googlegroups.com
Then you should make a separate function for whatever you need to manually execute later. Keep handleClientLoad free of anything that does not relate to the JS Client library, or anything that you don't want to immediately execute when the library loads.

<script type="text/javascript">
    function handleClientLoad() {
        gapi.client.setApiKey(apiKey);
        checkAuth(); 
    }
    // Function you want to call manually after form submission
    function handleEvent(...) {
      // Everything else you were previously handling in handleClientLoad
    }
</script>
<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>


Brendan O'Brien | Software Engineer | obr...@google.com | 650.450.4134


Dan Zoll

unread,
Jan 25, 2013, 3:07:53 PM1/25/13
to google-api-jav...@googlegroups.com
Brendan: Thanks a lot for the help. I'm off now, but I'll give your
suggestions a shot on Monday. Thanks again.--Dan.

Brendan O'Brien

unread,
Jan 25, 2013, 3:30:43 PM1/25/13
to google-api-jav...@googlegroups.com
You're welcome, and good luck!


Brendan O'Brien | Software Engineer | obr...@google.com | 650.450.4134


Dan Zoll

unread,
Jan 29, 2013, 8:43:16 AM1/29/13
to google-api-jav...@googlegroups.com
Brendan: I got my app working thanks to your help. Didn't understand how Javascript was working there.

I have a couple other problems. Don't know if you're the right person to ask, but here goes.

My app works as long as it's me running it. I believe I read that the client ID or API key (or both) is tied to my Google account. The thing is, my app will be used  by staff, so it can't be joined to me.

I have another Google ID I use to send emails from my CRM system. I'm thinking I can create another project using that ID and use its credentials to run the app. I'll give staff the password, so they'll be able to validate when it prompts for their logon.

Does that sound like it would work? Is there any other, less clunky way?

One other small problem I have: Although my code is mostly based on the Google sample code I mentioned earlier, the 2 functions I use execute twice each. No idea why; do you know why? The second function, which adds the event, would create 2 events each time. I hacked around the problem by adding a counter and allowing it to run only once, but I wouldn't mind a better solution. Anyway, here's the app's code:

<html><body><input type=button name=authorize-button id=authorize-button value='Click to log on'/>
<link rel=stylesheet type=text/css href=mmwstyle2.css>

<%
LibraryID=session("LibraryID")
TabSelected=session("TabSelected")
EventTitle=session("EventTitle")
EventDescription=session("EventDescription")
EventLocation=session("EventLocation")
EventDate=session("EventDate")

%>

<script type='text/javascript'>
    var clientId = [secret]
    var apiKey = [secret]
    var EventTitle='<%=EventTitle%>'
    var EventDescription='<%=EventDescription%>'
    var EventLocation='<%=EventLocation%>'
    var EventDate='<%=EventDate%>'

function handleClientLoad() {
    gapi.client.setApiKey(apiKey);
    window.setTimeout(checkAuth, 1);
    checkAuth();
}

function checkAuth() {
    gapi.auth.authorize({ client_id: clientId, scope: scopes, immediate: true },
      handleAuthResult);
}

function handleAuthResult(authResult) {
    var authorizeButton = document.getElementById('authorize-button');
    if (authResult) {
        authorizeButton.style.visibility = 'hidden';
        makeApiCall1();
    } else {
        authorizeButton.style.visibility = '';
        authorizeButton.onclick = handleAuthClick;t
    }
}

function handleAuthClick(event) {
    gapi.auth.authorize(
      { client_id: clientId, scope: scopes, immediate: false },
      handleAuthResult);
    return false;
}

var HasEvent = 0

function makeApiCall1() {
    gapi.client.load('calendar', 'v3', function() {
        var request = gapi.client.calendar.events.list({
            'calendarId': [secret]
        });

        request.execute(function(resp) {
            for (var i = 0; i < resp.items.length; i++) {
                //                var li = document.createElement('li');
                //                li.appendChild(document.createTextNode(resp.items[i].summary));
                //                document.getElementById('events').appendChild(li);
                if (resp.items[i].summary == EventTitle && resp.items[i].date == EventDate) HasEvent = 1;
            }
            if (HasEvent == 0) makeApiCall2();
        });
    });
}

var Count = 0;  // for some odd reason, functions want to execute twice! So I check for the 2nd time

function makeApiCall2() {
    Count += 1;
    if (Count == 1) {
        var resource = {
        "summary": EventTitle,
            "location": EventLocation,
            "description": EventDescription,
            "start": {
                "date": EventDate
            },
            "end": {
                "date": EventDate
            }
        };

        gapi.client.load('calendar', 'v3', function() {
            var request = gapi.client.calendar.events.insert({
                'calendarId': [secret],
                'resource': resource
            });

            request.execute(function(resp) {
                console.log(resp);
            });
        });
    }
}
</script>
<script type="text/javascript" src="http://www.google.com/jsapi?key=[secret]"></script>
<p>Event created! <a href=allsales.asp?ShowLibrary=<%=LibraryID%>&tabselected=<%=tabselected%>>Continue</a></p>
</body></html>
Reply all
Reply to author
Forward
0 new messages