Activate your free membership today | Log-in

Thursday, August 28th, 2008

GALGWT 1.0… it isn’t a land next to Mordor

Category: GWT, Gears, Google

GWT has long had a project that aimed to give rich support for Google APIs called GALGWT, or “Google API Libraries for Google Web Toolkit”.

This project has stepped up to higher gear recently, and we have seen the GALGWT 1.0 release candidate appear.

What is in GALGWT?

The project is a collection of libraries that provide Java language bindings
and API specific ‘plumbing’ for some Google JavaScript APIs. The goal is to
make it easy for developers to use these JavaScript APIs with GWT. Libraries
available at this time include a new version of Gears, as well as new
libraries for Gadgets and the Google AJAX Search API.

Gears 1.1 Library

A new version of the Gears library is available. In addition to the earlier
version’s support for the Gears LocalServer, Database, and WorkerPool, 1.1
adds integrated support for offline applications and updated sample
applications. The bindings have also been refactored to use GWT 1.5
JavaScript overlay types and a new package hierarchy.

Gadgets 1.0 Library

The Gadgets library simplifies gadget development with GWT by automatically
generating a Gadget specification from Java source and inserting a selection
script in the specification much like a regular GWT project. After compiling
your gadget with GWT, all files are in place to publish your gadget. This
version currently supports the legacy Gadgets API based on the _IG_…
namespace.

Google AJAX Search 1.0 Library

The Google AJAX Search API lets you put Google Search in your web pages,
including Web, Local, and Multimedia searches. This library allows you to
access the API from Java code compiled with the GWT compiler without having
to write additional JavaScript code.

Posted by Dion Almaer at 5:45 am
Comment here

++++-
4 rating from 5 votes

Wednesday, August 27th, 2008

YouTube Uploader now using Gears, and what people missed in Gears 0.4

Category: Gears

While we posted about the Gears 0.4 features a lot of the press only really talked about the Geolocation piece.

I think that is important, and posted on that too, but Brad's piece discussed the full gamut including the Blob API, resummable HTTP, and Desktop API improvements to allow controlled file system access. The example that Brad built was the upload movie tool which ties this all together.

Check out the source code and you will see the parts and pieces in action:

Geolocation

JAVASCRIPT:
  1.  
  2. MovieTool.prototype.getLocation = function(callback) {
  3.   var geolocation = google.gears.factory.create('beta.geolocation');
  4.   if (!geolocation.getPermission('Upload Movie Tool', '',
  5.                                   'This sample can use your '
  6.                                 + 'geographic coordinates in order to tag '
  7.                                 + 'uploaded videos with your location')) {
  8.     document.getElementById('location').innerHTML = 'Permission denied';
  9.     callback();
  10.     return;
  11.   }
  12.  
  13.   var self = this;
  14.   geolocation.getCurrentPosition(
  15.     function(p) {
  16.       var addr = p.gearsAddress;
  17.       var address = addr.city + ', ' + addr.region + ', ' + addr.country;
  18.       var latitude = p.latitude;
  19.       var longitude = p.longitude;
  20.       self.geoAddress_ = address + ' (' + latitude + ', ' + longitude + ')';
  21.       document.getElementById('location').innerHTML = self.geoAddress_;
  22.       callback();
  23.     },
  24.  
  25.     function(err) {
  26.       var msg = 'Error retrieving your location: ' + err.message;
  27.       document.getElementById('location').innerHTML = msg;
  28.       callback();
  29.     },
  30.    
  31.     {
  32.       enableHighAccuracy: true,
  33.       gearsRequestAddress: true,
  34.       gearsLocationProviderUrls: ['http://www.google.com/loc/json']
  35.     }
  36.   );
  37. }
  38.  

HTTPRequest

