Posts Tagged ‘Computers’

Chrome, continued

September 6, 2008

I just tried to edit a Google Groups page using Google Chrome, and I see:

Page editing not supported in your web browser. Download a new copy of Firefox or Internet Explorer to edit pages.

LOLZ!

Apart from that, I continue to be pretty impressed with Chrome. A few more observations:

  • I’ve seen a few crashes, and Google’s claims about sandboxing the tabs and apps seems mostly true:  a crash in one tab or app doesn’t usually bring down the whole browser.
  • I like the way that there’s no status bar taking up space all the time; addresses appear over the lower left corner of the window when you mouse over links, rather than in a dedicated space.
  • In-page search is incremental (as with Firefox), but has a few nice features: the browser tells you how many matches it found, and highlights both a “current” match and all the others, in different colors. It also shows you in the scrollbar area where the matches are, although it doesn’t let you click the indicators to go there immediately. I also like the location (upper-right) of the search window, I suppose because both my attention and the cursor are more often near the top than the bottom of the page.
  • Chrome DOES work with Java, but requires JRE 6 update 10, now in beta. Perhaps they needed the experimental “serialize user’s soul” feature…
  • While I wish the javascript debugger were friendlier—one thing that has annoyed me repeatedly is not being able to click on an error to go to the source; I’m told I should open the file in the inspector, but I seem not to be able to do that—but the DOM/css explorer is nice. Apparently webkit has a fuller version, but AFAIK it doesn’t work with Chrome (only Safari).
  • For some reason Chrome installs itself in your local app settings directory, not in \program files. I suppose there must be some reason for that…
  • The Application Shortcuts are surprisingly nifty for such a simple feature: all they really do is remove the browser ui. I have to assume that this is a harbinger of things to come. Chrome will become Google’s general application framework, a central part of their plan for world domination. Googlezon approacheth!
Advertisements

Chrome

September 2, 2008

google-chrome1 As the entire nerd world knows, today Google released a beta of its new browser, Chrome. I’m not really sure why they’re bothering; like everyone else, I’m vaguely assuming it’s something to do with to competing with Microsoft IE8 and its pornGoogle-blocker. Like others, I suspect it’s more likely to take market share from the more virtuous Firefox. The rest of the world can speculate more productively than I about what’s going on between Google and Mozilla.

I’ve been using Chrome for entire minutes now, and so far it seems pretty nice. It’s not enormously different from the rest of the world’s browsers, but then, other than generally behaving better what is there to do? And behave better it claims to do: read the comic book(!) to find out how (summary: multi-processing! one process per tab, basically).

The browser’s look and feel is Google-like, simple and streamlined—despite the name, it’s really not all that shiny, and I mean that in a good way. There’s no distracting flash cluttering up the screen; pretty much everything you see is functional.

Like IE7, Chrome has no menu bar; unlike IE7, it seems to have no way to get one. Which is probably just as well—if the browser is well-designed for menulessness you shouldn’t need them, and they can only clutter things up. The tabs are outside the rest of the app, giving a feel of “application inside tab” rather than “tab inside application,” which frankly doesn’t matter much to You the User, but which does presumably reflect the architecture of the browser. Having tabs on top does give the app a slightly different feel from most apps, especially with Windows Vista Aero.

The address bar does more or less what Firefox’s does, as far as I can tell. One nice feature is that the hostname is bolded, so it stands out from the rest of the URL, which for long crufty URLs is nice. There’s no search box, I suppose because the address bar is supposed to do all the searching you need. I’m not quite sure that’s true, as the dynamic autocompletion hints aren’t what they are in a real searchbox; they’re mixed with address history, I suppose.

To its credit it does seem very fast, both opening from scratch and opening new tabs. That’s one of my very few major beefs with Firefox; it takes so darned long to start the first time. IE starts relatively quickly—I assume that’s because most of its entrails are wrapped around the OS, and hence already loaded—but opens tabs infuriatingly slowly. Firefox can also hang waiting for applications, which Chrome claims not to do; but I can’t really judge that yet.

