Sunday, October 10, 2010

Google maps markers with numbers or text

This is a quick tip to add markers with numbers or text on demand to a Google Maps map.

The trick is replace the marker icon with a custom one that has the number/text on it, but the problem is how to do it on demand. Google charts dynamic icons has a simple interface to do this, by crafting simple urls it renders custom maps like markers. 

Some Examples:

  http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=X|ff776b
  http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=$|ff776b
  http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=-2|000000|ff0000
  http://chart.apis.google.com/chart?chst=d_map_xpin_icon&chld=pin|bank-dollar|52B552

Example marker code:

var image = 'http://chart.apis.google.com/chart?chst=d_map_xpin_icon&chld=pin|bank-dollar|52B552';
  var myLatLng = new google.maps.LatLng(-33.890542, 151.274856);
  var marker = new google.maps.Marker({
      position: myLatLng,
      map: map,
      icon: image
  });

You can see a complete example at http://studio.livemade.com/media/demo/marker.html

Have Fun, Sebastián

Reference:

http://code.google.com/apis/chart/docs/gallery/dynamic_icons.html

http://code.google.com/apis/maps/documentation/javascript/overlays.html#Icons

Sunday, October 3, 2010

Facebook login on iphone/phonegap

This is an approach to login with facebook in a phonegap iphone application, using the ChildBrowser plugin.

The technique is inspired from the facebook desktop authentication http://developers.facebook.com/docs/authentication/desktop

Briefly, the application opens a ChildBrowser with the facebook oauth page, setting the redirect_url to a blank page hosted by facebook. After that, every time the browser url changes, it checks if the url is the login success page, then extracts the token from the url to complete the authentication, which is done server side with a python/django service. To the code:

Install ChildBrowser plugin:  

  • Download the childbrowser plugin from http://github.com/purplecabbage/PhoneGap-Plugins
  • Install it, drag and drop the files under ChildBrowser/iPhone/ to the plugins folder on your xcode project; this should do the trick.
  • Put the file ChildBrowser.js inside the www folder

The html and js part:

  • Include the ChildBrowser.js in the head of the index.html file after the phonegap.js
...
<script src="phonegap.js" type="application/x-javascript" charset="utf-8"></script>
<script src="ChildBrowser.js" type="application/x-javascript" charset="utf-8"></script>
...

  • Add facebook login button that fires onPubFacebookBtn(), something like :
<a href="onPubFacebookBtn()">facebook login</a>
  • Add the following js code (the interesting part):
<script type="application/x-javascript" charset="utf-8">
    function onPubFacebookBtn(){ 
        /* On Facebook Login */
        var my_client_id  = "REPLACE_WITH_YOUR_FACEBOOK_APP_ID",
        my_redirect_uri   = "http://www.facebook.com/connect/login_success.html",
        my_type           = "user_agent",
        my_display        = "touch"

        var authorize_url  = "https://graph.facebook.com/oauth/authorize?";
        authorize_url += "client_id="+my_client_id;
        authorize_url += "&redirect_uri="+my_redirect_uri;
        authorize_url += "&display="+my_display;
        authorize_url += "&scope=publish_stream"

        client_browser = ChildBrowser.install(); 
        client_browser.onLocationChange = function(loc){ facebookLocChanged(loc); };
        if(client_browser != null) {  window.plugins.childBrowser.showWebPage(authorize_url); }
    }

    function facebookLocChanged(loc){
       /* Here we check if the url is the login success */
       if (/login_success/.test(loc)) { 
           var fbCode = loc.match(/code=(.*)$/)[1]
           /* I complete the login server side, but you could use the facebook js sdk */
           $.ajax({
              url: 'http://localhost:8000/api/login/facebook/', 
              dataType: 'jsonp',
              type: 'GET',
              data: {code: fbCode},
              success: function(data, textStatus) {
                  if (data['success']) {
                    localStorage.facebook_token = data['token']; /* store the token */
                    client_browser.close();
                    jQT.goTo('#home');
                  } else {
                      client_browser.close();
                  }
              },
              error: function(XMLHttpRequest, textStatus, errorThrown) {
                  alert(textStatus);
                  jQT.goTo('#home');
              }
           });
       }
    }


</script>

Python/Django service side code:

import urllib
import cgi

from django.utils import simplejson

def json_response(params, data):
    """
        Helper to handle JSON/JSONP calls
    """
    data = simplejson.dumps(data)
    if params.has_key('callback'):
        response = "%s(%s)" % (params['callback'], data)
        return HttpResponse(response, mimetype="application/javascript")
    return HttpResponse(data)

def login_facebook(request):
    try:
        code = urllib.unquote(request.GET['code']).replace("%7C", "|")
    except KeyError:
        return json_response(request.GET, {'success': False, 'message': 'code is required'})

    args = {
        "client_id": FACEBOOK_API_ID,
        "client_secret": FACEBOOK_API_SECRET,
        "redirect_uri": "http://www.facebook.com/connect/login_success.html",
        "code": code
    }
    args = urllib.urlencode(args)
    response = urllib.urlopen("https://graph.facebook.com/oauth/access_token?%s" % args).read()
    response = cgi.parse_qs(response)
    access_token = response["access_token"][-1]

    # Download the user profile
    args = urllib.urlencode(dict(access_token=access_token)
    profile = simplejson.load(urllib.urlopen("https://graph.facebook.com/me?%s" % args)))
    
    return json_response(request.GET, {'success': True, 'token': access_token, 'profile': profile})

Cheers, Sebastian Serrano