<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Chicken Scratches &#187; JavaScript</title>
	<atom:link href="http://www.chickenwingsw.com/scratches/category/javascript/feed" rel="self" type="application/rss+xml" />
	<link>http://www.chickenwingsw.com</link>
	<description>Developing ideas on developing.</description>
	<lastBuildDate>Fri, 22 Jul 2011 15:21:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Introducing Play Scopa: a new Scopa card game site</title>
		<link>http://www.chickenwingsw.com/scratches/programming/python/playscopa-co</link>
		<comments>http://www.chickenwingsw.com/scratches/programming/python/playscopa-co#comments</comments>
		<pubDate>Tue, 28 Sep 2010 18:06:51 +0000</pubDate>
		<dc:creator>Eddie Sullivan</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.chickenwingsw.com/scratches/uncategorized/introducing-playscopa-com-a-new-scopa-card-game-site</guid>
		<description><![CDATA[I have previously written about the Scopa game I developed for Facebook. Well, I became frustrated with the technical limitations of the Facebook canvas platform, and decided to move it off of Facebook onto its own site. So now you can practice your Italian and learn a new card game at www.playscopa.com. You can still [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.playscopa.com/"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="card-logo" border="0" alt="card-logo" align="right" src="http://www.chickenwingsw.com/wp-content/uploads/2010/09/cardlogo.png" width="300" height="212" /></a> I have previously written about the <a href="http://www.playscopa.com">Scopa</a> game I developed for <a href="http://www.facebook.com/">Facebook</a>. Well, I became frustrated with the technical limitations of the Facebook canvas platform, and decided to move it off of Facebook onto its own site. So now you can practice your Italian and learn a new card game at <a href="http://www.playscopa.com">www.playscopa.com</a>. You can still log in with your Facebook account, though.</p>  <p>If you’ve never heard of Scopa, it’s a fun Italian card game for two or more people. You can play with one of two gorgeous Italian decks of cards or a standard American deck with the face cards removed. There is a section on the site where you can <a href="http://www.playscopa.com/rules/">learn how to play Scopa</a> as well. You can practice by playing against the computer, and the game also has a “beginner” level where the computer will give you hints about what moves you can make next.</p>  <p>For my technical audience, the site is implemented in <a href="http://python.org/">Python</a> and <a href="http://www.djangoproject.com">Django</a> on the back end. The game play is completely handled in HTML and JavaScript, using the <a href="http://en.wikipedia.org/wiki/Comet_%28programming%29">Comet</a> technology for real-time player-to-player communication. The back end server is my custom-built Sully Server (soon to be released as open-source).</p>  <p>Enjoy, and go <a href="http://www.playscopa.com/">play Scopa</a>!</p>]]></content:encoded>
			<wfw:commentRss>http://www.chickenwingsw.com/scratches/programming/python/playscopa-co/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Making a Facebook app (with Django) &#8211; part 3: Python &amp; FBML</title>
		<link>http://www.chickenwingsw.com/scratches/programming/python/django-facebook-3</link>
		<comments>http://www.chickenwingsw.com/scratches/programming/python/django-facebook-3#comments</comments>
		<pubDate>Mon, 29 Sep 2008 21:17:57 +0000</pubDate>
		<dc:creator>Eddie Sullivan</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.chickenwingsoftware.com/?p=61</guid>
		<description><![CDATA[Welcome to the third part in my series of posts about creating a Facebook application. I am using Django as my web development framework, and this post will focus on some of the backend techniques I have worked out to make this work easier. This is not a tutorial, but a set of tools that [...]]]></description>
			<content:encoded><![CDATA[   <p>
      Welcome to the third part in my series of posts about creating a
      Facebook application. I am using Django as my web development
      framework, and this post will focus on some of the backend
      techniques I have worked out to make this work easier. This is
      not a tutorial, but a set of tools that I have developed. This
      is a long post, with a lot of source code; I hope you find at
      least some of it useful.
    </p>
    <p>
      Keep in mind as you read this that the Facebook platform is
      still very new, and likely to change. In fact, if you're a FB
      user, you are probably aware they recently completed a major
      transition to a new profile design. This included many changes
      behind the scenes for developers, some of which are still
      playing out. I recommend keeping up with
      the <a href="http://forum.developers.facebook.com/">Facebook
      Platform Developer Forum</a> and
      the <a href="http://developers.facebook.com/news.php?tab=blog">Facebook
      Developer Blog</a>.
    </p>
    <p>
      Also, I will assume you have already read
      the <a href="http://wiki.developers.facebook.com/index.php/API">API
      Documentation</a> and the documentation
      for <a href="http://wiki.developers.facebook.com/index.php/Python">PyFacebook</a>,
      and that you know how to create a web app
      using <a href="http://www.djangoproject.com">Django</a>. If not,
      you will want to start there.
    </p>
<span id="more-61"></span>
    <p>
      PyFacebook is very useful and includes some documentation on
      getting up and running with Django. You do still need an
      understanding of how Django works and how URLs are mapped.
    </p>
    <h4>
      My goal
    </h4>
    <p>
      My goal with these code snippets and techniques is to make
      developing a Facebook app as close as possible to developing a
      regular web app. The application I am using to develop and test
      these features is <a href="http://limericks.four32one.com">The
      Limerick Book</a>. Compare that page
      to <a href="http://apps.facebook.com/limericks">The Limerick
      Book Facebook App</a>. In fact, they are the same application,
      sharing the same code. I also have developed
      a <a href="http://apps.facebook.com/playscopa">multiplayer card
      game</a> based on the traditional Italian
      game <a href="http://apps.facebook.com/playscopa">Scopa</a>. This
      is a Facebook-only application, but I wanted to be able to test
      it outside of Facebook.
    </p>
    <p>
      Ideally, we would be able to write code and templates that can
      work equally well both inside Facebook and outside.  This is
      important even if you want users to only see your application
      within Facebook, because it makes testing infinitely easier. You
      want to be able to test on your local machine before publishing
      content, and you want to be able to test things out free from
      the limitations and frequent bugginess of the Facebook platform.
    </p>
    <h4>
      First steps
    </h4>
    <p>
      Here are some simple helper functions to make life as a Facebook
      Python developer easier.
    </p>
    <p>
      I am making a conscious decision here not to package all these
      helper functions into a downloadable library. My point here
      to <i>explain</i> code, rather than just hand it out. Many of
      these things are specific to my needs, and may not fit exactly
      what you want, so some tweaking may be required. I have most of
      these functions in a file called <i>fbUtil.py</i> that I import
      from most of my Django view code (except for the template tags,
      which need to be in a specific place, per Django). Feel free to
      do the same, or to copy and paste the code for your own use, but
      I recommend reading through the code, as your needs may not be
      the same as mine.
    <p>
      <b>inFb</b> is a simple function that takes a Request object and
      returns a boolean telling whether the request is taking place
      within the context of a Facebook canvas page.
    </p>
    <pre>
<span class="keyword">def</span> <span class="function-name">inFb</span>(request):
    <span class="keyword">return</span> (request.facebook <span class="keyword">and</span>
            (request.facebook.check_session(request) <span class="keyword">or</span>
             request.facebook.in_canvas))
</pre>
    <p>
      Once we have this, we can create some more useful functions.
    </p>
    <pre class="codeSnippet">
facebookUrl = settings.FACEBOOK_URL
<span class="keyword">def</span> <span class="function-name">fbReverse</span>(view, args=<span class="py-pseudo-keyword">None</span>, kwargs=<span class="py-pseudo-keyword">None</span>):
    '''<span class="string">
    Much like django.core.urlresolvers.reverse, except works
    in Facebook. Returns an absolute URL to a Facebook canvas
    page.
    </span>'''
    ret = reverse(view, args=args, kwargs=kwargs)
    <span class="keyword">return</span> facebookUrl + ret[1:] <span class="comment"># Remove leading slash
</span>
<span class="keyword">def</span> <span class="function-name">makeReverse</span>(request, view, args = <span class="py-pseudo-keyword">None</span>):
    '''<span class="string">
    Returns the URL of a the specified view, either in or out of Facebook.
    </span>'''
    <span class="keyword">if</span> inFb(request):
        <span class="keyword">return</span> fbReverse(view, args)
    <span class="keyword">return</span> reverse(view, args=args)

<span class="keyword">def</span> <span class="function-name">makeRedirect</span>(request, view, args = <span class="py-pseudo-keyword">None</span>, extra = ''):
    '''<span class="string">
    Returns a Response object for a HTTP redirect, either in or out of
    Facebook.
    </span>'''
    <span class="keyword">if</span> inFb(request):
        <span class="keyword">return</span> request.facebook.redirect(fbReverse(view, args) + extra)
    <span class="keyword">return</span> HttpResponseRedirect(reverse(view, args=args) + extra)
</pre>
    <p>
      These are designed to simplify URL calculations. See the
      comments in the code for explanations of what they do.
    </p>
    <pre class="codeSnippet">
<span class="keyword">def</span> <span class="function-name">makeResponse</span>(request, template, context, common=<span class="py-pseudo-keyword">False</span>):
    context['<span class="string">pageName</span>'] = template
    <span class="keyword">if</span> (<span class="keyword">not</span> common) <span class="keyword">and</span> inFb(request):
        tmpl = '<span class="string">fb/%s.fbml</span>' % template
    <span class="keyword">else:</span>
        tmpl = template + '<span class="string">.tmpl</span>'
    <span class="keyword">return</span> render_to_response(tmpl,
                              context,
                              context_instance=RequestContext(request))
</pre>      
    <p>
      This one is a little different, and may need updating depending
      on how your code is organized. I keep my templates in the
      directory 'mySite/myApp/templates' and give them names like
      'myTemplate.tmpl'. I put my Facebook-specific templates in the
      subdirectory called 'fb' and give them names like
      'myTemplate.fbml'. This function allows me to create two
      templates for a view: one for inside Facebook and one for
      outside. The function will detect which one to use and render it
      into a Response object. <b>request</b> is the Request object
      that is passed to the view function. <b>template</b> is a string
      holding the base-name of the template file, for example
      'myTemplate'. <b>context</b> is a dictionary with the template
      context variables. And if <b>common</b> is <b>True</b>, the
      function will use the main non-Facebook version of the template
      no matter what (because ideally we would be able to share even
      these as much as possible).
    </p>
    <p>
      One extra little bit that the function does is add an extra
      template variable called <b>pageName</b> with the base-name of
      the template. I find this useful for code re-use within
      templates, though it's not actually a Facebook-related feature.
    </p>
    <h4>
      Authentication
    </h4>
    <p>
      The next thing I wanted to do was to tie in Facebook's user
      information with Django's authentication mechanism. Depending on
      your application, you may or may not want to do this. If you
      want to remember information about user-contributed content, it
      is useful. The way I did it was to create a <i>UserProfile</i>
      model, tied in to the User model by a ForeignKey one-to-one
      relationship, and with a <b>facebookId</b> field (among other,
      app-specific fields). Then I created a Django authentication
      backend to allow authenticating by facebook ID. Here is my code
      for the authentication back end. If a user does not exist with
      the given facebook ID, a new one is created. (That, of course,
      may not be what you want, so you may have to modify that code.)
    </p>
    <p>
      This code assumes that Python's logging facilities have been set
      up, for error reporting.
    </p>
    <pre class="codeSnippet">
<span class="keyword">class</span> <span class="type">FacebookBackend</span>:
    '''<span class="string">
    Authenticate against Facebook.
    </span>'''

    <span class="keyword">def</span> <span class="function-name">authenticate</span>(<span class="py-pseudo-keyword">self</span>, facebookId=<span class="py-pseudo-keyword">None</span>):
        <span class="keyword">if</span> <span class="keyword">not</span> facebookId: <span class="keyword">return</span> <span class="py-pseudo-keyword">None</span>
        <span class="keyword">try:</span>
            profile = UserProfile.objects.get(facebookId=facebookId)
            UpdateFbUserDetails(profile.user, facebookId)
            <span class="keyword">return</span> profile.user
        <span class="keyword">except</span> UserProfile.DoesNotExist:
            <span class="comment"># No user. Create one.
</span>            <span class="keyword">pass</span>
        username = '<span class="string">fb_%s</span>' % facebookId
        <span class="keyword">try:</span>
            user = User.objects.get(username=username)
            <span class="comment"># This shouldn't really happen. Log an error.
</span>            logging.error('<span class="string">Strange: user %s already exists.</span>' % username)
        <span class="keyword">except</span> User.DoesNotExist:
            user = User.objects.create_user('<span class="string">fb_%s</span>' % facebookId, '')
        <span class="keyword">if</span> <span class="keyword">not</span> UpdateFbUserDetails(user, facebookId):
            <span class="keyword">return</span> <span class="py-pseudo-keyword">None</span>
        user.save()
        profile, created = UserProfile.objects.get_or_create(user=user)
        profile.facebookId = facebookId
        profile.save()
        <span class="keyword">return</span> user

    <span class="keyword">def</span> <span class="function-name">get_user</span>(<span class="py-pseudo-keyword">self</span>, user_id):
        <span class="keyword">try:</span>
            <span class="keyword">return</span> User.objects.get(pk=user_id)
        <span class="keyword">except</span> User.DoesNotExist:
            <span class="keyword">return</span> <span class="py-pseudo-keyword">None</span>

<span class="keyword">def</span> <span class="function-name">UpdateFbUserDetails</span>(user, fbId):
    """
<span class="string">    Fill in a user's first and last name, from Facebook.
    "</span>""
    <span class="keyword">if</span> (<span class="keyword">not</span> user.first_name) <span class="keyword">or</span> (<span class="keyword">not</span> user.last_name) :
        <span class="keyword">try:</span>
            fb = get_facebook_client()
            userDetails = fb.users.getInfo(fbId, ['<span class="string">last_name</span>', '<span class="string">first_name</span>'])
            user.first_name = userDetails[0]['<span class="string">first_name</span>'][:30]
            user.last_name = userDetails[0]['<span class="string">last_name</span>'][:30]
            user.save()
            <span class="keyword">return</span> <span class="py-pseudo-keyword">True</span>
        <span class="keyword">except</span> Exception, ex:
            logging.error('<span class="string">Error updating user: %s</span>' % ex)
            <span class="keyword">return</span> <span class="py-pseudo-keyword">False</span>
    <span class="keyword">return</span> <span class="py-pseudo-keyword">True</span>
</pre>
    <p>
      Now here is a function decorator you can use on your view
      functions. It will perform Facebook authentication if
      possible. It can also be used to require a login - either via
      Facebook or through a login page. With a parameter
      of <b>True</b>, it is equivalent to Django's
      built-in <b>login_required</b> decorator or to
      PyFacebook's <b>facebook.require_login</b> decorator, depending
      on whether the view is accessed inside or outside of Facebook.
    </p>
    <pre class="codeSnippet">
<span class="keyword">def</span> <span class="function-name">facebookView</span>(requireLogin=<span class="py-pseudo-keyword">False</span>):
    <span class="keyword">def</span> <span class="function-name">decorator</span>(func):
        <span class="keyword">def</span> <span class="function-name">wrapper</span>(request, *listArgs, **kwArgs):
            facebookLogin(request)
            fb = request.facebook
            <span class="keyword">if</span> requireLogin <span class="keyword">and</span> (<span class="keyword">not</span> request.user.is_authenticated()):
                <span class="keyword">if</span> inFb(request):
                    <span class="keyword">return</span> fb.redirect(fb.get_login_url(next=request.path))
                <span class="keyword">else:</span>
                    <span class="keyword">return</span> HttpResponseRedirect(settings.LOGIN_URL + '<span class="string">?next=%s</span>' % request.path)
            <span class="keyword">else:</span>
                <span class="keyword">return</span> func(request, *listArgs, **kwArgs)
        wrapper.__name__ = func.__name__
        wrapper.__doc__ = func.__doc__
        wrapper.__dict__ = func.__dict__
        wrapper.__module__ = func.__module__
        <span class="keyword">return</span> wrapper
    <span class="keyword">return</span> decorator

<span class="keyword">def</span> <span class="function-name">facebookLogin</span>(request):
    '''<span class="string">
    Attempt to login the user based on their Facebook credentials.
    Does nothing outside of Facebook.
    </span>'''
    facebook = get_facebook_client()
    <span class="keyword">if</span> (<span class="keyword">not</span> request.user.is_authenticated()) <span class="keyword">or</span> UserProfile.Get(request.user).facebookId != facebook.uid:
        <span class="keyword">if</span> request.facebook <span class="keyword">and</span> request.facebook.check_session(request):
            user = authenticate(facebookId=facebook.uid)
            login(request, user)
</pre>
    <p>
      And here is a very simple example of how to use it:
    </p>
    <pre class="codeSnippet">
@facebookView(<span class="py-pseudo-keyword">True</span>) <span class="comment"># Require login, in and out of Facebook
</span><span class="keyword">def</span> <span class="function-name">myView</span>(request):
    <span class="comment"># Put important view processing here.
</span>    <span class="keyword">return</span> makeResponse(request, '<span class="string">myTemplate</span>', {'<span class="string">templateVar</span>':'<span class="string">important data</span>'})
</pre>
    <h4>
      Templates
    </h4>
    <p>
      We are getting closer to the holy grail of being able to write
      one set of code that can run both in and out of Facebook. It
      would also be useful to be able to share templates, so I have
      worked out several mechanisms to facilitate this.
    </p>
    <h5>
      The Context Processor
    </h5>
    <p>
      Django has the useful concept of a "Context Processor," which
      allows pre-processing of a RequestContext object before the
      rendering of any template. I take advantage of this quite a
      bit. I already discussed the <b>cacheBreaker</b> variable in
      my <a href="http://www.chickenwingsoftware.com/scratches/python/django-facebook-2">post
      about Facebook and JavaScript</a>. Here are a couple more
      variables I've found useful:
    </p>
    <ul>
      <li>
	<b>fb</b> - The <i>facebook</i> object, for accessing the
	Facebook API, or <b>None</b> outside of Facebook.
      </li>
      <li>
	<b>profile</b> - The <i>UserProfile</i> object, if the user is
	logged in, or <b>None</b> otherwise.
      </li>
      <li>
	<b>baseTemplate</b> - The template to <i>extend</i> - either
	"base.tmpl" outside of Facebook or "fb/base.fbml" inside of
	Facebook.
      </li>
      <li>
	<b>loginRequired</b> - A useful string for including in
	hyperlinks. Within Facebook, it contains
	'loginrequired=true'. Outside of Facebook, it contains
	something like 'onclick="return checkLogin()"', which is some
	custom JavaScript to require the user to login before
	following the link. Of course, if the link already has an
	"onclick" event, this cannot be used.
      </li>
    </ul>
    <p>
      I'll leave it to you to write your custom template processor, as
      they can be very site-specific, but the above should get you
      started. Here
      is <a href="http://docs.djangoproject.com/en/dev/ref/templates/api/?from=olddocs#id1">Django's
      context processor documentation</a>.
    </p>
    <h5>
      Template tags
    </h5>
    <p>
      To allow more sharing, I've defined a couple of useful template
      tags. These must be defined in a file in a "templatetags"
      directory under your application directory, as described in
      the <a href="http://docs.djangoproject.com/en/dev//howto/custom-template-tags/#howto-custom-template-tags">Django
      custom tag and filter documentation</a>.
    </p>
    <p>
      The first is <b>fbUrl</b>. It is the equivalent of the built-in
      Django <b>url</b> tag, except that when used inside Facebook it
      produces an absolute link to the requested page within the
      context of the Facebook canvas. In fact, the code is copied
      directly from the Django implementation
      of <b>url</b>. <b>fbUrl</b> relies on the <b>fb</b> context
      variable, and the <b>fbReverse</b> function, as described above.
    </p>
    <pre class="codeSnippet">
<span class="keyword">from</span> django.template <span class="keyword">import</span> Node
<span class="keyword">class</span> <span class="type">FBURLNode</span>(Node):
    <span class="keyword">def</span> <span class="function-name">__init__</span>(<span class="py-pseudo-keyword">self</span>, view_name, args, kwargs):
        <span class="py-pseudo-keyword">self</span>.view_name = view_name
        <span class="py-pseudo-keyword">self</span>.args = args
        <span class="py-pseudo-keyword">self</span>.kwargs = kwargs

    <span class="keyword">def</span> <span class="function-name">render</span>(<span class="py-pseudo-keyword">self</span>, context):
        fb = template.Variable('<span class="string">fb</span>').resolve(context)
        <span class="keyword">if</span> fb:
            reverseFunc = fbReverse
        <span class="keyword">else:</span>
            reverseFunc = django.core.urlresolvers.reverse

        <span class="keyword">from</span> django.core.urlresolvers <span class="keyword">import</span> reverse, NoReverseMatch
        args = [arg.resolve(context) <span class="keyword">for</span> arg <span class="keyword">in</span> <span class="py-pseudo-keyword">self</span>.args]
        kwargs = <span class="py-builtins">dict</span>([(smart_str(k,'<span class="string">ascii</span>'), v.resolve(context))
                       <span class="keyword">for</span> k, v <span class="keyword">in</span> <span class="py-pseudo-keyword">self</span>.kwargs.items()])
        <span class="keyword">try:</span>
            <span class="keyword">return</span> reverseFunc(<span class="py-pseudo-keyword">self</span>.view_name, args=args, kwargs=kwargs)
        <span class="keyword">except</span> NoReverseMatch:
            <span class="keyword">try:</span>
                project_name = settings.SETTINGS_MODULE.split('<span class="string">.</span>')[0]
                <span class="keyword">return</span> reverseFunc(project_name + '<span class="string">.</span>' + <span class="py-pseudo-keyword">self</span>.view_name,
                                   args=args, kwargs=kwargs)
            <span class="keyword">except</span> NoReverseMatch:
                <span class="keyword">return</span> ''

<span class="keyword">def</span> <span class="function-name">fbUrl</span>(parser, token):
    """<span class="string">
    Just like Django's url tag, except also works inside Facebook.
    "</span>""
    bits = token.contents.split('<span class="string"> </span>', 2)
    <span class="keyword">if</span> <span class="py-builtins">len</span>(bits) &lt; 2:
        <span class="keyword">raise</span> TemplateSyntaxError("<span class="string">'%s' takes at least one argument</span>"
                                  "<span class="string"> (path to a view)</span>" % bits[0])
    args = []
    kwargs = {}
    <span class="keyword">if</span> <span class="py-builtins">len</span>(bits) &gt; 2:
        <span class="keyword">for</span> arg <span class="keyword">in</span> bits[2].split('<span class="string">,</span>'):
            <span class="keyword">if</span> '<span class="string">=</span>' <span class="keyword">in</span> arg:
                k, v = arg.split('<span class="string">=</span>', 1)
                k = k.strip()
                kwargs[k] = parser.compile_filter(v)
            <span class="keyword">else:</span>
                args.append(parser.compile_filter(arg))
    <span class="keyword">return</span> FBURLNode(bits[1], args, kwargs)
fbUrl = register.tag(fbUrl)
                        
</pre>
    <p>
      Next is <b>fbName</b>. This is to provide the same functionality
      as Facebook's <i>fb:name</i> FBML tag, except also useable
      outside of Facebook.
    </p>
    <p>
      The basic use of it looks like <i>{% fbName user %}</i>, where
      "user" is a template variable containing the user whose name to
      display. Then you can add options like <i>linked=false</i>,
      or <i>useyou=false</i>, as described in the Facebook
      documentation.
    </p>
    <p>
      Some differences from the FBML version are:
    </p>
    <ul>
      <li>
	<i>shownetwork</i>, <i>ifcantsee</i>, and <i>subjectid</i> are
	ignored outside of Facebook.
      </li>
      <li>
	<i>linked</i> behaves slightly differently. Outside of
	Facebook, or if its value is set to <i>internal</i>, the
	user's name will be linked to an app-specific profile
	page. The view for this page is specified in the
	variable <b>userProfileView</b>. The view is expected to take
	one parameter: the user ID.
      </li>
    </ul>
    <p>
      Here is the code:
    </p>
    <pre class="codeSnippet">
userProfileView = '<span class="string">userProfile</span>'
<span class="keyword">class</span> <span class="type">FbNameNode</span>(Node):
    <span class="keyword">def</span> <span class="function-name">__init__</span>(<span class="py-pseudo-keyword">self</span>, user, args, kwArgs):
        <span class="py-pseudo-keyword">self</span>.user = template.Variable(user)
        <span class="py-pseudo-keyword">self</span>.args = args
        <span class="py-pseudo-keyword">self</span>.kwArgs = kwArgs

    <span class="keyword">def</span> <span class="function-name">getBoolArg</span>(<span class="py-pseudo-keyword">self</span>, name, default=<span class="py-pseudo-keyword">False</span>):
        val = <span class="py-pseudo-keyword">self</span>.kwArgs.get(name, default)
        <span class="keyword">if</span> <span class="py-builtins">type</span>(val) <span class="keyword">is</span> <span class="keyword">not</span> bool:
            <span class="keyword">return</span> (val.lower() == '<span class="string">true</span>')
        <span class="keyword">return</span> val

    <span class="keyword">def</span> <span class="function-name">render</span>(<span class="py-pseudo-keyword">self</span>, context):
        user = <span class="py-pseudo-keyword">self</span>.user.resolve(context)
        fb = template.Variable('<span class="string">fb</span>').resolve(context)
        loggedInUser = template.Variable('<span class="string">user</span>').resolve(context)
        request = template.Variable('<span class="string">request</span>').resolve(context)
        <span class="keyword">if</span> fb:
            fbUserId = UserFbId(user)
            <span class="keyword">if</span> fbUserId:
                <span class="comment"># In Facebook
</span>                internalLink = <span class="py-pseudo-keyword">False</span>
                ret = '<span class="string">&lt;fb:name uid="%s" </span>' % fbUserId
                <span class="keyword">for</span> item, val <span class="keyword">in</span> <span class="py-pseudo-keyword">self</span>.kwArgs.items():
                    <span class="keyword">if</span> item == '<span class="string">linked</span>' <span class="keyword">and</span> val == '<span class="string">internal</span>':
                        internalLink = <span class="py-pseudo-keyword">True</span>
                        ret += '<span class="string">linked="false" </span>'
                    <span class="keyword">else:</span>
                        <span class="keyword">if</span> <span class="py-builtins">type</span>(val) <span class="keyword">is</span> bool:
                            <span class="keyword">if</span> val:
                                val = '<span class="string">true</span>'
                            <span class="keyword">else:</span>
                                val = '<span class="string">false</span>'
                        ret += '<span class="string">%s="%s" </span>' % (item, val)
                ret += '<span class="string">/&gt;</span>'
                <span class="keyword">if</span> internalLink:
                    ret = '<span class="string">&lt;a href="%s"&gt;%s&lt;/a&gt;</span>' % (fbReverse(userProfileView, [user.id]), ret)
                <span class="keyword">return</span> mark_safe(ret)
        <span class="comment"># Not in Facebook
</span>        <span class="keyword">if</span> <span class="py-pseudo-keyword">self</span>.getBoolArg('<span class="string">useyou</span>', <span class="py-pseudo-keyword">True</span>) <span class="keyword">and</span> user == loggedInUser:
            <span class="keyword">if</span> <span class="py-pseudo-keyword">self</span>.getBoolArg('<span class="string">capitalize</span>'):
                ret = '<span class="string">You</span>'
            <span class="keyword">else:</span>
                ret = '<span class="string">you</span>'
            <span class="keyword">if</span> <span class="py-pseudo-keyword">self</span>.getBoolArg('<span class="string">possessive</span>'):
                ret += '<span class="string">r</span>'
            <span class="keyword">elif</span> <span class="py-pseudo-keyword">self</span>.getBoolArg('<span class="string">reflexive</span>'):
                ret += '<span class="string">rself</span>'
            <span class="comment"># ES: How to handle subjectid?
</span>        <span class="keyword">else:</span>
            ret = UserDisplayName(user)
            <span class="keyword">if</span> <span class="py-pseudo-keyword">self</span>.getBoolArg('<span class="string">firstnameonly</span>'):
                ret = user.first_name <span class="keyword">or</span> user.username
            <span class="keyword">if</span> <span class="py-pseudo-keyword">self</span>.getBoolArg('<span class="string">lastnameonly</span>'):
                ret = user.last_name <span class="keyword">or</span> user.username
            <span class="keyword">if</span> <span class="py-pseudo-keyword">self</span>.getBoolArg('<span class="string">possessive</span>'):
                ret += "<span class="string">'s</span>"
        <span class="keyword">if</span> <span class="py-pseudo-keyword">self</span>.getBoolArg('<span class="string">linked</span>', <span class="py-pseudo-keyword">True</span>) <span class="keyword">or</span> <span class="py-pseudo-keyword">self</span>.kwArgs.get('<span class="string">linked</span>', <span class="py-pseudo-keyword">None</span>) == '<span class="string">internal</span>':
            ret = '<span class="string">&lt;a href="%s"&gt;%s&lt;/a&gt;</span>' % \
                (makeReverse(request, userProfileView, args=[user.id]),
                 ret)
        <span class="keyword">return</span> mark_safe(ret)
            

@register.tag
<span class="keyword">def</span> <span class="function-name">fbName</span>(parser, token):
    '''<span class="string">
    Returns the name for the given user, based on the parameters.

    Acts much like the fb:name FBML tag, except can work in or out of
    Facebook.
    </span>'''
    <span class="keyword">try:</span>
        bits = token.split_contents()[1:]
    <span class="keyword">except</span> ValueError:
        <span class="keyword">raise</span> template.TemplateSyntaxError, "<span class="string">%r tag requires at least 1 argument: the user (%s)</span>" %\
            (token.contents.split()[0], token.split_contents())
    args = []
    kwArgs = {}
    <span class="keyword">for</span> b <span class="keyword">in</span> bits:
        <span class="keyword">if</span> '<span class="string">=</span>' <span class="keyword">in</span> b:
            name,val = b.split('<span class="string">=</span>', 1)
            kwArgs[name.strip()] = val.strip()
        <span class="keyword">else:</span>
            args.append(b.strip())
    <span class="keyword">if</span> <span class="py-builtins">len</span>(args) &lt; 1:
        <span class="keyword">raise</span> template.TemplateSyntaxError, "<span class="string">%r tag requires at least one argument: the user</span>" %\
            token.contents.split()[0]

    <span class="keyword">return</span> FbNameNode(args[0], args[1:], kwArgs)

<span class="keyword">def</span> <span class="function-name">UserFbId</span>(user):
    <span class="keyword">try:</span>
        <span class="keyword">return</span> UserProfile.objects.get(user=user).facebookId
    <span class="keyword">except</span> UserProfile.DoesNotExist:
        <span class="keyword">return</span> <span class="py-pseudo-keyword">None</span>
</pre>
    <h4>
      Moving on
    </h4>
    <p>
      I think that should be enough to work with for now. Next time,
      I'll discuss publishing stories to news feeds and all that
      social good stuff. Until then, please feel free to post any
      comments, questions, or improvements below.
    </p>
]]></content:encoded>
			<wfw:commentRss>http://www.chickenwingsw.com/scratches/programming/python/django-facebook-3/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Making a Facebook app (with Django) &#8211; part 2: JavaScript and FBJS</title>
		<link>http://www.chickenwingsw.com/scratches/programming/python/django-facebook-2</link>
		<comments>http://www.chickenwingsw.com/scratches/programming/python/django-facebook-2#comments</comments>
		<pubDate>Sun, 17 Aug 2008 14:45:10 +0000</pubDate>
		<dc:creator>Eddie Sullivan</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.chickenwingsoftware.com/?p=54</guid>
		<description><![CDATA[Welcome to the second part in my series of posts about creating a Facebook application. I am using Django as my web development framework, but this post doesn't have much to do with Django, since it deals with the front end. In particular, it talks about how to write JavaScript that can work both in [...]]]></description>
			<content:encoded><![CDATA[    <p>
      Welcome to the second part in my series of posts about creating
      a Facebook application. I am using Django as my web development
      framework, but this post doesn't have much to do with Django,
      since it deals with the front end. In particular, it talks about
      how to write JavaScript that can work both in and out of
      Facebook.
    </p>
    <p>
      As I mentioned last time, Facebook lets developers use a subset
      of JavaScript, which they call FBJS. The FBJS is transformed on
      the fly into JavaScript as the page is loaded. All variables and
      functions you define or reference are prepended with a string
      like "a123456789_", including calls
      to <span class="code">document.getElementById</span>
      and <span class="code">setTimer</span> and the like. This is
      done in order to restrict what you can do with DOM elements, to
      avoid cross-site-scripting attacks and unwanted user-hostile
      behavior. <a href="http://wiki.developers.facebook.com/index.php/FBJS">FBJS is fairly well documented</a>, so if you plan to do
      some Facebook JavaScript development, you should start there.
    </p>
    <p>
      The biggest restriction that FBJS imposes is that you can no
      longer access the attributes of DOM elements directly, but must
      go through an abstraction API consisting of a series of setters
      and getters. For example, instead of saying something like
      <span class="code">imageEl.src = myImageUrl</span>, you instead need
      to call imageEl.setSrc(myImageUrl).
    </p>
<span id="more-54"></span>
    <p>
      This is not too big of an adjustment, if you are accustomed to
      writing raw JavaScript. It actually has some advantages, because
      FBJS abstracts away some of browser-dependent aspects into a
      standard API.
    </p>
    <p>
      The challenge, however, becomes apparent when you try debugging
      your JavaScript. With Internet Explorer and its horrendously
      useless error messages and debugging facilities, it's pretty
      much hopeless, since the line numbers don't correspond to line
      numbers in your source code. However, even with Firefox and the
      wonderful Firebug debugger, all the name mangling and rewriting
      makes tracking down problems more difficult. Ideally you would
      want to debug as much as possible <em>outside</em> of Facebook,
      before then testing on the real site.
    </p>
    <p>
      To make this easier, I developed some useful code to simulate as
      much as possible the FBJS environment when running locally or
      outside of Facebook. The idea was to re-create all the accessor
      functions on all DOM objects. You can <a href="http://www.chickenwingsoftware.com/static/fbHelper.js">download the file
      here</a>. You're free to use it, but please don't link directly to
      the file on my site - copy it to your site and use it there. And
      read the description below first.
    </p>
    <p>
      I considered several different approaches before settling on the
      final version. I considered trade-offs of performance and
      possible side-effects. Rejected approach number one was to
      modify Object.prototype to contain the new getters and
      setters. This would have been the fastest, but can cause
      problems with code like the following:
    </p>
    <pre>
<span class="keyword">for</span> (var param <span class="type">in</span> <span class="variable-name">obj</span>) {
  <span class="comment">// Do something with obj[param]
</span>}

</pre>
    <p>
      This would end up enumerating all of the added functions as well
      as the properties of the object in question. This is why it is
      generally considered a bad idea to modify Object.prototype.
    </p>
    <p>
      The second rejected approach was to create a wrapper class with
      all the accessor functions, that performs the requisite getting
      and setting on a member variable containing the actual DOM
      object. This one could have worked well, but it would have been
      a lot of code to implement, and would have made debugging with
      Firebug more difficult because of the added layer of
      indirection.
    </p>
    <p>
      The approach I settled on was to simply provide wrapper
      functions for document.getElementById and
      document.createElement, and for each element that is "getted" or
      created, to copy in the required member functions. This has a
      perfomance penalty during the getting or creation of elements,
      but the calls themselves are speedy. There is likely to be a lot
      more manipulation than getting, I would think.
    </p>
    <h3>
      How to use this code
    </h3>
    <p>
      To use this code, just reference this file from your web page
      before any of your own JavaScript, but only when you are outside
      of Facebook. Make sure to call fbGetEl and fbCreateEl instead of
      document.getElementById and document.createElement. In the
      version of your page that is intended to be run inside of
      Facebook, include this code:
    </p>
        <pre>
<span class="type">function</span> <span class="function-name">fbGetEl</span>(elId) {
  <span class="keyword">return</span> document.getElementById(elId);
}
<span class="type">function</span> <span class="function-name">fbCreateEl</span>(elType) {
  <span class="keyword">return</span> document.createElement(elType);
}
</pre>
    <p>
      Alternatively, if you are feeling a little tricky, you can add
      in some code like this to the end of fbHelper.js
    </p>
        <pre>
document.getElementById = fbGetEl;
document.createElement = fbGetEl;
</pre>
    <p>
      Then you can continue to use document.getElementById and
      document.createElement. (Note that I have not tested this
      approach.)
    </p>
    <p>
      I hope this comes in handy for some people.
    </p>
    <h3>
      More FBJS tips
    </h3>
    <h4>
      Beware of the cache!
    </h4>
    <p>
       If you make a change to your .js file and
      don't notice any difference in your app's behavior, chances are
      you are getting bitten by the cache bug. To get around this,
      Facebook recommends adding "cache-breaker" code to the URL. For
      example, instead of linking to "myFile.js", link to
      "myFile.js?v=2". The extra text from the question mark on is
      usually ignored by web servers for static files. In my Django
      context processor, I have code like the following:
    </p>
    <pre>
<span class="keyword">from</span> svnVersion <span class="keyword">import</span> svnVersion

<span class="comment"># Add this function to your TEMPLATE_CONTEXT_PROCESSORS
# list in settings.py
</span><span class="keyword">def</span> <span class="function-name">fbContextProcessor</span>(request):
    <span class="keyword">return</span> { <span class="comment"># Add any other template vars you want here.
</span>        '<span class="string">cacheBreaker</span>':'<span class="string">?v=%s</span>' % svnVersion }

</pre>
    <p>
      Then in my template, whenever a have a link, I do something like:
    </p>
    <pre>
&lt;a href="http://example.com/myFile.js{{ cacheBreaker }}"&gt;Click here!&lt;/a&gt;
    </pre>
      Then every time I update my code, I run a shell script that does
      something like:
    </p>
    <pre>
      #!/bin/sh
      echo "svnVersion = '`svnversion -n .`'" > svnVersion.py
    </pre>

    <p>
      That way, every time I update my code, I make sure to break the
      Facebook cache. Alternatively, you could call svnversion
      straight from Python.
    </p>
    <h4>
       console.log is your friend! 
    </h4>
    <p>
     This is true in general when
      JavaScript programming, but especially so with Facebook. Take
      the time to put in some extra logging messages while you're
      developing, and testing and debugging will be much easier. And
      read up on Firebug as much as possible.
    </p>
    <h4>
      Check out the <a href="http://wiki.developers.facebook.com/index.php/FBJS/Animation">Animation library</a>.
    </h4>
    <p>
      It's pretty cool, and it works outside of Facebook, too.
    </p>
    <h4>
      Beware the limitations.
    </h4>
    <p>
      Facebook only allows up to five external
      script files, so keep that in mind. You may unfortunately have
      to combine two or more .js files into one to work around this
      restriction. Also, FBJS doesn't run on profile pages until the
      user has interacted with the app.
    </p>]]></content:encoded>
			<wfw:commentRss>http://www.chickenwingsw.com/scratches/programming/python/django-facebook-2/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