The controls and options and settings are all simple, which is excellent. But of course the downside is that there are settings that just aren’t there. They’re mostly minor things—new tabs open next to the tab you’re in, while I’d like them to open at the far right; I’d like to make the controls a little smaller to save screen space (both settable in FF)—but they’re on the “need more features” side of the too-simple/too-complex spectrum. IE, being a Microsoft product, pegs the too-complex needle, and not for any discernable reason; MS’s Internet settings dialog is an Abomination Before the Lord. Firefox does an excellent job of presenting options, and indeed Google’s options box seems to be copying Firefox’s philosophy, just without so much there yet. I do see some tiny niggly UI flaws—there’s no ellipsis after “Options” in the tools menu, for example. I’m a stickler for other people getting fiddly details right.

I think what I miss most from Firefox is Adblock Plus (you can argue with me about the propriety of adblockers some other time; the quick version of my position is that I don’t mind ads per se—in fact I rather like good ones—but I can’t abide all the animation and seizure-inducing flashing, and most repugnant of all the noise, of so many ads). Chrome will of course accumulate plugins, but that might be one Google doesn’t really want to accumulate.

Some other problems. Chrome does not seem to run Java(!) I assume that will be fixed during the beta (but when you ASSUME you make an ASS of U and ME…). There’s no Print Preview (haven’t tried printing yet; that’s something browsers generally don’t do well). It doesn’t render unicode characters outside the Basic Multilingual Plane properly (see this for a simple example). (I filed a bug about that one, using the handy built-in bug reporter.) I’m sure there are more that I’ll run into. Or that I’ve already forgotten about.

Hm, what else? There’s gdb-like javascript debugger, not as nice as Firebug or Dragonfly (unless I’m missing something), but for what it does my initial impression is that it looks pretty solid. The individual-tab task manager and memory stats are neat, but I don’t know if I really have much use for them.

Well, that’s more than enough for now. My plan is to use both Chrome and my beloved Firefox for a while, and see if I get sick of Chrome or decide I can’t live without it.

Some AJAX in Django

May 11, 2008

Months ago I started looking into doing AJAXy things within Django, and (typically for me) never actually did any of them. Finally I’ve started looking at that again. My needs are simple and dull: I just wanted quick and seamless responses to changes in form data in the little utilities I just added to my website.

Now I know very little about Ruby on Rails, but some of what I’ve seen if does look kinda cool. In particular I liked the respond_to gadget, which switches on requested mimetypes to figure out what response to send from a view (or action, or whatever they’re called on Rails). That seems to allow nice code factoring with minimal syntax, in a way that’s concise and clever (typical for Ruby) and clear (not so typical, IMO…).

I’m not convinced this is a truly great idea, for reasons I’ll detail below, but what the hey, when did that ever stop anyone? So I hacked up a python/Django analogue (see the end of the post). I may have course have misunderstood completely what’s up with the Ruby thing, in which case, oh well.

Here’s an example of how you use this thing—a Responder object—in a view:

def index(request):
    data = { 'foo' : 'bar', 'this' : 'that' }
    responder = Responder(request, 'template', data)
            { 'raw' : raw, 'types' : types })

    responder.html

    responder.js

    return responder.response()

This says, more or less “If the request wants HTML, render the data with the template template.html. If it wants javascript, render with the template template.js and the javascript mimetype.” That is, it’s something like

def index(request):
    data = { 'foo' : 'bar', 'this' : 'that' }

    if <wants html>:
        return render_to_response('template.html', data)

    if <wants js>:
        return render_to_response('template.js', data,
            mimetype='text/javascript' )

    return responder.response()

[where that <wants html/javascript> conceals some complexity…]

The render-a-template behavior can be overridden: those hacky ‘html’ and ‘js’ attributes are callable. If one of them is passed a function, it calls it: if the function returns something, that something is used as the response. It can also modify data and return None to proceed with default handling. Here’s an example I used when testing this stuff on different browsers. It prints the contents of the HTTP_ACCEPT header, and provides a button to fire an ajax request to replace that. In this case I built the javascript messily by hand.