JAVASCRIPT:
  1.  
  2.   var req = google.gears.factory.create('beta.httprequest');
  3.   req.open('GET', '/list');
  4.   var self = this;
  5.   req.onreadystatechange = function() {
  6.     if (req.readyState == 4) {
  7.       if (req.status == 200) {
  8.         var loadingMsg = document.getElementById('loadingFilesMsg');
  9.         loadingMsg.parentNode.removeChild(loadingMsg);
  10.         self.movieList_ = eval(req.responseText);
  11.         for (var i = 0; i <self.movieList_.length; i++) {
  12.           var entry = self.movieList_[i];
  13.           // associative entry for fast lookup based on filename
  14.           self.movieList_['_' + entry.filename] = entry;
  15.           var status = 'Uploaded'
  16.           var percent = '100%';
  17.          
  18.           // was this movie partially uploaded during an earlier browser
  19.           // session?
  20.           if (entry.uploaded == false && entry.blob == null) {
  21.             status = 'Partially uploaded; re-select file to continue uploading';
  22.             percent = Math.round((entry.bytesUploaded / entry.length) * 100) + '%';
  23.           }
  24.          
  25.           // is this movie too large?
  26.           if (entry.uploaded == false && entry.length> self.MAX_FILE_SIZE) {
  27.             status = 'File too large';
  28.             percent = 'N/A';
  29.           }
  30.          
  31.           self.drawRow(entry.filename, entry.geoAddress, status, percent);
  32.         }
  33.       }
  34.      
  35.       callback();
  36.     }
  37.   }
  38.  
  39.   req.send();
  40. }
  41.  
  42. ....
  43.  
  44. // sending a piece
  45.   req.open('POST', uploadURL);
  46.  
  47.   req.setRequestHeader('Content-Disposition',
  48.                         'attachment; filename="' + fileName + '"');
  49.   req.setRequestHeader('Content-Type', 'application/octet-stream');
  50.   req.setRequestHeader('Content-Range', 'bytes ' + byteRange);
  51.  
  52.  

Desktop API

JAVASCRIPT:
  1.  
  2. MovieTool.prototype.selectFiles = function() {
  3.   var desktop = google.gears.factory.create('beta.desktop');
  4.   var self = this;
  5.   desktop.openFiles(
  6.     function(files) {
  7.       for (var i = 0; i <files.length; i++) {
  8.         var entry = {filename: files[i].name, uploaded: false,
  9.                             length: files[i].blob.length,
  10.                             blob: files[i].blob, bytesUploaded: 0,
  11.                             geoAddress: self.geoAddress_, uploadRetries: 0};
  12.         if (self.movieList_['_' + entry.filename]) {
  13.           // was previously uploaded at an earlier browser session
  14.           var oldEntry = self.movieList_['_' + entry.filename];
  15.           if (!oldEntry.uploaded) { // partial upload
  16.             oldEntry.length = entry.length;
  17.             oldEntry.blob = entry.blob;
  18.             var percent = Math.round((oldEntry.bytesUploaded / oldEntry.length) * 100);
  19.             self.updateStatus(oldEntry.filename, 'Not uploaded', percent + '%');
  20.           } else {
  21.             self.updateStatus(oldEntry.filename, 'Uploaded', '100%');
  22.           }
  23.         } else { // new file
  24.           // associative entry for fast lookup based on filename
  25.           self.movieList_['_' + entry.filename] = entry;                   
  26.           self.movieList_.push(entry);
  27.          
  28.           var status = 'Not uploaded';
  29.           var percent = '0%';
  30.           // is this movie too large?
  31.           if (entry.length> self.MAX_FILE_SIZE) {
  32.             status = 'File too large';
  33.             percent = 'N/A';
  34.           }
  35.          
  36.           self.drawRow(files[i].name, self.geoAddress_, status, percent);
  37.         }
  38.       }
  39.      
  40.       document.getElementById('movieUpload').disabled = false;
  41.       document.getElementById('clearMovies').disabled = false;
  42.     },
  43.    
  44.     { filter: ['video/quicktime', '.wmv', 'video/avi'] }
  45.   );
  46. }
  47.  

It turns out that YouTube has implemented a multifile upload using Gears which puts this into practice. As someone who uses YouTube a lot to upload files this is very welcome indeed, and I can't wait to see more sites use it now the building blocks are there in a different way (can always use Flash / other controls in the past).

Posted by Dion Almaer at 9:20 am
2 Comments

++++-
4.2 rating from 11 votes

Tuesday, August 26th, 2008

navigator.geolocation: Using the W3C Geolocation API today

Category: Gears, Google, JavaScript, Mapping, Standards

Last week I wrote a simple WhereAreYou? application that used the Google Ajax APIs ClientLocation API to access your location via your IP address.

