360-320-6221 caperren@caperren.com

Part 3 – Source Restructuring / First Features

Prev    Next

Now it’s time to actually show some useful information from this API. This will be a simple demo on how to formulate requests, parse the responses, and show that info on a simple web page. I’ve also split the previous example into three new files, index.html, style.css, and app.js to keep things a bit cleaner. Also, this page has some styling to make it look decent. If you’d like to download the code I used for this page, click HERE. If you got the last page’s example working, these should work for you as well. Just make sure and put in your own client ID! To start off, take a look at the images below to see what this new webpage does.

As you can see, things look a lot nicer. Other than these visual changes, the first thing you’ll notice is that once logged in there is now a sidebar with some common google drive information, including a picture of yourself. Here, I used the Google API Explorer to find out what options were available for me to query drive for. The sidebar information was all pulled using the ‘drive.about.get’ option. Also, once the page has loaded, if you go and edit some files in google drive, then hit the update button, it will list all the files that you changed since the page loaded, or the button was last pressed. If no changes were made, it tells you so. Anyways, let’s start by covering the changes to get user data.

function populate_user_data(){
    var request = gapi.client.drive.about.get({
        'fields': "user, storageQuota/usage, storageQuota/limit"
    });

    request.execute(function(resp) {
        var user_image = document.getElementById('user_image');
        var full_name = document.getElementById('full_name');
        var email_address = document.getElementById('email_address');
        var total_storage = document.getElementById('total_storage');
        var total_used = document.getElementById('total_used');
        var percent_used = document.getElementById('percent_used');

        user_image.src = get_full_res_profile_link(resp);
        full_name.textContent = resp.user.displayName;
        email_address.textContent = resp.user.emailAddress;
        total_storage.textContent = (resp.storageQuota.limit/1073741824).toFixed(2) + " GB Total";
        total_used.textContent = (resp.storageQuota.usage/ 1073741824).toFixed(2) + " GB Used";
        percent_used.textContent = ((resp.storageQuota.usage/resp.storageQuota.limit)*100).toFixed(0) + "% Used"

    });
}

The new and important aspect of this block of code is to notice that my ‘fields’ option as part of the request is different than the last example as well as the fact that I’m now querying ‘drive.about’. These new options came from looking at the fields editor on the API explorer, which lists all the available properties you can request. Here, it’s easy to see that all I’m doing is requesting user data and quotas and applying that textual data (after some conversion to nicer values for humans) to predefined paragraphs in my html file. The get full res profile function may seem strange, but was necessary if I wanted to get an image bigger than 64px by 64px. It essentially parses the link from the response and replaces a ‘s64’ with an ‘s0’ to give me a larger image to display.

function get_start_token(){
    gapi.client.drive.changes.getStartPageToken({}).then(function(resp){
        current_start_page_token = resp.result.startPageToken;
    });
}

function show_recent_changes(){
    gapi.client.drive.changes.list({
        'pageToken': current_start_page_token
    }).then(function(resp) {
        current_start_page_token = resp.result.newStartPageToken;

        var recent_changes = resp.result.changes;

        var listing_div = document.getElementById('listing_div');
        listing_div.innerHTML = '';


        if(recent_changes.length > 0) {
            var new_table = document.createElement('table');
            new_table.className = 'results_table';

            var new_thead = new_table.createTHead();
            var new_tbody = new_table.createTBody();
            var head_tr = new_thead.insertRow(0);


            head_tr.insertCell(0).textContent ="File Name";
            head_tr.insertCell(1).textContent = "When Changed";

            for (var x in recent_changes) {
                var curr_row = new_tbody.insertRow(x);
                curr_row.insertCell(0).textContent = recent_changes[x].file.name;
                curr_row.insertCell(1).textContent = recent_changes[x].time;
            }

            new_table.appendChild(new_thead);
            new_table.appendChild(new_tbody);

            new_table.style.border = '1px solid #e6e6e6';

            listing_div.className = 'drive_listing_div';
            listing_div.appendChild(new_table);

        }else{
            var new_par = document.createTextNode("No Recent Changes...");
            listing_div.appendChild(new_par);
        }

    });
}

Now for the listing of files that have changed, a bit more work is needed. Firstly, the function get_start_token is called when the page successfully authenticates. This requests a token from Drive that basically corresponds to a global revision status of the drive. So for example, if you have a new drive with nothing in it it might return a token of 0. Then, you add a file and now this function would return a 1. Change the name of the file, and it’s now 2.

So, by getting the token when the page starts, when the next function is run after hitting the button, the “current token” is sent off. If Google notices that the server token is different than the one I sent it, it sends back the changes that got me to the current token, and what the new token is. Then, it’s just a simple matter of parsing the data out. Here, after I’ve parsed the data, I format it into a table with headers to make things look nicer.

However, before I leave this code block behind, you might have noticed that instead of formulating a request, executing it, and using an inline callback, I’m doing something different here. What’s happening is that I’m calling the same function I was before when getting ready to make a request, but I’m immediately attaching a ‘.then(….)’ to it. What’s happening is called a promise in javascript. It’s another way of doing asynchronous callbacks, and is in fact the preferred method for Google API’s. The “request.execute” method is depreciated, so I wanted to show an example of their suggested method. Other than how it’s called, it pretty much works the same way, so don’t worry. Okay, onwards to the JSON response.

{
 "kind": "drive#changeList",
 "newStartPageToken": "1281063",
 "changes": [
  {
   "kind": "drive#change",
   "fileId": "0B45MBnGjUTjIUDVXdERRTE5RZ2s",
   "removed": false,
   "time": "2016-03-09T08:00:29.619Z",
   "file": {
    "kind": "drive#file",
    "id": "0B45MBnGjUTjIUDVXdERRTE5RZ2s",
    "name": "sdfgsdfg",
    "mimeType": "application/vnd.google-apps.folder"
   }
  },
  {
   "kind": "drive#change",
   "fileId": "0B45MBnGjUTjIRmFsR29wUk1nYjg",
   "removed": false,
   "time": "2016-03-09T08:00:32.192Z",
   "file": {
    "kind": "drive#file",
    "id": "0B45MBnGjUTjIRmFsR29wUk1nYjg",
    "name": "asdf.txt",
    "mimeType": "text/plain"
   }
  }
 ]
}

Here, we can see the raw JSON returned from the API after I deleted a folder called “sdfgsdfd” (oh, the fun button mashing names) with a file inside of it called “asdf.txt”. Inside of the response is a ‘changes’ array that contains a listing of any changes made since the id of the last token. Naturally, if no changes were made, the size of this array is zero and we can handle it accordingly. The nextPageToken is in this block, and in my code I save it globally for the next button press. When there have been changes, we get an assortment of details about them including the name of the file, when it was changed, what kind of file it was, and a Google specific fileId that is useful for directly manipulating files using other Google APIs. Looking at my previous code block, I simply got this data by:

var recent_changes = resp.result.changes;

If you haven’t noticed already, the Google Drive API we’ve been using has been nice enough to handle turning the response into a javascript object for us. No work needed on our part other than to do something with the data. This concludes the direct examples I will be giving for the API. The last page will be some more explanation of the scopes available for the API, and how using them in conjunction with other Drive API calls that let you do more in depth navigation and editing. I’ve left out any examples that let a user modify or delete files just for safety sake. As you can see from my gallery above, I’d rather not lose 55GB of my most important data.