def index(request):
    raw = request.META['HTTP_ACCEPT']
    types = parseAccept(request)

    responder = Responder(request, 'index.html',
            { 'raw' : raw, 'types' : types })

    responder.html

    @responder.js
    def jsresp(*args, **kwargs):
        text = raw + '<br><br>' + \
            '<br>'.join('%s %g' %(s, q) for s,q in types)
        js = "$('content').update('%s');" % text
        return HttpResponse(js, mimetype='text/javascript')

    return responder.response()

Here’s the corresponding template (which uses prototype):

<script src="/static/js/scriptaculous-js-1.8.1/lib/prototype.js" type="text/javascript"></script>
<script type="text/javascript">
    function ajaxUpdate () {
        headers = { Accept : 'text/javascript;q=1, */*;q=0.1' };
        if(Prototype.Browser.Opera)
        {
            headers.Accept += ',opera/hack'
        }

        new Ajax.Request('/',
            { method:'get', parameters: {}, requestHeaders : headers } );
    };
</script>

<div id="content">
    {{ raw }}<br><br>
    {% for s in types %}
    {{ s.0 }} {{ s.1 }}<br>
    {% endfor %}
</div>
<div>
    <br>
    <input id="b1" onclick="ajaxUpdate();" type="button" value="Click Me!">
    </input>
</div>

So What Have I Learned From This? Well, it all seems to work, so I’ll keep using it. But I’m not totally sold that this—switching on HTTP_ACCEPT, and my own particular implementation—is the Right Way to do things.

Philosophically, the general idea seems awfully prone to abuse. As I understand RESTful web services (i.e. not very well), different requests correspond to different representations of the same underlying data. But are the original html and the javascript that updates it really different representations of the same thing, or different animals altogether? I think that’s a murky point, at best. And I should think that in real life situations it could get messy. What happens, for example, if there is more than one sort of javascript request (e.g. if there are different forms on a page that do fundamentally different things)?

Rails and REST fans, please set me straight here!

Practically, the HTTP_ACCEPT thing seems delicate. I had to futz around a bit to get it to work in a way I felt at all confident of. Browsers seem to have different opinions about what they should ask for. Oddly, the browser that caused me the most problems was Opera—despite what I told prototype’s AJAX request, Opera insisted on concatenating the ACCEPTed mimetypes with the original request’s mimetypes. I hacked around that by throwing in a fake mimetype to separate the requests I wanted from those Opera wants; see the template above and the code below.

So anyway, maybe it would be better, or at least more Django, to be explicit about these AJAX requests, and either give them different URLs (and factor common code out of the various views) or add a piece of get/post data, as here. For now I’ll keep doing what I’m doing, and see if I run into problems.

Here’s the Responder code. It has numerous shortcomings, so use at your own risk. It is completely non-bulletproof (and non-debugged), and won’t work if you don’t use it just like I wanted to use it (e.g. you’d better give it a template name). It obviously needs more mimetype knowledge—it falls back on python’s mimetype library, but that seems seriously unacceptable here. And I’m very lame about how I parse the HTTP_ACCEPT strings.

import sys
import re
import os, os.path, mimetypes
import django
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext

class _ResponseHelper(object):
    def __init__(self, ext, mimetypes, responder):
        self.responder = responder
        self.ext = ext
        self.mimetypes = mimetypes
        self.fn = None

    def __call__(self, fn=None):
        self.fn = fn
        return fn

