Morse: de betere Gmail Notifier

Gmail is leuk. Zolang ik een internetverbinding heb kan ik altijd aan mijn e-mail. Gmail Notifier is ook leuk, want zo word ik automatisch verwittigd wanneer er nieuwe e-mails zijn. Maar je kan slechts één account in de gaten houden en ondertussen beschik ik over vier Gmail-accounts; 2 normale en 2 via Google Apps. Tijd voor iets beters dus. Tijd voor Morse.

Morse screenshot

Ik wilde al een tijdje wat nuttigs maken met Adobe AIR en dat is Morse geworden. Het is de bedoeling om Morse gratis te verspreiden, maar aangezien ik de enige ben die er tot nu toe wat mee heeft gespeeld, zou de applicatie nog wat getest moeten worden door anderen. Personen die de dingen wat anders aanpakken dan ik, vooral met Windows werken (de applicatie is momenteel vooral afgestemd op Windows) en niet panikeren als de applicatie zou ontploffen.

Update: gebruikers van OS X mogen me nu ook iets laten weten. Als je Sifter eens wil uittesten mag je dat ook vermelden.

Update: Morse kan je vanaf nu downloaden bij Roam.

Jij misschien? Reageer dan hier of stuur me een e-mail. Uw hulp zou welkom zijn.

Dit artikel werd opgenomen in ontwikkeling, software.


Even tussendoor

Soms geloof ik niet in toeval.


Drie opties; minstens één te veel

Tabelnamen in MySQL zijn niet noodzakelijk case insensitive. Zo komt de tabel POSTS niet per se overeen met de tabel posts. Op Windows wel. En op OS X ook. Maar op Unix niet. Tenzij je de lower_case_table_names variabele aanpast. Deze heeft 3 mogelijke opties: 0 (default op Unix), 1 (default op Windows), 2 (default op OS X).

Wacht, is dat nu geen overkill? Ofwel zijn de namen case sensitive, ofwel niet. Toch?

Ha, maar er is een ander gevolg van de gekozen optie: hoe wordt de tabelnaam opgeslagen. Lowercase? Zoals je hebt gespecifieerd bij het aanmaken van de tabel?

De 3 opties:

  • 0 (Unix): naam opslaan zoals gespecifieerd, case sensitive vergelijking
  • 1 (Windows): naam opslaan in lowercase, case insensitive vergelijking
  • 2 (OS X): naam opslaan zoals gespecifieerd, case insensitive vergelijking

Kom dat zien. Even ervan uitgaan dat je een default installatie hebt op de 3 bovenstaande besturingssystemen en dat je volgende tabel maakt:


CREATE TABLE BLA(id int);

Dan zal deze query werken op Windows en OS X, maar niet op Unix:


SELECT * FROM bla;

Yup, this sucker bit me in the ass today.

Dit artikel werd opgenomen in ontwikkeling.


Active links in Django

Django. Django. Nog eens? Django! Het is een geweldig framework, maar bij ieder framework zal je moeten vaststellen dat je wat mist.

Het probleem

De link voor de huidige pagina moet verdwijnen of er tenminste anders uitzien. Django komt niet met een directe oplossing en de meest relevante andere oplossing werkt met hardcoded paths. De beste oplossing zou zijn om met named URLs te werken.

Stel je voor dat dit de URL patterns zijn:


urlpatterns = patterns('',
    url(r'^archive/(?P\d{4})/(?P\d{2})/(?P\d{2})/$’,
        ‘proj.app.views.archive_for_a_day’,
        name=’proj_app_archive_for_a_day’),
    url(r’^search/$’,
        ‘proj.app.views.search’,
        name=’proj_app_search’),
)

In mijn menu wil ik linken naar het archief voor een bepaalde dag en de zoekpagina. Maar als ik op één van die pagina’s ben wil ik dat het list item met de overeenkomstige link de class active krijgt. Zoiets:


<ul>
    <li{{ request|on_active_link:"proj_app_archive_for_a_day,active" }}>
        <a href="{%url proj_app_archive_for_a_day year,month,day %}">Archive</a>
    </li>
    <li{{ request|on_active_link:"proj_app_search,active" }}>
        <a href="{%url proj_app_search %}">Search</a>
    </li>
</ul>

De oplossing

Die volgt uit 2 eenvoudige template filters:

  • matches_url_pattern zal True teruggeven bij een match, waardoor die kan gebruikt worden met een {% if %} om de link te verwijderen
  • on_active_link, uit bovenstaand voorbeeld, zal het tweede argument gebruiken als een class indien de naam van de URL pattern (het eerste argument) overeenkomt met het request path.

from django import template

register = template.Library()

@register.filter(name='matches_url_pattern')
def matches_url_pattern(value,args):
    return is_path_a_match_for_named_url(value, args)

@register.filter(name='on_active_link')
def on_active_link(value,args):
    parts = args.split(',')
    if is_path_a_match_for_named_url(value, parts[0]):
        return ' class="%s"' % parts[1]
    return ''

def is_path_a_match_for_named_url(request, named_url):
    from django.core.urlresolvers import get_resolver, Resolver404
    resolver = get_resolver(None)
    path = request.path
    tried = []
    match = resolver.regex.search(path)
    if match:
        new_path = path[match.end():]
        for pattern in resolver.urlconf_module.urlpatterns:
            try:
                sub_match = pattern.resolve(new_path)
            except Resolver404, e:
                tried.extend([(pattern.regex.pattern + '   ' + t) for t in e.args[0]['tried']])
            else:
                if sub_match:
                    return pattern.name == named_url
    return False

De laatste functie vergt het meeste uitleg. is_path_a_match_for_named_url gebruikt code die overgenomen is van de RegexURLResolver. Deze kan bepalen welk URL pattern met het huidige request path overeenkomt, maar biedt in de huidige versie geen mogelijkheid om de naam van dat pattern te achterhalen. Vandaar deze kopie die wel kan checken of de naam van het gevonden pattern overeenstemt met de gegeven parameter.

Het resultaat

Stel nu dat ik ben beland op /search/. De HTML zal er als volgt uitzien:


<ul>
    <li>
        <a href="/archive/2008/07/21/">Archive</a>
    </li>
    <li class="active">
        <a href="/search/">Search</a>
    </li>
</ul>

Een mooiere oplossing voor dit probleem zal de filters vervangen door tags en geen expliciete verwijzing naar de request variabele nodig hebben.

Dit artikel werd opgenomen in ontwikkeling.


Even tussendoor

Nee. Dit is geen echte verbetering.


Krassen op DVD? Pledge!

Pledge

Geverifieerd: als je een DVD bezit met de nodige krassen volstaat het om er wat Pledge op te spuiten en het boeltje af te vegen met een doekje.

Met dank aan Lifehacker.

Dit artikel werd opgenomen in elders.


Almost over now

Dit artikel werd opgenomen in elders.


Even tussendoor

Er komt géén spatie voor een uitroepteken! Er komt ook geen nieuwe lijn in normale, doorlopende tekst just for the hell of it. Maar, voor deze ene keer, laat ik het passeren.


Explorer, you bitch!

Net een tijdje zitten vloeken op Internet Explorer 7. Blijkbaar moet je een button-element echt wel als <button type="submit">Submit me!</button> schrijven als je een kans wilt maken om je formulier te verzenden.

Hoewel ik zou zweren dat ik al eens een button met succes heb gebruikt in IE7 zonder het type-attribuut te gebruiken…

Dit artikel werd opgenomen in webdesign.