<?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>Furry Brains &#187; Uncategorized</title>
	<atom:link href="http://furrybrains.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://furrybrains.com</link>
	<description>The Furry Brains blog tackles a wide range of issues related to web development and design.</description>
	<lastBuildDate>Mon, 22 Jun 2009 16:39:24 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Named Scopes for Django</title>
		<link>http://furrybrains.com/2009/06/22/named-scopes-for-django/</link>
		<comments>http://furrybrains.com/2009/06/22/named-scopes-for-django/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 16:24:10 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=155</guid>
		<description><![CDATA[There are really only a handful of features I miss about Ruby on Rails, having switched over to using only Django about a year ago. One of the biggest among these has been named scopes.
What a named scope does in Rails, in Django terms, is allow you to name a given query and use it [...]]]></description>
			<content:encoded><![CDATA[<p>There are really only a handful of features I miss about Ruby on Rails, having switched over to using only Django about a year ago. One of the biggest among these has been named scopes.</p>
<p>What a <a href="http://www.pathf.com/blogs/2008/06/named-scopes-are-awesome/">named scope</a> does in Rails, in Django terms, is allow you to name a given query and use it as a base, or &#8220;scope,&#8221; for further queries. In other words, your narrowing down the results upon which additional queries that you run will be executed.</p>
<p>It&#8217;s pretty much the same idea behind modifying initial Manager QuerySets <a href="http://docs.djangoproject.com/en/dev/topics/db/managers/#modifying-initial-manager-querysets">as outlined in the Django documentation</a>, with one major difference: Scopes can be chained. Chaining is the feature I had long coveted, and I had been banging my head around for a solution for the last few months.</p>
<p>The other day while I was poking around the internals a bit though, a decent idea came to me. I realized it would be quite simple for me to extend the default <code>Manager</code> class with an attribute where I could store <code>QuerySet</code> methods I wanted to execute as part of a scope, and then overwrite <code>get_query_set()</code> with a hook that ran these methods before executing the rest of the query.</p>
<p>This turned out to be a nice strategy, and with the addition of some decorators the interface itself turned out to be extraordinarily simple.</p>
<p><span id="more-155"></span></p>
<p>Anyhow, here&#8217;s a walkthrough of how my alpha &#8220;scopable&#8221; module would work, with example code.</p>
<p>Let&#8217;s start with a simplistic blog post model:</p>
<pre class="brush: python;">
class Post(models.Model):
    title           = models.CharField('title', max_length=200)
    author          = models.ForeignKey(User)
    body            = models.TextField('author')
    publish_at      = models.DateTimeField('published at', default=datetime.now)
    is_draft        = models.BooleanField('is draft', default=False)
    is_deleted      = models.BooleanField('deleted', default=False)
    objects         = PostManager()
</pre>
<p>That&#8217;s enough to provide for some good example scopes. Now, here&#8217;s what <code>PostManager</code> might look like, with explanation to follow:</p>
<pre class="brush: python;">
from scopable import ScopableManager, scope

class PostManager(ScopableManager):
    @property
    @scope
    def active(self):
       return self.filter(is_deleted=False, user__is_active=True)

    @property
    @scope
    def published(self):
       return self.filter(is_draft=False)

    @property
    @scope
    def public(self):
       return self.active.published
</pre>
<p>So as you can see, the <code>ScopableManager</code> class is very easy to use; you just add the <code>@scope</code> decorator to any method that you want to turn into a scope. (Note that I added the <code>@property</code> decorator as a stylistic preference; it&#8217;s not required.)</p>
<p>To use the code, you just have to be sure to call a QuerySet method after it, e.g.:</p>
<pre class="brush: python;">
Post.objects.active.all()
Post.objects.published.all()
Post.objects.active.published.filter(publish_at__lte=datetime.now())
Post.objects.public.all()
</pre>
<p>The only difference between a scoped and unscoped method is that execution of any <code>QuerySet</code> methods defined in a scoped method are deferred until a <code>QuerySet</code> method is called (e.g. <code>Post.objects.public.all()</code>), and scoped methods return an instance of your manager back, so they can be chained. As you can see from the <code>public</code> method, scoped methods can be nested as well.</p>
<p>Why is this awesome? Well the main advantage from my perspective is that it allows your business rules to be defined in one and only one discrete place.</p>
<p>So if, for example, I added a new business rule that blog posts shouldn&#8217;t be considered published unless they were not drafts and the publish date had already passed, I could just add that rule to the <code>published</code> method:</p>
<pre class="brush: python;">
    @property
    @scope
    def published(self):
       return self.filter(publish_at__lte=datetime.now(), is_draft=False)
</pre>
<p>This means that any other queries that were built on <code>published</code>, such as <code>public</code>, are now updated with the new business logic we added to <code>published</code>.</p>
<p>The implementation of all of this is pretty straightforward. The main complication comes from implementing scope as a decorator and trying to elegantly capture all of the <code>QuerySet</code> methods used in a scoped <code>Manager</code> method.</p>
<p>This is still alpha code, and as of now it doesn&#8217;t handle custom <code>Manager</code> methods that are not scoped. I mostly just wanted to get this idea out there before I do any more work:</p>
<pre class="brush: python;">
&quot;&quot;&quot;
scopable.py - A module for providing Rails-like named scopes to Django model Managers
Verson 0.1
&quot;&quot;&quot;

from functools import wraps
from django.db import models

class DummyManager(object):
    def __init__(self, actual_mgr, calls=[]):
        super(DummyManager, self).__init__()
        self.actual_mgr = actual_mgr
        self.calls = calls

    def __call__(self, *args, **kwargs):
        last_call = self.calls[-1]
        last_call[&quot;is_property&quot;] = False
        last_call[&quot;args&quot;] = args
        last_call[&quot;kwargs&quot;] = kwargs
        clone = DummyManager(self.actual_mgr, self.calls)
        self.calls = []
        return clone

    def __getattribute__(self, name):
        if name in [&quot;calls&quot;, &quot;actual_mgr&quot;]:
            return super(DummyManager, self).__getattribute__(name)

        # attr_type, args, and kwargs are set here by default in case the attr never gets called
        call = { &quot;attr&quot;: name, &quot;is_property&quot;: True, &quot;args&quot;: [], &quot;kwargs&quot;: {} }

        # if this is a default manager method
        if hasattr(models.Manager, name):
            call[&quot;definition&quot;] = &quot;default&quot;

        # else if this is a custom manager method
        elif hasattr(self.actual_mgr.__class__, name):
            call[&quot;definition&quot;] = &quot;custom&quot;

        # if it can't be found in those two classes, throw an error
        else:
            raise AttributeError(&quot;'%s' object has no attribute '%s'&quot; % (self.actual_mgr.__class__.__name__, name))

        self.calls.append(call)
        clone = DummyManager(self.actual_mgr, self.calls)
        self.calls = []
        return clone

def scope(fn):
    @wraps(fn)
    def scopified(*args, **kwargs):
        args_list = list(args)
        actual_mgr = args_list.pop(0)
        dummy = DummyManager(actual_mgr, [])
        args_list.insert(0, dummy)
        deferred_calls = get_deferred_calls(actual_mgr, fn, args_list, kwargs)
        a = actual_mgr.__class__(deferred_calls=deferred_calls)
        a.contribute_to_class(actual_mgr.model, actual_mgr.model.__name__)
        return a
    return scopified

def get_deferred_calls(mgr, fn, args, kwargs):
    deferred_calls = []
    result = fn(*args, **kwargs)
    if result.calls:
        for call in result.calls:
            if call[&quot;definition&quot;] == &quot;default&quot;:
                deferred_calls.append(call)
            elif call[&quot;definition&quot;] == &quot;custom&quot;:
                next_result = getattr(mgr, call[&quot;attr&quot;])
                if not call[&quot;is_property&quot;]:
                    next_result = next_result(*call[&quot;args&quot;], **call[&quot;kwargs&quot;])
                deferred_calls = deferred_calls + next_result.deferred_calls
            else:
                raise AssertionError(&quot;Something went wrong.&quot;)
    return deferred_calls

class ScopableManager(models.Manager):

    def __init__(self, deferred_calls=[]):
        super(ScopableManager, self).__init__()
        self.scopes = []
        self.deferred_calls = deferred_calls

    def get_query_set(self):
        qs = super(ScopableManager, self).get_query_set()
        if self.deferred_calls:
            for deferred_call in self.deferred_calls:
                next_qs = getattr(qs, deferred_call[&quot;attr&quot;])
                if not deferred_call[&quot;is_property&quot;]:
                    next_qs = next_qs(*deferred_call[&quot;args&quot;], **deferred_call[&quot;kwargs&quot;])
                qs = next_qs
        return qs
</pre>
<p>Please let me know in the comments if you have feedback, suggestions, bugs, grave warnings, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2009/06/22/named-scopes-for-django/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Organizing Unit Tests in Django</title>
		<link>http://furrybrains.com/2009/02/25/organizaing-unit-tests-in-django/</link>
		<comments>http://furrybrains.com/2009/02/25/organizaing-unit-tests-in-django/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 07:18:26 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=136</guid>
		<description><![CDATA[I just started a small side project last week, and I finally decided to take the opportunity to really make TDD (test-driven development) happen for me using Django. Though I&#8217;ve dabbled with testing in Django and done quite a bit more with testing in Ruby, I never managed to embrace TDD fully. It&#8217;s about time, [...]]]></description>
			<content:encoded><![CDATA[<p>I just started a small side project last week, and I finally decided to take the opportunity to really make <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> (test-driven development) happen for me using Django. Though I&#8217;ve dabbled with testing in <a href="http://www.djangoproject.com/">Django</a> and done quite a bit more with testing in Ruby, I never managed to embrace TDD fully. It&#8217;s about time, I figure.</p>
<p>Well, I hit some snags as I got underway. Partly this had to do with me being something of a novice when it comes to testing, and partly it has to do with the state of testing in Django at present.</p>
<p>My mini-gripe with testing in Django is that it&#8217;s just kind of loosey-goosey. You can use <a href="http://docs.python.org/library/doctest.html">doctest</a>, or you can use <a href="http://docs.python.org/library/unittest.html">unittest</a>. You can put your tests in your functions, or in your models, or in tests.py, or in a tests/ subfolder.</p>
<p>For me at least, I want my framework to be a bit more opinionated. I want a bunch of guys who are all smarter than me to have sat around and thought about (or better yet, generalized from a working production code) things like the best way to configure testing for a Python web framework, and then to tell me, in no uncertain terms, the exact way to do it.</p>
<p>I&#8217;m obviously exaggerating a bit, and I don&#8217;t really mean at all to rant about a phenomally awesome, not to mention open source, framework like Django. What all of the above amounts to is that I had to ponder deeply on the problem space myself and come up with a way of structuring my test code that would work for me.</p>
<p>So that&#8217;s what I did, and here is the organizational structure I intend to use as I proceed.</p>
<p><span id="more-136"></span></p>
<h3>An Organizational Structure for Test Code in Django</h3>
<p>This is how <a href="http://en.wikipedia.org/wiki/Unit_testing">Wikipedia defines unit testing</a>:</p>
<blockquote><p>In computer programming, unit testing is a software design and development method where the programmer verifies that individual units of source code are working properly. A unit is the smallest testable part of an application.</p></blockquote>
<p>One of the things that kept frustrating me about writing tests was that my tests were all methods of a test case class that referred to a model class or a view module. Most of the examples you see are written in that form, such as the following from the <a href="http://docs.djangoproject.com/en/dev/topics/testing/">Django testing documentation</a>:</p>
<pre class="brush: python;">
class AnimalTestCase(unittest.TestCase):
    def setUp(self):
        self.lion = Animal.objects.create(name=&quot;lion&quot;, sound=&quot;roar&quot;)
        self.cat = Animal.objects.create(name=&quot;cat&quot;, sound=&quot;meow&quot;)

    def testSpeaking(self):
        self.assertEquals(self.lion.speak(), 'The lion says &quot;roar&quot;')
        self.assertEquals(self.cat.speak(), 'The cat says &quot;meow&quot;')
</pre>
<p>What frustated me was that you&#8217;d end up with a big long catalog of test methods for all the various methods of Animal. It would also be hard to determine what the test was referring to by looking at the test method name. Sometimes a method might be <code>testSpeaking()</code>; other times it might be <code>testShouldSpeak()</code>. In either case, I didn&#8217;t feel like the methods were serving very well as documentation, which is one of the supposed benefits of user testing.</p>
<p>Then as I re-read the definition of a unit test to myself for the hundredth time, it dawned on me. Unit tests are supposed to focus on *the smallest testable part of an application.* But all the examples I was seeing had tests that were organized around the class, which is certainly not the smallest testable part. That distinction belongs to methods and class attributes.</p>
<p>I stumbled upon my first rule: <em>Organize test methods around the individual methods and attributes of a class, instead of the class itself.</em> How so? The easiest is to create a separate test case subclass for *each* method and attribute. Each test method of that subclass is then a test of a behavior of the method or attribute under test.</p>
<p>This mini-breakthrough also helped me flesh out a rule for writing better test method names: <em>Start every test method name with &#8220;test_should_&#8221;.</em> This borrows from a page in <a href="http://en.wikipedia.org/wiki/Behavior_driven_development">behavior-driven development</a>, but basically &#8220;should&#8221; is the perfect word to use to express a desired behavior.</p>
<h3>In Practice</h3>
<p>Here&#8217;s what all this looks like in practice, taking the <code>Animal</code> class as an example again from Django&#8217;s testing documentation:</p>
<pre class="brush: python;">
# models.py
from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=20)
    sound = models.CharField(max_length=20)

    def speak(self):
        return 'The %s says &quot;%s&quot;' % (self.name, self.sound)
</pre>
<p>And here&#8217;s how I would propose that test code for this class be structured (with a focus on the organization, not thoroughness of testing or appropriateness of implementation):</p>
<pre class="brush: python;">
from django.test import TestCase
from myapp.models import Animal

class AnimalTestCase(TestCase):
    def setUp(self):
        self.lion = Animal.objects.create(name=&quot;lion&quot;, sound=&quot;roar&quot;)

class Class(AnimalTestCase):
    # obviously a silly, trivial test
    def test_should_instantiate_object_of_its_own_type(self):
        self.failUnlessEqual(type(Animal()), Animal)

class NameAttribute(AnimalTestCase):
    def test_should_be_defined(self):
        self.failUnless(hasattr(self.lion, 'name'))

    def test_should_accept_string_value(self):
        a = Animal()
        a.name = &quot;bear&quot;
        a.save()
        self.failUnless(a.id) # object was saved successfully

    def test_should_allow_no_more_than_20_chars(self):
        self.lion.name = &quot;a&quot;*21
        self.failUnlessRaises(Warning, self.lion.save)

class SoundAttribute(AnimalTestCase):
    def test_should_be_defined(self):
        self.failUnless(hasattr(self.lion, 'sound'))

    # similar test_shoulds as with 'name' here

class SpeakMethod(AnimalTestCase):
    def test_should_be_defined(self):
        self.failUnless(hasattr(self.new_pp, 'speak'))

    def test_should_return_appropriate_string(self):
        self.failUnlessEquals(self.lion.speak(), 'The lion says &quot;roar&quot;')
</pre>
<p>(I have not executed the above code, so please don&#8217;t be surprised if it has errors.)</p>
<p>So, it&#8217;s pretty simple really. Each attribute or method being tested is given an explicitly named test class, which is a subclass of a single test case class for the class under test. Each specified behavior of that attribute or method is assigned a test method beneath the appropriate test class.</p>
<p>Here&#8217;s what I like about this approach:</p>
<ul>
<li>You don&#8217;t have to &#8220;think&#8221; while writing tests. If you&#8217;ve decided to define a method, you just list off to yourself all of the things it should do and/or require.</li>
<li>The tests actually <em>read</em> like documentation. Not that you&#8217;ll ever see them expressed anywhere in this format, but I like to read them as &#8220;NamedAttribute.should_accept_test_value&#8221; or &#8220;SpeakMethod.should_return_appropriate_string&#8221;. It&#8217;s just so easy to make sense out of exactly what each part of your model is supposed to do.</li>
<li>The class names provide some grouping structure to the test methods. Ten groups of ten methods, for example, are a lot easier to make sense of and keep organized than 100 test methods without any other structure.</li>
</ul>
<h3>Getting It To Work</h3>
<p>It&#8217;s actually quite easy to get this all to work. The only trick involved is that you have to specify which suites to run to the django test runner. (This may not in fact be a requirement, but I wanted adding new test case subclasses to be quick and easy; I didn&#8217;t want to spend my life configuring which tests to run in a bunch of places.)</p>
<p>Here&#8217;s a quick function I wrote to handle this:</p>
<pre class="brush: python;">
def build_test_suite_from(test_cases):
    &quot;&quot;&quot;
    Returns a single or group of unittest test suite(s) that's ready to be
    run. The function expects a list of classes that are subclasses of
    TestCase.

    The function will search the module where each class resides and
    build a test suite from that class and all subclasses of it.
    &quot;&quot;&quot;
    test_suites = []
    for test_case in test_cases:
        mod = __import__(test_case.__module__)
        components = test_case.__module__.split('.')
        for comp in components[1:]:
            mod = getattr(mod, comp)
        tests = []
        for item in mod.__dict__.values():
            if type(item) is type and issubclass(item, test_case):
                tests.append(item)
        test_suites.append(unittest.TestSuite(map(unittest.TestLoader().loadTestsFromTestCase, tests)))
    return unittest.TestSuite(test_suites)
</pre>
<p>Django allows you to define a <code>suite()</code> function in your test module, which is then automatically detected by the test runner when tests are executed. So we&#8217;ll just embed the above function in that, like this, for example:</p>
<pre class="brush: python;">
from myapp.test_utils import build_test_suite_from
from myapp.tests.models.some_model import SomeModelTestCase
from myapp.tests.models.another_model import AnotherModelTestCase

test_cases = [
    SomeModelTestCase,
    AnotherModelTestCase
]

def suite():
    return build_test_suite_from(test_cases)
</pre>
<p>Here&#8217;s what happens: <code>build_test_suite_from()</code> runs through each <code>TestCase</code> you pass to it, and searches the module where that <code>TestCase</code> is found for subclasses of that <code>TestCase</code> (including the <code>TestCase</code> itself). It then builds a test suite containing all of the test methods out of each of these, and then combines all of them together into one giant test suite which Django will run automatically when you do <code>./manage.py test</code>.</p>
<p>The idea again is to keep configuration to a minimum. For each model you create test cases for you have to import the model&#8217;s <code>TestCase</code> and add it to the <code>test_cases</code> list, but no additional configuration is required for subclasses you create of that <code>TestCase</code>.</p>
<p>I expect that this structure will evolve as I actually start using it more. In particular, tests for forms and views may or may not work as cleanly within this structure as do those for models.</p>
<p>If you have any comments or feedback (good or bad), I&#8217;d love to hear about it below.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2009/02/25/organizaing-unit-tests-in-django/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Prepending an Indefinite Article (a or an) in Front of a Word or Phrase</title>
		<link>http://furrybrains.com/2009/01/26/with_indefinite_article-a-django-template-tag/</link>
		<comments>http://furrybrains.com/2009/01/26/with_indefinite_article-a-django-template-tag/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 22:29:06 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=126</guid>
		<description><![CDATA[Today, I had to whip up a Django template tag to add &#8220;a&#8221; or &#8220;an&#8221; in front of a phrase.
It started off pretty easy &#8212; just use &#8220;an&#8221; when the first letter of the phrase is a vowel and otherwise use &#8220;a.&#8221; And then I remembered about abbreviations (&#8220;an HR department&#8221;), silent H words (&#8220;an [...]]]></description>
			<content:encoded><![CDATA[<p>Today, I had to whip up a Django template tag to add &#8220;a&#8221; or &#8220;an&#8221; in front of a phrase.</p>
<p>It started off pretty easy &#8212; just use &#8220;an&#8221; when the first letter of the phrase is a vowel and otherwise use &#8220;a.&#8221; And then I remembered about abbreviations (&#8220;an HR department&#8221;), silent H words (&#8220;an honorable man&#8221;), and exceptions among a few O and U words (&#8220;a one-time offer&#8221; or &#8220;a union representative&#8221;), and suddenly it wasn&#8217;t so easy.</p>
<p>Fortunately I managed to find an excellent <a href="http://www.speech.cs.cmu.edu/cgi-bin/cmudict">database of English words that includes pronunciations</a>, and in no time at all I was able to generate a list of exceptions.</p>
<p>Here&#8217;s the final result, implemented as a <a href="http://docs.djangoproject.com/en/dev/howto/custom-template-tags/">custom django template tag</a> (in my use case, I needed to able to wrap the original phrase in an HTML tag, so I couldn&#8217;t use a filter tag). This could also easily be a standalone Python function as well (literally by removing the <code>@register.simple_tag</code> decorator).</p>
<p><span id="more-126"></span></p>
<pre class="brush: python;">
import re

@register.simple_tag
def with_indefinite_article(phrase, before_phrase=&quot;&quot;, after_phrase=&quot;&quot;):
    silent_h_words = [&quot;homage&quot;, &quot;hour&quot;, &quot;herb&quot;, &quot;heir&quot;, &quot;honest&quot;, &quot;honor&quot;]
    letters_with_initial_vowel_sound = [&quot;a&quot;, &quot;e&quot;, &quot;f&quot;, &quot;h&quot;, &quot;i&quot;, &quot;l&quot;, &quot;m&quot;, &quot;n&quot;, &quot;o&quot;, &quot;r&quot;, &quot;s&quot;, &quot;x&quot;]
    vowels = [&quot;a&quot;, &quot;e&quot;, &quot;i&quot;, &quot;o&quot;, &quot;u&quot;]
    o_exceptions = [&quot;once&quot;,&quot;one&quot;,&quot;oneness&quot;,&quot;ones&quot;,&quot;oneself&quot;,&quot;onetime&quot;]
    u_exceptions = [&quot;ubiquitous&quot;,&quot;uganda&quot;,&quot;ugandan&quot;,&quot;ukraine&quot;,&quot;ukrainian&quot;,&quot;ukulele&quot;,&quot;ukuleles&quot;,&quot;unanimous&quot;,&quot;unanimously&quot;,&quot;unicellular&quot;,&quot;unicorn&quot;,&quot;unicorns&quot;,&quot;unicycle&quot;,&quot;unicycles&quot;,&quot;unification&quot;,&quot;unified&quot;,&quot;uniform&quot;,&quot;uniformed&quot;,&quot;uniformly&quot;,&quot;uniforms&quot;,&quot;unify&quot;,&quot;unifying&quot;,&quot;unilateral&quot;,&quot;unilateralism&quot;,&quot;unilaterally&quot;,&quot;union&quot;,&quot;unionist&quot;,&quot;unionists&quot;,&quot;unionization&quot;,&quot;unionized&quot;,&quot;unionizing&quot;,&quot;unions&quot;,&quot;unique&quot;,&quot;uniquely&quot;,&quot;uniqueness&quot;,&quot;unisex&quot;,&quot;unison&quot;,&quot;unisons&quot;,&quot;unit&quot;,&quot;unitarian&quot;,&quot;unitary&quot;,&quot;unite&quot;,&quot;united&quot;,&quot;uniting&quot;,&quot;units&quot;,&quot;unity&quot;,&quot;universal&quot;,&quot;universally&quot;,&quot;universe&quot;,&quot;universes&quot;,&quot;universities&quot;,&quot;university&quot;,&quot;universitys&quot;,&quot;unix&quot;,&quot;uranium&quot;,&quot;urinalysis&quot;,&quot;urinary&quot;,&quot;urinate&quot;,&quot;urinating&quot;,&quot;urine&quot;,&quot;urologist&quot;,&quot;urologists&quot;,&quot;urology&quot;,&quot;uruguay&quot;,&quot;uruguayan&quot;,&quot;uruguays&quot;,&quot;usable&quot;,&quot;usage&quot;,&quot;usages&quot;,&quot;use&quot;,&quot;used&quot;,&quot;useful&quot;,&quot;usefully&quot;,&quot;usefulness&quot;,&quot;useless&quot;,&quot;usenet&quot;,&quot;user&quot;,&quot;users&quot;,&quot;uses&quot;,&quot;usual&quot;,&quot;usually&quot;,&quot;usurp&quot;,&quot;usurpation&quot;,&quot;usurped&quot;,&quot;usurper&quot;,&quot;usurping&quot;,&quot;usury&quot;,&quot;utah&quot;,&quot;utahn&quot;,&quot;utahns&quot;,&quot;utahs&quot;,&quot;utensil&quot;,&quot;utensils&quot;,&quot;uterine&quot;,&quot;utero&quot;,&quot;uterus&quot;,&quot;utilitarian&quot;,&quot;utilities&quot;,&quot;utility&quot;,&quot;utilitys&quot;,&quot;utilization&quot;,&quot;utilize&quot;,&quot;utilized&quot;,&quot;utilizes&quot;,&quot;utilizing&quot;,&quot;utopia&quot;,&quot;utopian&quot;,&quot;utopians&quot;,&quot;utopias&quot;]

    # get rid of everything but letters and numbers and a few characters
    first_word = re.sub(r&quot;[^A-Za-z0-9\-]&quot;, &quot;&quot;, phrase.split()[0])
    first_letter = first_word[0].lower()

    # default to 'a'
    article = &quot;a&quot;

    if first_word.isupper() or (len(first_word) == 1):
        # if all caps or a single letter, we're going to assume it's an abbreviation
        if first_letter in letters_with_initial_vowel_sound:
            article = &quot;an&quot;
    elif first_letter == &quot;h&quot; and any( [re.match(r'(?i)%s' % w, first_word) for w in silent_h_words] ):
        article = &quot;an&quot;
    elif first_letter in vowels:
        if first_letter == 'e':
            article = &quot;a&quot; if first_word.lower().split('-')[0] == 'ewe' else &quot;an&quot;
        elif first_letter == 'o':
            article = &quot;a&quot; if first_word.lower().split('-')[0] in o_exceptions else &quot;an&quot;
        elif first_letter == 'u':
            article = &quot;a&quot; if first_word.lower().split('-')[0] in u_exceptions else &quot;an&quot;
        else:
            article = &quot;an&quot;

    return &quot;%s %s%s%s&quot; % (article, before_phrase, phrase, after_phrase)
</pre>
<p>Hopefully this will save someone who stumbles upon this some extra work down the road. If you find any bugs, please let me know in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2009/01/26/with_indefinite_article-a-django-template-tag/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JSON Parsing and Stringifying in jQuery (as a plugin)</title>
		<link>http://furrybrains.com/2009/01/15/json-parsing-and-stringifying-in-jquery-as-a-plugin/</link>
		<comments>http://furrybrains.com/2009/01/15/json-parsing-and-stringifying-in-jquery-as-a-plugin/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 23:46:56 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=117</guid>
		<description><![CDATA[jQuery has many kick-ass javascript utilities. Among these is a method (jQuery.getJSON()) that parses JSON that you grab from a remote source and gives it back to you as a JSON object. Excellent!
Surprisingly though, jQuery (as of 1.3, to my knowledge anyway) does not make any functions available to allow you to securely parse a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jquery.com">jQuery</a> has many kick-ass javascript utilities. Among these is a method (<a href="http://docs.jquery.com/Ajax/jQuery.getJSON"><code>jQuery.getJSON()</code></a>) that parses JSON that you grab from a remote source and gives it back to you as a JSON object. Excellent!</p>
<p>Surprisingly though, jQuery (as of 1.3, to my knowledge anyway) does not make any functions available to allow you to securely parse a simple <em>text string</em> into JSON. Not sure why this is so, especially since they must do it behind the scenes for the <code>getJSON()</code> method, but so be it.</p>
<p>I needed this functionality, though, so I could pass some data from one of my templates to a jQuery function I&#8217;m working on.</p>
<p>Fortunately, even though jQuery doesn&#8217;t have built-in functionality for this, it was relatively trivial to wrap the open source JSON parsing and stringifying library published by JSON.org in an easy-to-use jQuery plugin.</p>
<p>So that&#8217;s what I did. I changed nothing of the <a href="http://www.json.org/json2.js">JSON parsing library</a> implementation published by <a href="http://json.org/">JSON.org</a>; I just wrapped two jQuery methods around it, as follows:</p>
<pre class="brush: jscript;">
;(function($) {
    if (!this.JSON) {
        var JSON = {};
    }
    /* ... implementation of parse() and stringify() here ... */
    $.toJSON = function(text, reviver) {
        if (typeof reviver == &quot;undefined&quot;) {
            reviver = null;
        }
        return JSON.parse(text, reviver);
    };
    $.jSONToString = function(value, replacer, space) {
        if (typeof replacer == &quot;undefined&quot;) {
            replacer = null;
        }
        if (typeof space == &quot;undefined&quot;) {
            space = null;
        }
        return JSON.stringify(value, replacer, space);
    };

})(jQuery);
</pre>
<p>Pretty convenient. Now I can securely parse and decode JSON to my heart&#8217;s content.</p>
<p>Here&#8217;s the source code of the full <a href='http://furrybrains.com/media/2009/01/jquery.json.js'>jQuery JSON plugin</a>, if you&#8217;re interested. Note that I have not extensively tested the plugin, but since I did not actually touch any part of the JSON parsing library it&#8217;s based on (save for creating a local scope for the JSON variable), I wouldn&#8217;t foresee any issues.</p>
<p>Here&#8217;s a bit <a href="http://www.json.org/js.html">more information</a> about the library the plugin is based on.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2009/01/15/json-parsing-and-stringifying-in-jquery-as-a-plugin/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>An HTML Primer for Writers and Editors</title>
		<link>http://furrybrains.com/2009/01/06/an-html-primer-for-writers-and-editors/</link>
		<comments>http://furrybrains.com/2009/01/06/an-html-primer-for-writers-and-editors/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 20:26:13 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[html]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=108</guid>
		<description><![CDATA[A year ago, I wrote up a brief primer on HTML for some colleagues that was intended for writers and editors. By this I mean I tried to keep technical jargon to a minimum and focused on appealing to writers&#8217; and editors&#8217; love of semantics and grammar.
I was just forwarding it to someone who didn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>A year ago, I wrote up a brief primer on HTML for some colleagues that was intended for writers and editors. By this I mean I tried to keep technical jargon to a minimum and focused on appealing to writers&#8217; and editors&#8217; love of semantics and grammar.</p>
<p>I was just forwarding it to someone who didn&#8217;t know any HTML, and I figured it makes sense to post it here for the benefit of anyone else who stumbles upon it.</p>
<h3>Why You Should Care About <span class="caps">HTML</span></h3>
<p>For writers and editors, <span class="caps">HTML</span> probably seems at best like a minor nuisance. The fact that it was written by (and to some extent conceived of for) programmers is probably a big reason why.</p>
<p>In fact, <span class="caps">HTML</span> is pretty easy to learn conceptually. And these days, <span class="caps">HTML</span> has mostly been stripped of what once made it a  &#8220;programming&#8221; or design language. Properly used, <span class="caps">HTML</span> has now become a way for content authors to define the meaning of various aspects of a web document. In fact, content authors and editors are really the <em>only</em> people who can properly mark up a document and ensure it&#8217;s being done correctly.</p>
<p>Here are just a few of the reasons why you should care (passionately) about <span class="caps">HTML</span>:</p>
<p><span id="more-108"></span></p>
<ul>
<li><strong>Both people <em>and</em> computers need to read your documents.</strong> In general, we write and edit for people. But on the web, people aren&#8217;t the only ones who read your document — machines read it as well. Proper <span class="caps">HTML</span> is like good grammar for machines.</li>
<li><strong>Good <span class="caps">HTML</span> makes it easier for designers and programmers to do their jobs.</strong> Designers are charged with making your documents <em>look</em> right and programmers are charged with making them <em>work</em> right. When you play by the <span class="caps">HTML</span> rules, you give them the freedom to focus on what they do best.</li>
<li><strong>Your documents will last forever.</strong> The web is constantly evolving. Programmers come up with new tricks for working with web documents every day, and designers constantly have new design tools added to their arsenal. Good <span class="caps">HTML</span> is forward compatible, meaning your documents themselves can evolve as well, no matter which way technology goes in the future.</li>
<li><strong>You can add a whole new level of meaning to your documents for readers.</strong> Used properly, <span class="caps">HTML</span> allows you to give readers more information about what various parts of your documents mean. For example, you can seamlessly define abbreviations, cite quotations, or identify people and places without intefering with the readability of your documents.</li>
</ul>
<h3>What <span class="caps">HTML </span><em>Is</em> and <em>Isn&#8217;t</em></h3>
<p>In simple terms, <span class="caps">HTML</span> is a markup langauge that allows content authors and editors to explicitly define the <strong>semantic</strong> meaning of various aspects of a web document. That&#8217;s a simple and true definition, but it conflicts with what most people think <span class="caps">HTML</span> is and how most people use it. Unless you grasp this definition of <span class="caps">HTML</span>, you&#8217;re doomed to use it improperly.</p>
<p>Here&#8217;s an easy way to think about it:</p>
<blockquote>
<p>HTML is not a way of making a document <em>look</em> or <em>function</em> in a certain way. Instead, <span class="caps">HTML</span> is a way of <em>describing</em> what a document <em>is</em>.</p>
</blockquote>
<p>Here&#8217;s a quick little example that illustrates where most people go astray in their thinking.</p>
<pre>Our CEO was featured in Time magazine today.</pre>
<p>When preparing to mark this sentence up in <span class="caps">HTML</span>, most writers or editors would think: &#8220;Okay, I just need to put the title of the publication &#8216;Time&#8217; in italics.&#8221; This is a natural reaction, since you&#8217;ve been trained to put publications in italics throughout your life, and most of us are accustomed to pressing the little &#8220;I&#8221; button in Microsoft Word when we want something to appear in italics.</p>
<p>While that line of thinking isn&#8217;t entirely wrong, it isn&#8217;t entirely right either — at least from a sematnics perspective. The problem is that it conflates two related but separate concepts: presentation (in this case, the <em>italics</em>) and meaning (in this case, emphasis, which is what the italics are actually conveying).</p>
<p>We can see the difference in practice. One way to mark up the document (in an older version of <span class="caps">HTML</span>) was to use the italics tag, <code>&lt;i&gt;</code>:</p>
<pre>Our CEO was featured in &lt;i&gt;Time&lt;/i&gt; magazine today.</pre>
<p>The newer version of <span class="caps">HTML</span>, however, insists upon defining this text not by how it should appear, but by what it means, in this case using the <code>&lt;cite&gt;</code> (citation) tag:</p>
<pre>Our CEO was featured in &lt;cite&gt;Time&lt;/cite&gt; magazine today.</pre>
<p>Citations, by default, are rendered as italics in most browsers, so for readers, the two ways of coding this document appear the same. If that makes the distinction seem merely academic, it&#8217;s not. There are some real ramifications to the two different approaches. To name a few:</p>
<ul>
<li>A content author might decide to provide a link to the home page of the publication being cited.</li>
<li>A designer might choose to render citations with a different look — using the color green or a small graphic rather than just italics.</li>
<li>A programmer might build a function that provides a complete list of references cited in an article at the bottom of the article, which can be generated on the fly.</li>
</ul>
<p>There are many examples similar to this one — some with big implications, and others that are largely academic.</p>
<p>Nevertheless, good <span class="caps">HTML</span> is like good grammar. Although at the end of the day, you can very like ignore the rules of grammar and still get your point across, consistent use of good grammar makes your documents more readable and your image more professional. Good <span class="caps">HTML</span> has plenty of its own benefits — both obvious and hidden.</p>
<h3>HTML Basics</h3>
<p>Now that you understand the proper way to conceive of <span class="caps">HTML</span>, and are as convinced as I am of the importance of separating meaning from presentation and functionality, it&#8217;s time to get down to brass tacks and describe how to actually use <span class="caps">HTML</span>.</p>
<p><span class="caps">HTML</span> is a markup language; i.e. it&#8217;s used to &#8220;mark up&#8221; a document. Think of it like a highlighter pen. When you mark up a word or phrase with <span class="caps">HTML</span>, it&#8217;s like drawing a yellow line through it. The only difference is, you add a bit of description when using <span class="caps">HTML</span> to explain what the yellow line actually means.</p>
<p>Fortunately, <span class="caps">HTML</span> is quite simple. Like with any foreign language, there are some vocabulary words you&#8217;ll eventually need to learn, but conceptually <span class="caps">HTML</span> boils down to three concepts:</p>
<ol>
<li>Tags</li>
<li>Elements</li>
<li>Attributes and values</li>
</ol>
<p>Let&#8217;s briefly put these terms in context, and then tackle them one by one. Following is a phrase marked up with generic <span class="caps">HTML</span>:</p>
<pre>&lt;element attribute="value"&gt;The cat is black.&lt;/element&gt;</pre>
<p>In the context of the example above:</p>
<ul>
<li><strong>A <em>tag</em> is everything that comes between, and inclusive of, the angle brackets (<code>&lt;</code> and <code>&gt;</code>).</strong> <span class="caps">HTML</span> phrases <em>always</em> start with an opening tag (e.g. <code>&lt;element&gt;</code>) and end with a closing tag (e.g. <code>&lt;/element&gt;</code>). To use our metaphor from above, they define where you start putting your highlighter marker on the page and where you stop. (That&#8217;s why you <strong>must</strong> close all tags. If you don&#8217;t, a browser won&#8217;t be able to know where you wanted to stop your highlighter.)</li>
<li><strong>An <em>element</em> is a word that describes <em>what</em> the phrase your marking up is.</strong> Common elements include a paragraph (<code>&lt;p&gt;</code>), a list item (<code>&lt;li&gt;</code>), a hyperlink (<code>&lt;a&gt;</code>), an abberviation (<code>&lt;abbr&gt;</code>), or an image (<code>&lt;img</code>>). There are approximately 40 or so elements and only about 15 or 20 that are commonly used.</li>
<li><strong>An <em>attribute/value pair</em> provides more information about the phrase being marked up and is not always required.</strong> Attribue/value pairs are used, for example, to define the destination of a hyperlink (e.g. <code>&lt;a href="http://www.yahoo.com"&gt;</code>), the source of an image file (e.g. <code>&lt;img src="http://www.photo.com/my_picture.jpg"&gt;</code>, or the meaning of an abbreviation (e.g. <code>&lt;abbr title="United Nations"&gt;U.N.&lt;/abbr&gt;</code>).</li>
</ul>
<p>That&#8217;s really all there is to it. <span class="caps">HTML</span> is not more fancy than that. There are just a few syntax rules you need to learn and abide by in order to ensure your <span class="caps">HTML</span> is correct and a few element definitions you need to know to start using <span class="caps">HTML</span>.</p>
<p>Let&#8217;s start with syntax.</p>
<h3>HTML Syntax</h3>
<p>The example from above&#8230;</p>
<pre>&lt;element attribute="value"&gt;The cat is black.&lt;/element&gt;</pre>
<p>&#8230;is properly formatted <span class="caps">HTML</span>. The rules are pretty straightforward and easy to follow.</p>
<ol>
<li><strong>HTML is case sensitive.</strong> <em>Always</em> use lowercase for elements and attribute names.</li>
<li>A tag <em>always</em> starts with <code>&lt;</code> and ends with <code>&gt;</code>. If you forget to put a <code>&gt;</code> at the end of your tag, you&#8217;re going to confuse the computer, it won&#8217;t know where your tag ends!</li>
<li><strong>An <span class="caps">HTML</span> phrase <em>always</em> opens with a start tag (<code>&lt;element&gt;</code>) and closes with an end tag (<code>&lt;/element&gt;</code>).</strong> The forward slash <code>/</code> is what makes a tag an end tag. <strong>Exception</strong>: There are a few tags called &#8220;empty tags&#8221; that don&#8217;t a phrase between them. An example is the img tag, which generally looks like this: <code>&lt;img src="[image URL]"&gt;</code>. <em>Empty tags still must be closed.</em> They are closed by adding a space and a forward slash at the end, as follows in our example: <code>&lt;img src="[image URL]" /&gt;</code>.</li>
<li><strong>The value of an attribute must <em>always</em> be placed in quotes.</strong> For example <code>&lt;a href="http://www.yahoo.com"&gt;</code> and not <code>&lt;a href=http://www.yahoo.com&gt;</code>. Don&#8217;t forget to close your quotation marks! The incorrect <code>&lt;a href="http://www.yahoo.com&gt;</code> will cause you nightmares.</li>
<li><strong>Multiple attribute/value pairs should be separated by a space.</strong> For example, <code>&lt;a href="http://www.yahoo.com" title="Yahoo! home page" class="external_link"&gt;</code>.</li>
<li><strong>HTML phrases must be properly nested.</strong> This is best demonstrated by example. Correct: <code>&lt;p&gt;That statement is &lt;em&gt;ridiculous.&lt;/em&gt;&lt;/p&gt;</code> Incorrect: <code>&lt;p&gt;That statement is &lt;em&gt;ridiculous.&lt;/p&gt;&lt;/em&gt;</code></li>
</ol>
<p>Those are the ground rules — the <em>grammar</em> of <span class="caps">HTML</span>, if you will — and that&#8217;s all you really need to know. Everything else is just a matter of definitions and specifics. A good reference guide, like <a href="http://www.htmlhelp.com/reference/html40/" rel="nofollow">the guide at htmlhelp.com</a> will give you easy definitions for every element and attribute. (Be forwarned, however, that most guides are written for an earlier version of <span class="caps">HTML</span> and might imply that you can ignore the above syntax rules, which you cannot).</p>
<p>There are plenty of tools out there that will help you code <span class="caps">HTML</span> more quickly than you can by hand. But if you take the time to learn the actual mechanics of <span class="caps">HTML</span>, and if you internalize the concepts behind it, you&#8217;ll find yourself with much more control over the meaning of your documents and in a position to provide much more value to your readers.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2009/01/06/an-html-primer-for-writers-and-editors/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Capturing AutoFill as a Change Event</title>
		<link>http://furrybrains.com/2009/01/02/capturing-autofill-as-a-change-event/</link>
		<comments>http://furrybrains.com/2009/01/02/capturing-autofill-as-a-change-event/#comments</comments>
		<pubDate>Sat, 03 Jan 2009 06:29:25 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=104</guid>
		<description><![CDATA[I was working on a form design recently in which I wanted the corresponding labels to disappear whenever text was entered into an input field.
This was easy enough to accomplish via jQuery, but I quickly hit a snag. I had assigned an event listener to the &#8220;change&#8221; event, but it turns out that the change [...]]]></description>
			<content:encoded><![CDATA[<p>I was working on a form design recently in which I wanted the corresponding labels to disappear whenever text was entered into an input field.</p>
<p>This was easy enough to accomplish via jQuery, but I quickly hit a snag. I had assigned an event listener to the &#8220;change&#8221; event, but it turns out that the change event only gets fired when a user actively focuses on a field, inputs text, and then blurs. If a script &#8212; such as Google AutoFill &#8212; updates a value in a field on its own, the change event is unaware of it.</p>
<p>I poked around on Google a bit, and as far as I can tell, there doesn&#8217;t really seem to be an easy answer for this. So to make it work, I decided to write a quick jQuery plugin to handle the job.</p>
<p>I realized fortunately that rather than reinvent the wheel, all I need to do was find a way to listen for changes to input fields and then fire the change event manually if they were altered outside of the usual focus/blur routine (i.e. by a script).</p>
<p>Here&#8217;s the plugin code I came up with:</p>
<pre class="brush: jscript;">
(function($) {
    $.fn.listenForChange = function(options) {
        settings = $.extend({
            interval: 200 // in microseconds
        }, options);

        var jquery_object = this;
        var current_focus = null;

        jquery_object.filter(&quot;:input&quot;).add(&quot;:input&quot;, jquery_object).focus( function() {
            current_focus = this;
        }).blur( function() {
            current_focus = null;
        });

        setInterval(function() {
            // allow
            jquery_object.filter(&quot;:input&quot;).add(&quot;:input&quot;, jquery_object).each(function() {
                // set data cache on element to input value if not yet set
                if ($(this).data('change_listener') == undefined) {
                    $(this).data('change_listener', $(this).val());
                    return;
                }
                // return if the value matches the cache
                if ($(this).data('change_listener') == $(this).val()) {
                    return;
                }
                // ignore if element is in focus (since change event will fire on blur)
                if (this == current_focus) {
                    return;
                }
                // if we make it here, manually fire the change event and set the new value
                $(this).trigger('change');
                $(this).data('change_listener', $(this).val());
            });
        }, settings.interval);
        return this;
    };
})(jQuery);
</pre>
<p>The plugin makes use of the <a href="http://docs.jquery.com/Events/trigger"><code>trigger()</code></a> and <a href="http://docs.jquery.com/Core/data"><code>data()</code></a> functions. In a nutshell, we loop over the input element or set of children input elements, storing their initial value in the data cache provided by the <code>data()</code> function. We then check to see if the stored value matches the value of the input during the current iteration. If so, we do nothing, if not, we manually fire the change event via <code>trigger()</code>.</p>
<p>There&#8217;s also a bit of logic in there to ignore the element that has focus. We don&#8217;t need to worry about this element, since if the value is changed while the user has focus, the change event will be fired as normal when the element is blurred.</p>
<p>That&#8217;s all there is to it. To use the plugin, you simply call <code>listenForChange()</code> on the form or input you want to listen on, e.g.:</p>
<pre class="brush: jscript;">
$(&quot;form&quot;).listenForChange();
</pre>
<p>You can then assign whatever functions you want triggered to the change event as normal, and they&#8217;ll be fired regardless of whether the user types them or they are updated via a script.</p>
<p>I&#8217;ve tested this on Firefox with Google AutoFill and Safari&#8217;s built-in AutoFill, and it seems to work on both. I haven&#8217;t tested it on fields injected after page load, but presumably it would work for these as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2009/01/02/capturing-autofill-as-a-change-event/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>The Glass Hammer Wins Blog of the Year Award!</title>
		<link>http://furrybrains.com/2008/11/17/the-glass-hammer-wins-blog-of-the-year-award/</link>
		<comments>http://furrybrains.com/2008/11/17/the-glass-hammer-wins-blog-of-the-year-award/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 03:43:57 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=100</guid>
		<description><![CDATA[My congratulations go out to Nicki Gilmour and the gang of outstanding editors and contributors over at The Glass Hammer, who won a prestigious Stevie Award for Best Blog of the Year. The Glass Hammer was designed and developed by Furry Brains, and is based on Wordpress.
I&#8217;m not sure Furry Brains can take much credit [...]]]></description>
			<content:encoded><![CDATA[<p>My congratulations go out to Nicki Gilmour and the gang of outstanding editors and contributors over at <a href="http://www.theglasshammer.com/">The Glass Hammer</a>, who won a prestigious <a href="http://www.stevieawards.com/women/">Stevie Award</a> for <a href="http://www.theglasshammer.com/news/2008/11/18/the-glass-hammer-wins-%E2%80%9Cblog-of-the-year%E2%80%9D-award/">Best Blog of the Year</a>. The Glass Hammer was designed and developed by Furry Brains, and is based on Wordpress.</p>
<p>I&#8217;m not sure Furry Brains can take much credit for having a role in their winning this award, since it&#8217;s really the outstanding writing day in and day out that makes <em>The Glass Hammer</em> such a great publication. If anything, the design and implementation of the website step out of the way for the content itself to shine through.</p>
<p>But I&#8217;m pleased and proud if my contribution at least in some small way helped them get there. Way to go, TGH!</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2008/11/17/the-glass-hammer-wins-blog-of-the-year-award/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Address on the Spot: Using Google&#8217;s Reverse Geocoding API</title>
		<link>http://furrybrains.com/2008/11/01/address-on-the-spot-using-googles-reverse-geocoding-api/</link>
		<comments>http://furrybrains.com/2008/11/01/address-on-the-spot-using-googles-reverse-geocoding-api/#comments</comments>
		<pubDate>Sun, 02 Nov 2008 03:55:04 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[googlemaps]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=96</guid>
		<description><![CDATA[Google just launched a new feature as part of its geolocation services: a Reverse Geocoding feature as part of the Google Maps API.
The API is really simple to use. It took me only a few hours to put together a quick little utility called Address on the Spot, which allows you to double click anywhere [...]]]></description>
			<content:encoded><![CDATA[<p>Google just launched a new feature as part of its geolocation services: a <a href="http://code.google.com/apis/maps/documentation/services.html#ReverseGeocoding">Reverse Geocoding</a> feature as part of the Google Maps API.</p>
<p>The API is really simple to use. It took me only a few hours to put together a quick little utility called <a href="http://addressonthespot.com">Address on the Spot</a>, which allows you to double click anywhere on a map to find an address for a location.</p>
<p>So here&#8217;s a quick how to for using the Reverse Geocoding API.</p>
<p>First, create a <code>GLatLng</code> object with a set of geocoordinates:</p>
<pre class="brush: jscript;">
point = new GLatLng(45.523875, -122.670399);
</pre>
<p>Next, create a <code>GClientGeocoder</code> object and pass the <code>point</code> object to it, along with a callback function. The callback function <code>display_address()</code> will be executed when the geocoder returns a response.</p>
<pre class="brush: jscript;">
geocoder = new GClientGeocoder();
geocoder.getLocations(point, display_address);
</pre>
<p>Here&#8217;s what <code>display_address()</code> might look like:</p>
<pre class="brush: jscript;">
function display_address(response) {
    var address;
    if (!response || response.Status.code != 200) {
        address = &quot;No location data found.&quot;
    } else {
        address = response.Placemark[0].address;
    }
    alert(address);
}
</pre>
<p>Couldn&#8217;t be easier. It&#8217;s definitely a handy addition to the Google Maps API, and this utility was pretty fun and easy to build.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2008/11/01/address-on-the-spot-using-googles-reverse-geocoding-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using &#8220;in&#8221; in QuerySets in Django</title>
		<link>http://furrybrains.com/2008/10/23/using-in-in-querysets-in-django/</link>
		<comments>http://furrybrains.com/2008/10/23/using-in-in-querysets-in-django/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 03:11:14 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[queryset]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=85</guid>
		<description><![CDATA[So the purpose of this post is just to look at a neat way of solving a problem in Django, and explain its mechanics and how it was put together.
In today&#8217;s example, the goal was pretty straightforward. We have a model class, Topic, that has a one-to-many relationship to a ThreadedComment model class. Each ThreadedComment [...]]]></description>
			<content:encoded><![CDATA[<p>So the purpose of this post is just to look at a neat way of solving a problem in Django, and explain its mechanics and how it was put together.</p>
<p>In today&#8217;s example, the goal was pretty straightforward. We have a model class, <code>Topic</code>, that has a one-to-many relationship to a <code>ThreadedComment</code> model class. Each <code>ThreadedComment</code> for each <code>Topic</code>, has a <code>User</code> associated with it; furthermore the <code>Topic</code> itself as a <code>User</code> associated with it (the creator of the topic).</p>
<p><span id="more-85"></span></p>
<p>The issue here is that it&#8217;s not actually a straightforward relationship between <code>Topic</code> and <code>ThreadedComment</code>, due to some complicating factors beyond the scope of this discussion. Suffice it to say what we&#8217;re looking for is a list of users who are participants in the discussion, inclusive of the topic creator. But we&#8217;re not looking for just any old list &#8212; what we need is a QuerySet, for the reason that we are making use of some specialized tags in our templates that require data to be in a QuerySet.</p>
<p>Here&#8217;s a quick example of what we want the interface to look like in the template:</p>
<pre class="brush: xml;">
	&lt;ul&gt;
	{% for participant in topic.participants %}
		&lt;li&gt;{{ participant.name }}&lt;/li&gt;
	{% endfor %}
	&lt;/ul&gt;
</pre>
<p>So let&#8217;s do this step by step.</p>
<p>First, let&#8217;s get a list of the <code>ThreadedComment</code> objects we need:</p>
<pre class="brush: python;">
ThreadedComment.public.all_for_object(topic))
</pre>
<p>The <code>all_for_object()</code> method is one of the &#8220;complications&#8221; we were referring to above. All we care about is that it returns a set of <code>ThreadedComment</code> objects for a given topic.</p>
<p>Okay, but now that we have this set of objects, how are we going to return a QuerySet that yields us User objects?</p>
<p>My co-worker actually showed this to me, so I&#8217;ll share it here. We&#8217;ll use <code>in</code> keyword argument in <code>filter()</code>, which maps to the SQL <code>IN</code> clause. The Django documentation has a simple example:</p>
<pre class="brush: python;">
Entry.objects.filter(id__in=[1, 3, 4])
</pre>
<p>is equivalent to:</p>
<pre class="brush: sql;">
SELECT ... WHERE id IN (1, 3, 4)
</pre>
<p>So that&#8217;s just what we&#8217;re going to do: pass a list of user ids as an <code>in</code> keyword argument to identify the users we want.</p>
<p>First, let&#8217;s extend our original QuerySet to get the values we need as a list:</p>
<pre class="brush: python;">
ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)
</pre>
<p>One thing is missing &mdash; we need to include the user id of the topic creator, as I mentioned above. We&#8217;ll just evaluate the QuerySet to a list and then add the topic creator to it:</p>
<pre class="brush: python;">
list(ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)) + [self.creator.id]
</pre>
<p>Now let&#8217;s take the list of ids and pass it to a QuerySet that we&#8217;ll return <code>User</code> objects. Our list goes in the <code>pk__in</code> keyword argument:</p>
<pre class="brush: python;">
User.objects.filter(
    pk__in=list(
        list(ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)) + [self.creator.id]
    )
)
</pre>
<p>Now let&#8217;s add this as a method <code>participants()</code> to the <code>Topic</code> model and throw a <code>@property</code> decorator on it so we can call it as an attribute:</p>
<pre class="brush: python;">
@property
def participants(self):
    return User.objects.filter(
        pk__in=list(
            list(ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)) + [self.creator.id]
        )
    )
</pre>
<p>And that&#8217;s all there is to it.</p>
<p>What I love about this approach is that it&#8217;s a pattern that fits in to so many places (so many that I almost feel like it deserves a higher level abstraction within the QuerySet API). There are variations that make it slightly more efficient as well; for example, if I didn&#8217;t need to append the topic creator id in my example, then I could have passed the list of ids as a query as opposed to evaluating it:</p>
<pre class="brush: python;">
User.objects.filter(
    pk__in=ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)).query
)
</pre>
<p>The advantage here is that this is evaluated as a subselect statement, so it only requires a single database call.</p>
<p>Anyhow, this technique is really fantastic when you have a set of related objects that for whatever reason you aren&#8217;t able to easily obtain as a QuerySet. Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2008/10/23/using-in-in-querysets-in-django/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Figuring Out the Implementation of a Math Function Using Grapher on Mac OS X</title>
		<link>http://furrybrains.com/2008/10/13/using-grapher-to-get-your-head-around-a-math-problem/</link>
		<comments>http://furrybrains.com/2008/10/13/using-grapher-to-get-your-head-around-a-math-problem/#comments</comments>
		<pubDate>Tue, 14 Oct 2008 04:48:27 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=59</guid>
		<description><![CDATA[In a side project I&#8217;m working on right now in Django/Python, I need to do some work with latitudes and longitudes on a map. What follows is a description of how I tackled on of the specific challenges I faced.
In a nutshell, I&#8217;m going to be working with some data sets that are grouped into [...]]]></description>
			<content:encoded><![CDATA[<p>In a side project I&#8217;m working on right now in Django/Python, I need to do some work with latitudes and longitudes on a map. What follows is a description of how I tackled on of the specific challenges I faced.</p>
<p>In a nutshell, I&#8217;m going to be working with some data sets that are grouped into grid squares on a map. The grid squares are based on the integer values of <a href="http://en.wikipedia.org/wiki/Latitude">latitudes</a> and <a href="http://en.wikipedia.org/wiki/Longitude">longitudes</a>, which I have arbitrarily chosen to identify by the coordinates at their southwest corner.</p>
<p>So let&#8217;s put this in a picture to make it a bit easier to visualize. Basically, just try to visualize a <a href="http://en.wikipedia.org/wiki/Plate_carrée_projection">flat map</a> of the Earth. Longitude runs E/W along the X axis, with 0 degrees being the central horizontal point and 180/-180 degrees being the edges (which are actually the same thing, since the Earth wraps around in a sphere), while latitude runs N/S (along the Y axis), with 90 being the north pole and -90 being the south.</p>
<p>Note the following map isn&#8217;t really to &#8220;scale,&#8221; in the sense that the coordinate system I am using doesn&#8217;t perfectly match up in the real world with the map behind it. I&#8217;m just using the map to help visualize the grid:</p>
<p><span id="more-59"></span></p>
<p><a href="http://furrybrains.com/media/2008/10/map-example.gif"><img src="http://furrybrains.com/media/2008/10/map-example.gif" alt="" title="Map Grid" width="500" height="248" class="alignnone size-full wp-image-65" /></a></p>
<p>I&#8217;ve divvied up the map into &#8220;squares&#8221;, each of which is 1 degree of latitude tall and 1 degree longitude wide. The points are identified by their southwest corner coordinates, so the bottom left grid square on the map would be (-180,-90). I also plotted another random grid square at (-120,40).</p>
<p>So this is just a long-winded introduction to the problem at hand. I am going to be creating larger regions composed of these grid squares, which will be expanding outwards from a single grid square. There&#8217;s a chance that some of these regions will expand outwards at the edges of the map, so that the longitude and latitude points will have to be able to flip around and come back to the other side of the map.</p>
<p>In order to accomplish this, I basically need to be able to perform some simple math operations on the longitude and latitude integers that identify the grid squares. Take the grid square at (-180,-90). If I were to move three squares to the east, I would be at (-177,-90). If I were to move three squares to the west, though, I would be at (177,-90), because the longitude flips around to the other end of the scale at that point. Latitude is slightly different. If I go &#8220;up&#8221; three squares I&#8217;m at (-180, -87), whereas if I go &#8220;down&#8221; three squares, I&#8217;m at (0,-87)&#8230;in other words, the same latitude either direction.</p>
<p>Now we finally get to some programming.</p>
<p>To make sure that latitude and longitude behaved correctly in the calculations I would perform on them, I decided to encapsulate each of them in their own class. For my purposes (since the grid squares are spaced at integer values of latitude and longitude), I decided to subclass <code>int</code>, since the only behaviors I really needed to override were addition and subtraction.</p>
<p>Here&#8217;s a look at the final classes for both Longitude and Latitude:</p>
<pre class="brush: python;">
class Lng(int):

    def __add__(self, number):
        return self.__bound(int.__add__(self, number))

    def __sub__(self, number):
        return self.__bound(int.__sub__(self, number))

    def __bound(self, num):
        return int(num - 360*math.floor(num/360.0 + .5))
</pre>
<pre class="brush: python;">
class Lat(int):

    def __add__(self, number):
        return self.__bound(int.__add__(self, number))

    def __sub__(self, number):
        return self.__bound(int.__sub__(self, number))

    def __bound(self, num):
        return int((num - 180*math.floor((num/180.0) + .5))*2*(math.floor(math.sin((math.pi*num)/180 + math.pi/1.9999)) + .5))
</pre>
<p>What I really wanted to discuss here was my process for coming up with the &#8220;bound&#8221; functions in each class. &#8220;Bound&#8221; is what I named the function which takes the result of an addition or subtraction function and ensures that it stays within the boundaries defined by the map, according to the rules of that class.</p>
<p>Now, the last time I took a math class was in college (calculus), so what do I know about defining an oscillating function that repeats an upward movement in a linear fashion, or in the case of latitude, reverses that direction? In short, not much.</p>
<p>So how did I come up with a solution? Simple. I whipped out the excellent application called <a href="http://en.wikipedia.org/wiki/Grapher">Grapher</a>, which comes pre-installed on Mac OS X. This tool allows me to devise complex mathematical functions and see them plotted immediately. And that&#8217;s what I did.</p>
<p>Here&#8217;s how that process worked. Let&#8217;s start with longitude.</p>
<p>For longitude, I knew I needed a function that would start at (-180,-180) and proceed linearly until it reached (179,179). At x=180 though, the function would have to flip back down and start back at -180, since 180 and -180 are actually the same longitudinal line.</p>
<p>I basically started &#8220;brainstorming&#8221; at the Grapher function input, and finally stumbled upon:</p>
<p><em>Function 1.</em> <code>y=x-floor(x)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-1.gif"><img src="http://furrybrains.com/media/2008/10/grid-1.gif" alt="" title="grid-1" width="500" height="276" class="alignnone size-full wp-image-66" /></a></p>
<p>A good start, but the the lines are running from 0 to 1 on the y axis; we want the middle of the y axis to be 0. This should do the trick:</p>
<p><em>Function 2.</em> <code>y=x-floor(x+.5)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-2.gif"><img src="http://furrybrains.com/media/2008/10/grid-2.gif" alt="" title="grid-2" width="500" height="276" class="alignnone size-full wp-image-68" /></a></p>
<p>This function cycles through from -.5 to .5. We&#8217;re almost there, now we just need it to cycle through -180 to 180. A bit more fumbling around and we stumble upon:</p>
<p><em>Function 3.</em> <code>y=x-360*floor(x/360 + .5)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-3.gif"><img src="http://furrybrains.com/media/2008/10/grid-3.gif" alt="" title="grid-3" width="500" height="276" class="alignnone size-full wp-image-69" /></a></p>
<p>There you go, and that&#8217;s exactly what&#8217;s coded up in the <code>__bound()</code> method of Lng cited above.</p>
<p>Latitude was a bit trickier. In fact, I&#8217;m not thrilled with the implementation, but it works, so I&#8217;ll leave it alone until someone advises me of a better solution.</p>
<p>So our work with longitude sets things up nicely for latitude. We&#8217;ve already got a function that we can use to get us part of the way there:</p>
<p><em>Function 4.</em> <code>y=x-180*floor(x/180 + .5)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-4.gif"><img src="http://furrybrains.com/media/2008/10/grid-4.gif" alt="" title="grid-4" width="500" height="276" class="alignnone size-full wp-image-70" /></a></p>
<p>The only problem is, for latitude we need every other one of these upward sloping to be downward sloping (i.e. negative), since when latitude hits 90 degrees (the north pole) it then retreats back down rather than starting from the bottom again at -90 degrees.</p>
<p>What we need then is a function that oscillates back and forth between 1 and -1. If we can get that function to do its flip every 180 units, and we align it right, then we can apply it as a multiplier to Function 4 above.</p>
<p>I&#8217;m not very bright; the only function I know that oscillates is sin(x).</p>
<p><em>Function 5.</em> <code>y=sin(x)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-5.gif"><img src="http://furrybrains.com/media/2008/10/grid-5.gif" alt="" title="grid-5" width="500" height="276" class="alignnone size-full wp-image-71" /></a></p>
<p>Looks great. It&#8217;s flipping positive and negative at regular intervals. Now if we can only coax it to doing it at the intervals we want. Let&#8217;s see, it appears to be flipping signs in units of 3.14&#8230; hey, this is ringing a bell:</p>
<p><em>Function 6.</em> <code>y=sin(pi*x)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-6.gif"><img src="http://furrybrains.com/media/2008/10/grid-6.gif" alt="" title="grid-6" width="500" height="276" class="alignnone size-full wp-image-72" /></a></p>
<p>Sure enough, when we multiply x by a factor of &pi; we get a graph that oscillates between positive and negative every one unit. For the next step, let&#8217;s get it to truly flip from 1 to -1 and get rid of the curving line. To do that let&#8217;s apply a floor() function, which will cause the line to flip between 0 and -1. Then all we need to do is add 0.5 (so that it flips between -.5 and .5) and then multiply the whole thing by 2. Et voila:</p>
<p><em>Function 7.</em> <code>y=2*(floor(sin(pi*x))+.5)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-7.gif"><img src="http://furrybrains.com/media/2008/10/grid-7.gif" alt="" title="grid-7" width="500" height="276" class="alignnone size-full wp-image-73" /></a></p>
<p>Getting closer. Now, let&#8217;s see if we can&#8217;t get this to stretch across 180 units for each sign switch. Some messing around a bit gets us here:</p>
<p><em>Function 8.</em> <code>y=2*(floor(sin((pi*x)/180))+.5)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-8.gif"><img src="http://furrybrains.com/media/2008/10/grid-8.gif" alt="" title="grid-8" width="500" height="276" class="alignnone size-full wp-image-74" /></a></p>
<p>Almost there! Now the only problem is that we have to shift everything to the left, since right now each range starts at 0 and ends at 180 on the X axis, whereas latitude starts at -90 and ends at 90 on the X axis. To be honest this required a feat of minor inspiration, which yielded the following:</p>
<p><em>Function 9.</em> <code>y=2*(floor(sin((pi*x)/180) + (pi/2))+.5)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-9.gif"><img src="http://furrybrains.com/media/2008/10/grid-9.gif" alt="" title="grid-9" width="500" height="276" class="alignnone size-full wp-image-75" /></a></p>
<p>By adding pi/2 to the sin function, we shift everything over by half the range, which yields exactly the result we are looking for!* Now, all we need to do is apply our multiplier to Function 4:</p>
<p><em>Function 10.</em> <code>y=(x-180*floor(x/180 + .5))*2*(floor(sin((pi*x)/180) + (pi/2))+.5)</code></p>
<p><a href="http://furrybrains.com/media/2008/10/grid-10.gif"><img src="http://furrybrains.com/media/2008/10/grid-10.gif" alt="" title="grid-10" width="500" height="276" class="alignnone size-full wp-image-76" /></a></p>
<p>And as you can see, this is pretty much exactly what&#8217;s coded as the <code>__bound()</code> function for Latitude above.</p>
<p>So how does all of this at long last play out in our code? Well, since we&#8217;ve overridden the addition and subtraction functions for each of these and applied our <code>__bound()</code> function to the results of these calculations, it means we can add and subtract numbers from these objects and they will stay within the defined boundaries of our grid.</p>
<pre class="brush: python;">
&gt;&gt;&gt; import grid
&gt;&gt;&gt; x = grid.Lat(10)
&gt;&gt;&gt; x
10
&gt;&gt;&gt; x + 60
70
&gt;&gt;&gt; x + 80
90
&gt;&gt;&gt; x + 85
85
&gt;&gt;&gt; x + 250
-80
&gt;&gt;&gt; x + 270
-80
&gt;&gt;&gt; y = grid.Lat(10)
&gt;&gt;&gt; y
10
&gt;&gt;&gt; y + 60
70
&gt;&gt;&gt; y + 80
90
&gt;&gt;&gt; y + 85
85
&gt;&gt;&gt; y + 250
-80
&gt;&gt;&gt; y + 270
-80
&gt;&gt;&gt; y - 270
80
&gt;&gt;&gt; x = grid.Lng(10)
&gt;&gt;&gt; x
10
&gt;&gt;&gt; x + 120
130
&gt;&gt;&gt; x + 169
179
&gt;&gt;&gt; x + 170
-180
&gt;&gt;&gt; x + 350
0
&gt;&gt;&gt; x - 350
20
</pre>
<p>What&#8217;s the moral of the story here? I guess it&#8217;s that you don&#8217;t always have to know what you&#8217;re doing to figure out how to do something. My math and trigonometry skills are rusty at best, and yet with a little futzing around with Grapher I was able to whip together a pretty tidy little function that did just what I wanted. I hope this post inspires you to make use of Grapher if you ever find yourself in need of some serious math back-up.</p>
<p>On a final note, if anyone reading this has a better implementation of the mathematical functions I whipped up here, I&#8217;d love to hear about it.</p>
<p><strong>*Update:</strong> Re-reading my statement above that sin() was the only oscillating function I knew, I chuckled to myself that I also know cos()&#8230;at which point it dawned on me that I could replace out sin(x + pi/2) with cos(x), which I have since done.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2008/10/13/using-grapher-to-get-your-head-around-a-math-problem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