class Responder(object):
    """
    Utility for 'RESTful' responses based on requested mimitypes,
    in the request's HTTP_ACCEPT field, a la Reils' respond_to.

    To use, create a responder object.  Pass it the request object
    and the same arguments you would pass to render_to_response.
    Omit the file extension from the template name---it will be added
    automatically.
    For each type to be responded to, reference an attribute of the
    appropriate name (html, js, etc).
    Call the respond function to create a response.
    The response will be created by appending the extension to the filename
    and rendering to response, with the appropriate mimetype.

    To override the default behavior for a given type, treat its
    attribute as a function, and pass a function to it.
    It will be called with the same arguments as the Responder's constructor.
    If the function can modify the passed data, and either return None
    (in which case the template handling proceeds), or return a response.
    Function decorater syntax is a convenient way to do this.

    Example:

        responder = Responder(request, 'mytemplate', { 'foo': 'bar' })

        responder.html

        @responder.json
        def jsonresp(request, templ, data):
            data['foo' : 'baz']

        @responder.js
        def jsresp(request, templ, data):
            return HttpResponse(someJavascript,
                mimetype='application/javascript')

        return responder.response()

    Here an html request is processed as usual.
    A JSON request is processed with changed data.
    A JS request has its own response.

    """
    types = { 'html' : ('text/html',),
              'js' : ('text/javascript',
                      'application/javascript',
                      'application/x-javascript'),
              'json' : ('application/json',),
            }

    def __init__(self, request, *args, **kwargs):
        self.request = request
        self.resp = None
        self.args = [a for a in args]
        self.kwargs = kwargs
        self.priorities = {}
        for t, q in parseAccept(request):
            self.priorities.setdefault(t, q)
        self.defq = self.priorities.get('*/*', 0.0)
        self.bestq = 0.0

    def maybeadd(self, resp):
        try:
            thisq = self.bestq
            for mt in resp.mimetypes:
                q = self.priorities.get(mt, self.defq)
                if q > thisq:
                    resp.mimetype = mt
                    self.resp = resp
                    self.bestq = q
        except:
            pass

    def response(self):
        if self.resp:
            if self.resp.fn:
                result = self.resp.fn(self.request, *self.args, **self.kwargs)
                if result:
                    return result

            # the template name ought to be the first argument
            templ = self.args[0]
            base, ext = os.path.splitext(templ)
            if not ext:
                templ = "%s.%s" % (base, self.resp.ext)
            self.args[0] = templ
            self.kwargs['mimetype'] = self.resp.mimetype
        # if there wasn't a response, default to here
        response = render_to_response(
                context_instance=RequestContext(self.request),
                *self.args, **self.kwargs)
        return response

    def __getattr__(self, attr):
        mtypes = None
        if attr not in self.types:
            mtypes = [mt for mt, enc in [mimetypes.guess_type('.'+attr)]
                        if mt]
        else:
            mtypes = self.types[attr]
        if mtypes:
            resp = _ResponseHelper(attr, mtypes, self)
            self.maybeadd(resp)
            return resp
        else:
            return None

def parseAccept(request):
    """
    Turn a request's HTTP_ACCEPT string into a list
    of mimetype/priority pairs.
    Includes a hack to work around an Opera weirdness.
    """
    strings = request.META['HTTP_ACCEPT'].split(',')
    r = re.compile(r'(.*?)(?:\s*;\s*q\s*\=\s*(.*))?$')
    types = []
    for s in strings:
        m = r.match(s)
        q = float(m.groups()[1]) if m.groups()[1] else 1.0
        t = m.groups()[0].strip()
        if t == 'opera/hack':
            break
        types.append((t, q))
    return types

Some HTML text utilities

May 8, 2008

I’ve just added some utilities to my website:

  • A converter that takes HTML entities to/from the characters they represent. The input can be actual characters (e.g þ), named entity references (&thorn;), or numeric references, decimal or hexadecimal. It also accepts some abbreviations (two back-ticks for “, for example), which I’ll eventually document. Maybe.
  • Lorem Ipsum text, with settable font, font size, and line height.
  • A list of named HTML entities. (Yes, that’s easy to find, but I wanted a place I could get to easily.)

[Yes, I know all these things are easily available many places. I wanted to be able to get to them without having to think about it, and to be able to fiddle with the details.]

I wrote these for a target user base of one—me—so there’s no particular reason to think that they’ll be useful for anyone else. They’re also in a bit of a raw and unfinished state (in which they’ll stay until I get around to doing something about it). But hey, use them if you like.

All the entity names and unicode descriptions come from the python unicodedata and htmlentitydefs libraries. I love the way python includes stuff like that.