At the same time, we announced support for the Gears Geolocation API that can calculate your address using a GPS device, WiFi info, cell tower ids, and IP address lookups.

Add to all of that, the W3C Geolocation API that Andrei Popescu of the Gears team is editing. You will notice that it looks similar to the Gears API, with subtle differences. The ClientLocation API is quite different.

To make life easier, I decided to put together a shim called GeoMeta that give you the W3C Geolocation API, and happens to use the other APIs under the hood.

If you have the Geolocation API native in your browser (no one does yet, future proof!) that will be used. If you have Gears, that API will be used, and finally, with nothing the ClientLocation API will be used behind the scenes.

To you the API will look similar:

// navigator.geolocation.getCurrentPosition(successCallback, errorCallback, options)
navigator.geolocation.getCurrentPosition(function(position) {
      var location = [position.address.city, position.address.region, position.address.country].join(', ');
      createMap(position.latitude, position.longitude, location);
}, function() {
      document.getElementById('cantfindyou').innerHTML = "Crap, I don't know. Good hiding!";
});

At least, that is what I would like. Unfortunately, there are a few little differences that leak through.

  • The W3C API only seems to give you a lat / long, so you have to do the geocoding to get address info
  • The Gears API gives you an additional gearsAddress object attached to the resulting position object. This can contain a lot of information on the resulting area (street address to city to ...) however for certain providers the API returns that as null, the same as the W3C standard
  • That gearsAddress object has slightly different information from the address data that the ClientLocation API returns. NOTE: I would love to see this just called 'address' to help the shim.

To give you control when you need it, you can ask the navigator.geolocation object what type it is. navigator.geolocation.type will be null if it is native, but 'Gears' or 'ClientLocation' if a shim kicks in. You can also check navigator.geolocation.shim to see if it is augmented code.

Implementation

There is some fun implementation code in there if you poke around. For example, for the ClientLocation API, when you make a call, it will be added to a queue if the Google Loader hasn't fully loaded yet, and it will kick off that call when finished. Dealing with dynamically creating <script src> as a loading mechanism sure is fun!

I like the idea of jumping straight to the W3C standard and updating the shim as the APIs change. That way, when browsers catch up, the code will still work using the native APIs and you don't have to change a thing.

I also hope that we get general reverse geocoding in place, which would enable me to even take the native "standard" and strap on useful address info to the bare bones lat/long.

Where are you?

Posted by Dion Almaer at 9:14 am
5 Comments

+++--
3.9 rating from 15 votes

Friday, August 22nd, 2008

Gears 0.4 + Mashup of Gears and Google App Engine

Category: Announcements, Gears, Screencast

Hi folks, this is my first guest blog post here on Ajaxian. It's great to join the team.

Gears, the open source browser plugin that teaches web browsers new tricks, has pushed out a new 0.4 release

Andrei Popescu from the Gears team lets us in on some of the nifty new features:

We have added a new Geolocation API, which allows you to build applications that can do new and exciting things based on your users' location. You can query Gears for the user's current location using the getCurrentPosition() method or you can ask Gears to notify you every time the location changes, using the watchPosition() method. Of course, we take privacy issues very seriously, which is why we have a special permission dialog that allows users to decide which Web sites should have access to their location information. If you want to learn more about how the Geolocation API works, please see the Google Code blog post.

In addition, Gears now makes uploading large and multiple files on the web much easier, giving you the primitives to roll a resumable uploader, which means hopefully we can see custom desktop uploaders go away soon. In addition, Gears 0.4 introduces a new thing called Blobs:

Another cool new feature is the Blob API. Unlike strings, blobs let you reference arbitrary binary data — a first for JavaScript! Therefore, blobs can more naturally represent things like files and images, and they can be passed around efficiently. We have updated several existing APIs to work with blobs, such as WorkerPool sendMessage() and HttpRequest send(). And that's not all! We have also extended the Desktop API with a new method, openFiles(), which allows users to select multiple files of a particular content type, and then returns them as blobs for easy uploading or worker processing.

As a final note, Gears is continuing to push new features and experiments like the Geolocation API into the standards process:

Finally, an update on how we are doing on Web standards: in line with our earlier promises, the Geolocation API is a W3C Editor's draft and its current design is a result of open collaboration with many other people and organizations. We plan to continue to drive this standardization effort, as well as work with the community on new Web standards.