Windows Live Writer, cont.

April 29, 2008

Well, I’m impressed. Someone from the Live Writer team commented on my last post and told me how to use wordpress tags, my biggest complaint. Not only is the product free, you don’t even have to call to get technical support!

A more minor complaint turns out to have an interesting cause. I mentioned that Live Writer doesn’t format lists like WordPress itself. I was wrong—actually, it’s Firefox (which I mostly use) and IE that disagree (I assume, possibly wrongly, that LW uses IE’s rendering engine, or at least uses IE as a model). I found this bit of nastiness in WordPress’s CSS:

/* Begin Lists

	Special stylized non-IE bullets
	Do not work in Internet Explorer, which merely default to normal bullets. */

html>body .entry ul {
	margin-left: 0px;
	padding: 0 0 0 30px;
	list-style: none;
	padding-left: 10px;
	text-indent: -10px;
	}

html>body .entry li {
	margin: 7px 0 8px 10px;
	}

.entry ul li:before, #sidebar ul ul li:before {
	content: "0BB 020";
	}

So I’ll pin this one on WordPress, or whoever designed the “Kubrick” “I’m–too–lazy–to–change–it” theme, for knowingly doing something browser-dependent.

So, I’m feeling much warmer and fuzzier towards LW now. Definitely check it out.

Windows Live Writer

April 28, 2008

[UPDATE: See the comments, and this.  I am man enough to admit I was wrong about chunks of this.]

I’ve been using the Evil Empire’s Windows Live Writer for the last few blog posts, including this one. I haven’t made up my mind about it, but here are some impressions:

I do like the “form factor” of the Writer application as opposed to the in-browser WordPress interface, which I always find annoying. I find pretty much all web-based UI’s for inputting large swaths of text annoying, actually. WordPress’s, like many others, is naturally too short and too wide. I tend not to bother making it thinner, as that requires resizing the browser. I do make it taller, but that requires scrolling to get by all the stuff at the top of the page and allow space for the text.

A potential downside to WLV is that it stores drafts on the local machine, not online among WordPress’s drafts. That doesn’t matter for short posts, but for people like me who use multiple computers and write longer posts in multiple sittings, it could be a problem.

WLV is WYSIWYG, more or less, which for blogging is nice, but not really crucial. I imagine I will like it more the next time I add a picture, something that’s a pain to get right with WordPress’s native interface. WLV does not seem to understand WordPress’s “sourcecode” construct, which will be annoying for anything involving code. It also doesn’t get all the little details right—it doesn’t convert the keyboard pseudo-quotation marks to real quotes or multiple hyphens to em and en dashes, for example, and it doesn’t format lists correctly. For most purposes, though, I do find it an improvement over WP’s “visual editor,” which can be an over-aggressive pain at times.

Another minor complaint—the spellchecker highlights words even more obnoxiously than most Microsoft products, not only with squiggly underlines but with bolding. What on earth is that about?

The worst problem with WLV is that it doesn’t understand WordPress tags. Its tag interface is something else, requiring “tag sources,” that novice amateur incompetent blogger me doesn’t really understand. To get tags in I have to publish and then edit immediately. [UPDATE: it does understand them—see the comments.]

For now I’ll keep using it—the form factor thing is worth the problems. If anyone wants to correct my misapprehensions about said problems, please do.

UPDATE: Ha, I see one misapprehension already—there are options for “post as draft” and “open from weblog,” which get around the online/offline problem. My apologies for slandering you, Windows Live Writer!

Safari

April 12, 2008

For no particular reason I downloaded Safari for Windows and OMG MY EYES! THE GOGGLES, THEY DO NOTHING!

So it turns out I don’t much like the blurry eyestrain-inducing font rendering. I’m pretty late to the party here but I’ll pile on anyway.

It seems that Safari ignores Windows’ native font rendering—ClearType, on my machine—and use Apple’s own, Quartz. I would have expected them to be more or less the same, as they both mostly rely on subpixel rendering. But it turns out Quartz ignores TrueType hinting, relying only on the subpixel anti-aliasing, which is to say, blurrification. It’s especially noticeable in the vertical direction, where subpixels help not at all.

Apparently—and I don’t know how authoritative this is—Apple in its wisdom chose to ignore hinting in order to Preserve Design Intent. TrueType hints force features of glyphs to the pixel grid, meaning that some strokes get thinner and some thicker, that relative weights of bold and regular styles are distorted, that curves flatten out, and spacing can be a bit wonky. Relying solely on antialiasing does mitigate those problems, at the cost of blurring (and chromatic fringing, with subpixel renderers).

Windows’ ClearType does respect hinting, at least to some extent. Much as it pains me to say it, I’m with Microsoft on this one. [Caveat: ClearType’s effectiveness depends enormously on the monitor. It looks great on the relatively high-res laptop I’m using now. I’ve tried it on other monitors (yes, LCD ones) where it was unbearable. I imagine it depends heavily on the user as well.]

Now preserving design intent does make an enormous amount of sense in some contexts. If you’re actually trying to lay out a page for printing, font distortion is bad, and a bit of blurring is no biggie. Were I a graphic designer I’m sure I’d demand the better approximation of font weights and glyph shapes and positions and not care about the blurring.

But I’m not a graphic designer, I’m just some guy trying to read stuff on the web. I care much more about not getting a headache than about the aesthetic qualities of lower-case g’s descender. I can read slightly malformed but clear fonts much more easily than blurry ones.

Even from a philosophical point of view “design intent” is a tricky concept. TrueType hints are design intent. A lot of effort went into hinting Georgia and Verdana and the other core web fonts. So does the real intent reside entirely in the glyph outlines, or in the hinting as well? Well, really it sort of depends. Print and screen are different contexts (they will converge as screen resolutions get higher, but they haven’t yet), and good designers design for both. Apple, it seems to me, does not respect the latter. For a desktop publishing program that would make sense. But we’re talking about a web browser here.

[Yes, there are lots of crappily hinted fonts out there, including some that are beautiful in print. With those Quartz can look much nicer than ClearType, even to me. But a well-desgined website really should not use those fonts.]

It may be that were I a Mac person I would be used to Apple’s rendering and find Windows’ godawful and primitive. But I’m not. Does Apple want to show us benighted Windows drudges The Light? If so, it’s not working. I want Windows apps to act like Windows apps—consistency is important. Safari want to act like a Mac app, both in rendering and in a few other ways, things like the way it displays its scrollbars (yes, that’s pretty trivial). The weird part is that Apple understands better than anyone else the importance of strict user interface guidelines. Do they care about them only when the guidelines are their own?

Entering Exotic Characters

March 27, 2008

From Bill Poser at Language Log, some really useful resources for entering exotic characters, both as actual characters or as html codepoints (suitable for blogs, for example); and a set of links to nice IPA utilities (I particularly like the clickable pronunciation chart).

I generally get non-ascii characters using either vim digraphs, or a couple of macros I wrote for jEdit.

Another very nice-looking free font with lots of unicode coverage is Junicode, written by a medievalist for medievalists. And of course the DejaVu fonts have lots of coverage as well.

Upgrading Ubuntu

March 26, 2008

Throwing caution to the winds, I upgraded my Ubuntu laptop to the beta of Hardy Heron the other day. It almost worked…

The only serious problem I had–have–is that I can no longer get my WPA-encrypted wireless connection to work. Of course, that’s a bit of a showstopper–I am paranoid enough not to turn off encryption (and so should you be). I have just filed my first open-source bug report. Ah well, that’s betas.

The wireless problem may well have prevented me from running into any other major issues. I have hit a couple of minor ones, though. Most seriously, terminal fonts looked dreadful; that turns out to be known and easily fixable.

Other than some graphic coolness the new feature in Hardy I expect to find most immediately useful is wubi, which looks like it ought to make it possible to install, or at least test, ubuntu on a windows machine without doing scary things (well, disk partitioning tends to scare me) to it. I have just such a machine that I’d like to ubuntify, and I’d really like to make sure its wireless connection works before I do anything drastic.