I decided to give the new Gears 0.4 APIs a roll to illustrate how powerful they are when put together, mashing them up to create a sample application. In addition, I needed a server-side implementation, so I created a Python server-side that runs on Google App Engine. This mashup is named Upload Movie Tool (not the most creative name, I know ;)

This demo allows you to select multiple movies, and then upload them in a resumable way with feedback using the Gears Blob and File System API. We also use the Geolocation API to figure out what your location is for tagging the video, and the Google App Engine to store everything on the back-end.

Give the demo a try yourself, or check out its source code (see the client JavaScript and the Google App Engine Python). This code is open source so you can feel free to use it as the basis of your own Gears-based resumable uploader/geolocation app.

I put together a screencast where I run through the application. There is a bonus if you make it all the way to the end, with videos showing Dion and I using the new slide that was installed last week in the Google San Francisco office!


 
Disclosure: I work for Google

Posted by Brad Neuberg at 9:50 am
Comment here

++++-
4.4 rating from 15 votes

Friday, August 8th, 2008

Tombs of Asciiroth: GWT, Gears, and AIR enabled RPG Game

Category: Adobe, Games, Gears

Alx Dark has created The Tombs of Asciiroth a fully functional roguelike-meets-puzzle-arcade game.

Asciiroth is a a complete, functional, open source game, written using GWT, and distributed either as an Adobe AIR application, or as a game you can play over the web. In the latter case, it uses Gears to provide saved game support. (So bottom line is you can play it using AIR or Firefox... IE is too slow, Opera/Safari aren't supported by Gears.) It also has a map editor that is distributed as an Adobe AIR application.

It is very cool to see applications written using Ajax, and then using both Gears for in-browser functionality, and AIR for desktop deployment.

Posted by Dion Almaer at 6:22 am
1 Comment

++++-
4.2 rating from 16 votes

Tuesday, July 15th, 2008

PubTools Search: Fast client-side searching with Gears

Category: Dojo, Gears, Interview

Brad Neuberg has built a very easy to use client side search tool called PubTools Search using Gears. The project is open source and provides a great avenue to share knowledge on Gears itself.

To accompany the code, Brad wrote a detailed article:

Did you know that you can use Gearsto do fast, client-side searching of data, similar to a client-side search engine? Gears bundles Full-Text Search (FTS) abilities right into its local, SQLite database. MySpace, for example, uses this feature with their MySpace Mail application, downloading all of a user's messages for fast, client-side search. Because all of the data is local, you can do nifty things like search over the data in real-time as the user types, something that is much harder if you have to query over the network to a server to do the searching.

Would you like to add the same kind of fast, local searching to your own web page and web applications? This article introduces you to PubTools Search and the Gears features that power it, namely Full-Text Search and Workers. PubTools Search is an open source JavaScript library that drops a client-side search engine right into your page. You configure it with basic HTML plus a list of URLs to index. Once loaded, a search form that uses the local Gears full-text search abilities will appear in your page to quickly and locally search over the documents in real time as a user types into the search field.

Brad sat down with me to discuss the project, some of the best practices, and his use of Dojo.

Posted by Dion Almaer at 9:37 am
Comment here

+++--
3.6 rating from 21 votes

Monday, July 14th, 2008

Interview with the Gears on Rails team

Category: Gears, JavaScript, Podcasts, Rails, Ruby

With my Google hat on, I got to interview Michael Marcus and Rui Ma, two recent graduates from a masters program at NYU. They joined me to discuss Gears on Rails, their open source framework that makes it easier than ever to take a Rails code-base offline.

They take the approach of giving you a high level Ruby-ish way of developing your Rails app and having it work offline against local storage.

This means that you end up building actions like this:

RUBY:
    def create_local
     '
       post = Post.build(params("post"));
       Post.create_local(post);
       window.location.reload( false );
     '
    end

They build the local framework on the Jester framework that is a "JavaScript client for REST APIs that uses Rails conventions, and is inspired by Rails' own ActiveResource".

This means that you can write client side code like this:

JAVASCRIPT:
  1.  
  2. Resource.model("Twitter", {format: "json", prefix: "http://www.twitter.com", urls: {list: "/statuses/user_timeline/:username.json"}})
  3.  
  4. Twitter.find("all", {username: "bob"}, function(results) {